1829 lines
42 KiB
C
1829 lines
42 KiB
C
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||
|
/*
|
||
|
* FRR filter northbound implementation.
|
||
|
*
|
||
|
* Copyright (C) 2019 Network Device Education Foundation, Inc. ("NetDEF")
|
||
|
* Rafael Zalamena
|
||
|
*/
|
||
|
|
||
|
#include "zebra.h"
|
||
|
|
||
|
#include "lib/northbound.h"
|
||
|
#include "lib/prefix.h"
|
||
|
#include "lib/printfrr.h"
|
||
|
|
||
|
#include "lib/filter.h"
|
||
|
#include "lib/plist.h"
|
||
|
#include "lib/plist_int.h"
|
||
|
#include "lib/routemap.h"
|
||
|
|
||
|
static enum nb_error prefix_list_length_validate(struct nb_cb_modify_args *args)
|
||
|
{
|
||
|
int type = yang_dnode_get_enum(args->dnode, "../../type");
|
||
|
const char *xpath_le = NULL, *xpath_ge = NULL;
|
||
|
struct prefix p;
|
||
|
uint8_t le, ge;
|
||
|
|
||
|
if (type == YPLT_IPV4) {
|
||
|
yang_dnode_get_prefix(&p, args->dnode, "../ipv4-prefix");
|
||
|
xpath_le = "../ipv4-prefix-length-lesser-or-equal";
|
||
|
xpath_ge = "../ipv4-prefix-length-greater-or-equal";
|
||
|
} else {
|
||
|
yang_dnode_get_prefix(&p, args->dnode, "../ipv6-prefix");
|
||
|
xpath_le = "../ipv6-prefix-length-lesser-or-equal";
|
||
|
xpath_ge = "../ipv6-prefix-length-greater-or-equal";
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Check rule:
|
||
|
* prefix length <= le.
|
||
|
*/
|
||
|
if (yang_dnode_exists(args->dnode, xpath_le)) {
|
||
|
le = yang_dnode_get_uint8(args->dnode, "%s", xpath_le);
|
||
|
if (p.prefixlen > le)
|
||
|
goto log_and_fail;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Check rule:
|
||
|
* prefix length <= ge.
|
||
|
*/
|
||
|
if (yang_dnode_exists(args->dnode, xpath_ge)) {
|
||
|
ge = yang_dnode_get_uint8(args->dnode, "%s", xpath_ge);
|
||
|
if (p.prefixlen > ge)
|
||
|
goto log_and_fail;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Check rule:
|
||
|
* ge <= le.
|
||
|
*/
|
||
|
if (yang_dnode_exists(args->dnode, xpath_le)
|
||
|
&& yang_dnode_exists(args->dnode, xpath_ge)) {
|
||
|
le = yang_dnode_get_uint8(args->dnode, "%s", xpath_le);
|
||
|
ge = yang_dnode_get_uint8(args->dnode, "%s", xpath_ge);
|
||
|
if (ge > le)
|
||
|
goto log_and_fail;
|
||
|
}
|
||
|
|
||
|
return NB_OK;
|
||
|
|
||
|
log_and_fail:
|
||
|
snprintfrr(
|
||
|
args->errmsg, args->errmsg_len,
|
||
|
"Invalid prefix range for %pFX: Make sure that mask length <= ge <= le",
|
||
|
&p);
|
||
|
return NB_ERR_VALIDATION;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets prefix list entry to blank value.
|
||
|
*
|
||
|
* \param[out] ple prefix list entry to modify.
|
||
|
*/
|
||
|
static void prefix_list_entry_set_empty(struct prefix_list_entry *ple)
|
||
|
{
|
||
|
ple->any = false;
|
||
|
memset(&ple->prefix, 0, sizeof(ple->prefix));
|
||
|
ple->ge = 0;
|
||
|
ple->le = 0;
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
prefix_list_nb_validate_v4_af_type(const struct lyd_node *plist_dnode,
|
||
|
char *errmsg, size_t errmsg_len)
|
||
|
{
|
||
|
int af_type;
|
||
|
|
||
|
af_type = yang_dnode_get_enum(plist_dnode, "type");
|
||
|
if (af_type != YPLT_IPV4) {
|
||
|
snprintf(errmsg, errmsg_len,
|
||
|
"prefix-list type %u is mismatched.", af_type);
|
||
|
return NB_ERR_VALIDATION;
|
||
|
}
|
||
|
|
||
|
return NB_OK;
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
prefix_list_nb_validate_v6_af_type(const struct lyd_node *plist_dnode,
|
||
|
char *errmsg, size_t errmsg_len)
|
||
|
{
|
||
|
int af_type;
|
||
|
|
||
|
af_type = yang_dnode_get_enum(plist_dnode, "type");
|
||
|
if (af_type != YPLT_IPV6) {
|
||
|
snprintf(errmsg, errmsg_len,
|
||
|
"prefix-list type %u is mismatched.", af_type);
|
||
|
return NB_ERR_VALIDATION;
|
||
|
}
|
||
|
|
||
|
return NB_OK;
|
||
|
}
|
||
|
|
||
|
static int lib_prefix_list_entry_prefix_length_greater_or_equal_modify(
|
||
|
struct nb_cb_modify_args *args)
|
||
|
{
|
||
|
struct prefix_list_entry *ple;
|
||
|
|
||
|
if (args->event != NB_EV_APPLY)
|
||
|
return NB_OK;
|
||
|
|
||
|
ple = nb_running_get_entry(args->dnode, NULL, true);
|
||
|
|
||
|
/* Start prefix entry update procedure. */
|
||
|
prefix_list_entry_update_start(ple);
|
||
|
|
||
|
ple->ge = yang_dnode_get_uint8(args->dnode, NULL);
|
||
|
|
||
|
return NB_OK;
|
||
|
}
|
||
|
|
||
|
static int lib_prefix_list_entry_prefix_length_lesser_or_equal_modify(
|
||
|
struct nb_cb_modify_args *args)
|
||
|
{
|
||
|
struct prefix_list_entry *ple;
|
||
|
|
||
|
if (args->event != NB_EV_APPLY)
|
||
|
return NB_OK;
|
||
|
|
||
|
ple = nb_running_get_entry(args->dnode, NULL, true);
|
||
|
|
||
|
/* Start prefix entry update procedure. */
|
||
|
prefix_list_entry_update_start(ple);
|
||
|
|
||
|
ple->le = yang_dnode_get_uint8(args->dnode, NULL);
|
||
|
|
||
|
return NB_OK;
|
||
|
}
|
||
|
|
||
|
static int lib_prefix_list_entry_prefix_length_greater_or_equal_destroy(
|
||
|
struct nb_cb_destroy_args *args)
|
||
|
{
|
||
|
struct prefix_list_entry *ple;
|
||
|
|
||
|
if (args->event != NB_EV_APPLY)
|
||
|
return NB_OK;
|
||
|
|
||
|
ple = nb_running_get_entry(args->dnode, NULL, true);
|
||
|
|
||
|
/* Start prefix entry update procedure. */
|
||
|
prefix_list_entry_update_start(ple);
|
||
|
|
||
|
ple->ge = 0;
|
||
|
|
||
|
return NB_OK;
|
||
|
}
|
||
|
|
||
|
static int lib_prefix_list_entry_prefix_length_lesser_or_equal_destroy(
|
||
|
struct nb_cb_destroy_args *args)
|
||
|
{
|
||
|
struct prefix_list_entry *ple;
|
||
|
|
||
|
if (args->event != NB_EV_APPLY)
|
||
|
return NB_OK;
|
||
|
|
||
|
ple = nb_running_get_entry(args->dnode, NULL, true);
|
||
|
|
||
|
/* Start prefix entry update procedure. */
|
||
|
prefix_list_entry_update_start(ple);
|
||
|
|
||
|
ple->le = 0;
|
||
|
|
||
|
return NB_OK;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Unsets the cisco style rule for addresses so it becomes disabled (the
|
||
|
* equivalent of setting: `0.0.0.0/32`).
|
||
|
*
|
||
|
* \param addr address part.
|
||
|
* \param mask mask part.
|
||
|
*/
|
||
|
static void cisco_unset_addr_mask(struct in_addr *addr, struct in_addr *mask)
|
||
|
{
|
||
|
addr->s_addr = INADDR_ANY;
|
||
|
mask->s_addr = CISCO_BIN_HOST_WILDCARD_MASK;
|
||
|
}
|
||
|
|
||
|
static int _acl_is_dup(const struct lyd_node *dnode, void *arg)
|
||
|
{
|
||
|
struct acl_dup_args *ada = arg;
|
||
|
int idx;
|
||
|
|
||
|
/* This entry is the caller, so skip it. */
|
||
|
if (ada->ada_entry_dnode
|
||
|
&& ada->ada_entry_dnode == dnode)
|
||
|
return YANG_ITER_CONTINUE;
|
||
|
|
||
|
if (strcmp(yang_dnode_get_string(dnode, "action"), ada->ada_action))
|
||
|
return YANG_ITER_CONTINUE;
|
||
|
|
||
|
/* Check if all values match. */
|
||
|
for (idx = 0; idx < ADA_MAX_VALUES; idx++) {
|
||
|
/* No more values. */
|
||
|
if (ada->ada_xpath[idx] == NULL)
|
||
|
break;
|
||
|
|
||
|
/* Not same type, just skip it. */
|
||
|
if (!yang_dnode_exists(dnode, ada->ada_xpath[idx]))
|
||
|
return YANG_ITER_CONTINUE;
|
||
|
|
||
|
/* Check if different value. */
|
||
|
if (strcmp(yang_dnode_get_string(dnode, "%s",
|
||
|
ada->ada_xpath[idx]),
|
||
|
ada->ada_value[idx]))
|
||
|
return YANG_ITER_CONTINUE;
|
||
|
}
|
||
|
|
||
|
ada->ada_found = true;
|
||
|
ada->ada_seq = yang_dnode_get_uint32(dnode, "sequence");
|
||
|
|
||
|
return YANG_ITER_STOP;
|
||
|
}
|
||
|
|
||
|
bool acl_is_dup(const struct lyd_node *dnode, struct acl_dup_args *ada)
|
||
|
{
|
||
|
ada->ada_found = false;
|
||
|
|
||
|
yang_dnode_iterate(
|
||
|
_acl_is_dup, ada, dnode,
|
||
|
"/frr-filter:lib/access-list[type='%s'][name='%s']/entry",
|
||
|
ada->ada_type, ada->ada_name);
|
||
|
|
||
|
return ada->ada_found;
|
||
|
}
|
||
|
|
||
|
static bool acl_cisco_is_dup(const struct lyd_node *dnode)
|
||
|
{
|
||
|
const struct lyd_node *entry_dnode =
|
||
|
yang_dnode_get_parent(dnode, "entry");
|
||
|
struct acl_dup_args ada = {};
|
||
|
int idx = 0, arg_idx = 0;
|
||
|
static const char *cisco_entries[] = {
|
||
|
"./host",
|
||
|
"./network/address",
|
||
|
"./network/mask",
|
||
|
"./source-any",
|
||
|
"./destination-host",
|
||
|
"./destination-network/address",
|
||
|
"./destination-network/mask",
|
||
|
"./destination-any",
|
||
|
NULL
|
||
|
};
|
||
|
|
||
|
/* Initialize. */
|
||
|
ada.ada_type = "ipv4";
|
||
|
ada.ada_name = yang_dnode_get_string(entry_dnode, "../name");
|
||
|
ada.ada_action = yang_dnode_get_string(entry_dnode, "action");
|
||
|
ada.ada_entry_dnode = entry_dnode;
|
||
|
|
||
|
/* Load all values/XPaths. */
|
||
|
while (cisco_entries[idx] != NULL) {
|
||
|
if (!yang_dnode_exists(entry_dnode, cisco_entries[idx])) {
|
||
|
idx++;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
ada.ada_xpath[arg_idx] = cisco_entries[idx];
|
||
|
ada.ada_value[arg_idx] = yang_dnode_get_string(
|
||
|
entry_dnode, "%s", cisco_entries[idx]);
|
||
|
arg_idx++;
|
||
|
idx++;
|
||
|
}
|
||
|
|
||
|
return acl_is_dup(entry_dnode, &ada);
|
||
|
}
|
||
|
|
||
|
static bool acl_zebra_is_dup(const struct lyd_node *dnode,
|
||
|
enum yang_access_list_type type)
|
||
|
{
|
||
|
const struct lyd_node *entry_dnode =
|
||
|
yang_dnode_get_parent(dnode, "entry");
|
||
|
struct acl_dup_args ada = {};
|
||
|
int idx = 0, arg_idx = 0;
|
||
|
static const char *zebra_entries[] = {
|
||
|
"./ipv4-prefix",
|
||
|
"./ipv4-exact-match",
|
||
|
"./ipv6-prefix",
|
||
|
"./ipv6-exact-match",
|
||
|
"./mac",
|
||
|
"./any",
|
||
|
NULL
|
||
|
};
|
||
|
|
||
|
/* Initialize. */
|
||
|
switch (type) {
|
||
|
case YALT_IPV4:
|
||
|
ada.ada_type = "ipv4";
|
||
|
break;
|
||
|
case YALT_IPV6:
|
||
|
ada.ada_type = "ipv6";
|
||
|
break;
|
||
|
case YALT_MAC:
|
||
|
ada.ada_type = "mac";
|
||
|
break;
|
||
|
}
|
||
|
ada.ada_name = yang_dnode_get_string(entry_dnode, "../name");
|
||
|
ada.ada_action = yang_dnode_get_string(entry_dnode, "action");
|
||
|
ada.ada_entry_dnode = entry_dnode;
|
||
|
|
||
|
/* Load all values/XPaths. */
|
||
|
while (zebra_entries[idx] != NULL) {
|
||
|
if (!yang_dnode_exists(entry_dnode, zebra_entries[idx])) {
|
||
|
idx++;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
ada.ada_xpath[arg_idx] = zebra_entries[idx];
|
||
|
ada.ada_value[arg_idx] = yang_dnode_get_string(
|
||
|
entry_dnode, "%s", zebra_entries[idx]);
|
||
|
arg_idx++;
|
||
|
idx++;
|
||
|
}
|
||
|
|
||
|
return acl_is_dup(entry_dnode, &ada);
|
||
|
}
|
||
|
|
||
|
static void plist_dnode_to_prefix(const struct lyd_node *dnode, bool *any,
|
||
|
struct prefix *p, int *ge, int *le)
|
||
|
{
|
||
|
*any = false;
|
||
|
*ge = 0;
|
||
|
*le = 0;
|
||
|
|
||
|
if (yang_dnode_exists(dnode, "any")) {
|
||
|
*any = true;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
switch (yang_dnode_get_enum(dnode, "../type")) {
|
||
|
case YPLT_IPV4:
|
||
|
yang_dnode_get_prefix(p, dnode, "ipv4-prefix");
|
||
|
if (yang_dnode_exists(dnode,
|
||
|
"./ipv4-prefix-length-greater-or-equal"))
|
||
|
*ge = yang_dnode_get_uint8(
|
||
|
dnode, "./ipv4-prefix-length-greater-or-equal");
|
||
|
if (yang_dnode_exists(dnode,
|
||
|
"./ipv4-prefix-length-lesser-or-equal"))
|
||
|
*le = yang_dnode_get_uint8(
|
||
|
dnode, "./ipv4-prefix-length-lesser-or-equal");
|
||
|
break;
|
||
|
case YPLT_IPV6:
|
||
|
yang_dnode_get_prefix(p, dnode, "ipv6-prefix");
|
||
|
if (yang_dnode_exists(dnode,
|
||
|
"./ipv6-prefix-length-greater-or-equal"))
|
||
|
*ge = yang_dnode_get_uint8(
|
||
|
dnode, "./ipv6-prefix-length-greater-or-equal");
|
||
|
if (yang_dnode_exists(dnode,
|
||
|
"./ipv6-prefix-length-lesser-or-equal"))
|
||
|
*le = yang_dnode_get_uint8(
|
||
|
dnode, "./ipv6-prefix-length-lesser-or-equal");
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static int _plist_is_dup(const struct lyd_node *dnode, void *arg)
|
||
|
{
|
||
|
struct plist_dup_args *pda = arg;
|
||
|
struct prefix p = {};
|
||
|
int ge, le;
|
||
|
bool any;
|
||
|
|
||
|
/* This entry is the caller, so skip it. */
|
||
|
if (pda->pda_entry_dnode
|
||
|
&& pda->pda_entry_dnode == dnode)
|
||
|
return YANG_ITER_CONTINUE;
|
||
|
|
||
|
if (strcmp(yang_dnode_get_string(dnode, "action"), pda->pda_action))
|
||
|
return YANG_ITER_CONTINUE;
|
||
|
|
||
|
plist_dnode_to_prefix(dnode, &any, &p, &ge, &le);
|
||
|
|
||
|
if (pda->any) {
|
||
|
if (!any)
|
||
|
return YANG_ITER_CONTINUE;
|
||
|
} else {
|
||
|
if (!prefix_same(&pda->prefix, &p) || pda->ge != ge
|
||
|
|| pda->le != le)
|
||
|
return YANG_ITER_CONTINUE;
|
||
|
}
|
||
|
|
||
|
pda->pda_found = true;
|
||
|
pda->pda_seq = yang_dnode_get_uint32(dnode, "sequence");
|
||
|
|
||
|
return YANG_ITER_STOP;
|
||
|
}
|
||
|
|
||
|
bool plist_is_dup(const struct lyd_node *dnode, struct plist_dup_args *pda)
|
||
|
{
|
||
|
pda->pda_found = false;
|
||
|
|
||
|
yang_dnode_iterate(
|
||
|
_plist_is_dup, pda, dnode,
|
||
|
"/frr-filter:lib/prefix-list[type='%s'][name='%s']/entry",
|
||
|
pda->pda_type, pda->pda_name);
|
||
|
|
||
|
return pda->pda_found;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* XPath: /frr-filter:lib/access-list
|
||
|
*/
|
||
|
static int lib_access_list_create(struct nb_cb_create_args *args)
|
||
|
{
|
||
|
struct access_list *acl = NULL;
|
||
|
const char *acl_name;
|
||
|
int type;
|
||
|
|
||
|
if (args->event != NB_EV_APPLY)
|
||
|
return NB_OK;
|
||
|
|
||
|
type = yang_dnode_get_enum(args->dnode, "type");
|
||
|
acl_name = yang_dnode_get_string(args->dnode, "name");
|
||
|
|
||
|
switch (type) {
|
||
|
case YALT_IPV4:
|
||
|
acl = access_list_get(AFI_IP, acl_name);
|
||
|
break;
|
||
|
case YALT_IPV6:
|
||
|
acl = access_list_get(AFI_IP6, acl_name);
|
||
|
break;
|
||
|
case YALT_MAC:
|
||
|
acl = access_list_get(AFI_L2VPN, acl_name);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
nb_running_set_entry(args->dnode, acl);
|
||
|
|
||
|
return NB_OK;
|
||
|
}
|
||
|
|
||
|
static int lib_access_list_destroy(struct nb_cb_destroy_args *args)
|
||
|
{
|
||
|
struct access_list *acl;
|
||
|
|
||
|
if (args->event != NB_EV_APPLY)
|
||
|
return NB_OK;
|
||
|
|
||
|
acl = nb_running_unset_entry(args->dnode);
|
||
|
access_list_delete(acl);
|
||
|
|
||
|
return NB_OK;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* XPath: /frr-filter:lib/access-list/remark
|
||
|
*/
|
||
|
static int lib_access_list_remark_modify(struct nb_cb_modify_args *args)
|
||
|
{
|
||
|
struct access_list *acl;
|
||
|
const char *remark;
|
||
|
|
||
|
if (args->event != NB_EV_APPLY)
|
||
|
return NB_OK;
|
||
|
|
||
|
acl = nb_running_get_entry(args->dnode, NULL, true);
|
||
|
if (acl->remark)
|
||
|
XFREE(MTYPE_TMP, acl->remark);
|
||
|
|
||
|
remark = yang_dnode_get_string(args->dnode, NULL);
|
||
|
acl->remark = XSTRDUP(MTYPE_TMP, remark);
|
||
|
|
||
|
return NB_OK;
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
lib_access_list_remark_destroy(struct nb_cb_destroy_args *args)
|
||
|
{
|
||
|
struct access_list *acl;
|
||
|
|
||
|
if (args->event != NB_EV_APPLY)
|
||
|
return NB_OK;
|
||
|
|
||
|
acl = nb_running_get_entry(args->dnode, NULL, true);
|
||
|
if (acl->remark)
|
||
|
XFREE(MTYPE_TMP, acl->remark);
|
||
|
|
||
|
return NB_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* XPath: /frr-filter:lib/access-list/entry
|
||
|
*/
|
||
|
static int lib_access_list_entry_create(struct nb_cb_create_args *args)
|
||
|
{
|
||
|
struct access_list *acl;
|
||
|
struct filter *f;
|
||
|
|
||
|
if (args->event != NB_EV_APPLY)
|
||
|
return NB_OK;
|
||
|
|
||
|
f = filter_new();
|
||
|
f->seq = yang_dnode_get_uint32(args->dnode, "sequence");
|
||
|
|
||
|
acl = nb_running_get_entry(args->dnode, NULL, true);
|
||
|
f->acl = acl;
|
||
|
access_list_filter_add(acl, f);
|
||
|
nb_running_set_entry(args->dnode, f);
|
||
|
|
||
|
return NB_OK;
|
||
|
}
|
||
|
|
||
|
static int lib_access_list_entry_destroy(struct nb_cb_destroy_args *args)
|
||
|
{
|
||
|
struct access_list *acl;
|
||
|
struct filter *f;
|
||
|
|
||
|
if (args->event != NB_EV_APPLY)
|
||
|
return NB_OK;
|
||
|
|
||
|
f = nb_running_unset_entry(args->dnode);
|
||
|
acl = f->acl;
|
||
|
access_list_filter_delete(acl, f);
|
||
|
|
||
|
return NB_OK;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
lib_access_list_entry_apply_finish(struct nb_cb_apply_finish_args *args)
|
||
|
{
|
||
|
struct filter *f;
|
||
|
|
||
|
f = nb_running_get_entry(args->dnode, NULL, true);
|
||
|
access_list_filter_update(f->acl);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* XPath: /frr-filter:lib/access-list/entry/action
|
||
|
*/
|
||
|
static int
|
||
|
lib_access_list_entry_action_modify(struct nb_cb_modify_args *args)
|
||
|
{
|
||
|
const char *filter_type;
|
||
|
struct filter *f;
|
||
|
|
||
|
if (args->event != NB_EV_APPLY)
|
||
|
return NB_OK;
|
||
|
|
||
|
f = nb_running_get_entry(args->dnode, NULL, true);
|
||
|
filter_type = yang_dnode_get_string(args->dnode, NULL);
|
||
|
if (strcmp(filter_type, "permit") == 0)
|
||
|
f->type = FILTER_PERMIT;
|
||
|
else
|
||
|
f->type = FILTER_DENY;
|
||
|
|
||
|
return NB_OK;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* XPath: /frr-filter:lib/access-list/entry/ipv4-prefix
|
||
|
*/
|
||
|
static int
|
||
|
lib_access_list_entry_ipv4_prefix_modify(struct nb_cb_modify_args *args)
|
||
|
{
|
||
|
struct filter_zebra *fz;
|
||
|
struct filter *f;
|
||
|
|
||
|
/* Don't allow duplicated values. */
|
||
|
if (args->event == NB_EV_VALIDATE) {
|
||
|
if (acl_zebra_is_dup(
|
||
|
args->dnode,
|
||
|
yang_dnode_get_enum(args->dnode, "../../type"))) {
|
||
|
snprintfrr(args->errmsg, args->errmsg_len,
|
||
|
"duplicated access list value: %s",
|
||
|
yang_dnode_get_string(args->dnode, NULL));
|
||
|
return NB_ERR_VALIDATION;
|
||
|
}
|
||
|
return NB_OK;
|
||
|
}
|
||
|
|
||
|
if (args->event != NB_EV_APPLY)
|
||
|
return NB_OK;
|
||
|
|
||
|
f = nb_running_get_entry(args->dnode, NULL, true);
|
||
|
f->cisco = 0;
|
||
|
fz = &f->u.zfilter;
|
||
|
yang_dnode_get_prefix(&fz->prefix, args->dnode, NULL);
|
||
|
|
||
|
return NB_OK;
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
lib_access_list_entry_ipv4_prefix_destroy(struct nb_cb_destroy_args *args)
|
||
|
{
|
||
|
struct filter_zebra *fz;
|
||
|
struct filter *f;
|
||
|
|
||
|
if (args->event != NB_EV_APPLY)
|
||
|
return NB_OK;
|
||
|
|
||
|
f = nb_running_get_entry(args->dnode, NULL, true);
|
||
|
fz = &f->u.zfilter;
|
||
|
memset(&fz->prefix, 0, sizeof(fz->prefix));
|
||
|
|
||
|
return NB_OK;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* XPath: /frr-filter:lib/access-list/entry/ipv4-exact-match
|
||
|
*/
|
||
|
static int
|
||
|
lib_access_list_entry_ipv4_exact_match_modify(struct nb_cb_modify_args *args)
|
||
|
{
|
||
|
struct filter_zebra *fz;
|
||
|
struct filter *f;
|
||
|
|
||
|
/* Don't allow duplicated values. */
|
||
|
if (args->event == NB_EV_VALIDATE) {
|
||
|
if (acl_zebra_is_dup(
|
||
|
args->dnode,
|
||
|
yang_dnode_get_enum(args->dnode, "../../type"))) {
|
||
|
snprintfrr(args->errmsg, args->errmsg_len,
|
||
|
"duplicated access list value: %s",
|
||
|
yang_dnode_get_string(args->dnode, NULL));
|
||
|
return NB_ERR_VALIDATION;
|
||
|
}
|
||
|
return NB_OK;
|
||
|
}
|
||
|
|
||
|
if (args->event != NB_EV_APPLY)
|
||
|
return NB_OK;
|
||
|
|
||
|
f = nb_running_get_entry(args->dnode, NULL, true);
|
||
|
fz = &f->u.zfilter;
|
||
|
fz->exact = yang_dnode_get_bool(args->dnode, NULL);
|
||
|
|
||
|
return NB_OK;
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
lib_access_list_entry_ipv4_exact_match_destroy(struct nb_cb_destroy_args *args)
|
||
|
{
|
||
|
struct filter_zebra *fz;
|
||
|
struct filter *f;
|
||
|
|
||
|
if (args->event != NB_EV_APPLY)
|
||
|
return NB_OK;
|
||
|
|
||
|
f = nb_running_get_entry(args->dnode, NULL, true);
|
||
|
fz = &f->u.zfilter;
|
||
|
fz->exact = 0;
|
||
|
|
||
|
return NB_OK;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* XPath: /frr-filter:lib/access-list/entry/host
|
||
|
*/
|
||
|
static int
|
||
|
lib_access_list_entry_host_modify(struct nb_cb_modify_args *args)
|
||
|
{
|
||
|
struct filter_cisco *fc;
|
||
|
struct filter *f;
|
||
|
|
||
|
/* Don't allow duplicated values. */
|
||
|
if (args->event == NB_EV_VALIDATE) {
|
||
|
if (acl_cisco_is_dup(args->dnode)) {
|
||
|
snprintfrr(args->errmsg, args->errmsg_len,
|
||
|
"duplicated access list value: %s",
|
||
|
yang_dnode_get_string(args->dnode, NULL));
|
||
|
return NB_ERR_VALIDATION;
|
||
|
}
|
||
|
return NB_OK;
|
||
|
}
|
||
|
|
||
|
if (args->event != NB_EV_APPLY)
|
||
|
return NB_OK;
|
||
|
|
||
|
f = nb_running_get_entry(args->dnode, NULL, true);
|
||
|
f->cisco = 1;
|
||
|
fc = &f->u.cfilter;
|
||
|
yang_dnode_get_ipv4(&fc->addr, args->dnode, NULL);
|
||
|
fc->addr_mask.s_addr = CISCO_BIN_HOST_WILDCARD_MASK;
|
||
|
|
||
|
return NB_OK;
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
lib_access_list_entry_host_destroy(struct nb_cb_destroy_args *args)
|
||
|
{
|
||
|
struct filter_cisco *fc;
|
||
|
struct filter *f;
|
||
|
|
||
|
if (args->event != NB_EV_APPLY)
|
||
|
return NB_OK;
|
||
|
|
||
|
f = nb_running_get_entry(args->dnode, NULL, true);
|
||
|
fc = &f->u.cfilter;
|
||
|
cisco_unset_addr_mask(&fc->addr, &fc->addr_mask);
|
||
|
|
||
|
return NB_OK;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* XPath: /frr-filter:lib/access-list/entry/network
|
||
|
*/
|
||
|
static int lib_access_list_entry_network_create(struct nb_cb_create_args *args)
|
||
|
{
|
||
|
/* Nothing to do here, everything is done in children callbacks */
|
||
|
return NB_OK;
|
||
|
}
|
||
|
|
||
|
static int lib_access_list_entry_network_destroy(struct nb_cb_destroy_args *args)
|
||
|
{
|
||
|
struct filter_cisco *fc;
|
||
|
struct filter *f;
|
||
|
|
||
|
if (args->event != NB_EV_APPLY)
|
||
|
return NB_OK;
|
||
|
|
||
|
f = nb_running_get_entry(args->dnode, NULL, true);
|
||
|
fc = &f->u.cfilter;
|
||
|
cisco_unset_addr_mask(&fc->addr, &fc->addr_mask);
|
||
|
|
||
|
return NB_OK;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* XPath: /frr-filter:lib/access-list/entry/network/address
|
||
|
*/
|
||
|
static int
|
||
|
lib_access_list_entry_network_address_modify(struct nb_cb_modify_args *args)
|
||
|
{
|
||
|
struct filter_cisco *fc;
|
||
|
struct filter *f;
|
||
|
|
||
|
/* Don't allow duplicated values. */
|
||
|
if (args->event == NB_EV_VALIDATE) {
|
||
|
if (acl_cisco_is_dup(args->dnode)) {
|
||
|
snprintfrr(args->errmsg, args->errmsg_len,
|
||
|
"duplicated access list value: %s",
|
||
|
yang_dnode_get_string(args->dnode, NULL));
|
||
|
return NB_ERR_VALIDATION;
|
||
|
}
|
||
|
return NB_OK;
|
||
|
}
|
||
|
|
||
|
if (args->event != NB_EV_APPLY)
|
||
|
return NB_OK;
|
||
|
|
||
|
f = nb_running_get_entry(args->dnode, NULL, true);
|
||
|
f->cisco = 1;
|
||
|
fc = &f->u.cfilter;
|
||
|
yang_dnode_get_ipv4(&fc->addr, args->dnode, NULL);
|
||
|
|
||
|
return NB_OK;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* XPath: /frr-filter:lib/access-list/entry/network/mask
|
||
|
*/
|
||
|
static int
|
||
|
lib_access_list_entry_network_mask_modify(struct nb_cb_modify_args *args)
|
||
|
{
|
||
|
struct filter_cisco *fc;
|
||
|
struct filter *f;
|
||
|
|
||
|
/* Don't allow duplicated values. */
|
||
|
if (args->event == NB_EV_VALIDATE) {
|
||
|
if (acl_cisco_is_dup(args->dnode)) {
|
||
|
snprintfrr(args->errmsg, args->errmsg_len,
|
||
|
"duplicated access list value: %s",
|
||
|
yang_dnode_get_string(args->dnode, NULL));
|
||
|
return NB_ERR_VALIDATION;
|
||
|
}
|
||
|
return NB_OK;
|
||
|
}
|
||
|
|
||
|
if (args->event != NB_EV_APPLY)
|
||
|
return NB_OK;
|
||
|
|
||
|
f = nb_running_get_entry(args->dnode, NULL, true);
|
||
|
f->cisco = 1;
|
||
|
fc = &f->u.cfilter;
|
||
|
yang_dnode_get_ipv4(&fc->addr_mask, args->dnode, NULL);
|
||
|
|
||
|
return NB_OK;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* XPath: /frr-filter:lib/access-list/entry/source-any
|
||
|
*/
|
||
|
static int
|
||
|
lib_access_list_entry_source_any_create(struct nb_cb_create_args *args)
|
||
|
{
|
||
|
struct filter_cisco *fc;
|
||
|
struct filter *f;
|
||
|
|
||
|
/* Don't allow duplicated values. */
|
||
|
if (args->event == NB_EV_VALIDATE) {
|
||
|
if (acl_cisco_is_dup(args->dnode)) {
|
||
|
snprintfrr(args->errmsg, args->errmsg_len,
|
||
|
"duplicated access list value: %s",
|
||
|
yang_dnode_get_string(args->dnode, NULL));
|
||
|
return NB_ERR_VALIDATION;
|
||
|
}
|
||
|
return NB_OK;
|
||
|
}
|
||
|
|
||
|
if (args->event != NB_EV_APPLY)
|
||
|
return NB_OK;
|
||
|
|
||
|
f = nb_running_get_entry(args->dnode, NULL, true);
|
||
|
f->cisco = 1;
|
||
|
fc = &f->u.cfilter;
|
||
|
fc->addr.s_addr = INADDR_ANY;
|
||
|
fc->addr_mask.s_addr = CISCO_BIN_ANY_WILDCARD_MASK;
|
||
|
|
||
|
return NB_OK;
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
lib_access_list_entry_source_any_destroy(struct nb_cb_destroy_args *args)
|
||
|
{
|
||
|
struct filter_cisco *fc;
|
||
|
struct filter *f;
|
||
|
|
||
|
if (args->event != NB_EV_APPLY)
|
||
|
return NB_OK;
|
||
|
|
||
|
f = nb_running_get_entry(args->dnode, NULL, true);
|
||
|
fc = &f->u.cfilter;
|
||
|
cisco_unset_addr_mask(&fc->addr, &fc->addr_mask);
|
||
|
|
||
|
return NB_OK;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* XPath: /frr-filter:lib/access-list/entry/destination-host
|
||
|
*/
|
||
|
static int lib_access_list_entry_destination_host_modify(
|
||
|
struct nb_cb_modify_args *args)
|
||
|
{
|
||
|
struct filter_cisco *fc;
|
||
|
struct filter *f;
|
||
|
|
||
|
/* Don't allow duplicated values. */
|
||
|
if (args->event == NB_EV_VALIDATE) {
|
||
|
if (acl_cisco_is_dup(args->dnode)) {
|
||
|
snprintfrr(args->errmsg, args->errmsg_len,
|
||
|
"duplicated access list value: %s",
|
||
|
yang_dnode_get_string(args->dnode, NULL));
|
||
|
return NB_ERR_VALIDATION;
|
||
|
}
|
||
|
return NB_OK;
|
||
|
}
|
||
|
|
||
|
if (args->event != NB_EV_APPLY)
|
||
|
return NB_OK;
|
||
|
|
||
|
f = nb_running_get_entry(args->dnode, NULL, true);
|
||
|
fc = &f->u.cfilter;
|
||
|
fc->extended = 1;
|
||
|
yang_dnode_get_ipv4(&fc->mask, args->dnode, NULL);
|
||
|
fc->mask_mask.s_addr = CISCO_BIN_HOST_WILDCARD_MASK;
|
||
|
|
||
|
return NB_OK;
|
||
|
}
|
||
|
|
||
|
static int lib_access_list_entry_destination_host_destroy(
|
||
|
struct nb_cb_destroy_args *args)
|
||
|
{
|
||
|
struct filter_cisco *fc;
|
||
|
struct filter *f;
|
||
|
|
||
|
if (args->event != NB_EV_APPLY)
|
||
|
return NB_OK;
|
||
|
|
||
|
f = nb_running_get_entry(args->dnode, NULL, true);
|
||
|
fc = &f->u.cfilter;
|
||
|
fc->extended = 0;
|
||
|
cisco_unset_addr_mask(&fc->mask, &fc->mask_mask);
|
||
|
|
||
|
return NB_OK;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* XPath: /frr-filter:lib/access-list/entry/destination-network
|
||
|
*/
|
||
|
static int
|
||
|
lib_access_list_entry_destination_network_create(struct nb_cb_create_args *args)
|
||
|
{
|
||
|
/* Nothing to do here, everything is done in children callbacks */
|
||
|
return NB_OK;
|
||
|
}
|
||
|
|
||
|
static int lib_access_list_entry_destination_network_destroy(
|
||
|
struct nb_cb_destroy_args *args)
|
||
|
{
|
||
|
struct filter_cisco *fc;
|
||
|
struct filter *f;
|
||
|
|
||
|
if (args->event != NB_EV_APPLY)
|
||
|
return NB_OK;
|
||
|
|
||
|
f = nb_running_get_entry(args->dnode, NULL, true);
|
||
|
fc = &f->u.cfilter;
|
||
|
fc->extended = 0;
|
||
|
cisco_unset_addr_mask(&fc->mask, &fc->mask_mask);
|
||
|
|
||
|
return NB_OK;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* XPath: /frr-filter:lib/access-list/entry/destination-network/address
|
||
|
*/
|
||
|
static int lib_access_list_entry_destination_network_address_modify(
|
||
|
struct nb_cb_modify_args *args)
|
||
|
{
|
||
|
struct filter_cisco *fc;
|
||
|
struct filter *f;
|
||
|
|
||
|
/* Don't allow duplicated values. */
|
||
|
if (args->event == NB_EV_VALIDATE) {
|
||
|
if (acl_cisco_is_dup(args->dnode)) {
|
||
|
snprintfrr(args->errmsg, args->errmsg_len,
|
||
|
"duplicated access list value: %s",
|
||
|
yang_dnode_get_string(args->dnode, NULL));
|
||
|
return NB_ERR_VALIDATION;
|
||
|
}
|
||
|
return NB_OK;
|
||
|
}
|
||
|
|
||
|
if (args->event != NB_EV_APPLY)
|
||
|
return NB_OK;
|
||
|
|
||
|
f = nb_running_get_entry(args->dnode, NULL, true);
|
||
|
fc = &f->u.cfilter;
|
||
|
fc->extended = 1;
|
||
|
yang_dnode_get_ipv4(&fc->mask, args->dnode, NULL);
|
||
|
|
||
|
return NB_OK;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* XPath: /frr-filter:lib/access-list/entry/destination-network/mask
|
||
|
*/
|
||
|
static int lib_access_list_entry_destination_network_mask_modify(
|
||
|
struct nb_cb_modify_args *args)
|
||
|
{
|
||
|
struct filter_cisco *fc;
|
||
|
struct filter *f;
|
||
|
|
||
|
/* Don't allow duplicated values. */
|
||
|
if (args->event == NB_EV_VALIDATE) {
|
||
|
if (acl_cisco_is_dup(args->dnode)) {
|
||
|
snprintfrr(args->errmsg, args->errmsg_len,
|
||
|
"duplicated access list value: %s",
|
||
|
yang_dnode_get_string(args->dnode, NULL));
|
||
|
return NB_ERR_VALIDATION;
|
||
|
}
|
||
|
return NB_OK;
|
||
|
}
|
||
|
|
||
|
if (args->event != NB_EV_APPLY)
|
||
|
return NB_OK;
|
||
|
|
||
|
f = nb_running_get_entry(args->dnode, NULL, true);
|
||
|
fc = &f->u.cfilter;
|
||
|
fc->extended = 1;
|
||
|
yang_dnode_get_ipv4(&fc->mask_mask, args->dnode, NULL);
|
||
|
|
||
|
return NB_OK;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* XPath: /frr-filter:lib/access-list/entry/destination-any
|
||
|
*/
|
||
|
static int lib_access_list_entry_destination_any_create(
|
||
|
struct nb_cb_create_args *args)
|
||
|
{
|
||
|
struct filter_cisco *fc;
|
||
|
struct filter *f;
|
||
|
|
||
|
/* Don't allow duplicated values. */
|
||
|
if (args->event == NB_EV_VALIDATE) {
|
||
|
if (acl_cisco_is_dup(args->dnode)) {
|
||
|
snprintfrr(args->errmsg, args->errmsg_len,
|
||
|
"duplicated access list value: %s",
|
||
|
yang_dnode_get_string(args->dnode, NULL));
|
||
|
return NB_ERR_VALIDATION;
|
||
|
}
|
||
|
return NB_OK;
|
||
|
}
|
||
|
|
||
|
if (args->event != NB_EV_APPLY)
|
||
|
return NB_OK;
|
||
|
|
||
|
f = nb_running_get_entry(args->dnode, NULL, true);
|
||
|
fc = &f->u.cfilter;
|
||
|
fc->extended = 1;
|
||
|
fc->mask.s_addr = INADDR_ANY;
|
||
|
fc->mask_mask.s_addr = CISCO_BIN_ANY_WILDCARD_MASK;
|
||
|
|
||
|
return NB_OK;
|
||
|
}
|
||
|
|
||
|
static int lib_access_list_entry_destination_any_destroy(
|
||
|
struct nb_cb_destroy_args *args)
|
||
|
{
|
||
|
struct filter_cisco *fc;
|
||
|
struct filter *f;
|
||
|
|
||
|
if (args->event != NB_EV_APPLY)
|
||
|
return NB_OK;
|
||
|
|
||
|
f = nb_running_get_entry(args->dnode, NULL, true);
|
||
|
fc = &f->u.cfilter;
|
||
|
fc->extended = 0;
|
||
|
cisco_unset_addr_mask(&fc->mask, &fc->mask_mask);
|
||
|
|
||
|
return NB_OK;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* XPath: /frr-filter:lib/access-list/entry/any
|
||
|
*/
|
||
|
static int lib_access_list_entry_any_create(struct nb_cb_create_args *args)
|
||
|
{
|
||
|
struct filter_zebra *fz;
|
||
|
struct filter *f;
|
||
|
int type;
|
||
|
|
||
|
/* Don't allow duplicated values. */
|
||
|
if (args->event == NB_EV_VALIDATE) {
|
||
|
if (acl_zebra_is_dup(
|
||
|
args->dnode,
|
||
|
yang_dnode_get_enum(args->dnode, "../../type"))) {
|
||
|
snprintfrr(args->errmsg, args->errmsg_len,
|
||
|
"duplicated access list value: %s",
|
||
|
yang_dnode_get_string(args->dnode, NULL));
|
||
|
return NB_ERR_VALIDATION;
|
||
|
}
|
||
|
return NB_OK;
|
||
|
}
|
||
|
|
||
|
if (args->event != NB_EV_APPLY)
|
||
|
return NB_OK;
|
||
|
|
||
|
f = nb_running_get_entry(args->dnode, NULL, true);
|
||
|
f->cisco = 0;
|
||
|
fz = &f->u.zfilter;
|
||
|
memset(&fz->prefix, 0, sizeof(fz->prefix));
|
||
|
|
||
|
type = yang_dnode_get_enum(args->dnode, "../../type");
|
||
|
switch (type) {
|
||
|
case YALT_IPV4:
|
||
|
fz->prefix.family = AF_INET;
|
||
|
break;
|
||
|
case YALT_IPV6:
|
||
|
fz->prefix.family = AF_INET6;
|
||
|
break;
|
||
|
case YALT_MAC:
|
||
|
fz->prefix.family = AF_ETHERNET;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return NB_OK;
|
||
|
}
|
||
|
|
||
|
static int lib_access_list_entry_any_destroy(struct nb_cb_destroy_args *args)
|
||
|
{
|
||
|
struct filter_zebra *fz;
|
||
|
struct filter *f;
|
||
|
|
||
|
if (args->event != NB_EV_APPLY)
|
||
|
return NB_OK;
|
||
|
|
||
|
f = nb_running_get_entry(args->dnode, NULL, true);
|
||
|
fz = &f->u.zfilter;
|
||
|
fz->prefix.family = AF_UNSPEC;
|
||
|
|
||
|
return NB_OK;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* XPath: /frr-filter:lib/prefix-list
|
||
|
*/
|
||
|
static int lib_prefix_list_create(struct nb_cb_create_args *args)
|
||
|
{
|
||
|
struct prefix_list *pl = NULL;
|
||
|
const char *name;
|
||
|
int type;
|
||
|
|
||
|
if (args->event != NB_EV_APPLY)
|
||
|
return NB_OK;
|
||
|
|
||
|
type = yang_dnode_get_enum(args->dnode, "type");
|
||
|
name = yang_dnode_get_string(args->dnode, "name");
|
||
|
switch (type) {
|
||
|
case 0: /* ipv4 */
|
||
|
pl = prefix_list_get(AFI_IP, 0, name);
|
||
|
break;
|
||
|
case 1: /* ipv6 */
|
||
|
pl = prefix_list_get(AFI_IP6, 0, name);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
nb_running_set_entry(args->dnode, pl);
|
||
|
|
||
|
return NB_OK;
|
||
|
}
|
||
|
|
||
|
static int lib_prefix_list_destroy(struct nb_cb_destroy_args *args)
|
||
|
{
|
||
|
struct prefix_list *pl;
|
||
|
|
||
|
if (args->event != NB_EV_APPLY)
|
||
|
return NB_OK;
|
||
|
|
||
|
pl = nb_running_unset_entry(args->dnode);
|
||
|
prefix_list_delete(pl);
|
||
|
|
||
|
return NB_OK;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* XPath: /frr-filter:lib/prefix-list/remark
|
||
|
*/
|
||
|
static int lib_prefix_list_remark_modify(struct nb_cb_modify_args *args)
|
||
|
{
|
||
|
struct prefix_list *pl;
|
||
|
const char *remark;
|
||
|
|
||
|
if (args->event != NB_EV_APPLY)
|
||
|
return NB_OK;
|
||
|
|
||
|
pl = nb_running_get_entry(args->dnode, NULL, true);
|
||
|
if (pl->desc)
|
||
|
XFREE(MTYPE_TMP, pl->desc);
|
||
|
|
||
|
remark = yang_dnode_get_string(args->dnode, NULL);
|
||
|
pl->desc = XSTRDUP(MTYPE_TMP, remark);
|
||
|
|
||
|
return NB_OK;
|
||
|
}
|
||
|
|
||
|
static int lib_prefix_list_remark_destroy(struct nb_cb_destroy_args *args)
|
||
|
{
|
||
|
struct prefix_list *pl;
|
||
|
|
||
|
if (args->event != NB_EV_APPLY)
|
||
|
return NB_OK;
|
||
|
|
||
|
pl = nb_running_get_entry(args->dnode, NULL, true);
|
||
|
if (pl->desc)
|
||
|
XFREE(MTYPE_TMP, pl->desc);
|
||
|
|
||
|
return NB_OK;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* XPath: /frr-filter:lib/prefix-list/entry
|
||
|
*/
|
||
|
static int lib_prefix_list_entry_create(struct nb_cb_create_args *args)
|
||
|
{
|
||
|
struct prefix_list_entry *ple;
|
||
|
struct prefix_list *pl;
|
||
|
|
||
|
if (args->event != NB_EV_APPLY)
|
||
|
return NB_OK;
|
||
|
|
||
|
pl = nb_running_get_entry(args->dnode, NULL, true);
|
||
|
ple = prefix_list_entry_new();
|
||
|
ple->pl = pl;
|
||
|
ple->seq = yang_dnode_get_uint32(args->dnode, "sequence");
|
||
|
prefix_list_entry_set_empty(ple);
|
||
|
nb_running_set_entry(args->dnode, ple);
|
||
|
|
||
|
return NB_OK;
|
||
|
}
|
||
|
|
||
|
static int lib_prefix_list_entry_destroy(struct nb_cb_destroy_args *args)
|
||
|
{
|
||
|
struct prefix_list_entry *ple;
|
||
|
|
||
|
if (args->event != NB_EV_APPLY)
|
||
|
return NB_OK;
|
||
|
|
||
|
ple = nb_running_unset_entry(args->dnode);
|
||
|
if (ple->installed)
|
||
|
prefix_list_entry_delete2(ple);
|
||
|
else
|
||
|
prefix_list_entry_free(ple);
|
||
|
|
||
|
return NB_OK;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
lib_prefix_list_entry_apply_finish(struct nb_cb_apply_finish_args *args)
|
||
|
{
|
||
|
struct prefix_list_entry *ple;
|
||
|
|
||
|
ple = nb_running_get_entry(args->dnode, NULL, true);
|
||
|
|
||
|
/*
|
||
|
* Finish prefix entry update procedure. The procedure is started in
|
||
|
* children callbacks. `prefix_list_entry_update_start` can be called
|
||
|
* multiple times if multiple children are modified, but it is actually
|
||
|
* executed only once because of the protection by `ple->installed`.
|
||
|
*/
|
||
|
prefix_list_entry_update_finish(ple);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* XPath: /frr-filter:lib/prefix-list/entry/action
|
||
|
*/
|
||
|
static int lib_prefix_list_entry_action_modify(struct nb_cb_modify_args *args)
|
||
|
{
|
||
|
struct prefix_list_entry *ple;
|
||
|
int action_type;
|
||
|
|
||
|
if (args->event != NB_EV_APPLY)
|
||
|
return NB_OK;
|
||
|
|
||
|
ple = nb_running_get_entry(args->dnode, NULL, true);
|
||
|
|
||
|
/* Start prefix entry update procedure. */
|
||
|
prefix_list_entry_update_start(ple);
|
||
|
|
||
|
action_type = yang_dnode_get_enum(args->dnode, NULL);
|
||
|
if (action_type == YPLA_PERMIT)
|
||
|
ple->type = PREFIX_PERMIT;
|
||
|
else
|
||
|
ple->type = PREFIX_DENY;
|
||
|
|
||
|
return NB_OK;
|
||
|
}
|
||
|
|
||
|
static int lib_prefix_list_entry_prefix_modify(struct nb_cb_modify_args *args)
|
||
|
{
|
||
|
struct prefix_list_entry *ple;
|
||
|
struct prefix p;
|
||
|
|
||
|
if (args->event != NB_EV_APPLY)
|
||
|
return NB_OK;
|
||
|
|
||
|
ple = nb_running_get_entry(args->dnode, NULL, true);
|
||
|
|
||
|
/* Start prefix entry update procedure. */
|
||
|
prefix_list_entry_update_start(ple);
|
||
|
|
||
|
yang_dnode_get_prefix(&ple->prefix, args->dnode, NULL);
|
||
|
|
||
|
/* Apply mask and correct original address if necessary. */
|
||
|
prefix_copy(&p, &ple->prefix);
|
||
|
apply_mask(&p);
|
||
|
if (!prefix_same(&ple->prefix, &p)) {
|
||
|
zlog_info("%s: bad network %pFX correcting it to %pFX",
|
||
|
__func__, &ple->prefix, &p);
|
||
|
prefix_copy(&ple->prefix, &p);
|
||
|
}
|
||
|
|
||
|
return NB_OK;
|
||
|
}
|
||
|
|
||
|
static int lib_prefix_list_entry_prefix_destroy(struct nb_cb_destroy_args *args)
|
||
|
{
|
||
|
struct prefix_list_entry *ple;
|
||
|
|
||
|
if (args->event != NB_EV_APPLY)
|
||
|
return NB_OK;
|
||
|
|
||
|
ple = nb_running_get_entry(args->dnode, NULL, true);
|
||
|
|
||
|
/* Start prefix entry update procedure. */
|
||
|
prefix_list_entry_update_start(ple);
|
||
|
|
||
|
memset(&ple->prefix, 0, sizeof(ple->prefix));
|
||
|
|
||
|
return NB_OK;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* XPath: /frr-filter:lib/prefix-list/entry/ipv4-prefix
|
||
|
*/
|
||
|
static int
|
||
|
lib_prefix_list_entry_ipv4_prefix_modify(struct nb_cb_modify_args *args)
|
||
|
{
|
||
|
if (args->event == NB_EV_VALIDATE) {
|
||
|
const struct lyd_node *plist_dnode =
|
||
|
yang_dnode_get_parent(args->dnode, "prefix-list");
|
||
|
|
||
|
return prefix_list_nb_validate_v4_af_type(
|
||
|
plist_dnode, args->errmsg, args->errmsg_len);
|
||
|
}
|
||
|
|
||
|
return lib_prefix_list_entry_prefix_modify(args);
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
lib_prefix_list_entry_ipv4_prefix_destroy(struct nb_cb_destroy_args *args)
|
||
|
{
|
||
|
|
||
|
if (args->event != NB_EV_APPLY)
|
||
|
return NB_OK;
|
||
|
|
||
|
return lib_prefix_list_entry_prefix_destroy(args);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* XPath: /frr-filter:lib/prefix-list/entry/ipv6-prefix
|
||
|
*/
|
||
|
static int
|
||
|
lib_prefix_list_entry_ipv6_prefix_modify(struct nb_cb_modify_args *args)
|
||
|
{
|
||
|
|
||
|
if (args->event == NB_EV_VALIDATE) {
|
||
|
const struct lyd_node *plist_dnode =
|
||
|
yang_dnode_get_parent(args->dnode, "prefix-list");
|
||
|
|
||
|
return prefix_list_nb_validate_v6_af_type(
|
||
|
plist_dnode, args->errmsg, args->errmsg_len);
|
||
|
}
|
||
|
|
||
|
return lib_prefix_list_entry_prefix_modify(args);
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
lib_prefix_list_entry_ipv6_prefix_destroy(struct nb_cb_destroy_args *args)
|
||
|
{
|
||
|
|
||
|
if (args->event != NB_EV_APPLY)
|
||
|
return NB_OK;
|
||
|
|
||
|
return lib_prefix_list_entry_prefix_destroy(args);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* XPath: /frr-filter:lib/prefix-list/entry/ipv4-prefix-length-greater-or-equal
|
||
|
*/
|
||
|
static int lib_prefix_list_entry_ipv4_prefix_length_greater_or_equal_modify(
|
||
|
struct nb_cb_modify_args *args)
|
||
|
{
|
||
|
if (args->event == NB_EV_VALIDATE
|
||
|
&& prefix_list_length_validate(args) != NB_OK)
|
||
|
return NB_ERR_VALIDATION;
|
||
|
|
||
|
if (args->event == NB_EV_VALIDATE) {
|
||
|
const struct lyd_node *plist_dnode =
|
||
|
yang_dnode_get_parent(args->dnode, "prefix-list");
|
||
|
|
||
|
return prefix_list_nb_validate_v4_af_type(
|
||
|
plist_dnode, args->errmsg, args->errmsg_len);
|
||
|
}
|
||
|
|
||
|
return lib_prefix_list_entry_prefix_length_greater_or_equal_modify(
|
||
|
args);
|
||
|
}
|
||
|
|
||
|
static int lib_prefix_list_entry_ipv4_prefix_length_greater_or_equal_destroy(
|
||
|
struct nb_cb_destroy_args *args)
|
||
|
{
|
||
|
if (args->event == NB_EV_VALIDATE) {
|
||
|
const struct lyd_node *plist_dnode =
|
||
|
yang_dnode_get_parent(args->dnode, "prefix-list");
|
||
|
|
||
|
return prefix_list_nb_validate_v4_af_type(
|
||
|
plist_dnode, args->errmsg, args->errmsg_len);
|
||
|
}
|
||
|
|
||
|
return lib_prefix_list_entry_prefix_length_greater_or_equal_destroy(
|
||
|
args);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* XPath: /frr-filter:lib/prefix-list/entry/ipv4-prefix-length-lesser-or-equal
|
||
|
*/
|
||
|
static int lib_prefix_list_entry_ipv4_prefix_length_lesser_or_equal_modify(
|
||
|
struct nb_cb_modify_args *args)
|
||
|
{
|
||
|
if (args->event == NB_EV_VALIDATE
|
||
|
&& prefix_list_length_validate(args) != NB_OK)
|
||
|
return NB_ERR_VALIDATION;
|
||
|
|
||
|
if (args->event == NB_EV_VALIDATE) {
|
||
|
const struct lyd_node *plist_dnode =
|
||
|
yang_dnode_get_parent(args->dnode, "prefix-list");
|
||
|
|
||
|
return prefix_list_nb_validate_v4_af_type(
|
||
|
plist_dnode, args->errmsg, args->errmsg_len);
|
||
|
}
|
||
|
|
||
|
return lib_prefix_list_entry_prefix_length_lesser_or_equal_modify(
|
||
|
args);
|
||
|
}
|
||
|
|
||
|
static int lib_prefix_list_entry_ipv4_prefix_length_lesser_or_equal_destroy(
|
||
|
struct nb_cb_destroy_args *args)
|
||
|
{
|
||
|
if (args->event == NB_EV_VALIDATE) {
|
||
|
const struct lyd_node *plist_dnode =
|
||
|
yang_dnode_get_parent(args->dnode, "prefix-list");
|
||
|
|
||
|
return prefix_list_nb_validate_v4_af_type(
|
||
|
plist_dnode, args->errmsg, args->errmsg_len);
|
||
|
}
|
||
|
|
||
|
return lib_prefix_list_entry_prefix_length_lesser_or_equal_destroy(
|
||
|
args);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* XPath: /frr-filter:lib/prefix-list/entry/ipv6-prefix-length-greater-or-equal
|
||
|
*/
|
||
|
static int lib_prefix_list_entry_ipv6_prefix_length_greater_or_equal_modify(
|
||
|
struct nb_cb_modify_args *args)
|
||
|
{
|
||
|
if (args->event == NB_EV_VALIDATE
|
||
|
&& prefix_list_length_validate(args) != NB_OK)
|
||
|
return NB_ERR_VALIDATION;
|
||
|
|
||
|
if (args->event == NB_EV_VALIDATE) {
|
||
|
const struct lyd_node *plist_dnode =
|
||
|
yang_dnode_get_parent(args->dnode, "prefix-list");
|
||
|
|
||
|
return prefix_list_nb_validate_v6_af_type(
|
||
|
plist_dnode, args->errmsg, args->errmsg_len);
|
||
|
}
|
||
|
|
||
|
return lib_prefix_list_entry_prefix_length_greater_or_equal_modify(
|
||
|
args);
|
||
|
}
|
||
|
|
||
|
static int lib_prefix_list_entry_ipv6_prefix_length_greater_or_equal_destroy(
|
||
|
struct nb_cb_destroy_args *args)
|
||
|
{
|
||
|
if (args->event == NB_EV_VALIDATE) {
|
||
|
const struct lyd_node *plist_dnode =
|
||
|
yang_dnode_get_parent(args->dnode, "prefix-list");
|
||
|
|
||
|
return prefix_list_nb_validate_v6_af_type(
|
||
|
plist_dnode, args->errmsg, args->errmsg_len);
|
||
|
}
|
||
|
|
||
|
return lib_prefix_list_entry_prefix_length_greater_or_equal_destroy(
|
||
|
args);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* XPath: /frr-filter:lib/prefix-list/entry/ipv6-prefix-length-lesser-or-equal
|
||
|
*/
|
||
|
static int lib_prefix_list_entry_ipv6_prefix_length_lesser_or_equal_modify(
|
||
|
struct nb_cb_modify_args *args)
|
||
|
{
|
||
|
if (args->event == NB_EV_VALIDATE
|
||
|
&& prefix_list_length_validate(args) != NB_OK)
|
||
|
return NB_ERR_VALIDATION;
|
||
|
|
||
|
if (args->event == NB_EV_VALIDATE) {
|
||
|
const struct lyd_node *plist_dnode =
|
||
|
yang_dnode_get_parent(args->dnode, "prefix-list");
|
||
|
|
||
|
return prefix_list_nb_validate_v6_af_type(
|
||
|
plist_dnode, args->errmsg, args->errmsg_len);
|
||
|
}
|
||
|
|
||
|
return lib_prefix_list_entry_prefix_length_lesser_or_equal_modify(
|
||
|
args);
|
||
|
}
|
||
|
|
||
|
static int lib_prefix_list_entry_ipv6_prefix_length_lesser_or_equal_destroy(
|
||
|
struct nb_cb_destroy_args *args)
|
||
|
{
|
||
|
if (args->event == NB_EV_VALIDATE) {
|
||
|
const struct lyd_node *plist_dnode =
|
||
|
yang_dnode_get_parent(args->dnode, "prefix-list");
|
||
|
|
||
|
return prefix_list_nb_validate_v6_af_type(
|
||
|
plist_dnode, args->errmsg, args->errmsg_len);
|
||
|
}
|
||
|
|
||
|
return lib_prefix_list_entry_prefix_length_lesser_or_equal_destroy(
|
||
|
args);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* XPath: /frr-filter:lib/prefix-list/entry/any
|
||
|
*/
|
||
|
static int lib_prefix_list_entry_any_create(struct nb_cb_create_args *args)
|
||
|
{
|
||
|
struct prefix_list_entry *ple;
|
||
|
int type;
|
||
|
|
||
|
/*
|
||
|
* If we have gotten to this point, it's legal
|
||
|
*/
|
||
|
if (args->event == NB_EV_VALIDATE)
|
||
|
return NB_OK;
|
||
|
|
||
|
if (args->event != NB_EV_APPLY)
|
||
|
return NB_OK;
|
||
|
|
||
|
ple = nb_running_get_entry(args->dnode, NULL, true);
|
||
|
|
||
|
/* Start prefix entry update procedure. */
|
||
|
prefix_list_entry_update_start(ple);
|
||
|
|
||
|
ple->any = true;
|
||
|
|
||
|
/* Fill prefix struct from scratch. */
|
||
|
memset(&ple->prefix, 0, sizeof(ple->prefix));
|
||
|
|
||
|
type = yang_dnode_get_enum(args->dnode, "../../type");
|
||
|
switch (type) {
|
||
|
case YPLT_IPV4:
|
||
|
ple->prefix.family = AF_INET;
|
||
|
ple->ge = 0;
|
||
|
ple->le = IPV4_MAX_BITLEN;
|
||
|
break;
|
||
|
case YPLT_IPV6:
|
||
|
ple->prefix.family = AF_INET6;
|
||
|
ple->ge = 0;
|
||
|
ple->le = IPV6_MAX_BITLEN;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return NB_OK;
|
||
|
}
|
||
|
|
||
|
static int lib_prefix_list_entry_any_destroy(struct nb_cb_destroy_args *args)
|
||
|
{
|
||
|
struct prefix_list_entry *ple;
|
||
|
|
||
|
if (args->event != NB_EV_APPLY)
|
||
|
return NB_OK;
|
||
|
|
||
|
ple = nb_running_get_entry(args->dnode, NULL, true);
|
||
|
|
||
|
/* Start prefix entry update procedure. */
|
||
|
prefix_list_entry_update_start(ple);
|
||
|
|
||
|
ple->any = false;
|
||
|
|
||
|
return NB_OK;
|
||
|
}
|
||
|
|
||
|
/* clang-format off */
|
||
|
const struct frr_yang_module_info frr_filter_info = {
|
||
|
.name = "frr-filter",
|
||
|
.nodes = {
|
||
|
{
|
||
|
.xpath = "/frr-filter:lib/access-list",
|
||
|
.cbs = {
|
||
|
.create = lib_access_list_create,
|
||
|
.destroy = lib_access_list_destroy,
|
||
|
}
|
||
|
},
|
||
|
{
|
||
|
.xpath = "/frr-filter:lib/access-list/remark",
|
||
|
.cbs = {
|
||
|
.modify = lib_access_list_remark_modify,
|
||
|
.destroy = lib_access_list_remark_destroy,
|
||
|
.cli_show = access_list_remark_show,
|
||
|
}
|
||
|
},
|
||
|
{
|
||
|
.xpath = "/frr-filter:lib/access-list/entry",
|
||
|
.cbs = {
|
||
|
.create = lib_access_list_entry_create,
|
||
|
.destroy = lib_access_list_entry_destroy,
|
||
|
.apply_finish = lib_access_list_entry_apply_finish,
|
||
|
.cli_cmp = access_list_cmp,
|
||
|
.cli_show = access_list_show,
|
||
|
}
|
||
|
},
|
||
|
{
|
||
|
.xpath = "/frr-filter:lib/access-list/entry/action",
|
||
|
.cbs = {
|
||
|
.modify = lib_access_list_entry_action_modify,
|
||
|
}
|
||
|
},
|
||
|
{
|
||
|
.xpath = "/frr-filter:lib/access-list/entry/ipv4-prefix",
|
||
|
.cbs = {
|
||
|
.modify = lib_access_list_entry_ipv4_prefix_modify,
|
||
|
.destroy = lib_access_list_entry_ipv4_prefix_destroy,
|
||
|
}
|
||
|
},
|
||
|
{
|
||
|
.xpath = "/frr-filter:lib/access-list/entry/ipv4-exact-match",
|
||
|
.cbs = {
|
||
|
.modify = lib_access_list_entry_ipv4_exact_match_modify,
|
||
|
.destroy = lib_access_list_entry_ipv4_exact_match_destroy,
|
||
|
}
|
||
|
},
|
||
|
{
|
||
|
.xpath = "/frr-filter:lib/access-list/entry/host",
|
||
|
.cbs = {
|
||
|
.modify = lib_access_list_entry_host_modify,
|
||
|
.destroy = lib_access_list_entry_host_destroy,
|
||
|
}
|
||
|
},
|
||
|
{
|
||
|
.xpath = "/frr-filter:lib/access-list/entry/network",
|
||
|
.cbs = {
|
||
|
.create = lib_access_list_entry_network_create,
|
||
|
.destroy = lib_access_list_entry_network_destroy,
|
||
|
}
|
||
|
},
|
||
|
{
|
||
|
.xpath = "/frr-filter:lib/access-list/entry/network/address",
|
||
|
.cbs = {
|
||
|
.modify = lib_access_list_entry_network_address_modify,
|
||
|
}
|
||
|
},
|
||
|
{
|
||
|
.xpath = "/frr-filter:lib/access-list/entry/network/mask",
|
||
|
.cbs = {
|
||
|
.modify = lib_access_list_entry_network_mask_modify,
|
||
|
}
|
||
|
},
|
||
|
{
|
||
|
.xpath = "/frr-filter:lib/access-list/entry/source-any",
|
||
|
.cbs = {
|
||
|
.create = lib_access_list_entry_source_any_create,
|
||
|
.destroy = lib_access_list_entry_source_any_destroy,
|
||
|
}
|
||
|
},
|
||
|
{
|
||
|
.xpath = "/frr-filter:lib/access-list/entry/destination-host",
|
||
|
.cbs = {
|
||
|
.modify = lib_access_list_entry_destination_host_modify,
|
||
|
.destroy = lib_access_list_entry_destination_host_destroy,
|
||
|
}
|
||
|
},
|
||
|
{
|
||
|
.xpath = "/frr-filter:lib/access-list/entry/destination-network",
|
||
|
.cbs = {
|
||
|
.create = lib_access_list_entry_destination_network_create,
|
||
|
.destroy = lib_access_list_entry_destination_network_destroy,
|
||
|
}
|
||
|
},
|
||
|
{
|
||
|
.xpath = "/frr-filter:lib/access-list/entry/destination-network/address",
|
||
|
.cbs = {
|
||
|
.modify = lib_access_list_entry_destination_network_address_modify,
|
||
|
}
|
||
|
},
|
||
|
{
|
||
|
.xpath = "/frr-filter:lib/access-list/entry/destination-network/mask",
|
||
|
.cbs = {
|
||
|
.modify = lib_access_list_entry_destination_network_mask_modify,
|
||
|
}
|
||
|
},
|
||
|
{
|
||
|
.xpath = "/frr-filter:lib/access-list/entry/destination-any",
|
||
|
.cbs = {
|
||
|
.create = lib_access_list_entry_destination_any_create,
|
||
|
.destroy = lib_access_list_entry_destination_any_destroy,
|
||
|
}
|
||
|
},
|
||
|
{
|
||
|
.xpath = "/frr-filter:lib/access-list/entry/ipv6-prefix",
|
||
|
.cbs = {
|
||
|
.modify = lib_access_list_entry_ipv4_prefix_modify,
|
||
|
.destroy = lib_access_list_entry_ipv4_prefix_destroy,
|
||
|
}
|
||
|
},
|
||
|
{
|
||
|
.xpath = "/frr-filter:lib/access-list/entry/ipv6-exact-match",
|
||
|
.cbs = {
|
||
|
.modify = lib_access_list_entry_ipv4_exact_match_modify,
|
||
|
.destroy = lib_access_list_entry_ipv4_exact_match_destroy,
|
||
|
}
|
||
|
},
|
||
|
{
|
||
|
.xpath = "/frr-filter:lib/access-list/entry/mac",
|
||
|
.cbs = {
|
||
|
.modify = lib_access_list_entry_ipv4_prefix_modify,
|
||
|
.destroy = lib_access_list_entry_ipv4_prefix_destroy,
|
||
|
}
|
||
|
},
|
||
|
{
|
||
|
.xpath = "/frr-filter:lib/access-list/entry/any",
|
||
|
.cbs = {
|
||
|
.create = lib_access_list_entry_any_create,
|
||
|
.destroy = lib_access_list_entry_any_destroy,
|
||
|
}
|
||
|
},
|
||
|
{
|
||
|
.xpath = "/frr-filter:lib/prefix-list",
|
||
|
.cbs = {
|
||
|
.create = lib_prefix_list_create,
|
||
|
.destroy = lib_prefix_list_destroy,
|
||
|
}
|
||
|
},
|
||
|
{
|
||
|
.xpath = "/frr-filter:lib/prefix-list/remark",
|
||
|
.cbs = {
|
||
|
.modify = lib_prefix_list_remark_modify,
|
||
|
.destroy = lib_prefix_list_remark_destroy,
|
||
|
.cli_show = prefix_list_remark_show,
|
||
|
}
|
||
|
},
|
||
|
{
|
||
|
.xpath = "/frr-filter:lib/prefix-list/entry",
|
||
|
.cbs = {
|
||
|
.create = lib_prefix_list_entry_create,
|
||
|
.destroy = lib_prefix_list_entry_destroy,
|
||
|
.apply_finish = lib_prefix_list_entry_apply_finish,
|
||
|
.cli_cmp = prefix_list_cmp,
|
||
|
.cli_show = prefix_list_show,
|
||
|
}
|
||
|
},
|
||
|
{
|
||
|
.xpath = "/frr-filter:lib/prefix-list/entry/action",
|
||
|
.cbs = {
|
||
|
.modify = lib_prefix_list_entry_action_modify,
|
||
|
}
|
||
|
},
|
||
|
{
|
||
|
.xpath = "/frr-filter:lib/prefix-list/entry/ipv4-prefix",
|
||
|
.cbs = {
|
||
|
.modify = lib_prefix_list_entry_ipv4_prefix_modify,
|
||
|
.destroy = lib_prefix_list_entry_ipv4_prefix_destroy,
|
||
|
}
|
||
|
},
|
||
|
{
|
||
|
.xpath = "/frr-filter:lib/prefix-list/entry/ipv4-prefix-length-greater-or-equal",
|
||
|
.cbs = {
|
||
|
.modify = lib_prefix_list_entry_ipv4_prefix_length_greater_or_equal_modify,
|
||
|
.destroy = lib_prefix_list_entry_ipv4_prefix_length_greater_or_equal_destroy,
|
||
|
}
|
||
|
},
|
||
|
{
|
||
|
.xpath = "/frr-filter:lib/prefix-list/entry/ipv4-prefix-length-lesser-or-equal",
|
||
|
.cbs = {
|
||
|
.modify = lib_prefix_list_entry_ipv4_prefix_length_lesser_or_equal_modify,
|
||
|
.destroy = lib_prefix_list_entry_ipv4_prefix_length_lesser_or_equal_destroy,
|
||
|
}
|
||
|
},
|
||
|
{
|
||
|
.xpath = "/frr-filter:lib/prefix-list/entry/ipv6-prefix",
|
||
|
.cbs = {
|
||
|
.modify = lib_prefix_list_entry_ipv6_prefix_modify,
|
||
|
.destroy = lib_prefix_list_entry_ipv6_prefix_destroy,
|
||
|
}
|
||
|
},
|
||
|
{
|
||
|
.xpath = "/frr-filter:lib/prefix-list/entry/ipv6-prefix-length-greater-or-equal",
|
||
|
.cbs = {
|
||
|
.modify = lib_prefix_list_entry_ipv6_prefix_length_greater_or_equal_modify,
|
||
|
.destroy = lib_prefix_list_entry_ipv6_prefix_length_greater_or_equal_destroy,
|
||
|
}
|
||
|
},
|
||
|
{
|
||
|
.xpath = "/frr-filter:lib/prefix-list/entry/ipv6-prefix-length-lesser-or-equal",
|
||
|
.cbs = {
|
||
|
.modify = lib_prefix_list_entry_ipv6_prefix_length_lesser_or_equal_modify,
|
||
|
.destroy = lib_prefix_list_entry_ipv6_prefix_length_lesser_or_equal_destroy,
|
||
|
}
|
||
|
},
|
||
|
{
|
||
|
.xpath = "/frr-filter:lib/prefix-list/entry/any",
|
||
|
.cbs = {
|
||
|
.create = lib_prefix_list_entry_any_create,
|
||
|
.destroy = lib_prefix_list_entry_any_destroy,
|
||
|
}
|
||
|
},
|
||
|
{
|
||
|
.xpath = NULL,
|
||
|
},
|
||
|
}
|
||
|
};
|
||
|
|
||
|
const struct frr_yang_module_info frr_filter_cli_info = {
|
||
|
.name = "frr-filter",
|
||
|
.ignore_cfg_cbs = true,
|
||
|
.nodes = {
|
||
|
{
|
||
|
.xpath = "/frr-filter:lib/access-list/remark",
|
||
|
.cbs.cli_show = access_list_remark_show,
|
||
|
},
|
||
|
{
|
||
|
.xpath = "/frr-filter:lib/access-list/entry",
|
||
|
.cbs = {
|
||
|
.cli_cmp = access_list_cmp,
|
||
|
.cli_show = access_list_show,
|
||
|
}
|
||
|
},
|
||
|
{
|
||
|
.xpath = "/frr-filter:lib/prefix-list/remark",
|
||
|
.cbs.cli_show = prefix_list_remark_show,
|
||
|
},
|
||
|
{
|
||
|
.xpath = "/frr-filter:lib/prefix-list/entry",
|
||
|
.cbs = {
|
||
|
.cli_cmp = prefix_list_cmp,
|
||
|
.cli_show = prefix_list_show,
|
||
|
}
|
||
|
},
|
||
|
{
|
||
|
.xpath = NULL,
|
||
|
},
|
||
|
}
|
||
|
};
|