1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * FRR filter northbound implementation.
5 * Copyright (C) 2019 Network Device Education Foundation, Inc. ("NetDEF")
11 #include "lib/northbound.h"
12 #include "lib/prefix.h"
13 #include "lib/printfrr.h"
15 #include "lib/filter.h"
16 #include "lib/plist.h"
17 #include "lib/plist_int.h"
18 #include "lib/routemap.h"
20 /* Helper function. */
21 static void acl_notify_route_map(struct access_list
*acl
, int route_map_event
)
23 switch (route_map_event
) {
24 case RMAP_EVENT_FILTER_ADDED
:
25 if (acl
->master
->add_hook
)
26 (*acl
->master
->add_hook
)(acl
);
28 case RMAP_EVENT_FILTER_DELETED
:
29 if (acl
->master
->delete_hook
)
30 (*acl
->master
->delete_hook
)(acl
);
34 route_map_notify_dependencies(acl
->name
, route_map_event
);
37 static enum nb_error
prefix_list_length_validate(struct nb_cb_modify_args
*args
)
39 int type
= yang_dnode_get_enum(args
->dnode
, "../../type");
40 const char *xpath_le
= NULL
, *xpath_ge
= NULL
;
44 if (type
== YPLT_IPV4
) {
45 yang_dnode_get_prefix(&p
, args
->dnode
, "../ipv4-prefix");
46 xpath_le
= "../ipv4-prefix-length-lesser-or-equal";
47 xpath_ge
= "../ipv4-prefix-length-greater-or-equal";
49 yang_dnode_get_prefix(&p
, args
->dnode
, "../ipv6-prefix");
50 xpath_le
= "../ipv6-prefix-length-lesser-or-equal";
51 xpath_ge
= "../ipv6-prefix-length-greater-or-equal";
56 * prefix length <= le.
58 if (yang_dnode_exists(args
->dnode
, xpath_le
)) {
59 le
= yang_dnode_get_uint8(args
->dnode
, "%s", xpath_le
);
66 * prefix length <= ge.
68 if (yang_dnode_exists(args
->dnode
, xpath_ge
)) {
69 ge
= yang_dnode_get_uint8(args
->dnode
, "%s", xpath_ge
);
78 if (yang_dnode_exists(args
->dnode
, xpath_le
)
79 && yang_dnode_exists(args
->dnode
, xpath_ge
)) {
80 le
= yang_dnode_get_uint8(args
->dnode
, "%s", xpath_le
);
81 ge
= yang_dnode_get_uint8(args
->dnode
, "%s", xpath_ge
);
90 args
->errmsg
, args
->errmsg_len
,
91 "Invalid prefix range for %pFX: Make sure that mask length <= ge <= le",
93 return NB_ERR_VALIDATION
;
97 * Sets prefix list entry to blank value.
99 * \param[out] ple prefix list entry to modify.
101 static void prefix_list_entry_set_empty(struct prefix_list_entry
*ple
)
104 memset(&ple
->prefix
, 0, sizeof(ple
->prefix
));
110 prefix_list_nb_validate_v4_af_type(const struct lyd_node
*plist_dnode
,
111 char *errmsg
, size_t errmsg_len
)
115 af_type
= yang_dnode_get_enum(plist_dnode
, "./type");
116 if (af_type
!= YPLT_IPV4
) {
117 snprintf(errmsg
, errmsg_len
,
118 "prefix-list type %u is mismatched.", af_type
);
119 return NB_ERR_VALIDATION
;
126 prefix_list_nb_validate_v6_af_type(const struct lyd_node
*plist_dnode
,
127 char *errmsg
, size_t errmsg_len
)
131 af_type
= yang_dnode_get_enum(plist_dnode
, "./type");
132 if (af_type
!= YPLT_IPV6
) {
133 snprintf(errmsg
, errmsg_len
,
134 "prefix-list type %u is mismatched.", af_type
);
135 return NB_ERR_VALIDATION
;
141 static int lib_prefix_list_entry_prefix_length_greater_or_equal_modify(
142 struct nb_cb_modify_args
*args
)
144 struct prefix_list_entry
*ple
;
146 if (args
->event
!= NB_EV_APPLY
)
149 ple
= nb_running_get_entry(args
->dnode
, NULL
, true);
151 /* Start prefix entry update procedure. */
152 prefix_list_entry_update_start(ple
);
154 ple
->ge
= yang_dnode_get_uint8(args
->dnode
, NULL
);
156 /* Finish prefix entry update procedure. */
157 prefix_list_entry_update_finish(ple
);
162 static int lib_prefix_list_entry_prefix_length_lesser_or_equal_modify(
163 struct nb_cb_modify_args
*args
)
165 struct prefix_list_entry
*ple
;
167 if (args
->event
!= NB_EV_APPLY
)
170 ple
= nb_running_get_entry(args
->dnode
, NULL
, true);
172 /* Start prefix entry update procedure. */
173 prefix_list_entry_update_start(ple
);
175 ple
->le
= yang_dnode_get_uint8(args
->dnode
, NULL
);
177 /* Finish prefix entry update procedure. */
178 prefix_list_entry_update_finish(ple
);
183 static int lib_prefix_list_entry_prefix_length_greater_or_equal_destroy(
184 struct nb_cb_destroy_args
*args
)
186 struct prefix_list_entry
*ple
;
188 if (args
->event
!= NB_EV_APPLY
)
191 ple
= nb_running_get_entry(args
->dnode
, NULL
, true);
193 /* Start prefix entry update procedure. */
194 prefix_list_entry_update_start(ple
);
198 /* Finish prefix entry update procedure. */
199 prefix_list_entry_update_finish(ple
);
204 static int lib_prefix_list_entry_prefix_length_lesser_or_equal_destroy(
205 struct nb_cb_destroy_args
*args
)
207 struct prefix_list_entry
*ple
;
209 if (args
->event
!= NB_EV_APPLY
)
212 ple
= nb_running_get_entry(args
->dnode
, NULL
, true);
214 /* Start prefix entry update procedure. */
215 prefix_list_entry_update_start(ple
);
219 /* Finish prefix entry update procedure. */
220 prefix_list_entry_update_finish(ple
);
226 * Unsets the cisco style rule for addresses so it becomes disabled (the
227 * equivalent of setting: `0.0.0.0/32`).
229 * \param addr address part.
230 * \param mask mask part.
232 static void cisco_unset_addr_mask(struct in_addr
*addr
, struct in_addr
*mask
)
234 addr
->s_addr
= INADDR_ANY
;
235 mask
->s_addr
= CISCO_BIN_HOST_WILDCARD_MASK
;
238 static int _acl_is_dup(const struct lyd_node
*dnode
, void *arg
)
240 struct acl_dup_args
*ada
= arg
;
243 /* This entry is the caller, so skip it. */
244 if (ada
->ada_entry_dnode
245 && ada
->ada_entry_dnode
== dnode
)
246 return YANG_ITER_CONTINUE
;
248 if (strcmp(yang_dnode_get_string(dnode
, "action"), ada
->ada_action
))
249 return YANG_ITER_CONTINUE
;
251 /* Check if all values match. */
252 for (idx
= 0; idx
< ADA_MAX_VALUES
; idx
++) {
253 /* No more values. */
254 if (ada
->ada_xpath
[idx
] == NULL
)
257 /* Not same type, just skip it. */
258 if (!yang_dnode_exists(dnode
, ada
->ada_xpath
[idx
]))
259 return YANG_ITER_CONTINUE
;
261 /* Check if different value. */
262 if (strcmp(yang_dnode_get_string(dnode
, "%s",
263 ada
->ada_xpath
[idx
]),
264 ada
->ada_value
[idx
]))
265 return YANG_ITER_CONTINUE
;
268 ada
->ada_found
= true;
269 ada
->ada_seq
= yang_dnode_get_uint32(dnode
, "sequence");
271 return YANG_ITER_STOP
;
274 bool acl_is_dup(const struct lyd_node
*dnode
, struct acl_dup_args
*ada
)
276 ada
->ada_found
= false;
279 _acl_is_dup
, ada
, dnode
,
280 "/frr-filter:lib/access-list[type='%s'][name='%s']/entry",
281 ada
->ada_type
, ada
->ada_name
);
283 return ada
->ada_found
;
286 static bool acl_cisco_is_dup(const struct lyd_node
*dnode
)
288 const struct lyd_node
*entry_dnode
=
289 yang_dnode_get_parent(dnode
, "entry");
290 struct acl_dup_args ada
= {};
291 int idx
= 0, arg_idx
= 0;
292 static const char *cisco_entries
[] = {
297 "./destination-host",
298 "./destination-network/address",
299 "./destination-network/mask",
305 ada
.ada_type
= "ipv4";
306 ada
.ada_name
= yang_dnode_get_string(entry_dnode
, "../name");
307 ada
.ada_action
= yang_dnode_get_string(entry_dnode
, "action");
308 ada
.ada_entry_dnode
= entry_dnode
;
310 /* Load all values/XPaths. */
311 while (cisco_entries
[idx
] != NULL
) {
312 if (!yang_dnode_exists(entry_dnode
, cisco_entries
[idx
])) {
317 ada
.ada_xpath
[arg_idx
] = cisco_entries
[idx
];
318 ada
.ada_value
[arg_idx
] = yang_dnode_get_string(
319 entry_dnode
, "%s", cisco_entries
[idx
]);
324 return acl_is_dup(entry_dnode
, &ada
);
327 static bool acl_zebra_is_dup(const struct lyd_node
*dnode
,
328 enum yang_access_list_type type
)
330 const struct lyd_node
*entry_dnode
=
331 yang_dnode_get_parent(dnode
, "entry");
332 struct acl_dup_args ada
= {};
333 int idx
= 0, arg_idx
= 0;
334 static const char *zebra_entries
[] = {
336 "./ipv4-exact-match",
338 "./ipv6-exact-match",
347 ada
.ada_type
= "ipv4";
350 ada
.ada_type
= "ipv6";
353 ada
.ada_type
= "mac";
356 ada
.ada_name
= yang_dnode_get_string(entry_dnode
, "../name");
357 ada
.ada_action
= yang_dnode_get_string(entry_dnode
, "action");
358 ada
.ada_entry_dnode
= entry_dnode
;
360 /* Load all values/XPaths. */
361 while (zebra_entries
[idx
] != NULL
) {
362 if (!yang_dnode_exists(entry_dnode
, zebra_entries
[idx
])) {
367 ada
.ada_xpath
[arg_idx
] = zebra_entries
[idx
];
368 ada
.ada_value
[arg_idx
] = yang_dnode_get_string(
369 entry_dnode
, "%s", zebra_entries
[idx
]);
374 return acl_is_dup(entry_dnode
, &ada
);
377 static void plist_dnode_to_prefix(const struct lyd_node
*dnode
, bool *any
,
378 struct prefix
*p
, int *ge
, int *le
)
384 if (yang_dnode_exists(dnode
, "./any")) {
389 switch (yang_dnode_get_enum(dnode
, "../type")) {
391 yang_dnode_get_prefix(p
, dnode
, "./ipv4-prefix");
392 if (yang_dnode_exists(dnode
,
393 "./ipv4-prefix-length-greater-or-equal"))
394 *ge
= yang_dnode_get_uint8(
395 dnode
, "./ipv4-prefix-length-greater-or-equal");
396 if (yang_dnode_exists(dnode
,
397 "./ipv4-prefix-length-lesser-or-equal"))
398 *le
= yang_dnode_get_uint8(
399 dnode
, "./ipv4-prefix-length-lesser-or-equal");
402 yang_dnode_get_prefix(p
, dnode
, "./ipv6-prefix");
403 if (yang_dnode_exists(dnode
,
404 "./ipv6-prefix-length-greater-or-equal"))
405 *ge
= yang_dnode_get_uint8(
406 dnode
, "./ipv6-prefix-length-greater-or-equal");
407 if (yang_dnode_exists(dnode
,
408 "./ipv6-prefix-length-lesser-or-equal"))
409 *le
= yang_dnode_get_uint8(
410 dnode
, "./ipv6-prefix-length-lesser-or-equal");
415 static int _plist_is_dup(const struct lyd_node
*dnode
, void *arg
)
417 struct plist_dup_args
*pda
= arg
;
418 struct prefix p
= {};
422 /* This entry is the caller, so skip it. */
423 if (pda
->pda_entry_dnode
424 && pda
->pda_entry_dnode
== dnode
)
425 return YANG_ITER_CONTINUE
;
427 if (strcmp(yang_dnode_get_string(dnode
, "action"), pda
->pda_action
))
428 return YANG_ITER_CONTINUE
;
430 plist_dnode_to_prefix(dnode
, &any
, &p
, &ge
, &le
);
434 return YANG_ITER_CONTINUE
;
436 if (!prefix_same(&pda
->prefix
, &p
) || pda
->ge
!= ge
438 return YANG_ITER_CONTINUE
;
441 pda
->pda_found
= true;
442 pda
->pda_seq
= yang_dnode_get_uint32(dnode
, "sequence");
444 return YANG_ITER_STOP
;
447 bool plist_is_dup(const struct lyd_node
*dnode
, struct plist_dup_args
*pda
)
449 pda
->pda_found
= false;
452 _plist_is_dup
, pda
, dnode
,
453 "/frr-filter:lib/prefix-list[type='%s'][name='%s']/entry",
454 pda
->pda_type
, pda
->pda_name
);
456 return pda
->pda_found
;
460 * XPath: /frr-filter:lib/access-list
462 static int lib_access_list_create(struct nb_cb_create_args
*args
)
464 struct access_list
*acl
= NULL
;
465 const char *acl_name
;
468 if (args
->event
!= NB_EV_APPLY
)
471 type
= yang_dnode_get_enum(args
->dnode
, "./type");
472 acl_name
= yang_dnode_get_string(args
->dnode
, "./name");
476 acl
= access_list_get(AFI_IP
, acl_name
);
479 acl
= access_list_get(AFI_IP6
, acl_name
);
482 acl
= access_list_get(AFI_L2VPN
, acl_name
);
486 nb_running_set_entry(args
->dnode
, acl
);
491 static int lib_access_list_destroy(struct nb_cb_destroy_args
*args
)
493 struct access_list
*acl
;
495 if (args
->event
!= NB_EV_APPLY
)
498 acl
= nb_running_unset_entry(args
->dnode
);
499 access_list_delete(acl
);
505 * XPath: /frr-filter:lib/access-list/remark
507 static int lib_access_list_remark_modify(struct nb_cb_modify_args
*args
)
509 struct access_list
*acl
;
512 if (args
->event
!= NB_EV_APPLY
)
515 acl
= nb_running_get_entry(args
->dnode
, NULL
, true);
517 XFREE(MTYPE_TMP
, acl
->remark
);
519 remark
= yang_dnode_get_string(args
->dnode
, NULL
);
520 acl
->remark
= XSTRDUP(MTYPE_TMP
, remark
);
526 lib_access_list_remark_destroy(struct nb_cb_destroy_args
*args
)
528 struct access_list
*acl
;
530 if (args
->event
!= NB_EV_APPLY
)
533 acl
= nb_running_get_entry(args
->dnode
, NULL
, true);
535 XFREE(MTYPE_TMP
, acl
->remark
);
542 * XPath: /frr-filter:lib/access-list/entry
544 static int lib_access_list_entry_create(struct nb_cb_create_args
*args
)
546 struct access_list
*acl
;
549 if (args
->event
!= NB_EV_APPLY
)
553 f
->seq
= yang_dnode_get_uint32(args
->dnode
, "./sequence");
555 acl
= nb_running_get_entry(args
->dnode
, NULL
, true);
557 access_list_filter_add(acl
, f
);
558 nb_running_set_entry(args
->dnode
, f
);
563 static int lib_access_list_entry_destroy(struct nb_cb_destroy_args
*args
)
565 struct access_list
*acl
;
568 if (args
->event
!= NB_EV_APPLY
)
571 f
= nb_running_unset_entry(args
->dnode
);
573 access_list_filter_delete(acl
, f
);
579 * XPath: /frr-filter:lib/access-list/entry/action
582 lib_access_list_entry_action_modify(struct nb_cb_modify_args
*args
)
584 const char *filter_type
;
587 if (args
->event
!= NB_EV_APPLY
)
590 f
= nb_running_get_entry(args
->dnode
, NULL
, true);
591 filter_type
= yang_dnode_get_string(args
->dnode
, NULL
);
592 if (strcmp(filter_type
, "permit") == 0)
593 f
->type
= FILTER_PERMIT
;
595 f
->type
= FILTER_DENY
;
597 acl_notify_route_map(f
->acl
, RMAP_EVENT_FILTER_ADDED
);
603 * XPath: /frr-filter:lib/access-list/entry/ipv4-prefix
606 lib_access_list_entry_ipv4_prefix_modify(struct nb_cb_modify_args
*args
)
608 struct filter_zebra
*fz
;
611 /* Don't allow duplicated values. */
612 if (args
->event
== NB_EV_VALIDATE
) {
613 if (acl_zebra_is_dup(
615 yang_dnode_get_enum(args
->dnode
, "../../type"))) {
616 snprintfrr(args
->errmsg
, args
->errmsg_len
,
617 "duplicated access list value: %s",
618 yang_dnode_get_string(args
->dnode
, NULL
));
619 return NB_ERR_VALIDATION
;
624 if (args
->event
!= NB_EV_APPLY
)
627 f
= nb_running_get_entry(args
->dnode
, NULL
, true);
630 yang_dnode_get_prefix(&fz
->prefix
, args
->dnode
, NULL
);
632 acl_notify_route_map(f
->acl
, RMAP_EVENT_FILTER_ADDED
);
638 lib_access_list_entry_ipv4_prefix_destroy(struct nb_cb_destroy_args
*args
)
640 struct filter_zebra
*fz
;
643 if (args
->event
!= NB_EV_APPLY
)
646 f
= nb_running_get_entry(args
->dnode
, NULL
, true);
648 memset(&fz
->prefix
, 0, sizeof(fz
->prefix
));
650 acl_notify_route_map(f
->acl
, RMAP_EVENT_FILTER_DELETED
);
656 * XPath: /frr-filter:lib/access-list/entry/ipv4-exact-match
659 lib_access_list_entry_ipv4_exact_match_modify(struct nb_cb_modify_args
*args
)
661 struct filter_zebra
*fz
;
664 /* Don't allow duplicated values. */
665 if (args
->event
== NB_EV_VALIDATE
) {
666 if (acl_zebra_is_dup(
668 yang_dnode_get_enum(args
->dnode
, "../../type"))) {
669 snprintfrr(args
->errmsg
, args
->errmsg_len
,
670 "duplicated access list value: %s",
671 yang_dnode_get_string(args
->dnode
, NULL
));
672 return NB_ERR_VALIDATION
;
677 if (args
->event
!= NB_EV_APPLY
)
680 f
= nb_running_get_entry(args
->dnode
, NULL
, true);
682 fz
->exact
= yang_dnode_get_bool(args
->dnode
, NULL
);
684 acl_notify_route_map(f
->acl
, RMAP_EVENT_FILTER_ADDED
);
690 lib_access_list_entry_ipv4_exact_match_destroy(struct nb_cb_destroy_args
*args
)
692 struct filter_zebra
*fz
;
695 if (args
->event
!= NB_EV_APPLY
)
698 f
= nb_running_get_entry(args
->dnode
, NULL
, true);
702 acl_notify_route_map(f
->acl
, RMAP_EVENT_FILTER_DELETED
);
708 * XPath: /frr-filter:lib/access-list/entry/host
711 lib_access_list_entry_host_modify(struct nb_cb_modify_args
*args
)
713 struct filter_cisco
*fc
;
716 /* Don't allow duplicated values. */
717 if (args
->event
== NB_EV_VALIDATE
) {
718 if (acl_cisco_is_dup(args
->dnode
)) {
719 snprintfrr(args
->errmsg
, args
->errmsg_len
,
720 "duplicated access list value: %s",
721 yang_dnode_get_string(args
->dnode
, NULL
));
722 return NB_ERR_VALIDATION
;
727 if (args
->event
!= NB_EV_APPLY
)
730 f
= nb_running_get_entry(args
->dnode
, NULL
, true);
733 yang_dnode_get_ipv4(&fc
->addr
, args
->dnode
, NULL
);
734 fc
->addr_mask
.s_addr
= CISCO_BIN_HOST_WILDCARD_MASK
;
736 acl_notify_route_map(f
->acl
, RMAP_EVENT_FILTER_ADDED
);
742 lib_access_list_entry_host_destroy(struct nb_cb_destroy_args
*args
)
744 struct filter_cisco
*fc
;
747 if (args
->event
!= NB_EV_APPLY
)
750 f
= nb_running_get_entry(args
->dnode
, NULL
, true);
752 cisco_unset_addr_mask(&fc
->addr
, &fc
->addr_mask
);
754 acl_notify_route_map(f
->acl
, RMAP_EVENT_FILTER_DELETED
);
760 * XPath: /frr-filter:lib/access-list/entry/network/address
763 lib_access_list_entry_network_address_modify(struct nb_cb_modify_args
*args
)
765 struct filter_cisco
*fc
;
768 /* Don't allow duplicated values. */
769 if (args
->event
== NB_EV_VALIDATE
) {
770 if (acl_cisco_is_dup(args
->dnode
)) {
771 snprintfrr(args
->errmsg
, args
->errmsg_len
,
772 "duplicated access list value: %s",
773 yang_dnode_get_string(args
->dnode
, NULL
));
774 return NB_ERR_VALIDATION
;
779 if (args
->event
!= NB_EV_APPLY
)
782 f
= nb_running_get_entry(args
->dnode
, NULL
, true);
785 yang_dnode_get_ipv4(&fc
->addr
, args
->dnode
, NULL
);
787 acl_notify_route_map(f
->acl
, RMAP_EVENT_FILTER_ADDED
);
793 * XPath: /frr-filter:lib/access-list/entry/network/mask
796 lib_access_list_entry_network_mask_modify(struct nb_cb_modify_args
*args
)
798 struct filter_cisco
*fc
;
801 /* Don't allow duplicated values. */
802 if (args
->event
== NB_EV_VALIDATE
) {
803 if (acl_cisco_is_dup(args
->dnode
)) {
804 snprintfrr(args
->errmsg
, args
->errmsg_len
,
805 "duplicated access list value: %s",
806 yang_dnode_get_string(args
->dnode
, NULL
));
807 return NB_ERR_VALIDATION
;
812 if (args
->event
!= NB_EV_APPLY
)
815 f
= nb_running_get_entry(args
->dnode
, NULL
, true);
818 yang_dnode_get_ipv4(&fc
->addr_mask
, args
->dnode
, NULL
);
820 acl_notify_route_map(f
->acl
, RMAP_EVENT_FILTER_ADDED
);
826 * XPath: /frr-filter:lib/access-list/entry/source-any
829 lib_access_list_entry_source_any_create(struct nb_cb_create_args
*args
)
831 struct filter_cisco
*fc
;
834 /* Don't allow duplicated values. */
835 if (args
->event
== NB_EV_VALIDATE
) {
836 if (acl_cisco_is_dup(args
->dnode
)) {
837 snprintfrr(args
->errmsg
, args
->errmsg_len
,
838 "duplicated access list value: %s",
839 yang_dnode_get_string(args
->dnode
, NULL
));
840 return NB_ERR_VALIDATION
;
845 if (args
->event
!= NB_EV_APPLY
)
848 f
= nb_running_get_entry(args
->dnode
, NULL
, true);
851 fc
->addr
.s_addr
= INADDR_ANY
;
852 fc
->addr_mask
.s_addr
= CISCO_BIN_ANY_WILDCARD_MASK
;
854 acl_notify_route_map(f
->acl
, RMAP_EVENT_FILTER_ADDED
);
860 lib_access_list_entry_source_any_destroy(struct nb_cb_destroy_args
*args
)
862 struct filter_cisco
*fc
;
865 if (args
->event
!= NB_EV_APPLY
)
868 f
= nb_running_get_entry(args
->dnode
, NULL
, true);
870 cisco_unset_addr_mask(&fc
->addr
, &fc
->addr_mask
);
872 acl_notify_route_map(f
->acl
, RMAP_EVENT_FILTER_DELETED
);
878 * XPath: /frr-filter:lib/access-list/entry/destination-host
880 static int lib_access_list_entry_destination_host_modify(
881 struct nb_cb_modify_args
*args
)
883 struct filter_cisco
*fc
;
886 /* Don't allow duplicated values. */
887 if (args
->event
== NB_EV_VALIDATE
) {
888 if (acl_cisco_is_dup(args
->dnode
)) {
889 snprintfrr(args
->errmsg
, args
->errmsg_len
,
890 "duplicated access list value: %s",
891 yang_dnode_get_string(args
->dnode
, NULL
));
892 return NB_ERR_VALIDATION
;
897 if (args
->event
!= NB_EV_APPLY
)
900 f
= nb_running_get_entry(args
->dnode
, NULL
, true);
903 yang_dnode_get_ipv4(&fc
->mask
, args
->dnode
, NULL
);
904 fc
->mask_mask
.s_addr
= CISCO_BIN_HOST_WILDCARD_MASK
;
906 acl_notify_route_map(f
->acl
, RMAP_EVENT_FILTER_ADDED
);
911 static int lib_access_list_entry_destination_host_destroy(
912 struct nb_cb_destroy_args
*args
)
914 struct filter_cisco
*fc
;
917 if (args
->event
!= NB_EV_APPLY
)
920 f
= nb_running_get_entry(args
->dnode
, NULL
, true);
923 cisco_unset_addr_mask(&fc
->mask
, &fc
->mask_mask
);
925 acl_notify_route_map(f
->acl
, RMAP_EVENT_FILTER_DELETED
);
931 * XPath: /frr-filter:lib/access-list/entry/destination-network/address
933 static int lib_access_list_entry_destination_network_address_modify(
934 struct nb_cb_modify_args
*args
)
936 struct filter_cisco
*fc
;
939 /* Don't allow duplicated values. */
940 if (args
->event
== NB_EV_VALIDATE
) {
941 if (acl_cisco_is_dup(args
->dnode
)) {
942 snprintfrr(args
->errmsg
, args
->errmsg_len
,
943 "duplicated access list value: %s",
944 yang_dnode_get_string(args
->dnode
, NULL
));
945 return NB_ERR_VALIDATION
;
950 if (args
->event
!= NB_EV_APPLY
)
953 f
= nb_running_get_entry(args
->dnode
, NULL
, true);
956 yang_dnode_get_ipv4(&fc
->mask
, args
->dnode
, NULL
);
958 acl_notify_route_map(f
->acl
, RMAP_EVENT_FILTER_ADDED
);
964 * XPath: /frr-filter:lib/access-list/entry/destination-network/mask
966 static int lib_access_list_entry_destination_network_mask_modify(
967 struct nb_cb_modify_args
*args
)
969 struct filter_cisco
*fc
;
972 /* Don't allow duplicated values. */
973 if (args
->event
== NB_EV_VALIDATE
) {
974 if (acl_cisco_is_dup(args
->dnode
)) {
975 snprintfrr(args
->errmsg
, args
->errmsg_len
,
976 "duplicated access list value: %s",
977 yang_dnode_get_string(args
->dnode
, NULL
));
978 return NB_ERR_VALIDATION
;
983 if (args
->event
!= NB_EV_APPLY
)
986 f
= nb_running_get_entry(args
->dnode
, NULL
, true);
989 yang_dnode_get_ipv4(&fc
->mask_mask
, args
->dnode
, NULL
);
991 acl_notify_route_map(f
->acl
, RMAP_EVENT_FILTER_ADDED
);
997 * XPath: /frr-filter:lib/access-list/entry/destination-any
999 static int lib_access_list_entry_destination_any_create(
1000 struct nb_cb_create_args
*args
)
1002 struct filter_cisco
*fc
;
1005 /* Don't allow duplicated values. */
1006 if (args
->event
== NB_EV_VALIDATE
) {
1007 if (acl_cisco_is_dup(args
->dnode
)) {
1008 snprintfrr(args
->errmsg
, args
->errmsg_len
,
1009 "duplicated access list value: %s",
1010 yang_dnode_get_string(args
->dnode
, NULL
));
1011 return NB_ERR_VALIDATION
;
1016 if (args
->event
!= NB_EV_APPLY
)
1019 f
= nb_running_get_entry(args
->dnode
, NULL
, true);
1022 fc
->mask
.s_addr
= INADDR_ANY
;
1023 fc
->mask_mask
.s_addr
= CISCO_BIN_ANY_WILDCARD_MASK
;
1025 acl_notify_route_map(f
->acl
, RMAP_EVENT_FILTER_ADDED
);
1030 static int lib_access_list_entry_destination_any_destroy(
1031 struct nb_cb_destroy_args
*args
)
1033 struct filter_cisco
*fc
;
1036 if (args
->event
!= NB_EV_APPLY
)
1039 f
= nb_running_get_entry(args
->dnode
, NULL
, true);
1042 cisco_unset_addr_mask(&fc
->mask
, &fc
->mask_mask
);
1044 acl_notify_route_map(f
->acl
, RMAP_EVENT_FILTER_DELETED
);
1050 * XPath: /frr-filter:lib/access-list/entry/any
1052 static int lib_access_list_entry_any_create(struct nb_cb_create_args
*args
)
1054 struct filter_zebra
*fz
;
1058 /* Don't allow duplicated values. */
1059 if (args
->event
== NB_EV_VALIDATE
) {
1060 if (acl_zebra_is_dup(
1062 yang_dnode_get_enum(args
->dnode
, "../../type"))) {
1063 snprintfrr(args
->errmsg
, args
->errmsg_len
,
1064 "duplicated access list value: %s",
1065 yang_dnode_get_string(args
->dnode
, NULL
));
1066 return NB_ERR_VALIDATION
;
1071 if (args
->event
!= NB_EV_APPLY
)
1074 f
= nb_running_get_entry(args
->dnode
, NULL
, true);
1077 memset(&fz
->prefix
, 0, sizeof(fz
->prefix
));
1079 type
= yang_dnode_get_enum(args
->dnode
, "../../type");
1082 fz
->prefix
.family
= AF_INET
;
1085 fz
->prefix
.family
= AF_INET6
;
1088 fz
->prefix
.family
= AF_ETHERNET
;
1092 acl_notify_route_map(f
->acl
, RMAP_EVENT_FILTER_ADDED
);
1097 static int lib_access_list_entry_any_destroy(struct nb_cb_destroy_args
*args
)
1099 struct filter_zebra
*fz
;
1102 if (args
->event
!= NB_EV_APPLY
)
1105 f
= nb_running_get_entry(args
->dnode
, NULL
, true);
1107 fz
->prefix
.family
= AF_UNSPEC
;
1109 acl_notify_route_map(f
->acl
, RMAP_EVENT_FILTER_DELETED
);
1115 * XPath: /frr-filter:lib/prefix-list
1117 static int lib_prefix_list_create(struct nb_cb_create_args
*args
)
1119 struct prefix_list
*pl
= NULL
;
1123 if (args
->event
!= NB_EV_APPLY
)
1126 type
= yang_dnode_get_enum(args
->dnode
, "./type");
1127 name
= yang_dnode_get_string(args
->dnode
, "./name");
1130 pl
= prefix_list_get(AFI_IP
, 0, name
);
1133 pl
= prefix_list_get(AFI_IP6
, 0, name
);
1137 nb_running_set_entry(args
->dnode
, pl
);
1142 static int lib_prefix_list_destroy(struct nb_cb_destroy_args
*args
)
1144 struct prefix_list
*pl
;
1146 if (args
->event
!= NB_EV_APPLY
)
1149 pl
= nb_running_unset_entry(args
->dnode
);
1150 prefix_list_delete(pl
);
1156 * XPath: /frr-filter:lib/prefix-list/remark
1158 static int lib_prefix_list_remark_modify(struct nb_cb_modify_args
*args
)
1160 struct prefix_list
*pl
;
1163 if (args
->event
!= NB_EV_APPLY
)
1166 pl
= nb_running_get_entry(args
->dnode
, NULL
, true);
1168 XFREE(MTYPE_TMP
, pl
->desc
);
1170 remark
= yang_dnode_get_string(args
->dnode
, NULL
);
1171 pl
->desc
= XSTRDUP(MTYPE_TMP
, remark
);
1176 static int lib_prefix_list_remark_destroy(struct nb_cb_destroy_args
*args
)
1178 struct prefix_list
*pl
;
1180 if (args
->event
!= NB_EV_APPLY
)
1183 pl
= nb_running_get_entry(args
->dnode
, NULL
, true);
1185 XFREE(MTYPE_TMP
, pl
->desc
);
1191 * XPath: /frr-filter:lib/prefix-list/entry
1193 static int lib_prefix_list_entry_create(struct nb_cb_create_args
*args
)
1195 struct prefix_list_entry
*ple
;
1196 struct prefix_list
*pl
;
1198 if (args
->event
!= NB_EV_APPLY
)
1201 pl
= nb_running_get_entry(args
->dnode
, NULL
, true);
1202 ple
= prefix_list_entry_new();
1204 ple
->seq
= yang_dnode_get_uint32(args
->dnode
, "./sequence");
1205 prefix_list_entry_set_empty(ple
);
1206 nb_running_set_entry(args
->dnode
, ple
);
1211 static int lib_prefix_list_entry_destroy(struct nb_cb_destroy_args
*args
)
1213 struct prefix_list_entry
*ple
;
1215 if (args
->event
!= NB_EV_APPLY
)
1218 ple
= nb_running_unset_entry(args
->dnode
);
1220 prefix_list_entry_delete2(ple
);
1222 prefix_list_entry_free(ple
);
1228 * XPath: /frr-filter:lib/prefix-list/entry/action
1230 static int lib_prefix_list_entry_action_modify(struct nb_cb_modify_args
*args
)
1232 struct prefix_list_entry
*ple
;
1235 if (args
->event
!= NB_EV_APPLY
)
1238 ple
= nb_running_get_entry(args
->dnode
, NULL
, true);
1240 /* Start prefix entry update procedure. */
1241 prefix_list_entry_update_start(ple
);
1243 action_type
= yang_dnode_get_enum(args
->dnode
, NULL
);
1244 if (action_type
== YPLA_PERMIT
)
1245 ple
->type
= PREFIX_PERMIT
;
1247 ple
->type
= PREFIX_DENY
;
1249 /* Finish prefix entry update procedure. */
1250 prefix_list_entry_update_finish(ple
);
1255 static int lib_prefix_list_entry_prefix_modify(struct nb_cb_modify_args
*args
)
1257 struct prefix_list_entry
*ple
;
1260 if (args
->event
!= NB_EV_APPLY
)
1263 ple
= nb_running_get_entry(args
->dnode
, NULL
, true);
1265 /* Start prefix entry update procedure. */
1266 prefix_list_entry_update_start(ple
);
1268 yang_dnode_get_prefix(&ple
->prefix
, args
->dnode
, NULL
);
1270 /* Apply mask and correct original address if necessary. */
1271 prefix_copy(&p
, &ple
->prefix
);
1273 if (!prefix_same(&ple
->prefix
, &p
)) {
1274 zlog_info("%s: bad network %pFX correcting it to %pFX",
1275 __func__
, &ple
->prefix
, &p
);
1276 prefix_copy(&ple
->prefix
, &p
);
1280 /* Finish prefix entry update procedure. */
1281 prefix_list_entry_update_finish(ple
);
1286 static int lib_prefix_list_entry_prefix_destroy(struct nb_cb_destroy_args
*args
)
1288 struct prefix_list_entry
*ple
;
1290 if (args
->event
!= NB_EV_APPLY
)
1293 ple
= nb_running_get_entry(args
->dnode
, NULL
, true);
1295 /* Start prefix entry update procedure. */
1296 prefix_list_entry_update_start(ple
);
1298 memset(&ple
->prefix
, 0, sizeof(ple
->prefix
));
1300 /* Finish prefix entry update procedure. */
1301 prefix_list_entry_update_finish(ple
);
1307 * XPath: /frr-filter:lib/prefix-list/entry/ipv4-prefix
1310 lib_prefix_list_entry_ipv4_prefix_modify(struct nb_cb_modify_args
*args
)
1312 if (args
->event
== NB_EV_VALIDATE
) {
1313 const struct lyd_node
*plist_dnode
=
1314 yang_dnode_get_parent(args
->dnode
, "prefix-list");
1316 return prefix_list_nb_validate_v4_af_type(
1317 plist_dnode
, args
->errmsg
, args
->errmsg_len
);
1320 return lib_prefix_list_entry_prefix_modify(args
);
1324 lib_prefix_list_entry_ipv4_prefix_destroy(struct nb_cb_destroy_args
*args
)
1327 if (args
->event
!= NB_EV_APPLY
)
1330 return lib_prefix_list_entry_prefix_destroy(args
);
1334 * XPath: /frr-filter:lib/prefix-list/entry/ipv6-prefix
1337 lib_prefix_list_entry_ipv6_prefix_modify(struct nb_cb_modify_args
*args
)
1340 if (args
->event
== NB_EV_VALIDATE
) {
1341 const struct lyd_node
*plist_dnode
=
1342 yang_dnode_get_parent(args
->dnode
, "prefix-list");
1344 return prefix_list_nb_validate_v6_af_type(
1345 plist_dnode
, args
->errmsg
, args
->errmsg_len
);
1348 return lib_prefix_list_entry_prefix_modify(args
);
1352 lib_prefix_list_entry_ipv6_prefix_destroy(struct nb_cb_destroy_args
*args
)
1355 if (args
->event
!= NB_EV_APPLY
)
1358 return lib_prefix_list_entry_prefix_destroy(args
);
1362 * XPath: /frr-filter:lib/prefix-list/entry/ipv4-prefix-length-greater-or-equal
1364 static int lib_prefix_list_entry_ipv4_prefix_length_greater_or_equal_modify(
1365 struct nb_cb_modify_args
*args
)
1367 if (args
->event
== NB_EV_VALIDATE
1368 && prefix_list_length_validate(args
) != NB_OK
)
1369 return NB_ERR_VALIDATION
;
1371 if (args
->event
== NB_EV_VALIDATE
) {
1372 const struct lyd_node
*plist_dnode
=
1373 yang_dnode_get_parent(args
->dnode
, "prefix-list");
1375 return prefix_list_nb_validate_v4_af_type(
1376 plist_dnode
, args
->errmsg
, args
->errmsg_len
);
1379 return lib_prefix_list_entry_prefix_length_greater_or_equal_modify(
1383 static int lib_prefix_list_entry_ipv4_prefix_length_greater_or_equal_destroy(
1384 struct nb_cb_destroy_args
*args
)
1386 if (args
->event
== NB_EV_VALIDATE
) {
1387 const struct lyd_node
*plist_dnode
=
1388 yang_dnode_get_parent(args
->dnode
, "prefix-list");
1390 return prefix_list_nb_validate_v4_af_type(
1391 plist_dnode
, args
->errmsg
, args
->errmsg_len
);
1394 return lib_prefix_list_entry_prefix_length_greater_or_equal_destroy(
1399 * XPath: /frr-filter:lib/prefix-list/entry/ipv4-prefix-length-lesser-or-equal
1401 static int lib_prefix_list_entry_ipv4_prefix_length_lesser_or_equal_modify(
1402 struct nb_cb_modify_args
*args
)
1404 if (args
->event
== NB_EV_VALIDATE
1405 && prefix_list_length_validate(args
) != NB_OK
)
1406 return NB_ERR_VALIDATION
;
1408 if (args
->event
== NB_EV_VALIDATE
) {
1409 const struct lyd_node
*plist_dnode
=
1410 yang_dnode_get_parent(args
->dnode
, "prefix-list");
1412 return prefix_list_nb_validate_v4_af_type(
1413 plist_dnode
, args
->errmsg
, args
->errmsg_len
);
1416 return lib_prefix_list_entry_prefix_length_lesser_or_equal_modify(
1420 static int lib_prefix_list_entry_ipv4_prefix_length_lesser_or_equal_destroy(
1421 struct nb_cb_destroy_args
*args
)
1423 if (args
->event
== NB_EV_VALIDATE
) {
1424 const struct lyd_node
*plist_dnode
=
1425 yang_dnode_get_parent(args
->dnode
, "prefix-list");
1427 return prefix_list_nb_validate_v4_af_type(
1428 plist_dnode
, args
->errmsg
, args
->errmsg_len
);
1431 return lib_prefix_list_entry_prefix_length_lesser_or_equal_destroy(
1436 * XPath: /frr-filter:lib/prefix-list/entry/ipv6-prefix-length-greater-or-equal
1438 static int lib_prefix_list_entry_ipv6_prefix_length_greater_or_equal_modify(
1439 struct nb_cb_modify_args
*args
)
1441 if (args
->event
== NB_EV_VALIDATE
1442 && prefix_list_length_validate(args
) != NB_OK
)
1443 return NB_ERR_VALIDATION
;
1445 if (args
->event
== NB_EV_VALIDATE
) {
1446 const struct lyd_node
*plist_dnode
=
1447 yang_dnode_get_parent(args
->dnode
, "prefix-list");
1449 return prefix_list_nb_validate_v6_af_type(
1450 plist_dnode
, args
->errmsg
, args
->errmsg_len
);
1453 return lib_prefix_list_entry_prefix_length_greater_or_equal_modify(
1457 static int lib_prefix_list_entry_ipv6_prefix_length_greater_or_equal_destroy(
1458 struct nb_cb_destroy_args
*args
)
1460 if (args
->event
== NB_EV_VALIDATE
) {
1461 const struct lyd_node
*plist_dnode
=
1462 yang_dnode_get_parent(args
->dnode
, "prefix-list");
1464 return prefix_list_nb_validate_v6_af_type(
1465 plist_dnode
, args
->errmsg
, args
->errmsg_len
);
1468 return lib_prefix_list_entry_prefix_length_greater_or_equal_destroy(
1473 * XPath: /frr-filter:lib/prefix-list/entry/ipv6-prefix-length-lesser-or-equal
1475 static int lib_prefix_list_entry_ipv6_prefix_length_lesser_or_equal_modify(
1476 struct nb_cb_modify_args
*args
)
1478 if (args
->event
== NB_EV_VALIDATE
1479 && prefix_list_length_validate(args
) != NB_OK
)
1480 return NB_ERR_VALIDATION
;
1482 if (args
->event
== NB_EV_VALIDATE
) {
1483 const struct lyd_node
*plist_dnode
=
1484 yang_dnode_get_parent(args
->dnode
, "prefix-list");
1486 return prefix_list_nb_validate_v6_af_type(
1487 plist_dnode
, args
->errmsg
, args
->errmsg_len
);
1490 return lib_prefix_list_entry_prefix_length_lesser_or_equal_modify(
1494 static int lib_prefix_list_entry_ipv6_prefix_length_lesser_or_equal_destroy(
1495 struct nb_cb_destroy_args
*args
)
1497 if (args
->event
== NB_EV_VALIDATE
) {
1498 const struct lyd_node
*plist_dnode
=
1499 yang_dnode_get_parent(args
->dnode
, "prefix-list");
1501 return prefix_list_nb_validate_v6_af_type(
1502 plist_dnode
, args
->errmsg
, args
->errmsg_len
);
1505 return lib_prefix_list_entry_prefix_length_lesser_or_equal_destroy(
1510 * XPath: /frr-filter:lib/prefix-list/entry/any
1512 static int lib_prefix_list_entry_any_create(struct nb_cb_create_args
*args
)
1514 struct prefix_list_entry
*ple
;
1518 * If we have gotten to this point, it's legal
1520 if (args
->event
== NB_EV_VALIDATE
)
1523 if (args
->event
!= NB_EV_APPLY
)
1526 ple
= nb_running_get_entry(args
->dnode
, NULL
, true);
1528 /* Start prefix entry update procedure. */
1529 prefix_list_entry_update_start(ple
);
1533 /* Fill prefix struct from scratch. */
1534 memset(&ple
->prefix
, 0, sizeof(ple
->prefix
));
1536 type
= yang_dnode_get_enum(args
->dnode
, "../../type");
1539 ple
->prefix
.family
= AF_INET
;
1541 ple
->le
= IPV4_MAX_BITLEN
;
1544 ple
->prefix
.family
= AF_INET6
;
1546 ple
->le
= IPV6_MAX_BITLEN
;
1550 /* Finish prefix entry update procedure. */
1551 prefix_list_entry_update_finish(ple
);
1556 static int lib_prefix_list_entry_any_destroy(struct nb_cb_destroy_args
*args
)
1558 struct prefix_list_entry
*ple
;
1560 if (args
->event
!= NB_EV_APPLY
)
1563 ple
= nb_running_get_entry(args
->dnode
, NULL
, true);
1565 /* Start prefix entry update procedure. */
1566 prefix_list_entry_update_start(ple
);
1570 /* Finish prefix entry update procedure. */
1571 prefix_list_entry_update_finish(ple
);
1576 /* clang-format off */
1577 const struct frr_yang_module_info frr_filter_info
= {
1578 .name
= "frr-filter",
1581 .xpath
= "/frr-filter:lib/access-list",
1583 .create
= lib_access_list_create
,
1584 .destroy
= lib_access_list_destroy
,
1588 .xpath
= "/frr-filter:lib/access-list/remark",
1590 .modify
= lib_access_list_remark_modify
,
1591 .destroy
= lib_access_list_remark_destroy
,
1592 .cli_show
= access_list_remark_show
,
1596 .xpath
= "/frr-filter:lib/access-list/entry",
1598 .create
= lib_access_list_entry_create
,
1599 .destroy
= lib_access_list_entry_destroy
,
1600 .cli_cmp
= access_list_cmp
,
1601 .cli_show
= access_list_show
,
1605 .xpath
= "/frr-filter:lib/access-list/entry/action",
1607 .modify
= lib_access_list_entry_action_modify
,
1611 .xpath
= "/frr-filter:lib/access-list/entry/ipv4-prefix",
1613 .modify
= lib_access_list_entry_ipv4_prefix_modify
,
1614 .destroy
= lib_access_list_entry_ipv4_prefix_destroy
,
1618 .xpath
= "/frr-filter:lib/access-list/entry/ipv4-exact-match",
1620 .modify
= lib_access_list_entry_ipv4_exact_match_modify
,
1621 .destroy
= lib_access_list_entry_ipv4_exact_match_destroy
,
1625 .xpath
= "/frr-filter:lib/access-list/entry/host",
1627 .modify
= lib_access_list_entry_host_modify
,
1628 .destroy
= lib_access_list_entry_host_destroy
,
1632 .xpath
= "/frr-filter:lib/access-list/entry/network/address",
1634 .modify
= lib_access_list_entry_network_address_modify
,
1638 .xpath
= "/frr-filter:lib/access-list/entry/network/mask",
1640 .modify
= lib_access_list_entry_network_mask_modify
,
1644 .xpath
= "/frr-filter:lib/access-list/entry/source-any",
1646 .create
= lib_access_list_entry_source_any_create
,
1647 .destroy
= lib_access_list_entry_source_any_destroy
,
1651 .xpath
= "/frr-filter:lib/access-list/entry/destination-host",
1653 .modify
= lib_access_list_entry_destination_host_modify
,
1654 .destroy
= lib_access_list_entry_destination_host_destroy
,
1658 .xpath
= "/frr-filter:lib/access-list/entry/destination-network/address",
1660 .modify
= lib_access_list_entry_destination_network_address_modify
,
1664 .xpath
= "/frr-filter:lib/access-list/entry/destination-network/mask",
1666 .modify
= lib_access_list_entry_destination_network_mask_modify
,
1670 .xpath
= "/frr-filter:lib/access-list/entry/destination-any",
1672 .create
= lib_access_list_entry_destination_any_create
,
1673 .destroy
= lib_access_list_entry_destination_any_destroy
,
1677 .xpath
= "/frr-filter:lib/access-list/entry/ipv6-prefix",
1679 .modify
= lib_access_list_entry_ipv4_prefix_modify
,
1680 .destroy
= lib_access_list_entry_ipv4_prefix_destroy
,
1684 .xpath
= "/frr-filter:lib/access-list/entry/ipv6-exact-match",
1686 .modify
= lib_access_list_entry_ipv4_exact_match_modify
,
1687 .destroy
= lib_access_list_entry_ipv4_exact_match_destroy
,
1691 .xpath
= "/frr-filter:lib/access-list/entry/mac",
1693 .modify
= lib_access_list_entry_ipv4_prefix_modify
,
1694 .destroy
= lib_access_list_entry_ipv4_prefix_destroy
,
1698 .xpath
= "/frr-filter:lib/access-list/entry/any",
1700 .create
= lib_access_list_entry_any_create
,
1701 .destroy
= lib_access_list_entry_any_destroy
,
1705 .xpath
= "/frr-filter:lib/prefix-list",
1707 .create
= lib_prefix_list_create
,
1708 .destroy
= lib_prefix_list_destroy
,
1712 .xpath
= "/frr-filter:lib/prefix-list/remark",
1714 .modify
= lib_prefix_list_remark_modify
,
1715 .destroy
= lib_prefix_list_remark_destroy
,
1716 .cli_show
= prefix_list_remark_show
,
1720 .xpath
= "/frr-filter:lib/prefix-list/entry",
1722 .create
= lib_prefix_list_entry_create
,
1723 .destroy
= lib_prefix_list_entry_destroy
,
1724 .cli_cmp
= prefix_list_cmp
,
1725 .cli_show
= prefix_list_show
,
1729 .xpath
= "/frr-filter:lib/prefix-list/entry/action",
1731 .modify
= lib_prefix_list_entry_action_modify
,
1735 .xpath
= "/frr-filter:lib/prefix-list/entry/ipv4-prefix",
1737 .modify
= lib_prefix_list_entry_ipv4_prefix_modify
,
1738 .destroy
= lib_prefix_list_entry_ipv4_prefix_destroy
,
1742 .xpath
= "/frr-filter:lib/prefix-list/entry/ipv4-prefix-length-greater-or-equal",
1744 .modify
= lib_prefix_list_entry_ipv4_prefix_length_greater_or_equal_modify
,
1745 .destroy
= lib_prefix_list_entry_ipv4_prefix_length_greater_or_equal_destroy
,
1749 .xpath
= "/frr-filter:lib/prefix-list/entry/ipv4-prefix-length-lesser-or-equal",
1751 .modify
= lib_prefix_list_entry_ipv4_prefix_length_lesser_or_equal_modify
,
1752 .destroy
= lib_prefix_list_entry_ipv4_prefix_length_lesser_or_equal_destroy
,
1756 .xpath
= "/frr-filter:lib/prefix-list/entry/ipv6-prefix",
1758 .modify
= lib_prefix_list_entry_ipv6_prefix_modify
,
1759 .destroy
= lib_prefix_list_entry_ipv6_prefix_destroy
,
1763 .xpath
= "/frr-filter:lib/prefix-list/entry/ipv6-prefix-length-greater-or-equal",
1765 .modify
= lib_prefix_list_entry_ipv6_prefix_length_greater_or_equal_modify
,
1766 .destroy
= lib_prefix_list_entry_ipv6_prefix_length_greater_or_equal_destroy
,
1770 .xpath
= "/frr-filter:lib/prefix-list/entry/ipv6-prefix-length-lesser-or-equal",
1772 .modify
= lib_prefix_list_entry_ipv6_prefix_length_lesser_or_equal_modify
,
1773 .destroy
= lib_prefix_list_entry_ipv6_prefix_length_lesser_or_equal_destroy
,
1777 .xpath
= "/frr-filter:lib/prefix-list/entry/any",
1779 .create
= lib_prefix_list_entry_any_create
,
1780 .destroy
= lib_prefix_list_entry_any_destroy
,