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/access-list-num
521 static int lib_route_map_entry_match_condition_access_list_num_modify(
522 struct nb_cb_modify_args
*args
)
524 struct routemap_hook_context
*rhc
;
528 if (args
->event
!= NB_EV_APPLY
)
531 /* Check for hook function. */
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 3: /* ipv4-next-hop-list */
548 if (rmap_match_set_hook
.match_ip_next_hop
== NULL
)
550 rhc
->rhc_mhook
= rmap_match_set_hook
.no_match_ip_next_hop
;
551 rhc
->rhc_rule
= "ip next-hop";
552 rhc
->rhc_event
= RMAP_EVENT_FILTER_DELETED
;
553 rv
= rmap_match_set_hook
.match_ip_next_hop(
554 NULL
, rhc
->rhc_rmi
, "ip next-hop", acl
,
555 RMAP_EVENT_FILTER_ADDED
);
558 if (rv
!= CMD_SUCCESS
) {
559 rhc
->rhc_mhook
= NULL
;
560 return NB_ERR_INCONSISTENCY
;
566 static int lib_route_map_entry_match_condition_access_list_num_destroy(
567 struct nb_cb_destroy_args
*args
)
569 return lib_route_map_entry_match_destroy(args
);
574 * /frr-route-map:lib/route-map/entry/match-condition/access-list-num-extended
576 static int lib_route_map_entry_match_condition_access_list_num_extended_modify(
577 struct nb_cb_modify_args
*args
)
579 return lib_route_map_entry_match_condition_access_list_num_modify(args
);
582 static int lib_route_map_entry_match_condition_access_list_num_extended_destroy(
583 struct nb_cb_destroy_args
*args
)
585 return lib_route_map_entry_match_condition_access_list_num_destroy(
590 * XPath: /frr-route-map:lib/route-map/entry/match-condition/list-name
592 static int lib_route_map_entry_match_condition_list_name_modify(
593 struct nb_cb_modify_args
*args
)
595 struct routemap_hook_context
*rhc
;
600 if (args
->event
!= NB_EV_APPLY
)
603 /* Check for hook installation, otherwise we can just stop. */
604 acl
= yang_dnode_get_string(args
->dnode
, NULL
);
605 rhc
= nb_running_get_entry(args
->dnode
, NULL
, true);
606 condition
= yang_dnode_get_enum(args
->dnode
, "../condition");
608 case 1: /* ipv4-address-list */
609 if (rmap_match_set_hook
.match_ip_address
== NULL
)
611 rhc
->rhc_mhook
= rmap_match_set_hook
.no_match_ip_address
;
612 rhc
->rhc_rule
= "ip address";
613 rhc
->rhc_event
= RMAP_EVENT_FILTER_DELETED
;
614 rv
= rmap_match_set_hook
.match_ip_address(
615 NULL
, rhc
->rhc_rmi
, "ip address", acl
,
616 RMAP_EVENT_FILTER_ADDED
);
618 case 2: /* ipv4-prefix-list */
619 if (rmap_match_set_hook
.match_ip_address_prefix_list
== NULL
)
622 rmap_match_set_hook
.no_match_ip_address_prefix_list
;
623 rhc
->rhc_rule
= "ip address prefix-list";
624 rhc
->rhc_event
= RMAP_EVENT_PLIST_DELETED
;
625 rv
= rmap_match_set_hook
.match_ip_address_prefix_list(
626 NULL
, rhc
->rhc_rmi
, "ip address prefix-list", acl
,
627 RMAP_EVENT_PLIST_ADDED
);
629 case 3: /* ipv4-next-hop-list */
630 if (rmap_match_set_hook
.match_ip_next_hop
== NULL
)
632 rhc
->rhc_mhook
= rmap_match_set_hook
.no_match_ip_next_hop
;
633 rhc
->rhc_rule
= "ip next-hop";
634 rhc
->rhc_event
= RMAP_EVENT_FILTER_DELETED
;
635 rv
= rmap_match_set_hook
.match_ip_next_hop(
636 NULL
, rhc
->rhc_rmi
, "ip next-hop", acl
,
637 RMAP_EVENT_FILTER_ADDED
);
639 case 4: /* ipv4-next-hop-prefix-list */
640 if (rmap_match_set_hook
.match_ip_next_hop_prefix_list
== NULL
)
643 rmap_match_set_hook
.no_match_ip_next_hop_prefix_list
;
644 rhc
->rhc_rule
= "ip next-hop prefix-list";
645 rhc
->rhc_event
= RMAP_EVENT_PLIST_DELETED
;
646 rv
= rmap_match_set_hook
.match_ip_next_hop_prefix_list(
647 NULL
, rhc
->rhc_rmi
, "ip next-hop prefix-list", acl
,
648 RMAP_EVENT_PLIST_ADDED
);
650 case 6: /* ipv6-address-list */
651 if (rmap_match_set_hook
.match_ipv6_address
== NULL
)
653 rhc
->rhc_mhook
= rmap_match_set_hook
.no_match_ipv6_address
;
654 rhc
->rhc_rule
= "ipv6 address";
655 rhc
->rhc_event
= RMAP_EVENT_FILTER_DELETED
;
656 rv
= rmap_match_set_hook
.match_ipv6_address(
657 NULL
, rhc
->rhc_rmi
, "ipv6 address", acl
,
658 RMAP_EVENT_FILTER_ADDED
);
660 case 7: /* ipv6-prefix-list */
661 if (rmap_match_set_hook
.match_ipv6_address_prefix_list
== NULL
)
664 rmap_match_set_hook
.no_match_ipv6_address_prefix_list
;
665 rhc
->rhc_rule
= "ipv6 address prefix-list";
666 rhc
->rhc_event
= RMAP_EVENT_PLIST_DELETED
;
667 rv
= rmap_match_set_hook
.match_ipv6_address_prefix_list(
668 NULL
, rhc
->rhc_rmi
, "ipv6 address prefix-list", acl
,
669 RMAP_EVENT_PLIST_ADDED
);
672 rv
= CMD_ERR_NO_MATCH
;
675 if (rv
!= CMD_SUCCESS
) {
676 rhc
->rhc_mhook
= NULL
;
677 return NB_ERR_INCONSISTENCY
;
683 static int lib_route_map_entry_match_condition_list_name_destroy(
684 struct nb_cb_destroy_args
*args
)
686 return lib_route_map_entry_match_destroy(args
);
690 * XPath: /frr-route-map:lib/route-map/entry/match-condition/ipv4-next-hop-type
692 static int lib_route_map_entry_match_condition_ipv4_next_hop_type_modify(
693 struct nb_cb_modify_args
*args
)
695 struct routemap_hook_context
*rhc
;
699 if (args
->event
!= NB_EV_APPLY
)
702 /* Check for hook function. */
703 if (rmap_match_set_hook
.match_ip_next_hop_type
== NULL
)
706 /* Add configuration. */
707 rhc
= nb_running_get_entry(args
->dnode
, NULL
, true);
708 type
= yang_dnode_get_string(args
->dnode
, NULL
);
710 /* Set destroy information. */
711 rhc
->rhc_mhook
= rmap_match_set_hook
.no_match_ip_next_hop_type
;
712 rhc
->rhc_rule
= "ip next-hop type";
713 rhc
->rhc_event
= RMAP_EVENT_MATCH_DELETED
;
715 rv
= rmap_match_set_hook
.match_ip_next_hop_type(
716 NULL
, rhc
->rhc_rmi
, "ip next-hop type", type
,
717 RMAP_EVENT_MATCH_ADDED
);
718 if (rv
!= CMD_SUCCESS
) {
719 rhc
->rhc_mhook
= NULL
;
720 return NB_ERR_INCONSISTENCY
;
726 static int lib_route_map_entry_match_condition_ipv4_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/ipv6-next-hop-type
735 static int lib_route_map_entry_match_condition_ipv6_next_hop_type_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_ipv6_next_hop_type
== 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_ipv6_next_hop_type
;
755 rhc
->rhc_rule
= "ipv6 next-hop type";
756 rhc
->rhc_event
= RMAP_EVENT_MATCH_DELETED
;
758 rv
= rmap_match_set_hook
.match_ipv6_next_hop_type(
759 NULL
, rhc
->rhc_rmi
, "ipv6 next-hop type", type
,
760 RMAP_EVENT_MATCH_ADDED
);
761 if (rv
!= CMD_SUCCESS
) {
762 rhc
->rhc_mhook
= NULL
;
763 return NB_ERR_INCONSISTENCY
;
769 static int lib_route_map_entry_match_condition_ipv6_next_hop_type_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/metric
778 static int lib_route_map_entry_match_condition_metric_modify(
779 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_metric
== NULL
)
792 /* Add configuration. */
793 rhc
= nb_running_get_entry(args
->dnode
, NULL
, true);
794 type
= yang_dnode_get_string(args
->dnode
, NULL
);
796 /* Set destroy information. */
797 rhc
->rhc_mhook
= rmap_match_set_hook
.no_match_metric
;
798 rhc
->rhc_rule
= "metric";
799 rhc
->rhc_event
= RMAP_EVENT_MATCH_DELETED
;
801 rv
= rmap_match_set_hook
.match_metric(NULL
, rhc
->rhc_rmi
, "metric",
802 type
, RMAP_EVENT_MATCH_ADDED
);
803 if (rv
!= CMD_SUCCESS
) {
804 rhc
->rhc_mhook
= NULL
;
805 return NB_ERR_INCONSISTENCY
;
811 static int lib_route_map_entry_match_condition_metric_destroy(
812 struct nb_cb_destroy_args
*args
)
814 return lib_route_map_entry_match_destroy(args
);
818 * XPath: /frr-route-map:lib/route-map/entry/match-condition/tag
821 lib_route_map_entry_match_condition_tag_modify(struct nb_cb_modify_args
*args
)
823 struct routemap_hook_context
*rhc
;
827 if (args
->event
!= NB_EV_APPLY
)
830 /* Check for hook function. */
831 if (rmap_match_set_hook
.match_tag
== NULL
)
834 /* Add configuration. */
835 rhc
= nb_running_get_entry(args
->dnode
, NULL
, true);
836 tag
= yang_dnode_get_string(args
->dnode
, NULL
);
838 /* Set destroy information. */
839 rhc
->rhc_mhook
= rmap_match_set_hook
.no_match_tag
;
840 rhc
->rhc_rule
= "tag";
841 rhc
->rhc_event
= RMAP_EVENT_MATCH_DELETED
;
843 rv
= rmap_match_set_hook
.match_tag(NULL
, rhc
->rhc_rmi
, "tag", tag
,
844 RMAP_EVENT_MATCH_ADDED
);
845 if (rv
!= CMD_SUCCESS
) {
846 rhc
->rhc_mhook
= NULL
;
847 return NB_ERR_INCONSISTENCY
;
854 lib_route_map_entry_match_condition_tag_destroy(struct nb_cb_destroy_args
*args
)
856 return lib_route_map_entry_match_destroy(args
);
860 * XPath: /frr-route-map:lib/route-map/entry/set-action
862 static int lib_route_map_entry_set_action_create(struct nb_cb_create_args
*args
)
864 return lib_route_map_entry_match_condition_create(args
);
868 lib_route_map_entry_set_action_destroy(struct nb_cb_destroy_args
*args
)
870 struct routemap_hook_context
*rhc
;
873 if (args
->event
!= NB_EV_APPLY
)
876 rv
= lib_route_map_entry_set_destroy(args
);
877 rhc
= nb_running_unset_entry(args
->dnode
);
878 routemap_hook_context_free(rhc
);
884 * XPath: /frr-route-map:lib/route-map/entry/set-action/ipv4-address
886 static int lib_route_map_entry_set_action_ipv4_address_modify(
887 struct nb_cb_modify_args
*args
)
889 struct routemap_hook_context
*rhc
;
894 switch (args
->event
) {
897 * NOTE: validate if 'action' is 'ipv4-next-hop',
898 * currently it is not necessary because this is the
899 * only implemented action.
901 yang_dnode_get_ipv4(&ia
, args
->dnode
, NULL
);
902 if (ia
.s_addr
== INADDR_ANY
|| IPV4_CLASS_DE(ntohl(ia
.s_addr
)))
903 return NB_ERR_VALIDATION
;
912 /* Check for hook function. */
913 if (rmap_match_set_hook
.set_ip_nexthop
== NULL
)
916 /* Add configuration. */
917 rhc
= nb_running_get_entry(args
->dnode
, NULL
, true);
918 address
= yang_dnode_get_string(args
->dnode
, NULL
);
920 /* Set destroy information. */
921 rhc
->rhc_shook
= rmap_match_set_hook
.no_set_ip_nexthop
;
922 rhc
->rhc_rule
= "ip next-hop";
924 rv
= rmap_match_set_hook
.set_ip_nexthop(NULL
, rhc
->rhc_rmi
,
925 "ip next-hop", address
);
926 if (rv
!= CMD_SUCCESS
) {
927 rhc
->rhc_shook
= NULL
;
928 return NB_ERR_INCONSISTENCY
;
934 static int lib_route_map_entry_set_action_ipv4_address_destroy(
935 struct nb_cb_destroy_args
*args
)
937 return lib_route_map_entry_set_destroy(args
);
941 * XPath: /frr-route-map:lib/route-map/entry/set-action/ipv6-address
943 static int lib_route_map_entry_set_action_ipv6_address_modify(
944 struct nb_cb_modify_args
*args
)
946 struct routemap_hook_context
*rhc
;
951 switch (args
->event
) {
954 * NOTE: validate if 'action' is 'ipv6-next-hop',
955 * currently it is not necessary because this is the
956 * only implemented action. Other actions might have
957 * different validations.
959 yang_dnode_get_ipv6(&i6a
, args
->dnode
, NULL
);
960 if (!IN6_IS_ADDR_LINKLOCAL(&i6a
))
961 return NB_ERR_VALIDATION
;
970 /* Check for hook function. */
971 if (rmap_match_set_hook
.set_ipv6_nexthop_local
== NULL
)
974 /* Add configuration. */
975 rhc
= nb_running_get_entry(args
->dnode
, NULL
, true);
976 address
= yang_dnode_get_string(args
->dnode
, NULL
);
978 /* Set destroy information. */
979 rhc
->rhc_shook
= rmap_match_set_hook
.no_set_ipv6_nexthop_local
;
980 rhc
->rhc_rule
= "ipv6 next-hop local";
982 rv
= rmap_match_set_hook
.set_ipv6_nexthop_local(
983 NULL
, rhc
->rhc_rmi
, "ipv6 next-hop local", address
);
984 if (rv
!= CMD_SUCCESS
) {
985 rhc
->rhc_shook
= NULL
;
986 return NB_ERR_INCONSISTENCY
;
992 static int lib_route_map_entry_set_action_ipv6_address_destroy(
993 struct nb_cb_destroy_args
*args
)
995 return lib_route_map_entry_set_destroy(args
);
999 * XPath: /frr-route-map:lib/route-map/entry/set-action/value
1001 static int set_action_modify(enum nb_event event
, const struct lyd_node
*dnode
,
1002 union nb_resource
*resource
, const char *value
)
1004 struct routemap_hook_context
*rhc
;
1008 * NOTE: validate if 'action' is 'metric', currently it is not
1009 * necessary because this is the only implemented action. Other
1010 * actions might have different validations.
1012 if (event
!= NB_EV_APPLY
)
1015 /* Check for hook function. */
1016 if (rmap_match_set_hook
.set_metric
== NULL
)
1019 /* Add configuration. */
1020 rhc
= nb_running_get_entry(dnode
, NULL
, true);
1022 /* Set destroy information. */
1023 rhc
->rhc_shook
= rmap_match_set_hook
.no_set_metric
;
1024 rhc
->rhc_rule
= "metric";
1026 rv
= rmap_match_set_hook
.set_metric(NULL
, rhc
->rhc_rmi
, "metric",
1028 if (rv
!= CMD_SUCCESS
) {
1029 rhc
->rhc_shook
= NULL
;
1030 return NB_ERR_INCONSISTENCY
;
1037 lib_route_map_entry_set_action_value_modify(struct nb_cb_modify_args
*args
)
1039 const char *metric
= yang_dnode_get_string(args
->dnode
, NULL
);
1041 return set_action_modify(args
->event
, args
->dnode
, args
->resource
,
1046 lib_route_map_entry_set_action_value_destroy(struct nb_cb_destroy_args
*args
)
1048 return lib_route_map_entry_set_destroy(args
);
1052 * XPath: /frr-route-map:lib/route-map/entry/set-action/add-metric
1055 lib_route_map_entry_set_action_add_metric_modify(struct nb_cb_modify_args
*args
)
1057 return set_action_modify(args
->event
, args
->dnode
, args
->resource
,
1061 static int lib_route_map_entry_set_action_add_metric_destroy(
1062 struct nb_cb_destroy_args
*args
)
1064 return lib_route_map_entry_set_action_value_destroy(args
);
1068 * XPath: /frr-route-map:lib/route-map/entry/set-action/subtract-metric
1070 static int lib_route_map_entry_set_action_subtract_metric_modify(
1071 struct nb_cb_modify_args
*args
)
1073 return set_action_modify(args
->event
, args
->dnode
, args
->resource
,
1077 static int lib_route_map_entry_set_action_subtract_metric_destroy(
1078 struct nb_cb_destroy_args
*args
)
1080 return lib_route_map_entry_set_action_value_destroy(args
);
1084 * XPath: /frr-route-map:lib/route-map/entry/set-action/use-round-trip-time
1086 static int lib_route_map_entry_set_action_use_round_trip_time_modify(
1087 struct nb_cb_modify_args
*args
)
1089 return set_action_modify(args
->event
, args
->dnode
, args
->resource
,
1093 static int lib_route_map_entry_set_action_use_round_trip_time_destroy(
1094 struct nb_cb_destroy_args
*args
)
1096 return lib_route_map_entry_set_action_value_destroy(args
);
1100 * XPath: /frr-route-map:lib/route-map/entry/set-action/add-round-trip-time
1102 static int lib_route_map_entry_set_action_add_round_trip_time_modify(
1103 struct nb_cb_modify_args
*args
)
1105 return set_action_modify(args
->event
, args
->dnode
, args
->resource
,
1109 static int lib_route_map_entry_set_action_add_round_trip_time_destroy(
1110 struct nb_cb_destroy_args
*args
)
1112 return lib_route_map_entry_set_action_value_destroy(args
);
1116 * XPath: /frr-route-map:lib/route-map/entry/set-action/subtract-round-trip-time
1118 static int lib_route_map_entry_set_action_subtract_round_trip_time_modify(
1119 struct nb_cb_modify_args
*args
)
1121 return set_action_modify(args
->event
, args
->dnode
, args
->resource
,
1125 static int lib_route_map_entry_set_action_subtract_round_trip_time_destroy(
1126 struct nb_cb_destroy_args
*args
)
1128 return lib_route_map_entry_set_action_value_destroy(args
);
1132 * XPath: /frr-route-map:lib/route-map/entry/set-action/tag
1135 lib_route_map_entry_set_action_tag_modify(struct nb_cb_modify_args
*args
)
1137 struct routemap_hook_context
*rhc
;
1142 * NOTE: validate if 'action' is 'tag', currently it is not
1143 * necessary because this is the only implemented action. Other
1144 * actions might have different validations.
1146 if (args
->event
!= NB_EV_APPLY
)
1149 /* Check for hook function. */
1150 if (rmap_match_set_hook
.set_tag
== NULL
)
1153 /* Add configuration. */
1154 rhc
= nb_running_get_entry(args
->dnode
, NULL
, true);
1155 tag
= yang_dnode_get_string(args
->dnode
, NULL
);
1157 /* Set destroy information. */
1158 rhc
->rhc_shook
= rmap_match_set_hook
.no_set_tag
;
1159 rhc
->rhc_rule
= "tag";
1161 rv
= rmap_match_set_hook
.set_tag(NULL
, rhc
->rhc_rmi
, "tag", tag
);
1162 if (rv
!= CMD_SUCCESS
) {
1163 rhc
->rhc_shook
= NULL
;
1164 return NB_ERR_INCONSISTENCY
;
1171 lib_route_map_entry_set_action_tag_destroy(struct nb_cb_destroy_args
*args
)
1173 return lib_route_map_entry_set_destroy(args
);
1176 /* clang-format off */
1177 const struct frr_yang_module_info frr_route_map_info
= {
1178 .name
= "frr-route-map",
1181 .xpath
= "/frr-route-map:lib/route-map",
1183 .create
= lib_route_map_create
,
1184 .destroy
= lib_route_map_destroy
,
1188 .xpath
= "/frr-route-map:lib/route-map/entry",
1190 .create
= lib_route_map_entry_create
,
1191 .destroy
= lib_route_map_entry_destroy
,
1192 .cli_show
= route_map_instance_show
,
1193 .cli_show_end
= route_map_instance_show_end
,
1197 .xpath
= "/frr-route-map:lib/route-map/entry/description",
1199 .modify
= lib_route_map_entry_description_modify
,
1200 .destroy
= lib_route_map_entry_description_destroy
,
1201 .cli_show
= route_map_description_show
,
1205 .xpath
= "/frr-route-map:lib/route-map/entry/action",
1207 .modify
= lib_route_map_entry_action_modify
,
1211 .xpath
= "/frr-route-map:lib/route-map/entry/call",
1213 .modify
= lib_route_map_entry_call_modify
,
1214 .destroy
= lib_route_map_entry_call_destroy
,
1215 .cli_show
= route_map_call_show
,
1219 .xpath
= "/frr-route-map:lib/route-map/entry/exit-policy",
1221 .modify
= lib_route_map_entry_exit_policy_modify
,
1222 .cli_show
= route_map_exit_policy_show
,
1226 .xpath
= "/frr-route-map:lib/route-map/entry/goto-value",
1228 .modify
= lib_route_map_entry_goto_value_modify
,
1229 .destroy
= lib_route_map_entry_goto_value_destroy
,
1233 .xpath
= "/frr-route-map:lib/route-map/entry/match-condition",
1235 .create
= lib_route_map_entry_match_condition_create
,
1236 .destroy
= lib_route_map_entry_match_condition_destroy
,
1237 .cli_show
= route_map_condition_show
,
1241 .xpath
= "/frr-route-map:lib/route-map/entry/match-condition/interface",
1243 .modify
= lib_route_map_entry_match_condition_interface_modify
,
1244 .destroy
= lib_route_map_entry_match_condition_interface_destroy
,
1248 .xpath
= "/frr-route-map:lib/route-map/entry/match-condition/access-list-num",
1250 .modify
= lib_route_map_entry_match_condition_access_list_num_modify
,
1251 .destroy
= lib_route_map_entry_match_condition_access_list_num_destroy
,
1255 .xpath
= "/frr-route-map:lib/route-map/entry/match-condition/access-list-num-extended",
1257 .modify
= lib_route_map_entry_match_condition_access_list_num_extended_modify
,
1258 .destroy
= lib_route_map_entry_match_condition_access_list_num_extended_destroy
,
1262 .xpath
= "/frr-route-map:lib/route-map/entry/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/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/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/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/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/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/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/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/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/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/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/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/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/tag",
1363 .modify
= lib_route_map_entry_set_action_tag_modify
,
1364 .destroy
= lib_route_map_entry_set_action_tag_destroy
,