2 * Route map northbound implementation.
4 * Copyright (C) 2019 Network Device Education Foundation, Inc. ("NetDEF")
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 #include "lib/command.h"
27 #include "lib/northbound.h"
28 #include "lib/routemap.h"
31 * Auxiliary functions to avoid code duplication:
33 * lib_route_map_entry_set_destroy: unset `set` commands.
34 * lib_route_map_entry_match_destroy: unset `match` commands.
36 int lib_route_map_entry_match_destroy(enum nb_event event
,
37 const struct lyd_node
*dnode
)
39 struct routemap_hook_context
*rhc
;
42 if (event
!= NB_EV_APPLY
)
45 rhc
= nb_running_get_entry(dnode
, NULL
, true);
46 if (rhc
->rhc_mhook
== NULL
)
49 rv
= rhc
->rhc_mhook(NULL
, rhc
->rhc_rmi
, rhc
->rhc_rule
, NULL
,
51 if (rv
!= CMD_SUCCESS
)
52 return NB_ERR_INCONSISTENCY
;
57 int lib_route_map_entry_set_destroy(enum nb_event event
,
58 const struct lyd_node
*dnode
)
60 struct routemap_hook_context
*rhc
;
63 if (event
!= NB_EV_APPLY
)
66 rhc
= nb_running_get_entry(dnode
, NULL
, true);
67 if (rhc
->rhc_shook
== NULL
)
70 rv
= rhc
->rhc_shook(NULL
, rhc
->rhc_rmi
, rhc
->rhc_rule
, NULL
);
71 if (rv
!= CMD_SUCCESS
)
72 return NB_ERR_INCONSISTENCY
;
78 * Auxiliary hook context list manipulation functions.
80 struct routemap_hook_context
*
81 routemap_hook_context_insert(struct route_map_index
*rmi
)
83 struct routemap_hook_context
*rhc
;
85 rhc
= XCALLOC(MTYPE_TMP
, sizeof(*rhc
));
87 TAILQ_INSERT_TAIL(&rmi
->rhclist
, rhc
, rhc_entry
);
93 routemap_hook_context_free(struct routemap_hook_context
*rhc
)
95 struct route_map_index
*rmi
= rhc
->rhc_rmi
;
97 TAILQ_REMOVE(&rmi
->rhclist
, rhc
, rhc_entry
);
98 XFREE(MTYPE_TMP
, rhc
);
102 * XPath: /frr-route-map:lib/route-map
104 static int lib_route_map_create(enum nb_event event
,
105 const struct lyd_node
*dnode
,
106 union nb_resource
*resource
)
108 struct route_map
*rm
;
118 rm_name
= yang_dnode_get_string(dnode
, "./name");
119 rm
= route_map_get(rm_name
);
120 nb_running_set_entry(dnode
, rm
);
127 static int lib_route_map_destroy(enum nb_event event
,
128 const struct lyd_node
*dnode
)
130 struct route_map
*rm
;
139 rm
= nb_running_unset_entry(dnode
);
140 route_map_delete(rm
);
148 * XPath: /frr-route-map:lib/route-map/entry
150 static int lib_route_map_entry_create(enum nb_event event
,
151 const struct lyd_node
*dnode
,
152 union nb_resource
*resource
)
154 struct route_map_index
*rmi
;
155 struct route_map
*rm
;
166 sequence
= yang_dnode_get_uint16(dnode
, "./sequence");
167 action
= yang_dnode_get_enum(dnode
, "./action") == 0
170 rm
= nb_running_get_entry(dnode
, NULL
, true);
171 rmi
= route_map_index_get(rm
, action
, sequence
);
172 nb_running_set_entry(dnode
, rmi
);
179 static int lib_route_map_entry_destroy(enum nb_event event
,
180 const struct lyd_node
*dnode
)
182 struct route_map_index
*rmi
;
191 rmi
= nb_running_unset_entry(dnode
);
192 route_map_index_delete(rmi
, 1);
200 * XPath: /frr-route-map:lib/route-map/entry/description
202 static int lib_route_map_entry_description_modify(enum nb_event event
,
203 const struct lyd_node
*dnode
,
204 union nb_resource
*resource
)
206 struct route_map_index
*rmi
;
207 const char *description
;
214 description
= yang_dnode_get_string(dnode
, NULL
);
215 resource
->ptr
= XSTRDUP(MTYPE_TMP
, description
);
216 if (resource
->ptr
== NULL
)
217 return NB_ERR_RESOURCE
;
220 XFREE(MTYPE_TMP
, resource
->ptr
);
223 rmi
= nb_running_get_entry(dnode
, NULL
, true);
224 if (rmi
->description
!= NULL
)
225 XFREE(MTYPE_TMP
, rmi
->description
);
226 rmi
->description
= resource
->ptr
;
233 static int lib_route_map_entry_description_destroy(enum nb_event event
,
234 const struct lyd_node
*dnode
)
236 struct route_map_index
*rmi
;
245 rmi
= nb_running_get_entry(dnode
, NULL
, true);
246 if (rmi
->description
!= NULL
)
247 XFREE(MTYPE_TMP
, rmi
->description
);
248 rmi
->description
= NULL
;
256 * XPath: /frr-route-map:lib/route-map/entry/action
258 static int lib_route_map_entry_action_modify(enum nb_event event
,
259 const struct lyd_node
*dnode
,
260 union nb_resource
*resource
)
262 struct route_map_index
*rmi
;
271 rmi
= nb_running_get_entry(dnode
, NULL
, true);
272 rmi
->type
= yang_dnode_get_enum(dnode
, NULL
);
281 * XPath: /frr-route-map:lib/route-map/entry/call
283 static int lib_route_map_entry_call_modify(enum nb_event event
,
284 const struct lyd_node
*dnode
,
285 union nb_resource
*resource
)
287 struct route_map_index
*rmi
;
288 const char *rm_name
, *rmn_name
;
292 rm_name
= yang_dnode_get_string(dnode
, "../../name");
293 rmn_name
= yang_dnode_get_string(dnode
, NULL
);
294 /* Don't allow to jump to the same route map instance. */
295 if (strcmp(rm_name
, rmn_name
) == 0)
296 return NB_ERR_VALIDATION
;
298 /* TODO: detect circular route map sequences. */
301 rmn_name
= yang_dnode_get_string(dnode
, NULL
);
302 resource
->ptr
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmn_name
);
305 XFREE(MTYPE_ROUTE_MAP_NAME
, resource
->ptr
);
308 rmi
= nb_running_get_entry(dnode
, NULL
, true);
310 route_map_upd8_dependency(RMAP_EVENT_CALL_DELETED
,
311 rmi
->nextrm
, rmi
->map
->name
);
312 XFREE(MTYPE_ROUTE_MAP_NAME
, rmi
->nextrm
);
314 rmi
->nextrm
= resource
->ptr
;
315 route_map_upd8_dependency(RMAP_EVENT_CALL_ADDED
, rmi
->nextrm
,
323 static int lib_route_map_entry_call_destroy(enum nb_event event
,
324 const struct lyd_node
*dnode
)
326 struct route_map_index
*rmi
;
335 rmi
= nb_running_get_entry(dnode
, NULL
, true);
336 route_map_upd8_dependency(RMAP_EVENT_CALL_DELETED
, rmi
->nextrm
,
338 XFREE(MTYPE_ROUTE_MAP_NAME
, rmi
->nextrm
);
347 * XPath: /frr-route-map:lib/route-map/entry/exit-policy
349 static int lib_route_map_entry_exit_policy_modify(enum nb_event event
,
350 const struct lyd_node
*dnode
,
351 union nb_resource
*resource
)
353 struct route_map_index
*rmi
;
359 policy
= yang_dnode_get_enum(dnode
, NULL
);
361 case 0: /* permit-or-deny */
366 rm_action
= yang_dnode_get_enum(dnode
, "../action");
367 if (rm_action
== 1 /* deny */) {
369 * On deny it is not possible to 'goto'
372 return NB_ERR_VALIDATION
;
381 rmi
= nb_running_get_entry(dnode
, NULL
, true);
382 policy
= yang_dnode_get_enum(dnode
, NULL
);
385 case 0: /* permit-or-deny */
386 rmi
->exitpolicy
= RMAP_EXIT
;
389 rmi
->exitpolicy
= RMAP_NEXT
;
392 rmi
->exitpolicy
= RMAP_GOTO
;
402 * XPath: /frr-route-map:lib/route-map/entry/goto-value
404 static int lib_route_map_entry_goto_value_modify(enum nb_event event
,
405 const struct lyd_node
*dnode
,
406 union nb_resource
*resource
)
408 struct route_map_index
*rmi
;
414 rmi_index
= yang_dnode_get_uint16(dnode
, "../sequence");
415 rmi_next
= yang_dnode_get_uint16(dnode
, NULL
);
416 if (rmi_next
<= rmi_index
) {
417 /* Can't jump backwards on a route map. */
418 return NB_ERR_VALIDATION
;
426 rmi
= nb_running_get_entry(dnode
, NULL
, true);
427 rmi
->nextpref
= yang_dnode_get_uint16(dnode
, NULL
);
434 static int lib_route_map_entry_goto_value_destroy(enum nb_event event
,
435 const struct lyd_node
*dnode
)
437 struct route_map_index
*rmi
;
446 rmi
= nb_running_get_entry(dnode
, NULL
, true);
455 * XPath: /frr-route-map:lib/route-map/entry/match-condition
458 lib_route_map_entry_match_condition_create(enum nb_event event
,
459 const struct lyd_node
*dnode
,
460 union nb_resource
*resource
)
462 struct routemap_hook_context
*rhc
;
463 struct route_map_index
*rmi
;
472 rmi
= nb_running_get_entry(dnode
, NULL
, true);
473 rhc
= routemap_hook_context_insert(rmi
);
474 nb_running_set_entry(dnode
, rhc
);
482 lib_route_map_entry_match_condition_destroy(enum nb_event event
,
483 const struct lyd_node
*dnode
)
485 struct routemap_hook_context
*rhc
;
488 if (event
!= NB_EV_APPLY
)
491 rv
= lib_route_map_entry_match_destroy(event
, dnode
);
492 rhc
= nb_running_unset_entry(dnode
);
493 routemap_hook_context_free(rhc
);
499 * XPath: /frr-route-map:lib/route-map/entry/match-condition/interface
501 static int lib_route_map_entry_match_condition_interface_modify(
502 enum nb_event event
, const struct lyd_node
*dnode
,
503 union nb_resource
*resource
)
505 struct routemap_hook_context
*rhc
;
509 if (event
!= NB_EV_APPLY
)
512 /* Check for hook function. */
513 if (rmap_match_set_hook
.match_interface
== NULL
)
516 /* Add configuration. */
517 rhc
= nb_running_get_entry(dnode
, NULL
, true);
518 ifname
= yang_dnode_get_string(dnode
, NULL
);
520 /* Set destroy information. */
521 rhc
->rhc_mhook
= rmap_match_set_hook
.no_match_interface
;
522 rhc
->rhc_rule
= "interface";
523 rhc
->rhc_event
= RMAP_EVENT_MATCH_DELETED
;
525 rv
= rmap_match_set_hook
.match_interface(NULL
, rhc
->rhc_rmi
,
527 RMAP_EVENT_MATCH_ADDED
);
528 if (rv
!= CMD_SUCCESS
) {
529 rhc
->rhc_mhook
= NULL
;
530 return NB_ERR_INCONSISTENCY
;
536 static int lib_route_map_entry_match_condition_interface_destroy(
537 enum nb_event event
, const struct lyd_node
*dnode
)
539 return lib_route_map_entry_match_destroy(event
, dnode
);
543 * XPath: /frr-route-map:lib/route-map/entry/match-condition/access-list-num
545 static int lib_route_map_entry_match_condition_access_list_num_modify(
546 enum nb_event event
, const struct lyd_node
*dnode
,
547 union nb_resource
*resource
)
549 struct routemap_hook_context
*rhc
;
553 if (event
!= NB_EV_APPLY
)
556 /* Check for hook function. */
558 acl
= yang_dnode_get_string(dnode
, NULL
);
559 rhc
= nb_running_get_entry(dnode
, NULL
, true);
560 condition
= yang_dnode_get_enum(dnode
, "../condition");
562 case 1: /* ipv4-address-list */
563 if (rmap_match_set_hook
.match_ip_address
== NULL
)
565 rhc
->rhc_mhook
= rmap_match_set_hook
.no_match_ip_address
;
566 rhc
->rhc_rule
= "ip address";
567 rhc
->rhc_event
= RMAP_EVENT_FILTER_DELETED
;
568 rv
= rmap_match_set_hook
.match_ip_address(
569 NULL
, rhc
->rhc_rmi
, "ip address", acl
,
570 RMAP_EVENT_FILTER_ADDED
);
572 case 3: /* ipv4-next-hop-list */
573 if (rmap_match_set_hook
.match_ip_next_hop
== NULL
)
575 rhc
->rhc_mhook
= rmap_match_set_hook
.no_match_ip_next_hop
;
576 rhc
->rhc_rule
= "ip next-hop";
577 rhc
->rhc_event
= RMAP_EVENT_FILTER_DELETED
;
578 rv
= rmap_match_set_hook
.match_ip_next_hop(
579 NULL
, rhc
->rhc_rmi
, "ip next-hop", acl
,
580 RMAP_EVENT_FILTER_ADDED
);
583 if (rv
!= CMD_SUCCESS
) {
584 rhc
->rhc_mhook
= NULL
;
585 return NB_ERR_INCONSISTENCY
;
591 static int lib_route_map_entry_match_condition_access_list_num_destroy(
592 enum nb_event event
, const struct lyd_node
*dnode
)
594 return lib_route_map_entry_match_destroy(event
, dnode
);
599 * /frr-route-map:lib/route-map/entry/match-condition/access-list-num-extended
601 static int lib_route_map_entry_match_condition_access_list_num_extended_modify(
602 enum nb_event event
, const struct lyd_node
*dnode
,
603 union nb_resource
*resource
)
605 return lib_route_map_entry_match_condition_access_list_num_modify(
606 event
, dnode
, resource
);
609 static int lib_route_map_entry_match_condition_access_list_num_extended_destroy(
610 enum nb_event event
, const struct lyd_node
*dnode
)
612 return lib_route_map_entry_match_condition_access_list_num_destroy(
617 * XPath: /frr-route-map:lib/route-map/entry/match-condition/list-name
619 static int lib_route_map_entry_match_condition_list_name_modify(
620 enum nb_event event
, const struct lyd_node
*dnode
,
621 union nb_resource
*resource
)
623 struct routemap_hook_context
*rhc
;
628 if (event
!= NB_EV_APPLY
)
631 /* Check for hook installation, otherwise we can just stop. */
632 acl
= yang_dnode_get_string(dnode
, NULL
);
633 rhc
= nb_running_get_entry(dnode
, NULL
, true);
634 condition
= yang_dnode_get_enum(dnode
, "../condition");
636 case 1: /* ipv4-address-list */
637 if (rmap_match_set_hook
.match_ip_address
== NULL
)
639 rhc
->rhc_mhook
= rmap_match_set_hook
.no_match_ip_address
;
640 rhc
->rhc_rule
= "ip address";
641 rhc
->rhc_event
= RMAP_EVENT_FILTER_DELETED
;
642 rv
= rmap_match_set_hook
.match_ip_address(
643 NULL
, rhc
->rhc_rmi
, "ip address", acl
,
644 RMAP_EVENT_FILTER_ADDED
);
646 case 2: /* ipv4-prefix-list */
647 if (rmap_match_set_hook
.match_ip_address_prefix_list
== NULL
)
650 rmap_match_set_hook
.no_match_ip_address_prefix_list
;
651 rhc
->rhc_rule
= "ip address prefix-list";
652 rhc
->rhc_event
= RMAP_EVENT_PLIST_DELETED
;
653 rv
= rmap_match_set_hook
.match_ip_address_prefix_list(
654 NULL
, rhc
->rhc_rmi
, "ip address prefix-list", acl
,
655 RMAP_EVENT_PLIST_ADDED
);
657 case 3: /* ipv4-next-hop-list */
658 if (rmap_match_set_hook
.match_ip_next_hop
== NULL
)
660 rhc
->rhc_mhook
= rmap_match_set_hook
.no_match_ip_next_hop
;
661 rhc
->rhc_rule
= "ip next-hop";
662 rhc
->rhc_event
= RMAP_EVENT_FILTER_DELETED
;
663 rv
= rmap_match_set_hook
.match_ip_next_hop(
664 NULL
, rhc
->rhc_rmi
, "ip next-hop", acl
,
665 RMAP_EVENT_FILTER_ADDED
);
667 case 4: /* ipv4-next-hop-prefix-list */
668 if (rmap_match_set_hook
.match_ip_next_hop_prefix_list
== NULL
)
671 rmap_match_set_hook
.no_match_ip_next_hop_prefix_list
;
672 rhc
->rhc_rule
= "ip next-hop prefix-list";
673 rhc
->rhc_event
= RMAP_EVENT_PLIST_DELETED
;
674 rv
= rmap_match_set_hook
.match_ip_next_hop_prefix_list(
675 NULL
, rhc
->rhc_rmi
, "ip next-hop prefix-list", acl
,
676 RMAP_EVENT_PLIST_ADDED
);
678 case 6: /* ipv6-address-list */
679 if (rmap_match_set_hook
.match_ipv6_address
== NULL
)
681 rhc
->rhc_mhook
= rmap_match_set_hook
.no_match_ipv6_address
;
682 rhc
->rhc_rule
= "ipv6 address";
683 rhc
->rhc_event
= RMAP_EVENT_FILTER_DELETED
;
684 rv
= rmap_match_set_hook
.match_ipv6_address(
685 NULL
, rhc
->rhc_rmi
, "ipv6 address", acl
,
686 RMAP_EVENT_FILTER_ADDED
);
688 case 7: /* ipv6-prefix-list */
689 if (rmap_match_set_hook
.match_ipv6_address_prefix_list
== NULL
)
692 rmap_match_set_hook
.no_match_ipv6_address_prefix_list
;
693 rhc
->rhc_rule
= "ipv6 address prefix-list";
694 rhc
->rhc_event
= RMAP_EVENT_PLIST_DELETED
;
695 rv
= rmap_match_set_hook
.match_ipv6_address_prefix_list(
696 NULL
, rhc
->rhc_rmi
, "ipv6 address prefix-list", acl
,
697 RMAP_EVENT_PLIST_ADDED
);
700 rv
= CMD_ERR_NO_MATCH
;
703 if (rv
!= CMD_SUCCESS
) {
704 rhc
->rhc_mhook
= NULL
;
705 return NB_ERR_INCONSISTENCY
;
711 static int lib_route_map_entry_match_condition_list_name_destroy(
712 enum nb_event event
, const struct lyd_node
*dnode
)
714 return lib_route_map_entry_match_destroy(event
, dnode
);
718 * XPath: /frr-route-map:lib/route-map/entry/match-condition/ipv4-next-hop-type
720 static int lib_route_map_entry_match_condition_ipv4_next_hop_type_modify(
721 enum nb_event event
, const struct lyd_node
*dnode
,
722 union nb_resource
*resource
)
724 struct routemap_hook_context
*rhc
;
728 if (event
!= NB_EV_APPLY
)
731 /* Check for hook function. */
732 if (rmap_match_set_hook
.match_ip_next_hop_type
== NULL
)
735 /* Add configuration. */
736 rhc
= nb_running_get_entry(dnode
, NULL
, true);
737 type
= yang_dnode_get_string(dnode
, NULL
);
739 /* Set destroy information. */
740 rhc
->rhc_mhook
= rmap_match_set_hook
.no_match_ip_next_hop_type
;
741 rhc
->rhc_rule
= "ip next-hop type";
742 rhc
->rhc_event
= RMAP_EVENT_MATCH_DELETED
;
744 rv
= rmap_match_set_hook
.match_ip_next_hop_type(
745 NULL
, rhc
->rhc_rmi
, "ip next-hop type", type
,
746 RMAP_EVENT_MATCH_ADDED
);
747 if (rv
!= CMD_SUCCESS
) {
748 rhc
->rhc_mhook
= NULL
;
749 return NB_ERR_INCONSISTENCY
;
755 static int lib_route_map_entry_match_condition_ipv4_next_hop_type_destroy(
756 enum nb_event event
, const struct lyd_node
*dnode
)
758 return lib_route_map_entry_match_destroy(event
, dnode
);
762 * XPath: /frr-route-map:lib/route-map/entry/match-condition/ipv6-next-hop-type
764 static int lib_route_map_entry_match_condition_ipv6_next_hop_type_modify(
765 enum nb_event event
, const struct lyd_node
*dnode
,
766 union nb_resource
*resource
)
768 struct routemap_hook_context
*rhc
;
772 if (event
!= NB_EV_APPLY
)
775 /* Check for hook function. */
776 if (rmap_match_set_hook
.match_ipv6_next_hop_type
== NULL
)
779 /* Add configuration. */
780 rhc
= nb_running_get_entry(dnode
, NULL
, true);
781 type
= yang_dnode_get_string(dnode
, NULL
);
783 /* Set destroy information. */
784 rhc
->rhc_mhook
= rmap_match_set_hook
.no_match_ipv6_next_hop_type
;
785 rhc
->rhc_rule
= "ipv6 next-hop type";
786 rhc
->rhc_event
= RMAP_EVENT_MATCH_DELETED
;
788 rv
= rmap_match_set_hook
.match_ipv6_next_hop_type(
789 NULL
, rhc
->rhc_rmi
, "ipv6 next-hop type", type
,
790 RMAP_EVENT_MATCH_ADDED
);
791 if (rv
!= CMD_SUCCESS
) {
792 rhc
->rhc_mhook
= NULL
;
793 return NB_ERR_INCONSISTENCY
;
799 static int lib_route_map_entry_match_condition_ipv6_next_hop_type_destroy(
800 enum nb_event event
, const struct lyd_node
*dnode
)
802 return lib_route_map_entry_match_destroy(event
, dnode
);
806 * XPath: /frr-route-map:lib/route-map/entry/match-condition/metric
809 lib_route_map_entry_match_condition_metric_modify(enum nb_event event
,
810 const struct lyd_node
*dnode
,
811 union nb_resource
*resource
)
813 struct routemap_hook_context
*rhc
;
817 if (event
!= NB_EV_APPLY
)
820 /* Check for hook function. */
821 if (rmap_match_set_hook
.match_metric
== NULL
)
824 /* Add configuration. */
825 rhc
= nb_running_get_entry(dnode
, NULL
, true);
826 type
= yang_dnode_get_string(dnode
, NULL
);
828 /* Set destroy information. */
829 rhc
->rhc_mhook
= rmap_match_set_hook
.no_match_metric
;
830 rhc
->rhc_rule
= "metric";
831 rhc
->rhc_event
= RMAP_EVENT_MATCH_DELETED
;
833 rv
= rmap_match_set_hook
.match_metric(NULL
, rhc
->rhc_rmi
, "metric",
834 type
, RMAP_EVENT_MATCH_ADDED
);
835 if (rv
!= CMD_SUCCESS
) {
836 rhc
->rhc_mhook
= NULL
;
837 return NB_ERR_INCONSISTENCY
;
844 lib_route_map_entry_match_condition_metric_destroy(enum nb_event event
,
845 const struct lyd_node
*dnode
)
847 return lib_route_map_entry_match_destroy(event
, dnode
);
851 * XPath: /frr-route-map:lib/route-map/entry/match-condition/tag
854 lib_route_map_entry_match_condition_tag_modify(enum nb_event event
,
855 const struct lyd_node
*dnode
,
856 union nb_resource
*resource
)
858 struct routemap_hook_context
*rhc
;
862 if (event
!= NB_EV_APPLY
)
865 /* Check for hook function. */
866 if (rmap_match_set_hook
.match_tag
== NULL
)
869 /* Add configuration. */
870 rhc
= nb_running_get_entry(dnode
, NULL
, true);
871 tag
= yang_dnode_get_string(dnode
, NULL
);
873 /* Set destroy information. */
874 rhc
->rhc_mhook
= rmap_match_set_hook
.no_match_tag
;
875 rhc
->rhc_rule
= "tag";
876 rhc
->rhc_event
= RMAP_EVENT_MATCH_DELETED
;
878 rv
= rmap_match_set_hook
.match_tag(NULL
, rhc
->rhc_rmi
, "tag", tag
,
879 RMAP_EVENT_MATCH_ADDED
);
880 if (rv
!= CMD_SUCCESS
) {
881 rhc
->rhc_mhook
= NULL
;
882 return NB_ERR_INCONSISTENCY
;
889 lib_route_map_entry_match_condition_tag_destroy(enum nb_event event
,
890 const struct lyd_node
*dnode
)
892 return lib_route_map_entry_match_destroy(event
, dnode
);
896 * XPath: /frr-route-map:lib/route-map/entry/set-action
898 static int lib_route_map_entry_set_action_create(enum nb_event event
,
899 const struct lyd_node
*dnode
,
900 union nb_resource
*resource
)
902 return lib_route_map_entry_match_condition_create(event
, dnode
,
906 static int lib_route_map_entry_set_action_destroy(enum nb_event event
,
907 const struct lyd_node
*dnode
)
909 struct routemap_hook_context
*rhc
;
912 if (event
!= NB_EV_APPLY
)
915 rv
= lib_route_map_entry_set_destroy(event
, dnode
);
916 rhc
= nb_running_unset_entry(dnode
);
917 routemap_hook_context_free(rhc
);
923 * XPath: /frr-route-map:lib/route-map/entry/set-action/ipv4-address
926 lib_route_map_entry_set_action_ipv4_address_modify(enum nb_event event
,
927 const struct lyd_node
*dnode
,
928 union nb_resource
*resource
)
930 struct routemap_hook_context
*rhc
;
938 * NOTE: validate if 'action' is 'ipv4-next-hop',
939 * currently it is not necessary because this is the
940 * only implemented action.
942 yang_dnode_get_ipv4(&ia
, dnode
, NULL
);
943 if (ia
.s_addr
== INADDR_ANY
|| IPV4_CLASS_DE(ntohl(ia
.s_addr
)))
944 return NB_ERR_VALIDATION
;
953 /* Check for hook function. */
954 if (rmap_match_set_hook
.set_ip_nexthop
== NULL
)
957 /* Add configuration. */
958 rhc
= nb_running_get_entry(dnode
, NULL
, true);
959 address
= yang_dnode_get_string(dnode
, NULL
);
961 /* Set destroy information. */
962 rhc
->rhc_shook
= rmap_match_set_hook
.no_set_ip_nexthop
;
963 rhc
->rhc_rule
= "ip next-hop";
965 rv
= rmap_match_set_hook
.set_ip_nexthop(NULL
, rhc
->rhc_rmi
,
966 "ip next-hop", address
);
967 if (rv
!= CMD_SUCCESS
) {
968 rhc
->rhc_shook
= NULL
;
969 return NB_ERR_INCONSISTENCY
;
975 static int lib_route_map_entry_set_action_ipv4_address_destroy(
976 enum nb_event event
, const struct lyd_node
*dnode
)
978 return lib_route_map_entry_set_destroy(event
, dnode
);
982 * XPath: /frr-route-map:lib/route-map/entry/set-action/ipv6-address
985 lib_route_map_entry_set_action_ipv6_address_modify(enum nb_event event
,
986 const struct lyd_node
*dnode
,
987 union nb_resource
*resource
)
989 struct routemap_hook_context
*rhc
;
997 * NOTE: validate if 'action' is 'ipv6-next-hop',
998 * currently it is not necessary because this is the
999 * only implemented action. Other actions might have
1000 * different validations.
1002 yang_dnode_get_ipv6(&i6a
, dnode
, NULL
);
1003 if (!IN6_IS_ADDR_LINKLOCAL(&i6a
))
1004 return NB_ERR_VALIDATION
;
1013 /* Check for hook function. */
1014 if (rmap_match_set_hook
.set_ipv6_nexthop_local
== NULL
)
1017 /* Add configuration. */
1018 rhc
= nb_running_get_entry(dnode
, NULL
, true);
1019 address
= yang_dnode_get_string(dnode
, NULL
);
1021 /* Set destroy information. */
1022 rhc
->rhc_shook
= rmap_match_set_hook
.no_set_ipv6_nexthop_local
;
1023 rhc
->rhc_rule
= "ipv6 next-hop local";
1025 rv
= rmap_match_set_hook
.set_ipv6_nexthop_local(
1026 NULL
, rhc
->rhc_rmi
, "ipv6 next-hop local", address
);
1027 if (rv
!= CMD_SUCCESS
) {
1028 rhc
->rhc_shook
= NULL
;
1029 return NB_ERR_INCONSISTENCY
;
1035 static int lib_route_map_entry_set_action_ipv6_address_destroy(
1036 enum nb_event event
, const struct lyd_node
*dnode
)
1038 return lib_route_map_entry_set_destroy(event
, dnode
);
1042 * XPath: /frr-route-map:lib/route-map/entry/set-action/value
1044 static int set_action_modify(enum nb_event event
, const struct lyd_node
*dnode
,
1045 union nb_resource
*resource
, const char *value
)
1047 struct routemap_hook_context
*rhc
;
1051 * NOTE: validate if 'action' is 'metric', currently it is not
1052 * necessary because this is the only implemented action. Other
1053 * actions might have different validations.
1055 if (event
!= NB_EV_APPLY
)
1058 /* Check for hook function. */
1059 if (rmap_match_set_hook
.set_metric
== NULL
)
1062 /* Add configuration. */
1063 rhc
= nb_running_get_entry(dnode
, NULL
, true);
1065 /* Set destroy information. */
1066 rhc
->rhc_shook
= rmap_match_set_hook
.no_set_metric
;
1067 rhc
->rhc_rule
= "metric";
1069 rv
= rmap_match_set_hook
.set_metric(NULL
, rhc
->rhc_rmi
, "metric",
1071 if (rv
!= CMD_SUCCESS
) {
1072 rhc
->rhc_shook
= NULL
;
1073 return NB_ERR_INCONSISTENCY
;
1080 lib_route_map_entry_set_action_value_modify(enum nb_event event
,
1081 const struct lyd_node
*dnode
,
1082 union nb_resource
*resource
)
1084 const char *metric
= yang_dnode_get_string(dnode
, NULL
);
1086 return set_action_modify(event
, dnode
, resource
, metric
);
1090 lib_route_map_entry_set_action_value_destroy(enum nb_event event
,
1091 const struct lyd_node
*dnode
)
1093 return lib_route_map_entry_set_destroy(event
, dnode
);
1097 * XPath: /frr-route-map:lib/route-map/entry/set-action/add-metric
1100 lib_route_map_entry_set_action_add_metric_modify(enum nb_event event
,
1101 const struct lyd_node
*dnode
,
1102 union nb_resource
*resource
)
1104 return set_action_modify(event
, dnode
, resource
, "+metric");
1108 lib_route_map_entry_set_action_add_metric_destroy(enum nb_event event
,
1109 const struct lyd_node
*dnode
)
1111 return lib_route_map_entry_set_action_value_destroy(event
, dnode
);
1115 * XPath: /frr-route-map:lib/route-map/entry/set-action/subtract-metric
1117 static int lib_route_map_entry_set_action_subtract_metric_modify(
1118 enum nb_event event
, const struct lyd_node
*dnode
,
1119 union nb_resource
*resource
)
1121 return set_action_modify(event
, dnode
, resource
, "-metric");
1124 static int lib_route_map_entry_set_action_subtract_metric_destroy(
1125 enum nb_event event
, const struct lyd_node
*dnode
)
1127 return lib_route_map_entry_set_action_value_destroy(event
, dnode
);
1131 * XPath: /frr-route-map:lib/route-map/entry/set-action/use-round-trip-time
1133 static int lib_route_map_entry_set_action_use_round_trip_time_modify(
1134 enum nb_event event
, const struct lyd_node
*dnode
,
1135 union nb_resource
*resource
)
1137 return set_action_modify(event
, dnode
, resource
, "rtt");
1140 static int lib_route_map_entry_set_action_use_round_trip_time_destroy(
1141 enum nb_event event
, const struct lyd_node
*dnode
)
1143 return lib_route_map_entry_set_action_value_destroy(event
, dnode
);
1147 * XPath: /frr-route-map:lib/route-map/entry/set-action/add-round-trip-time
1149 static int lib_route_map_entry_set_action_add_round_trip_time_modify(
1150 enum nb_event event
, const struct lyd_node
*dnode
,
1151 union nb_resource
*resource
)
1153 return set_action_modify(event
, dnode
, resource
, "+rtt");
1156 static int lib_route_map_entry_set_action_add_round_trip_time_destroy(
1157 enum nb_event event
, const struct lyd_node
*dnode
)
1159 return lib_route_map_entry_set_action_value_destroy(event
, dnode
);
1163 * XPath: /frr-route-map:lib/route-map/entry/set-action/subtract-round-trip-time
1165 static int lib_route_map_entry_set_action_subtract_round_trip_time_modify(
1166 enum nb_event event
, const struct lyd_node
*dnode
,
1167 union nb_resource
*resource
)
1169 return set_action_modify(event
, dnode
, resource
, "-rtt");
1172 static int lib_route_map_entry_set_action_subtract_round_trip_time_destroy(
1173 enum nb_event event
, const struct lyd_node
*dnode
)
1175 return lib_route_map_entry_set_action_value_destroy(event
, dnode
);
1179 * XPath: /frr-route-map:lib/route-map/entry/set-action/tag
1182 lib_route_map_entry_set_action_tag_modify(enum nb_event event
,
1183 const struct lyd_node
*dnode
,
1184 union nb_resource
*resource
)
1186 struct routemap_hook_context
*rhc
;
1191 * NOTE: validate if 'action' is 'tag', currently it is not
1192 * necessary because this is the only implemented action. Other
1193 * actions might have different validations.
1195 if (event
!= NB_EV_APPLY
)
1198 /* Check for hook function. */
1199 if (rmap_match_set_hook
.set_tag
== NULL
)
1202 /* Add configuration. */
1203 rhc
= nb_running_get_entry(dnode
, NULL
, true);
1204 tag
= yang_dnode_get_string(dnode
, NULL
);
1206 /* Set destroy information. */
1207 rhc
->rhc_shook
= rmap_match_set_hook
.no_set_tag
;
1208 rhc
->rhc_rule
= "tag";
1210 rv
= rmap_match_set_hook
.set_tag(NULL
, rhc
->rhc_rmi
, "tag", tag
);
1211 if (rv
!= CMD_SUCCESS
) {
1212 rhc
->rhc_shook
= NULL
;
1213 return NB_ERR_INCONSISTENCY
;
1220 lib_route_map_entry_set_action_tag_destroy(enum nb_event event
,
1221 const struct lyd_node
*dnode
)
1223 return lib_route_map_entry_set_destroy(event
, dnode
);
1226 /* clang-format off */
1227 #if defined(__GNUC__) && ((__GNUC__ - 0) < 5) && !defined(__clang__)
1229 * gcc versions before 5.x miscalculate the size for structs with variable
1230 * length arrays (they just count it as size 0)
1232 struct frr_yang_module_info_sizen
{
1233 /* YANG module name. */
1236 /* Northbound callbacks. */
1238 /* Data path of this YANG node. */
1241 /* Callbacks implemented for this node. */
1242 struct nb_callbacks cbs
;
1244 /* Priority - lower priorities are processed first. */
1249 const struct frr_yang_module_info_sizen frr_route_map_info_sizen
asm("frr_route_map_info") = {
1251 const struct frr_yang_module_info frr_route_map_info
= {
1253 .name
= "frr-route-map",
1256 .xpath
= "/frr-route-map:lib/route-map",
1258 .create
= lib_route_map_create
,
1259 .destroy
= lib_route_map_destroy
,
1263 .xpath
= "/frr-route-map:lib/route-map/entry",
1265 .create
= lib_route_map_entry_create
,
1266 .destroy
= lib_route_map_entry_destroy
,
1267 .cli_show
= route_map_instance_show
,
1268 .cli_show_end
= route_map_instance_show_end
,
1272 .xpath
= "/frr-route-map:lib/route-map/entry/description",
1274 .modify
= lib_route_map_entry_description_modify
,
1275 .destroy
= lib_route_map_entry_description_destroy
,
1276 .cli_show
= route_map_description_show
,
1280 .xpath
= "/frr-route-map:lib/route-map/entry/action",
1282 .modify
= lib_route_map_entry_action_modify
,
1286 .xpath
= "/frr-route-map:lib/route-map/entry/call",
1288 .modify
= lib_route_map_entry_call_modify
,
1289 .destroy
= lib_route_map_entry_call_destroy
,
1290 .cli_show
= route_map_call_show
,
1294 .xpath
= "/frr-route-map:lib/route-map/entry/exit-policy",
1296 .modify
= lib_route_map_entry_exit_policy_modify
,
1297 .cli_show
= route_map_exit_policy_show
,
1301 .xpath
= "/frr-route-map:lib/route-map/entry/goto-value",
1303 .modify
= lib_route_map_entry_goto_value_modify
,
1304 .destroy
= lib_route_map_entry_goto_value_destroy
,
1308 .xpath
= "/frr-route-map:lib/route-map/entry/match-condition",
1310 .create
= lib_route_map_entry_match_condition_create
,
1311 .destroy
= lib_route_map_entry_match_condition_destroy
,
1312 .cli_show
= route_map_condition_show
,
1316 .xpath
= "/frr-route-map:lib/route-map/entry/match-condition/interface",
1318 .modify
= lib_route_map_entry_match_condition_interface_modify
,
1319 .destroy
= lib_route_map_entry_match_condition_interface_destroy
,
1323 .xpath
= "/frr-route-map:lib/route-map/entry/match-condition/access-list-num",
1325 .modify
= lib_route_map_entry_match_condition_access_list_num_modify
,
1326 .destroy
= lib_route_map_entry_match_condition_access_list_num_destroy
,
1330 .xpath
= "/frr-route-map:lib/route-map/entry/match-condition/access-list-num-extended",
1332 .modify
= lib_route_map_entry_match_condition_access_list_num_extended_modify
,
1333 .destroy
= lib_route_map_entry_match_condition_access_list_num_extended_destroy
,
1337 .xpath
= "/frr-route-map:lib/route-map/entry/match-condition/list-name",
1339 .modify
= lib_route_map_entry_match_condition_list_name_modify
,
1340 .destroy
= lib_route_map_entry_match_condition_list_name_destroy
,
1344 .xpath
= "/frr-route-map:lib/route-map/entry/match-condition/ipv4-next-hop-type",
1346 .modify
= lib_route_map_entry_match_condition_ipv4_next_hop_type_modify
,
1347 .destroy
= lib_route_map_entry_match_condition_ipv4_next_hop_type_destroy
,
1351 .xpath
= "/frr-route-map:lib/route-map/entry/match-condition/ipv6-next-hop-type",
1353 .modify
= lib_route_map_entry_match_condition_ipv6_next_hop_type_modify
,
1354 .destroy
= lib_route_map_entry_match_condition_ipv6_next_hop_type_destroy
,
1358 .xpath
= "/frr-route-map:lib/route-map/entry/match-condition/metric",
1360 .modify
= lib_route_map_entry_match_condition_metric_modify
,
1361 .destroy
= lib_route_map_entry_match_condition_metric_destroy
,
1365 .xpath
= "/frr-route-map:lib/route-map/entry/match-condition/tag",
1367 .modify
= lib_route_map_entry_match_condition_tag_modify
,
1368 .destroy
= lib_route_map_entry_match_condition_tag_destroy
,
1372 .xpath
= "/frr-route-map:lib/route-map/entry/set-action",
1374 .create
= lib_route_map_entry_set_action_create
,
1375 .destroy
= lib_route_map_entry_set_action_destroy
,
1376 .cli_show
= route_map_action_show
,
1380 .xpath
= "/frr-route-map:lib/route-map/entry/set-action/ipv4-address",
1382 .modify
= lib_route_map_entry_set_action_ipv4_address_modify
,
1383 .destroy
= lib_route_map_entry_set_action_ipv4_address_destroy
,
1387 .xpath
= "/frr-route-map:lib/route-map/entry/set-action/ipv6-address",
1389 .modify
= lib_route_map_entry_set_action_ipv6_address_modify
,
1390 .destroy
= lib_route_map_entry_set_action_ipv6_address_destroy
,
1394 .xpath
= "/frr-route-map:lib/route-map/entry/set-action/value",
1396 .modify
= lib_route_map_entry_set_action_value_modify
,
1397 .destroy
= lib_route_map_entry_set_action_value_destroy
,
1401 .xpath
= "/frr-route-map:lib/route-map/entry/set-action/add-metric",
1403 .modify
= lib_route_map_entry_set_action_add_metric_modify
,
1404 .destroy
= lib_route_map_entry_set_action_add_metric_destroy
,
1408 .xpath
= "/frr-route-map:lib/route-map/entry/set-action/subtract-metric",
1410 .modify
= lib_route_map_entry_set_action_subtract_metric_modify
,
1411 .destroy
= lib_route_map_entry_set_action_subtract_metric_destroy
,
1415 .xpath
= "/frr-route-map:lib/route-map/entry/set-action/use-round-trip-time",
1417 .modify
= lib_route_map_entry_set_action_use_round_trip_time_modify
,
1418 .destroy
= lib_route_map_entry_set_action_use_round_trip_time_destroy
,
1422 .xpath
= "/frr-route-map:lib/route-map/entry/set-action/add-round-trip-time",
1424 .modify
= lib_route_map_entry_set_action_add_round_trip_time_modify
,
1425 .destroy
= lib_route_map_entry_set_action_add_round_trip_time_destroy
,
1429 .xpath
= "/frr-route-map:lib/route-map/entry/set-action/subtract-round-trip-time",
1431 .modify
= lib_route_map_entry_set_action_subtract_round_trip_time_modify
,
1432 .destroy
= lib_route_map_entry_set_action_subtract_round_trip_time_destroy
,
1436 .xpath
= "/frr-route-map:lib/route-map/entry/set-action/tag",
1438 .modify
= lib_route_map_entry_set_action_tag_modify
,
1439 .destroy
= lib_route_map_entry_set_action_tag_destroy
,