frr/zebra/zebra_nb_config.c
David Lamparter 38ea0258ae zebra: implement RFC8781 (NAT64 prefix in RAs)
This tells hosts on the subnet if (and which) NAT64 prefix is in use.
Useful for things like xlat464, or local dns64.

Updated from the previous -03 draft implementation.  (PLC field did not
exist before.)

Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
2025-04-15 14:20:05 +02:00

3966 lines
86 KiB
C

// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2019 Cumulus Networks, Inc.
* Chirag Shah
*/
#include <zebra.h>
#include "lib/admin_group.h"
#include "lib/affinitymap.h"
#include "lib/log.h"
#include "lib/northbound.h"
#include "lib/printfrr.h"
#include "libfrr.h"
#include "lib/command.h"
#include "lib/routemap.h"
#include "zebra/rtadv.h"
#include "zebra/zebra_nb.h"
#include "zebra/rib.h"
#include "zebra_nb.h"
#include "zebra/interface.h"
#include "zebra/connected.h"
#include "zebra/zebra_router.h"
#include "zebra/debug.h"
#include "zebra/zebra_vxlan_private.h"
#include "zebra/zebra_vxlan.h"
#include "zebra/zebra_evpn_mh.h"
#include "zebra/zebra_ptm.h"
#include "zebra/router-id.h"
#include "zebra/zebra_routemap.h"
#include "zebra/zebra_rnh.h"
#include "zebra/table_manager.h"
/*
* XPath: /frr-zebra:zebra/ip-forwarding
*/
int zebra_ip_forwarding_modify(struct nb_cb_modify_args *args)
{
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
/* TODO: implement me. */
break;
}
return NB_OK;
}
int zebra_ip_forwarding_destroy(struct nb_cb_destroy_args *args)
{
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
/* TODO: implement me. */
break;
}
return NB_OK;
}
/*
* XPath: /frr-zebra:zebra/ipv6-forwarding
*/
int zebra_ipv6_forwarding_modify(struct nb_cb_modify_args *args)
{
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
/* TODO: implement me. */
break;
}
return NB_OK;
}
int zebra_ipv6_forwarding_destroy(struct nb_cb_destroy_args *args)
{
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
/* TODO: implement me. */
break;
}
return NB_OK;
}
/*
* XPath: /frr-zebra:zebra/workqueue-hold-timer
*/
int zebra_workqueue_hold_timer_modify(struct nb_cb_modify_args *args)
{
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
/* TODO: implement me. */
break;
}
return NB_OK;
}
/*
* XPath: /frr-zebra:zebra/zapi-packets
*/
int zebra_zapi_packets_modify(struct nb_cb_modify_args *args)
{
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
/* TODO: implement me. */
break;
}
return NB_OK;
}
/*
* XPath: /frr-zebra:zebra/import-kernel-table/table-id
*/
int zebra_import_kernel_table_table_id_modify(struct nb_cb_modify_args *args)
{
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
/* TODO: implement me. */
break;
}
return NB_OK;
}
int zebra_import_kernel_table_table_id_destroy(struct nb_cb_destroy_args *args)
{
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
/* TODO: implement me. */
break;
}
return NB_OK;
}
/*
* XPath: /frr-zebra:zebra/import-kernel-table/distance
*/
int zebra_import_kernel_table_distance_modify(struct nb_cb_modify_args *args)
{
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
/* TODO: implement me. */
break;
}
return NB_OK;
}
/*
* XPath: /frr-zebra:zebra/import-kernel-table/route-map
*/
int zebra_import_kernel_table_route_map_modify(struct nb_cb_modify_args *args)
{
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
/* TODO: implement me. */
break;
}
return NB_OK;
}
int zebra_import_kernel_table_route_map_destroy(struct nb_cb_destroy_args *args)
{
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
/* TODO: implement me. */
break;
}
return NB_OK;
}
/*
* XPath: /frr-zebra:zebra/allow-external-route-update
*/
int zebra_allow_external_route_update_create(struct nb_cb_create_args *args)
{
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
/* TODO: implement me. */
break;
}
return NB_OK;
}
int zebra_allow_external_route_update_destroy(struct nb_cb_destroy_args *args)
{
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
/* TODO: implement me. */
break;
}
return NB_OK;
}
/*
* XPath: /frr-zebra:zebra/dplane-queue-limit
*/
int zebra_dplane_queue_limit_modify(struct nb_cb_modify_args *args)
{
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
/* TODO: implement me. */
break;
}
return NB_OK;
}
#if HAVE_BFDD == 0
/*
* XPath: /frr-zebra:zebra/ptm-enable
*/
int zebra_ptm_enable_modify(struct nb_cb_modify_args *args)
{
bool ptm;
if (args->event != NB_EV_APPLY)
return NB_OK;
ptm = yang_dnode_get_bool(args->dnode, NULL);
if (ptm)
zebra_global_ptm_enable();
else
zebra_global_ptm_disable();
return NB_OK;
}
#endif
/*
* XPath: /frr-zebra:zebra/route-map-delay
*/
int zebra_route_map_delay_modify(struct nb_cb_modify_args *args)
{
uint32_t delay = yang_dnode_get_uint32(args->dnode, NULL);
if (args->event != NB_EV_APPLY)
return NB_OK;
zebra_route_map_set_delay_timer(delay);
return NB_OK;
}
/*
* XPath: /frr-zebra:zebra/debugs/debug-events
*/
int zebra_debugs_debug_events_modify(struct nb_cb_modify_args *args)
{
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
/* TODO: implement me. */
break;
}
return NB_OK;
}
int zebra_debugs_debug_events_destroy(struct nb_cb_destroy_args *args)
{
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
/* TODO: implement me. */
break;
}
return NB_OK;
}
/*
* XPath: /frr-zebra:zebra/debugs/debug-zapi-send
*/
int zebra_debugs_debug_zapi_send_modify(struct nb_cb_modify_args *args)
{
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
/* TODO: implement me. */
break;
}
return NB_OK;
}
int zebra_debugs_debug_zapi_send_destroy(struct nb_cb_destroy_args *args)
{
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
/* TODO: implement me. */
break;
}
return NB_OK;
}
/*
* XPath: /frr-zebra:zebra/debugs/debug-zapi-recv
*/
int zebra_debugs_debug_zapi_recv_modify(struct nb_cb_modify_args *args)
{
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
/* TODO: implement me. */
break;
}
return NB_OK;
}
int zebra_debugs_debug_zapi_recv_destroy(struct nb_cb_destroy_args *args)
{
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
/* TODO: implement me. */
break;
}
return NB_OK;
}
/*
* XPath: /frr-zebra:zebra/debugs/debug-zapi-detail
*/
int zebra_debugs_debug_zapi_detail_modify(struct nb_cb_modify_args *args)
{
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
/* TODO: implement me. */
break;
}
return NB_OK;
}
int zebra_debugs_debug_zapi_detail_destroy(struct nb_cb_destroy_args *args)
{
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
/* TODO: implement me. */
break;
}
return NB_OK;
}
/*
* XPath: /frr-zebra:zebra/debugs/debug-kernel
*/
int zebra_debugs_debug_kernel_modify(struct nb_cb_modify_args *args)
{
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
/* TODO: implement me. */
break;
}
return NB_OK;
}
int zebra_debugs_debug_kernel_destroy(struct nb_cb_destroy_args *args)
{
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
/* TODO: implement me. */
break;
}
return NB_OK;
}
/*
* XPath: /frr-zebra:zebra/debugs/debug-kernel-msg-send
*/
int zebra_debugs_debug_kernel_msg_send_modify(struct nb_cb_modify_args *args)
{
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
/* TODO: implement me. */
break;
}
return NB_OK;
}
int zebra_debugs_debug_kernel_msg_send_destroy(struct nb_cb_destroy_args *args)
{
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
/* TODO: implement me. */
break;
}
return NB_OK;
}
/*
* XPath: /frr-zebra:zebra/debugs/debug-kernel-msg-recv
*/
int zebra_debugs_debug_kernel_msg_recv_modify(struct nb_cb_modify_args *args)
{
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
/* TODO: implement me. */
break;
}
return NB_OK;
}
int zebra_debugs_debug_kernel_msg_recv_destroy(struct nb_cb_destroy_args *args)
{
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
/* TODO: implement me. */
break;
}
return NB_OK;
}
/*
* XPath: /frr-zebra:zebra/debugs/debug-rib
*/
int zebra_debugs_debug_rib_modify(struct nb_cb_modify_args *args)
{
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
/* TODO: implement me. */
break;
}
return NB_OK;
}
int zebra_debugs_debug_rib_destroy(struct nb_cb_destroy_args *args)
{
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
/* TODO: implement me. */
break;
}
return NB_OK;
}
/*
* XPath: /frr-zebra:zebra/debugs/debug-rib-detail
*/
int zebra_debugs_debug_rib_detail_modify(struct nb_cb_modify_args *args)
{
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
/* TODO: implement me. */
break;
}
return NB_OK;
}
int zebra_debugs_debug_rib_detail_destroy(struct nb_cb_destroy_args *args)
{
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
/* TODO: implement me. */
break;
}
return NB_OK;
}
/*
* XPath: /frr-zebra:zebra/debugs/debug-fpm
*/
int zebra_debugs_debug_fpm_modify(struct nb_cb_modify_args *args)
{
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
/* TODO: implement me. */
break;
}
return NB_OK;
}
int zebra_debugs_debug_fpm_destroy(struct nb_cb_destroy_args *args)
{
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
/* TODO: implement me. */
break;
}
return NB_OK;
}
/*
* XPath: /frr-zebra:zebra/debugs/debug-nht
*/
int zebra_debugs_debug_nht_modify(struct nb_cb_modify_args *args)
{
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
/* TODO: implement me. */
break;
}
return NB_OK;
}
int zebra_debugs_debug_nht_destroy(struct nb_cb_destroy_args *args)
{
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
/* TODO: implement me. */
break;
}
return NB_OK;
}
/*
* XPath: /frr-zebra:zebra/debugs/debug-nht-detail
*/
int zebra_debugs_debug_nht_detail_modify(struct nb_cb_modify_args *args)
{
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
/* TODO: implement me. */
break;
}
return NB_OK;
}
int zebra_debugs_debug_nht_detail_destroy(struct nb_cb_destroy_args *args)
{
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
/* TODO: implement me. */
break;
}
return NB_OK;
}
/*
* XPath: /frr-zebra:zebra/debugs/debug-mpls
*/
int zebra_debugs_debug_mpls_modify(struct nb_cb_modify_args *args)
{
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
/* TODO: implement me. */
break;
}
return NB_OK;
}
int zebra_debugs_debug_mpls_destroy(struct nb_cb_destroy_args *args)
{
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
/* TODO: implement me. */
break;
}
return NB_OK;
}
/*
* XPath: /frr-zebra:zebra/debugs/debug-vxlan
*/
int zebra_debugs_debug_vxlan_modify(struct nb_cb_modify_args *args)
{
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
/* TODO: implement me. */
break;
}
return NB_OK;
}
int zebra_debugs_debug_vxlan_destroy(struct nb_cb_destroy_args *args)
{
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
/* TODO: implement me. */
break;
}
return NB_OK;
}
/*
* XPath: /frr-zebra:zebra/debugs/debug-pw
*/
int zebra_debugs_debug_pw_modify(struct nb_cb_modify_args *args)
{
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
/* TODO: implement me. */
break;
}
return NB_OK;
}
int zebra_debugs_debug_pw_destroy(struct nb_cb_destroy_args *args)
{
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
/* TODO: implement me. */
break;
}
return NB_OK;
}
/*
* XPath: /frr-zebra:zebra/debugs/debug-dplane
*/
int zebra_debugs_debug_dplane_modify(struct nb_cb_modify_args *args)
{
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
/* TODO: implement me. */
break;
}
return NB_OK;
}
int zebra_debugs_debug_dplane_destroy(struct nb_cb_destroy_args *args)
{
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
/* TODO: implement me. */
break;
}
return NB_OK;
}
/*
* XPath: /frr-zebra:zebra/debugs/debug-dplane-detail
*/
int zebra_debugs_debug_dplane_detail_modify(struct nb_cb_modify_args *args)
{
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
/* TODO: implement me. */
break;
}
return NB_OK;
}
int zebra_debugs_debug_dplane_detail_destroy(struct nb_cb_destroy_args *args)
{
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
/* TODO: implement me. */
break;
}
return NB_OK;
}
/*
* XPath: /frr-zebra:zebra/debugs/debug-mlag
*/
int zebra_debugs_debug_mlag_modify(struct nb_cb_modify_args *args)
{
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
/* TODO: implement me. */
break;
}
return NB_OK;
}
int zebra_debugs_debug_mlag_destroy(struct nb_cb_destroy_args *args)
{
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
/* TODO: implement me. */
break;
}
return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv4-addrs
*/
int lib_interface_zebra_ipv4_addrs_create(struct nb_cb_create_args *args)
{
struct interface *ifp;
struct prefix p;
const char *label = NULL;
p.family = AF_INET;
yang_dnode_get_ipv4(&p.u.prefix4, args->dnode, "ip");
p.prefixlen = yang_dnode_get_uint8(args->dnode, "prefix-length");
if (yang_dnode_exists(args->dnode, "label"))
label = yang_dnode_get_string(args->dnode, "label");
switch (args->event) {
case NB_EV_VALIDATE:
if (ipv4_martian(&p.u.prefix4)) {
snprintfrr(args->errmsg, args->errmsg_len,
"invalid address %pFX", &p);
return NB_ERR_VALIDATION;
}
break;
case NB_EV_PREPARE:
case NB_EV_ABORT:
break;
case NB_EV_APPLY:
ifp = nb_running_get_entry(args->dnode, NULL, true);
if_ip_address_install(ifp, &p, label, NULL);
/* set something for checking on label modify */
nb_running_set_entry(args->dnode, (void *)0x1);
break;
}
return NB_OK;
}
int lib_interface_zebra_ipv4_addrs_destroy(struct nb_cb_destroy_args *args)
{
struct interface *ifp;
struct prefix p;
p.family = AF_INET;
yang_dnode_get_ipv4(&p.u.prefix4, args->dnode, "ip");
p.prefixlen = yang_dnode_get_uint8(args->dnode, "prefix-length");
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
break;
case NB_EV_APPLY:
nb_running_unset_entry(args->dnode);
ifp = nb_running_get_entry(args->dnode, NULL, false);
if_ip_address_uninstall(ifp, &p, NULL);
break;
}
return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv4-addrs/label
*/
int lib_interface_zebra_ipv4_addrs_label_modify(struct nb_cb_modify_args *args)
{
switch (args->event) {
case NB_EV_VALIDATE:
if (nb_running_get_entry_non_rec(lyd_parent(args->dnode), NULL,
false)) {
snprintf(args->errmsg, args->errmsg_len,
"Changing label is not allowed");
return NB_ERR_VALIDATION;
}
break;
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
break;
}
return NB_OK;
}
int lib_interface_zebra_ipv4_addrs_label_destroy(struct nb_cb_destroy_args *args)
{
switch (args->event) {
case NB_EV_VALIDATE:
snprintf(args->errmsg, args->errmsg_len,
"Removing label is not allowed");
return NB_ERR_VALIDATION;
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
break;
}
return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv4-p2p-addrs
*/
int lib_interface_zebra_ipv4_p2p_addrs_create(struct nb_cb_create_args *args)
{
struct interface *ifp;
struct prefix p, pp;
const char *label = NULL;
p.family = AF_INET;
yang_dnode_get_ipv4(&p.u.prefix4, args->dnode, "ip");
p.prefixlen = 32;
pp.family = AF_INET;
yang_dnode_get_ipv4(&pp.u.prefix4, args->dnode, "peer-ip");
pp.prefixlen = yang_dnode_get_uint8(args->dnode, "peer-prefix-length");
if (yang_dnode_exists(args->dnode, "label"))
label = yang_dnode_get_string(args->dnode, "label");
switch (args->event) {
case NB_EV_VALIDATE:
if (ipv4_martian(&p.u.prefix4)) {
snprintfrr(args->errmsg, args->errmsg_len,
"invalid address %pFX", &p);
return NB_ERR_VALIDATION;
}
break;
case NB_EV_PREPARE:
case NB_EV_ABORT:
break;
case NB_EV_APPLY:
ifp = nb_running_get_entry(args->dnode, NULL, true);
if_ip_address_install(ifp, &p, label, &pp);
/* set something for checking on label modify */
nb_running_set_entry(args->dnode, (void *)0x1);
break;
}
return NB_OK;
}
int lib_interface_zebra_ipv4_p2p_addrs_destroy(struct nb_cb_destroy_args *args)
{
struct interface *ifp;
struct prefix p, pp;
p.family = AF_INET;
yang_dnode_get_ipv4(&p.u.prefix4, args->dnode, "ip");
p.prefixlen = 32;
pp.family = AF_INET;
yang_dnode_get_ipv4(&pp.u.prefix4, args->dnode, "peer-ip");
pp.prefixlen = yang_dnode_get_uint8(args->dnode, "peer-prefix-length");
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
break;
case NB_EV_APPLY:
nb_running_unset_entry(args->dnode);
ifp = nb_running_get_entry(args->dnode, NULL, false);
if_ip_address_uninstall(ifp, &p, &pp);
break;
}
return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv4-p2p-addrs/label
*/
int lib_interface_zebra_ipv4_p2p_addrs_label_modify(struct nb_cb_modify_args *args)
{
switch (args->event) {
case NB_EV_VALIDATE:
if (nb_running_get_entry_non_rec(lyd_parent(args->dnode), NULL,
false)) {
snprintf(args->errmsg, args->errmsg_len,
"Changing label is not allowed");
return NB_ERR_VALIDATION;
}
break;
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
break;
}
return NB_OK;
}
int lib_interface_zebra_ipv4_p2p_addrs_label_destroy(
struct nb_cb_destroy_args *args)
{
switch (args->event) {
case NB_EV_VALIDATE:
snprintf(args->errmsg, args->errmsg_len,
"Removing label is not allowed");
return NB_ERR_VALIDATION;
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
break;
}
return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-addrs
*/
int lib_interface_zebra_ipv6_addrs_create(struct nb_cb_create_args *args)
{
struct interface *ifp;
struct prefix p;
p.family = AF_INET6;
yang_dnode_get_ipv6(&p.u.prefix6, args->dnode, "ip");
p.prefixlen = yang_dnode_get_uint8(args->dnode, "prefix-length");
switch (args->event) {
case NB_EV_VALIDATE:
if (ipv6_martian(&p.u.prefix6)) {
snprintfrr(args->errmsg, args->errmsg_len,
"invalid address %pFX", &p);
return NB_ERR_VALIDATION;
}
break;
case NB_EV_PREPARE:
case NB_EV_ABORT:
break;
case NB_EV_APPLY:
ifp = nb_running_get_entry(args->dnode, NULL, true);
if_ipv6_address_install(ifp, &p);
break;
}
return NB_OK;
}
int lib_interface_zebra_ipv6_addrs_destroy(struct nb_cb_destroy_args *args)
{
struct interface *ifp;
struct prefix p;
p.family = AF_INET6;
yang_dnode_get_ipv6(&p.u.prefix6, args->dnode, "ip");
p.prefixlen = yang_dnode_get_uint8(args->dnode, "prefix-length");
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
break;
case NB_EV_APPLY:
ifp = nb_running_get_entry(args->dnode, NULL, false);
if_ipv6_address_uninstall(ifp, &p);
break;
}
return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/multicast
*/
int lib_interface_zebra_multicast_modify(struct nb_cb_modify_args *args)
{
if (args->event != NB_EV_APPLY)
return NB_OK;
struct interface *ifp;
bool multicast = yang_dnode_get_bool(args->dnode, NULL);
ifp = nb_running_get_entry(args->dnode, NULL, true);
if (multicast)
if_multicast_set(ifp);
else
if_multicast_unset(ifp);
return NB_OK;
}
int lib_interface_zebra_multicast_destroy(struct nb_cb_destroy_args *args)
{
if (args->event != NB_EV_APPLY)
return NB_OK;
struct interface *ifp;
struct zebra_if *zif;
ifp = nb_running_get_entry(args->dnode, NULL, true);
zif = ifp->info;
zif->multicast = IF_ZEBRA_DATA_UNSPEC;
return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/link-detect
*/
int lib_interface_zebra_link_detect_modify(struct nb_cb_modify_args *args)
{
if (args->event != NB_EV_APPLY)
return NB_OK;
struct interface *ifp;
bool link_detect;
ifp = nb_running_get_entry(args->dnode, NULL, true);
link_detect = yang_dnode_get_bool(args->dnode, NULL);
if_linkdetect(ifp, link_detect);
return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/enabled
*/
int lib_interface_zebra_enabled_modify(struct nb_cb_modify_args *args)
{
if (args->event != NB_EV_APPLY)
return NB_OK;
struct interface *ifp;
bool enabled;
ifp = nb_running_get_entry(args->dnode, NULL, true);
enabled = yang_dnode_get_bool(args->dnode, NULL);
if (enabled)
if_no_shutdown(ifp);
else
if_shutdown(ifp);
return NB_OK;
}
int lib_interface_zebra_enabled_destroy(struct nb_cb_destroy_args *args)
{
if (args->event != NB_EV_APPLY)
return NB_OK;
struct interface *ifp;
struct zebra_if *zif;
ifp = nb_running_get_entry(args->dnode, NULL, true);
zif = ifp->info;
zif->shutdown = IF_ZEBRA_DATA_UNSPEC;
return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/mpls
*/
int lib_interface_zebra_mpls_modify(struct nb_cb_modify_args *args)
{
struct interface *ifp;
bool mpls;
struct zebra_if *zif;
if (args->event != NB_EV_APPLY)
return NB_OK;
ifp = nb_running_get_entry(args->dnode, NULL, true);
zif = ifp->info;
mpls = yang_dnode_get_bool(args->dnode, NULL);
if (mpls)
zif->mpls_config = IF_ZEBRA_DATA_ON;
else
zif->mpls_config = IF_ZEBRA_DATA_OFF;
dplane_intf_mpls_modify_state(ifp, mpls);
return NB_OK;
}
int lib_interface_zebra_mpls_destroy(struct nb_cb_destroy_args *args)
{
struct interface *ifp;
struct zebra_if *zif;
if (args->event != NB_EV_APPLY)
return NB_OK;
ifp = nb_running_get_entry(args->dnode, NULL, true);
zif = ifp->info;
zif->mpls_config = IF_ZEBRA_DATA_UNSPEC;
/* keep the state as it is */
return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/bandwidth
*/
int lib_interface_zebra_bandwidth_modify(struct nb_cb_modify_args *args)
{
if (args->event != NB_EV_APPLY)
return NB_OK;
struct interface *ifp;
uint32_t bandwidth;
ifp = nb_running_get_entry(args->dnode, NULL, true);
bandwidth = yang_dnode_get_uint32(args->dnode, NULL);
ifp->bandwidth = bandwidth;
/* force protocols to recalculate routes due to cost change */
if (if_is_operative(ifp))
zebra_interface_up_update(ifp);
return NB_OK;
}
int lib_interface_zebra_bandwidth_destroy(struct nb_cb_destroy_args *args)
{
if (args->event != NB_EV_APPLY)
return NB_OK;
struct interface *ifp;
ifp = nb_running_get_entry(args->dnode, NULL, true);
ifp->bandwidth = 0;
/* force protocols to recalculate routes due to cost change */
if (if_is_operative(ifp))
zebra_interface_up_update(ifp);
return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/link-params
*/
int lib_interface_zebra_link_params_create(struct nb_cb_create_args *args)
{
struct interface *ifp;
if (args->event != NB_EV_APPLY)
return NB_OK;
ifp = nb_running_get_entry(args->dnode, NULL, true);
if_link_params_enable(ifp);
/*
* The interface is updated in the apply_finish callback after all
* parameters are set in the corresponding callbacks.
*/
return NB_OK;
}
int lib_interface_zebra_link_params_destroy(struct nb_cb_destroy_args *args)
{
struct interface *ifp;
if (args->event != NB_EV_APPLY)
return NB_OK;
ifp = nb_running_get_entry(args->dnode, NULL, true);
if_link_params_free(ifp);
if (if_is_operative(ifp))
zebra_interface_parameters_update(ifp);
return NB_OK;
}
void lib_interface_zebra_link_params_apply_finish(
struct nb_cb_apply_finish_args *args)
{
struct interface *ifp;
ifp = nb_running_get_entry(args->dnode, NULL, true);
if (if_is_operative(ifp))
zebra_interface_parameters_update(ifp);
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/link-params/metric
*/
int lib_interface_zebra_link_params_metric_modify(struct nb_cb_modify_args *args)
{
struct interface *ifp;
struct if_link_params *iflp;
uint32_t metric;
if (args->event != NB_EV_APPLY)
return NB_OK;
ifp = nb_running_get_entry(args->dnode, NULL, true);
iflp = if_link_params_get(ifp);
metric = yang_dnode_get_uint32(args->dnode, NULL);
link_param_cmd_set_uint32(ifp, &iflp->te_metric, LP_TE_METRIC, metric);
return NB_OK;
}
int lib_interface_zebra_link_params_metric_destroy(struct nb_cb_destroy_args *args)
{
struct interface *ifp;
if (args->event != NB_EV_APPLY)
return NB_OK;
ifp = nb_running_get_entry(args->dnode, NULL, true);
link_param_cmd_unset(ifp, LP_TE_METRIC);
return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/link-params/max-bandwidth
*/
int lib_interface_zebra_link_params_max_bandwidth_modify(
struct nb_cb_modify_args *args)
{
struct interface *ifp;
struct if_link_params *iflp;
float max_bw, res_bw, ava_bw, use_bw;
max_bw = yang_dnode_get_bandwidth_ieee_float32(args->dnode, NULL);
switch (args->event) {
case NB_EV_VALIDATE:
if (yang_dnode_exists(args->dnode, "../residual-bandwidth")) {
res_bw = yang_dnode_get_bandwidth_ieee_float32(
args->dnode, "../residual-bandwidth");
if (max_bw < res_bw) {
snprintfrr(args->errmsg, args->errmsg_len,
"max-bandwidth %f is less than residual-bandwidth %f",
max_bw, res_bw);
return NB_ERR_VALIDATION;
}
}
if (yang_dnode_exists(args->dnode, "../available-bandwidth")) {
ava_bw = yang_dnode_get_bandwidth_ieee_float32(
args->dnode, "../available-bandwidth");
if (max_bw < ava_bw) {
snprintfrr(args->errmsg, args->errmsg_len,
"max-bandwidth %f is less than available-bandwidth %f",
max_bw, ava_bw);
return NB_ERR_VALIDATION;
}
}
if (yang_dnode_exists(args->dnode, "../utilized-bandwidth")) {
use_bw = yang_dnode_get_bandwidth_ieee_float32(
args->dnode, "../utilized-bandwidth");
if (max_bw < use_bw) {
snprintfrr(args->errmsg, args->errmsg_len,
"max-bandwidth %f is less than utilized-bandwidth %f",
max_bw, use_bw);
return NB_ERR_VALIDATION;
}
}
break;
case NB_EV_PREPARE:
case NB_EV_ABORT:
break;
case NB_EV_APPLY:
ifp = nb_running_get_entry(args->dnode, NULL, true);
iflp = if_link_params_get(ifp);
link_param_cmd_set_float(ifp, &iflp->max_bw, LP_MAX_BW, max_bw);
break;
}
return NB_OK;
}
int lib_interface_zebra_link_params_max_bandwidth_destroy(
struct nb_cb_destroy_args *args)
{
if (args->event == NB_EV_VALIDATE) {
snprintfrr(args->errmsg, args->errmsg_len,
"Removing max-bandwidth is not allowed");
return NB_ERR_VALIDATION;
}
return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/link-params/max-reservable-bandwidth
*/
int lib_interface_zebra_link_params_max_reservable_bandwidth_modify(
struct nb_cb_modify_args *args)
{
struct interface *ifp;
struct if_link_params *iflp;
float max_rsv_bw;
if (args->event != NB_EV_APPLY)
return NB_OK;
max_rsv_bw = yang_dnode_get_bandwidth_ieee_float32(args->dnode, NULL);
ifp = nb_running_get_entry(args->dnode, NULL, true);
iflp = if_link_params_get(ifp);
link_param_cmd_set_float(ifp, &iflp->max_rsv_bw, LP_MAX_RSV_BW,
max_rsv_bw);
return NB_OK;
}
int lib_interface_zebra_link_params_max_reservable_bandwidth_destroy(
struct nb_cb_destroy_args *args)
{
if (args->event == NB_EV_VALIDATE) {
snprintfrr(args->errmsg, args->errmsg_len,
"Removing max-reservable-bandwidth is not allowed");
return NB_ERR_VALIDATION;
}
return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/link-params/unreserved-bandwidths/unreserved-bandwidth
*/
int lib_interface_zebra_link_params_unreserved_bandwidths_unreserved_bandwidth_create(
struct nb_cb_create_args *args)
{
struct interface *ifp;
struct if_link_params *iflp;
uint8_t priority;
float unrsv_bw;
if (args->event != NB_EV_APPLY)
return NB_OK;
priority = yang_dnode_get_uint8(args->dnode, "priority");
unrsv_bw = yang_dnode_get_bandwidth_ieee_float32(args->dnode,
"unreserved-bandwidth");
ifp = nb_running_get_entry(args->dnode, NULL, true);
iflp = if_link_params_get(ifp);
link_param_cmd_set_float(ifp, &iflp->unrsv_bw[priority], LP_UNRSV_BW,
unrsv_bw);
return NB_OK;
}
int lib_interface_zebra_link_params_unreserved_bandwidths_unreserved_bandwidth_destroy(
struct nb_cb_destroy_args *args)
{
if (args->event == NB_EV_VALIDATE) {
snprintfrr(args->errmsg, args->errmsg_len,
"Removing unreserved-bandwidth is not allowed");
return NB_ERR_VALIDATION;
}
return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/link-params/unreserved-bandwidths/unreserved-bandwidth/unreserved-bandwidth
*/
int lib_interface_zebra_link_params_unreserved_bandwidths_unreserved_bandwidth_unreserved_bandwidth_modify(
struct nb_cb_modify_args *args)
{
struct interface *ifp;
struct if_link_params *iflp;
uint8_t priority;
float unrsv_bw;
if (args->event != NB_EV_APPLY)
return NB_OK;
priority = yang_dnode_get_uint8(args->dnode, "../priority");
unrsv_bw = yang_dnode_get_bandwidth_ieee_float32(args->dnode, NULL);
ifp = nb_running_get_entry(args->dnode, NULL, true);
iflp = if_link_params_get(ifp);
link_param_cmd_set_float(ifp, &iflp->unrsv_bw[priority], LP_UNRSV_BW,
unrsv_bw);
return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/link-params/residual-bandwidth
*/
int lib_interface_zebra_link_params_residual_bandwidth_modify(
struct nb_cb_modify_args *args)
{
struct interface *ifp;
struct if_link_params *iflp;
float max_bw, res_bw;
res_bw = yang_dnode_get_bandwidth_ieee_float32(args->dnode, NULL);
switch (args->event) {
case NB_EV_VALIDATE:
if (yang_dnode_exists(args->dnode, "../max-bandwidth")) {
max_bw =
yang_dnode_get_bandwidth_ieee_float32(args->dnode,
"../max-bandwidth");
if (max_bw < res_bw) {
snprintfrr(args->errmsg, args->errmsg_len,
"max-bandwidth %f is less than residual-bandwidth %f",
max_bw, res_bw);
return NB_ERR_VALIDATION;
}
}
break;
case NB_EV_PREPARE:
case NB_EV_ABORT:
break;
case NB_EV_APPLY:
ifp = nb_running_get_entry(args->dnode, NULL, true);
iflp = if_link_params_get(ifp);
link_param_cmd_set_float(ifp, &iflp->res_bw, LP_RES_BW, res_bw);
break;
}
return NB_OK;
}
int lib_interface_zebra_link_params_residual_bandwidth_destroy(
struct nb_cb_destroy_args *args)
{
struct interface *ifp;
if (args->event != NB_EV_APPLY)
return NB_OK;
ifp = nb_running_get_entry(args->dnode, NULL, true);
link_param_cmd_unset(ifp, LP_RES_BW);
return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/link-params/available-bandwidth
*/
int lib_interface_zebra_link_params_available_bandwidth_modify(
struct nb_cb_modify_args *args)
{
struct interface *ifp;
struct if_link_params *iflp;
float max_bw, ava_bw;
ava_bw = yang_dnode_get_bandwidth_ieee_float32(args->dnode, NULL);
switch (args->event) {
case NB_EV_VALIDATE:
if (yang_dnode_exists(args->dnode, "../max-bandwidth")) {
max_bw =
yang_dnode_get_bandwidth_ieee_float32(args->dnode,
"../max-bandwidth");
if (max_bw < ava_bw) {
snprintfrr(args->errmsg, args->errmsg_len,
"max-bandwidth %f is less than available-bandwidth %f",
max_bw, ava_bw);
return NB_ERR_VALIDATION;
}
}
break;
case NB_EV_PREPARE:
case NB_EV_ABORT:
break;
case NB_EV_APPLY:
ifp = nb_running_get_entry(args->dnode, NULL, true);
iflp = if_link_params_get(ifp);
link_param_cmd_set_float(ifp, &iflp->ava_bw, LP_AVA_BW, ava_bw);
break;
}
return NB_OK;
}
int lib_interface_zebra_link_params_available_bandwidth_destroy(
struct nb_cb_destroy_args *args)
{
struct interface *ifp;
if (args->event != NB_EV_APPLY)
return NB_OK;
ifp = nb_running_get_entry(args->dnode, NULL, true);
link_param_cmd_unset(ifp, LP_AVA_BW);
return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/link-params/utilized-bandwidth
*/
int lib_interface_zebra_link_params_utilized_bandwidth_modify(
struct nb_cb_modify_args *args)
{
struct interface *ifp;
struct if_link_params *iflp;
float max_bw, use_bw;
use_bw = yang_dnode_get_bandwidth_ieee_float32(args->dnode, NULL);
switch (args->event) {
case NB_EV_VALIDATE:
if (yang_dnode_exists(args->dnode, "../max-bandwidth")) {
max_bw =
yang_dnode_get_bandwidth_ieee_float32(args->dnode,
"../max-bandwidth");
if (max_bw < use_bw) {
snprintfrr(args->errmsg, args->errmsg_len,
"max-bandwidth %f is less than utilized-bandwidth %f",
max_bw, use_bw);
return NB_ERR_VALIDATION;
}
}
break;
case NB_EV_PREPARE:
case NB_EV_ABORT:
break;
case NB_EV_APPLY:
ifp = nb_running_get_entry(args->dnode, NULL, true);
iflp = if_link_params_get(ifp);
link_param_cmd_set_float(ifp, &iflp->use_bw, LP_USE_BW, use_bw);
break;
}
return NB_OK;
}
int lib_interface_zebra_link_params_utilized_bandwidth_destroy(
struct nb_cb_destroy_args *args)
{
struct interface *ifp;
if (args->event != NB_EV_APPLY)
return NB_OK;
ifp = nb_running_get_entry(args->dnode, NULL, true);
link_param_cmd_unset(ifp, LP_USE_BW);
return NB_OK;
}
/*
* XPath:
* /frr-interface:lib/interface/frr-zebra:zebra/link-params/legacy-admin-group
*/
int lib_interface_zebra_legacy_admin_group_modify(
struct nb_cb_modify_args *args)
{
struct interface *ifp;
struct if_link_params *iflp;
uint32_t admin_group_value;
admin_group_value = yang_dnode_get_uint32(args->dnode, ".");
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
break;
case NB_EV_APPLY:
ifp = nb_running_get_entry(args->dnode, NULL, true);
iflp = if_link_params_get(ifp);
iflp->admin_grp = admin_group_value;
SET_PARAM(iflp, LP_ADM_GRP);
break;
}
return NB_OK;
}
int lib_interface_zebra_legacy_admin_group_destroy(
struct nb_cb_destroy_args *args)
{
struct interface *ifp;
struct if_link_params *iflp;
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
break;
case NB_EV_APPLY:
ifp = nb_running_get_entry(args->dnode, NULL, true);
iflp = if_link_params_get(ifp);
iflp->admin_grp = 0;
UNSET_PARAM(iflp, LP_ADM_GRP);
break;
}
return NB_OK;
}
/*
* XPath:
* /frr-interface:lib/interface/frr-zebra:zebra/link-params/affinities
*/
int lib_interface_zebra_affinities_create(struct nb_cb_create_args *args)
{
return NB_OK;
}
int lib_interface_zebra_affinities_destroy(struct nb_cb_destroy_args *args)
{
struct interface *ifp;
struct if_link_params *iflp;
if (args->event != NB_EV_APPLY)
return NB_OK;
ifp = nb_running_get_entry(args->dnode, NULL, true);
iflp = if_link_params_get(ifp);
iflp->admin_grp = 0;
UNSET_PARAM(iflp, LP_ADM_GRP);
admin_group_clear(&iflp->ext_admin_grp);
UNSET_PARAM(iflp, LP_EXTEND_ADM_GRP);
return NB_OK;
}
/*
* XPath:
* /frr-interface:lib/interface/frr-zebra:zebra/link-params/affinities/affinity
*/
int lib_interface_zebra_affinity_create(struct nb_cb_create_args *args)
{
struct interface *ifp;
const char *affname;
struct if_link_params *iflp;
struct affinity_map *affmap;
enum affinity_mode affinity_mode;
affname = yang_dnode_get_string(args->dnode, ".");
affinity_mode = yang_dnode_get_enum(args->dnode, "../../affinity-mode");
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
break;
case NB_EV_APPLY:
ifp = nb_running_get_entry(args->dnode, NULL, true);
iflp = if_link_params_get(ifp);
affmap = affinity_map_get(affname);
if (affmap->bit_position < 32 &&
(affinity_mode == AFFINITY_MODE_STANDARD ||
affinity_mode == AFFINITY_MODE_BOTH)) {
iflp->admin_grp |= 1 << affmap->bit_position;
SET_PARAM(iflp, LP_ADM_GRP);
}
if (affinity_mode == AFFINITY_MODE_EXTENDED ||
affinity_mode == AFFINITY_MODE_BOTH) {
admin_group_set(&iflp->ext_admin_grp,
affmap->bit_position);
SET_PARAM(iflp, LP_EXTEND_ADM_GRP);
}
break;
}
return NB_OK;
}
int lib_interface_zebra_affinity_destroy(struct nb_cb_destroy_args *args)
{
struct interface *ifp;
const char *affname;
struct if_link_params *iflp;
struct affinity_map *affmap;
enum affinity_mode affinity_mode;
affname = yang_dnode_get_string(args->dnode, ".");
affinity_mode = yang_dnode_get_enum(args->dnode, "../../affinity-mode");
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
break;
case NB_EV_APPLY:
ifp = nb_running_get_entry(args->dnode, NULL, true);
iflp = if_link_params_get(ifp);
affmap = affinity_map_get(affname);
if (affmap->bit_position < 32 &&
(affinity_mode == AFFINITY_MODE_STANDARD ||
affinity_mode == AFFINITY_MODE_BOTH)) {
iflp->admin_grp &= ~(1 << affmap->bit_position);
if (iflp->admin_grp == 0)
UNSET_PARAM(iflp, LP_ADM_GRP);
}
if (affinity_mode == AFFINITY_MODE_EXTENDED ||
affinity_mode == AFFINITY_MODE_BOTH) {
admin_group_unset(&iflp->ext_admin_grp,
affmap->bit_position);
if (admin_group_zero(&iflp->ext_admin_grp))
UNSET_PARAM(iflp, LP_EXTEND_ADM_GRP);
}
break;
}
return NB_OK;
}
/*
* XPath:
* /frr-interface:lib/interface/frr-zebra:zebra/link-params/affinity-mode
*/
int lib_interface_zebra_affinity_mode_modify(struct nb_cb_modify_args *args)
{
struct interface *ifp;
struct if_link_params *iflp;
enum affinity_mode affinity_mode;
affinity_mode = yang_dnode_get_enum(args->dnode, ".");
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
break;
case NB_EV_APPLY:
ifp = nb_running_get_entry(args->dnode, NULL, true);
iflp = if_link_params_get(ifp);
if (affinity_mode == AFFINITY_MODE_STANDARD) {
if (!IS_PARAM_SET(iflp, LP_ADM_GRP) &&
IS_PARAM_SET(iflp, LP_EXTEND_ADM_GRP)) {
iflp->admin_grp = admin_group_get_offset(
&iflp->ext_admin_grp, 0);
SET_PARAM(iflp, LP_ADM_GRP);
}
admin_group_clear(&iflp->ext_admin_grp);
UNSET_PARAM(iflp, LP_EXTEND_ADM_GRP);
}
if (affinity_mode == AFFINITY_MODE_EXTENDED) {
if (!IS_PARAM_SET(iflp, LP_EXTEND_ADM_GRP) &&
IS_PARAM_SET(iflp, LP_ADM_GRP)) {
admin_group_bulk_set(&iflp->ext_admin_grp,
iflp->admin_grp, 0);
SET_PARAM(iflp, LP_EXTEND_ADM_GRP);
}
iflp->admin_grp = 0;
UNSET_PARAM(iflp, LP_ADM_GRP);
}
if (affinity_mode == AFFINITY_MODE_BOTH) {
if (!IS_PARAM_SET(iflp, LP_EXTEND_ADM_GRP) &&
IS_PARAM_SET(iflp, LP_ADM_GRP)) {
admin_group_bulk_set(&iflp->ext_admin_grp,
iflp->admin_grp, 0);
SET_PARAM(iflp, LP_EXTEND_ADM_GRP);
} else if (!IS_PARAM_SET(iflp, LP_ADM_GRP) &&
IS_PARAM_SET(iflp, LP_EXTEND_ADM_GRP)) {
iflp->admin_grp = admin_group_get_offset(
&iflp->ext_admin_grp, 0);
SET_PARAM(iflp, LP_ADM_GRP);
}
}
break;
}
return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/link-params/neighbor
*/
int lib_interface_zebra_link_params_neighbor_create(struct nb_cb_create_args *args)
{
struct interface *ifp;
struct if_link_params *iflp;
struct in_addr ip;
uint32_t as;
if (args->event != NB_EV_APPLY)
return NB_OK;
as = yang_dnode_get_uint32(args->dnode, "remote-as");
yang_dnode_get_ipv4(&ip, args->dnode, "ipv4-remote-id");
ifp = nb_running_get_entry(args->dnode, NULL, true);
iflp = if_link_params_get(ifp);
iflp->rmt_as = as;
iflp->rmt_ip = ip;
SET_PARAM(iflp, LP_RMT_AS);
return NB_OK;
}
int lib_interface_zebra_link_params_neighbor_destroy(
struct nb_cb_destroy_args *args)
{
struct interface *ifp;
struct if_link_params *iflp;
if (args->event != NB_EV_APPLY)
return NB_OK;
ifp = nb_running_get_entry(args->dnode, NULL, true);
iflp = if_link_params_get(ifp);
iflp->rmt_as = 0;
iflp->rmt_ip.s_addr = 0;
UNSET_PARAM(iflp, LP_RMT_AS);
return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/link-params/neighbor/remote-as
*/
int lib_interface_zebra_link_params_neighbor_remote_as_modify(
struct nb_cb_modify_args *args)
{
struct interface *ifp;
struct if_link_params *iflp;
uint32_t as;
if (args->event != NB_EV_APPLY)
return NB_OK;
as = yang_dnode_get_uint32(args->dnode, NULL);
ifp = nb_running_get_entry(args->dnode, NULL, true);
iflp = if_link_params_get(ifp);
iflp->rmt_as = as;
return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/link-params/neighbor/ipv4-remote-id
*/
int lib_interface_zebra_link_params_neighbor_ipv4_remote_id_modify(
struct nb_cb_modify_args *args)
{
struct interface *ifp;
struct if_link_params *iflp;
struct in_addr ip;
if (args->event != NB_EV_APPLY)
return NB_OK;
yang_dnode_get_ipv4(&ip, args->dnode, NULL);
ifp = nb_running_get_entry(args->dnode, NULL, true);
iflp = if_link_params_get(ifp);
iflp->rmt_ip = ip;
return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/link-params/delay
*/
int lib_interface_zebra_link_params_delay_modify(struct nb_cb_modify_args *args)
{
struct interface *ifp;
struct if_link_params *iflp;
uint32_t delay;
if (args->event != NB_EV_APPLY)
return NB_OK;
delay = yang_dnode_get_uint32(args->dnode, NULL);
ifp = nb_running_get_entry(args->dnode, NULL, true);
iflp = if_link_params_get(ifp);
link_param_cmd_set_uint32(ifp, &iflp->av_delay, LP_DELAY, delay);
return NB_OK;
}
int lib_interface_zebra_link_params_delay_destroy(struct nb_cb_destroy_args *args)
{
struct interface *ifp;
struct if_link_params *iflp;
if (args->event != NB_EV_APPLY)
return NB_OK;
ifp = nb_running_get_entry(args->dnode, NULL, true);
iflp = if_link_params_get(ifp);
iflp->av_delay = 0;
link_param_cmd_unset(ifp, LP_DELAY);
return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/link-params/min-max-delay
*/
int lib_interface_zebra_link_params_min_max_delay_create(
struct nb_cb_create_args *args)
{
struct interface *ifp;
struct if_link_params *iflp;
uint32_t delay_min, delay_max;
if (args->event != NB_EV_APPLY)
return NB_OK;
delay_min = yang_dnode_get_uint32(args->dnode, "delay-min");
delay_max = yang_dnode_get_uint32(args->dnode, "delay-max");
ifp = nb_running_get_entry(args->dnode, NULL, true);
iflp = if_link_params_get(ifp);
iflp->min_delay = delay_min;
iflp->max_delay = delay_max;
SET_PARAM(iflp, LP_MM_DELAY);
return NB_OK;
}
int lib_interface_zebra_link_params_min_max_delay_destroy(
struct nb_cb_destroy_args *args)
{
struct interface *ifp;
struct if_link_params *iflp;
if (args->event != NB_EV_APPLY)
return NB_OK;
ifp = nb_running_get_entry(args->dnode, NULL, true);
iflp = if_link_params_get(ifp);
iflp->min_delay = 0;
iflp->max_delay = 0;
UNSET_PARAM(iflp, LP_MM_DELAY);
return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/link-params/min-max-delay/delay-min
*/
int lib_interface_zebra_link_params_min_max_delay_delay_min_modify(
struct nb_cb_modify_args *args)
{
struct interface *ifp;
struct if_link_params *iflp;
uint32_t delay_min;
if (args->event != NB_EV_APPLY)
return NB_OK;
delay_min = yang_dnode_get_uint32(args->dnode, NULL);
ifp = nb_running_get_entry(args->dnode, NULL, true);
iflp = if_link_params_get(ifp);
iflp->min_delay = delay_min;
return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/link-params/min-max-delay/delay-max
*/
int lib_interface_zebra_link_params_min_max_delay_delay_max_modify(
struct nb_cb_modify_args *args)
{
struct interface *ifp;
struct if_link_params *iflp;
uint32_t delay_max;
if (args->event != NB_EV_APPLY)
return NB_OK;
delay_max = yang_dnode_get_uint32(args->dnode, NULL);
ifp = nb_running_get_entry(args->dnode, NULL, true);
iflp = if_link_params_get(ifp);
iflp->max_delay = delay_max;
return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/link-params/delay-variation
*/
int lib_interface_zebra_link_params_delay_variation_modify(
struct nb_cb_modify_args *args)
{
struct interface *ifp;
struct if_link_params *iflp;
uint32_t delay_var;
if (args->event != NB_EV_APPLY)
return NB_OK;
delay_var = yang_dnode_get_uint32(args->dnode, NULL);
ifp = nb_running_get_entry(args->dnode, NULL, true);
iflp = if_link_params_get(ifp);
link_param_cmd_set_uint32(ifp, &iflp->delay_var, LP_DELAY_VAR,
delay_var);
return NB_OK;
}
int lib_interface_zebra_link_params_delay_variation_destroy(
struct nb_cb_destroy_args *args)
{
struct interface *ifp;
if (args->event != NB_EV_APPLY)
return NB_OK;
ifp = nb_running_get_entry(args->dnode, NULL, true);
link_param_cmd_unset(ifp, LP_DELAY_VAR);
return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/link-params/packet-loss
*/
int lib_interface_zebra_link_params_packet_loss_modify(
struct nb_cb_modify_args *args)
{
struct interface *ifp;
struct if_link_params *iflp;
double packet_loss;
uint32_t value;
if (args->event != NB_EV_APPLY)
return NB_OK;
packet_loss = yang_dnode_get_dec64(args->dnode, NULL);
value = (uint32_t)(packet_loss / LOSS_PRECISION);
ifp = nb_running_get_entry(args->dnode, NULL, true);
iflp = if_link_params_get(ifp);
link_param_cmd_set_uint32(ifp, &iflp->pkt_loss, LP_PKT_LOSS, value);
return NB_OK;
}
int lib_interface_zebra_link_params_packet_loss_destroy(
struct nb_cb_destroy_args *args)
{
struct interface *ifp;
if (args->event != NB_EV_APPLY)
return NB_OK;
ifp = nb_running_get_entry(args->dnode, NULL, true);
link_param_cmd_unset(ifp, LP_PKT_LOSS);
return NB_OK;
}
static bool evpn_mh_dnode_to_esi(const struct lyd_node *dnode, esi_t *esi)
{
if (yang_dnode_exists(dnode, "type-0/esi")) {
if (!str_to_esi(yang_dnode_get_string(dnode, "type-0/esi"), esi))
assert(false);
} else if (yang_dnode_exists(dnode, "type-3/system-mac") &&
yang_dnode_exists(dnode, "type-3/local-discriminator")) {
struct ethaddr mac;
uint32_t lid;
yang_dnode_get_mac(&mac, dnode, "type-3/system-mac");
lid = yang_dnode_get_uint32(dnode, "type-3/local-discriminator");
zebra_build_type3_esi(lid, &mac, esi);
} else {
return false;
}
return true;
}
struct esi_cmp_iter_arg {
struct lyd_node *dnode;
esi_t esi;
bool exists;
};
static int esi_cmp_iter_cb(const struct lyd_node *dnode, void *arg)
{
struct esi_cmp_iter_arg *iter = arg;
esi_t esi;
if (dnode == iter->dnode)
return YANG_ITER_CONTINUE;
if (!evpn_mh_dnode_to_esi(dnode, &esi))
return YANG_ITER_CONTINUE;
if (!memcmp(&esi, &iter->esi, ESI_BYTES)) {
iter->exists = true;
return YANG_ITER_STOP;
}
return YANG_ITER_CONTINUE;
}
/* evpn-mh should be passed to this function */
static bool esi_unique(struct lyd_node *dnode)
{
struct esi_cmp_iter_arg iter;
iter.dnode = dnode;
evpn_mh_dnode_to_esi(dnode, &iter.esi);
iter.exists = false;
yang_dnode_iterate(esi_cmp_iter_cb, &iter, dnode,
"/frr-interface:lib/interface/frr-zebra:zebra/evpn-mh");
if (iter.exists)
return false;
return true;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/evpn-mh/type-0
*/
int lib_interface_zebra_evpn_mh_type_0_create(struct nb_cb_create_args *args)
{
return NB_OK;
}
int lib_interface_zebra_evpn_mh_type_0_destroy(struct nb_cb_destroy_args *args)
{
struct interface *ifp;
if (args->event != NB_EV_APPLY)
return NB_OK;
ifp = nb_running_get_entry(args->dnode, NULL, true);
zebra_evpn_es_type0_esi_update(ifp->info, NULL);
return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/evpn-mh/type-0/esi
*/
int lib_interface_zebra_evpn_mh_type_0_esi_modify(struct nb_cb_modify_args *args)
{
struct interface *ifp;
esi_t esi;
switch (args->event) {
case NB_EV_VALIDATE:
if (!esi_unique(lyd_parent(lyd_parent(args->dnode)))) {
snprintfrr(args->errmsg, args->errmsg_len,
"ESI already exists on a different interface");
return NB_ERR_VALIDATION;
}
break;
case NB_EV_PREPARE:
case NB_EV_ABORT:
break;
case NB_EV_APPLY:
ifp = nb_running_get_entry(args->dnode, NULL, true);
if (!str_to_esi(yang_dnode_get_string(args->dnode, NULL), &esi))
assert(false);
zebra_evpn_es_type0_esi_update(ifp->info, &esi);
break;
}
return NB_OK;
}
int lib_interface_zebra_evpn_mh_type_0_esi_destroy(struct nb_cb_destroy_args *args)
{
struct interface *ifp;
if (args->event != NB_EV_APPLY)
return NB_OK;
ifp = nb_running_get_entry(args->dnode, NULL, true);
zebra_evpn_es_type0_esi_update(ifp->info, NULL);
return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/evpn-mh/type-3
*/
int lib_interface_zebra_evpn_mh_type_3_create(struct nb_cb_create_args *args)
{
return NB_OK;
}
int lib_interface_zebra_evpn_mh_type_3_destroy(struct nb_cb_destroy_args *args)
{
struct interface *ifp;
if (args->event != NB_EV_APPLY)
return NB_OK;
ifp = nb_running_get_entry(args->dnode, NULL, true);
zebra_evpn_es_sys_mac_update(ifp->info, NULL);
zebra_evpn_es_lid_update(ifp->info, 0);
return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/evpn-mh/type-3/system-mac
*/
int lib_interface_zebra_evpn_mh_type_3_system_mac_modify(
struct nb_cb_modify_args *args)
{
struct interface *ifp;
struct ethaddr mac;
yang_dnode_get_mac(&mac, args->dnode, NULL);
switch (args->event) {
case NB_EV_VALIDATE:
if (is_zero_mac(&mac)) {
snprintfrr(args->errmsg, args->errmsg_len,
"MAC cannot be all-zeroes");
return NB_ERR_VALIDATION;
}
if (!esi_unique(lyd_parent(lyd_parent(args->dnode)))) {
snprintfrr(args->errmsg, args->errmsg_len,
"ESI already exists on a different interface");
return NB_ERR_VALIDATION;
}
break;
case NB_EV_PREPARE:
case NB_EV_ABORT:
break;
case NB_EV_APPLY:
ifp = nb_running_get_entry(args->dnode, NULL, true);
zebra_evpn_es_sys_mac_update(ifp->info, &mac);
break;
}
return NB_OK;
}
int lib_interface_zebra_evpn_mh_type_3_system_mac_destroy(
struct nb_cb_destroy_args *args)
{
struct interface *ifp;
if (args->event != NB_EV_APPLY)
return NB_OK;
ifp = nb_running_get_entry(args->dnode, NULL, true);
zebra_evpn_es_sys_mac_update(ifp->info, NULL);
return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/evpn-mh/type-3/local-discriminator
*/
int lib_interface_zebra_evpn_mh_type_3_local_discriminator_modify(
struct nb_cb_modify_args *args)
{
struct interface *ifp;
uint32_t lid;
switch (args->event) {
case NB_EV_VALIDATE:
if (!esi_unique(lyd_parent(lyd_parent(args->dnode)))) {
snprintfrr(args->errmsg, args->errmsg_len,
"ESI already exists on a different interface");
return NB_ERR_VALIDATION;
}
break;
case NB_EV_PREPARE:
case NB_EV_ABORT:
break;
case NB_EV_APPLY:
ifp = nb_running_get_entry(args->dnode, NULL, true);
lid = yang_dnode_get_uint32(args->dnode, NULL);
zebra_evpn_es_lid_update(ifp->info, lid);
break;
}
return NB_OK;
}
int lib_interface_zebra_evpn_mh_type_3_local_discriminator_destroy(
struct nb_cb_destroy_args *args)
{
struct interface *ifp;
if (args->event != NB_EV_APPLY)
return NB_OK;
ifp = nb_running_get_entry(args->dnode, NULL, true);
zebra_evpn_es_lid_update(ifp->info, 0);
return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/evpn-mh/df-preference
*/
int lib_interface_zebra_evpn_mh_df_preference_modify(
struct nb_cb_modify_args *args)
{
struct interface *ifp;
uint16_t df_pref;
if (args->event != NB_EV_APPLY)
return NB_OK;
ifp = nb_running_get_entry(args->dnode, NULL, true);
df_pref = yang_dnode_get_uint16(args->dnode, NULL);
zebra_evpn_es_df_pref_update(ifp->info, df_pref);
return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/evpn-mh/bypass
*/
int lib_interface_zebra_evpn_mh_bypass_modify(struct nb_cb_modify_args *args)
{
struct interface *ifp;
bool bypass;
if (args->event != NB_EV_APPLY)
return NB_OK;
ifp = nb_running_get_entry(args->dnode, NULL, true);
bypass = yang_dnode_get_bool(args->dnode, NULL);
zebra_evpn_es_bypass_cfg_update(ifp->info, bypass);
return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/evpn-mh/uplink
*/
int lib_interface_zebra_evpn_mh_uplink_modify(struct nb_cb_modify_args *args)
{
struct interface *ifp;
bool uplink;
if (args->event != NB_EV_APPLY)
return NB_OK;
ifp = nb_running_get_entry(args->dnode, NULL, true);
uplink = yang_dnode_get_bool(args->dnode, NULL);
zebra_evpn_mh_uplink_cfg_update(ifp->info, uplink);
return NB_OK;
}
#if defined(HAVE_RTADV)
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/send-advertisements
*/
int lib_interface_zebra_ipv6_router_advertisements_send_advertisements_modify(
struct nb_cb_modify_args *args)
{
struct interface *ifp;
struct zebra_if *zif;
bool send_adv;
if (args->event != NB_EV_APPLY)
return NB_OK;
ifp = nb_running_get_entry(args->dnode, NULL, true);
zif = ifp->info;
send_adv = yang_dnode_get_bool(args->dnode, NULL);
if (send_adv) {
ipv6_nd_suppress_ra_set(ifp, RA_ENABLE);
SET_FLAG(zif->rtadv.ra_configured, VTY_RA_CONFIGURED);
} else {
if (!CHECK_FLAG(zif->rtadv.ra_configured, BGP_RA_CONFIGURED))
ipv6_nd_suppress_ra_set(ifp, RA_SUPPRESS);
UNSET_FLAG(zif->rtadv.ra_configured, VTY_RA_CONFIGURED);
}
return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/max-rtr-adv-interval
*/
int lib_interface_zebra_ipv6_router_advertisements_max_rtr_adv_interval_modify(
struct nb_cb_modify_args *args)
{
struct interface *ifp;
uint32_t interval;
if (args->event != NB_EV_APPLY)
return NB_OK;
ifp = nb_running_get_entry(args->dnode, NULL, true);
interval = yang_dnode_get_uint32(args->dnode, NULL);
ipv6_nd_interval_set(ifp, interval);
return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/managed-flag
*/
int lib_interface_zebra_ipv6_router_advertisements_managed_flag_modify(
struct nb_cb_modify_args *args)
{
struct interface *ifp;
struct zebra_if *zif;
bool managed_flag;
if (args->event != NB_EV_APPLY)
return NB_OK;
ifp = nb_running_get_entry(args->dnode, NULL, true);
zif = ifp->info;
managed_flag = yang_dnode_get_bool(args->dnode, NULL);
zif->rtadv.AdvManagedFlag = managed_flag;
return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/other-config-flag
*/
int lib_interface_zebra_ipv6_router_advertisements_other_config_flag_modify(
struct nb_cb_modify_args *args)
{
struct interface *ifp;
struct zebra_if *zif;
bool other_config_flag;
if (args->event != NB_EV_APPLY)
return NB_OK;
ifp = nb_running_get_entry(args->dnode, NULL, true);
zif = ifp->info;
other_config_flag = yang_dnode_get_bool(args->dnode, NULL);
zif->rtadv.AdvOtherConfigFlag = other_config_flag;
return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/home-agent-flag
*/
int lib_interface_zebra_ipv6_router_advertisements_home_agent_flag_modify(
struct nb_cb_modify_args *args)
{
struct interface *ifp;
struct zebra_if *zif;
bool home_agent_flag;
if (args->event != NB_EV_APPLY)
return NB_OK;
ifp = nb_running_get_entry(args->dnode, NULL, true);
zif = ifp->info;
home_agent_flag = yang_dnode_get_bool(args->dnode, NULL);
zif->rtadv.AdvHomeAgentFlag = home_agent_flag;
return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/link-mtu
*/
int lib_interface_zebra_ipv6_router_advertisements_link_mtu_modify(
struct nb_cb_modify_args *args)
{
struct interface *ifp;
struct zebra_if *zif;
uint32_t mtu;
if (args->event != NB_EV_APPLY)
return NB_OK;
ifp = nb_running_get_entry(args->dnode, NULL, true);
zif = ifp->info;
mtu = yang_dnode_get_uint32(args->dnode, NULL);
zif->rtadv.AdvLinkMTU = mtu;
return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/reachable-time
*/
int lib_interface_zebra_ipv6_router_advertisements_reachable_time_modify(
struct nb_cb_modify_args *args)
{
struct interface *ifp;
struct zebra_if *zif;
uint32_t time;
if (args->event != NB_EV_APPLY)
return NB_OK;
ifp = nb_running_get_entry(args->dnode, NULL, true);
zif = ifp->info;
time = yang_dnode_get_uint32(args->dnode, NULL);
zif->rtadv.AdvReachableTime = time;
return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/retrans-timer
*/
int lib_interface_zebra_ipv6_router_advertisements_retrans_timer_modify(
struct nb_cb_modify_args *args)
{
struct interface *ifp;
struct zebra_if *zif;
uint32_t timer;
if (args->event != NB_EV_APPLY)
return NB_OK;
ifp = nb_running_get_entry(args->dnode, NULL, true);
zif = ifp->info;
timer = yang_dnode_get_uint32(args->dnode, NULL);
zif->rtadv.AdvRetransTimer = timer;
return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/cur-hop-limit
*/
int lib_interface_zebra_ipv6_router_advertisements_cur_hop_limit_modify(
struct nb_cb_modify_args *args)
{
struct interface *ifp;
struct zebra_if *zif;
uint8_t limit;
if (args->event != NB_EV_APPLY)
return NB_OK;
ifp = nb_running_get_entry(args->dnode, NULL, true);
zif = ifp->info;
limit = yang_dnode_get_uint8(args->dnode, NULL);
zif->rtadv.AdvCurHopLimit = limit;
return NB_OK;
}
int lib_interface_zebra_ipv6_router_advertisements_cur_hop_limit_destroy(
struct nb_cb_destroy_args *args)
{
struct interface *ifp;
struct zebra_if *zif;
if (args->event != NB_EV_APPLY)
return NB_OK;
ifp = nb_running_get_entry(args->dnode, NULL, true);
zif = ifp->info;
zif->rtadv.AdvCurHopLimit = RTADV_DEFAULT_HOPLIMIT;
return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/default-lifetime
*/
int lib_interface_zebra_ipv6_router_advertisements_default_lifetime_modify(
struct nb_cb_modify_args *args)
{
struct interface *ifp;
struct zebra_if *zif;
uint16_t lifetime;
if (args->event != NB_EV_APPLY)
return NB_OK;
ifp = nb_running_get_entry(args->dnode, NULL, true);
zif = ifp->info;
lifetime = yang_dnode_get_uint16(args->dnode, NULL);
zif->rtadv.AdvDefaultLifetime = lifetime;
return NB_OK;
}
int lib_interface_zebra_ipv6_router_advertisements_default_lifetime_destroy(
struct nb_cb_destroy_args *args)
{
struct interface *ifp;
struct zebra_if *zif;
if (args->event != NB_EV_APPLY)
return NB_OK;
ifp = nb_running_get_entry(args->dnode, NULL, true);
zif = ifp->info;
zif->rtadv.AdvDefaultLifetime = -1;
return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/fast-retransmit
*/
int lib_interface_zebra_ipv6_router_advertisements_fast_retransmit_modify(
struct nb_cb_modify_args *args)
{
struct interface *ifp;
struct zebra_if *zif;
bool fast_retransmit;
if (args->event != NB_EV_APPLY)
return NB_OK;
ifp = nb_running_get_entry(args->dnode, NULL, true);
zif = ifp->info;
fast_retransmit = yang_dnode_get_bool(args->dnode, NULL);
zif->rtadv.UseFastRexmit = fast_retransmit;
return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/advertisement-interval-option
*/
int lib_interface_zebra_ipv6_router_advertisements_advertisement_interval_option_modify(
struct nb_cb_modify_args *args)
{
struct interface *ifp;
struct zebra_if *zif;
bool option;
if (args->event != NB_EV_APPLY)
return NB_OK;
ifp = nb_running_get_entry(args->dnode, NULL, true);
zif = ifp->info;
option = yang_dnode_get_bool(args->dnode, NULL);
zif->rtadv.AdvIntervalOption = option;
return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/home-agent-preference
*/
int lib_interface_zebra_ipv6_router_advertisements_home_agent_preference_modify(
struct nb_cb_modify_args *args)
{
struct interface *ifp;
struct zebra_if *zif;
uint16_t preference;
if (args->event != NB_EV_APPLY)
return NB_OK;
ifp = nb_running_get_entry(args->dnode, NULL, true);
zif = ifp->info;
preference = yang_dnode_get_uint16(args->dnode, NULL);
zif->rtadv.HomeAgentPreference = preference;
return NB_OK;
}
int lib_interface_zebra_ipv6_router_advertisements_home_agent_preference_destroy(
struct nb_cb_destroy_args *args)
{
struct interface *ifp;
struct zebra_if *zif;
if (args->event != NB_EV_APPLY)
return NB_OK;
ifp = nb_running_get_entry(args->dnode, NULL, true);
zif = ifp->info;
zif->rtadv.HomeAgentPreference = 0;
return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/home-agent-lifetime
*/
int lib_interface_zebra_ipv6_router_advertisements_home_agent_lifetime_modify(
struct nb_cb_modify_args *args)
{
struct interface *ifp;
struct zebra_if *zif;
uint16_t lifetime;
if (args->event != NB_EV_APPLY)
return NB_OK;
ifp = nb_running_get_entry(args->dnode, NULL, true);
zif = ifp->info;
lifetime = yang_dnode_get_uint16(args->dnode, NULL);
zif->rtadv.HomeAgentLifetime = lifetime;
return NB_OK;
}
int lib_interface_zebra_ipv6_router_advertisements_home_agent_lifetime_destroy(
struct nb_cb_destroy_args *args)
{
struct interface *ifp;
struct zebra_if *zif;
if (args->event != NB_EV_APPLY)
return NB_OK;
ifp = nb_running_get_entry(args->dnode, NULL, true);
zif = ifp->info;
zif->rtadv.HomeAgentLifetime = -1;
return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/default-router-preference
*/
int lib_interface_zebra_ipv6_router_advertisements_default_router_preference_modify(
struct nb_cb_modify_args *args)
{
struct interface *ifp;
struct zebra_if *zif;
int preference;
if (args->event != NB_EV_APPLY)
return NB_OK;
ifp = nb_running_get_entry(args->dnode, NULL, true);
zif = ifp->info;
preference = yang_dnode_get_enum(args->dnode, NULL);
zif->rtadv.DefaultPreference = preference;
return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/prefix-list/prefix
*/
int lib_interface_zebra_ipv6_router_advertisements_prefix_list_prefix_create(
struct nb_cb_create_args *args)
{
struct interface *ifp;
struct rtadv_prefix rp, *prefix;
if (args->event != NB_EV_APPLY)
return NB_OK;
ifp = nb_running_get_entry(args->dnode, NULL, true);
yang_dnode_get_ipv6p(&rp.prefix, args->dnode, "prefix-spec");
rp.AdvOnLinkFlag = yang_dnode_get_bool(args->dnode, "on-link-flag");
rp.AdvAutonomousFlag = yang_dnode_get_bool(args->dnode,
"autonomous-flag");
rp.AdvRouterAddressFlag = yang_dnode_get_bool(args->dnode,
"router-address-flag");
rp.AdvValidLifetime = yang_dnode_get_uint32(args->dnode,
"valid-lifetime");
rp.AdvPreferredLifetime = yang_dnode_get_uint32(args->dnode,
"preferred-lifetime");
prefix = rtadv_add_prefix_manual(ifp->info, &rp);
nb_running_set_entry(args->dnode, prefix);
return NB_OK;
}
int lib_interface_zebra_ipv6_router_advertisements_prefix_list_prefix_destroy(
struct nb_cb_destroy_args *args)
{
struct interface *ifp;
struct rtadv_prefix *prefix;
if (args->event != NB_EV_APPLY)
return NB_OK;
prefix = nb_running_unset_entry(args->dnode);
ifp = nb_running_get_entry(args->dnode, NULL, true);
rtadv_delete_prefix_manual(ifp->info, prefix);
return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/prefix-list/prefix/valid-lifetime
*/
int lib_interface_zebra_ipv6_router_advertisements_prefix_list_prefix_valid_lifetime_modify(
struct nb_cb_modify_args *args)
{
struct rtadv_prefix *prefix;
if (args->event != NB_EV_APPLY)
return NB_OK;
prefix = nb_running_get_entry(args->dnode, NULL, true);
prefix->AdvValidLifetime = yang_dnode_get_uint32(args->dnode, NULL);
return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/prefix-list/prefix/on-link-flag
*/
int lib_interface_zebra_ipv6_router_advertisements_prefix_list_prefix_on_link_flag_modify(
struct nb_cb_modify_args *args)
{
struct rtadv_prefix *prefix;
if (args->event != NB_EV_APPLY)
return NB_OK;
prefix = nb_running_get_entry(args->dnode, NULL, true);
prefix->AdvOnLinkFlag = yang_dnode_get_bool(args->dnode, NULL);
return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/prefix-list/prefix/preferred-lifetime
*/
int lib_interface_zebra_ipv6_router_advertisements_prefix_list_prefix_preferred_lifetime_modify(
struct nb_cb_modify_args *args)
{
struct rtadv_prefix *prefix;
if (args->event != NB_EV_APPLY)
return NB_OK;
prefix = nb_running_get_entry(args->dnode, NULL, true);
prefix->AdvPreferredLifetime = yang_dnode_get_uint32(args->dnode, NULL);
return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/prefix-list/prefix/autonomous-flag
*/
int lib_interface_zebra_ipv6_router_advertisements_prefix_list_prefix_autonomous_flag_modify(
struct nb_cb_modify_args *args)
{
struct rtadv_prefix *prefix;
if (args->event != NB_EV_APPLY)
return NB_OK;
prefix = nb_running_get_entry(args->dnode, NULL, true);
prefix->AdvAutonomousFlag = yang_dnode_get_bool(args->dnode, NULL);
return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/prefix-list/prefix/router-address-flag
*/
int lib_interface_zebra_ipv6_router_advertisements_prefix_list_prefix_router_address_flag_modify(
struct nb_cb_modify_args *args)
{
struct rtadv_prefix *prefix;
if (args->event != NB_EV_APPLY)
return NB_OK;
prefix = nb_running_get_entry(args->dnode, NULL, true);
prefix->AdvRouterAddressFlag = yang_dnode_get_bool(args->dnode, NULL);
return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/rdnss/rdnss-address
*/
int lib_interface_zebra_ipv6_router_advertisements_rdnss_rdnss_address_create(
struct nb_cb_create_args *args)
{
struct interface *ifp;
struct rtadv_rdnss rdnss = {{{{0}}}}, *p;
if (args->event != NB_EV_APPLY)
return NB_OK;
ifp = nb_running_get_entry(args->dnode, NULL, true);
yang_dnode_get_ipv6(&rdnss.addr, args->dnode, "address");
if (yang_dnode_exists(args->dnode, "lifetime")) {
rdnss.lifetime = yang_dnode_get_uint32(args->dnode, "lifetime");
rdnss.lifetime_set = 1;
} else {
rdnss.lifetime_set = 0;
}
p = rtadv_rdnss_set(ifp->info, &rdnss);
nb_running_set_entry(args->dnode, p);
return NB_OK;
}
int lib_interface_zebra_ipv6_router_advertisements_rdnss_rdnss_address_destroy(
struct nb_cb_destroy_args *args)
{
struct interface *ifp;
struct rtadv_rdnss *p;
if (args->event != NB_EV_APPLY)
return NB_OK;
p = nb_running_unset_entry(args->dnode);
ifp = nb_running_get_entry(args->dnode, NULL, true);
rtadv_rdnss_reset(ifp->info, p);
return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/rdnss/rdnss-address/lifetime
*/
int lib_interface_zebra_ipv6_router_advertisements_rdnss_rdnss_address_lifetime_modify(
struct nb_cb_modify_args *args)
{
struct rtadv_rdnss *p;
if (args->event != NB_EV_APPLY)
return NB_OK;
p = nb_running_get_entry(args->dnode, NULL, true);
p->lifetime = yang_dnode_get_uint32(args->dnode, NULL);
p->lifetime_set = 1;
return NB_OK;
}
int lib_interface_zebra_ipv6_router_advertisements_rdnss_rdnss_address_lifetime_destroy(
struct nb_cb_destroy_args *args)
{
struct rtadv_rdnss *p;
if (args->event != NB_EV_APPLY)
return NB_OK;
p = nb_running_get_entry(args->dnode, NULL, true);
p->lifetime_set = 0;
return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/dnssl/dnssl-domain
*/
int lib_interface_zebra_ipv6_router_advertisements_dnssl_dnssl_domain_create(
struct nb_cb_create_args *args)
{
struct interface *ifp;
struct rtadv_dnssl dnssl = {{0}}, *p;
int ret;
strlcpy(dnssl.name, yang_dnode_get_string(args->dnode, "domain"),
sizeof(dnssl.name));
ret = rtadv_dnssl_encode(dnssl.encoded_name, dnssl.name);
dnssl.encoded_len = ret;
if (args->event == NB_EV_VALIDATE) {
if (ret < 0) {
snprintfrr(args->errmsg, args->errmsg_len,
"Malformed DNS search domain");
return NB_ERR_VALIDATION;
}
}
if (args->event != NB_EV_APPLY)
return NB_OK;
ifp = nb_running_get_entry(args->dnode, NULL, true);
if (yang_dnode_exists(args->dnode, "lifetime")) {
dnssl.lifetime = yang_dnode_get_uint32(args->dnode, "lifetime");
dnssl.lifetime_set = 1;
} else {
dnssl.lifetime_set = 0;
}
p = rtadv_dnssl_set(ifp->info, &dnssl);
nb_running_set_entry(args->dnode, p);
return NB_OK;
}
int lib_interface_zebra_ipv6_router_advertisements_dnssl_dnssl_domain_destroy(
struct nb_cb_destroy_args *args)
{
struct interface *ifp;
struct rtadv_dnssl *p;
if (args->event != NB_EV_APPLY)
return NB_OK;
p = nb_running_unset_entry(args->dnode);
ifp = nb_running_get_entry(args->dnode, NULL, true);
rtadv_dnssl_reset(ifp->info, p);
return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/dnssl/dnssl-domain/lifetime
*/
int lib_interface_zebra_ipv6_router_advertisements_dnssl_dnssl_domain_lifetime_modify(
struct nb_cb_modify_args *args)
{
struct rtadv_dnssl *p;
if (args->event != NB_EV_APPLY)
return NB_OK;
p = nb_running_get_entry(args->dnode, NULL, true);
p->lifetime = yang_dnode_get_uint32(args->dnode, NULL);
p->lifetime_set = 1;
return NB_OK;
}
int lib_interface_zebra_ipv6_router_advertisements_dnssl_dnssl_domain_lifetime_destroy(
struct nb_cb_destroy_args *args)
{
struct rtadv_dnssl *p;
if (args->event != NB_EV_APPLY)
return NB_OK;
p = nb_running_get_entry(args->dnode, NULL, true);
p->lifetime_set = 0;
return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/pref64/pref64-prefix
*/
int lib_interface_zebra_ipv6_router_advertisements_pref64_pref64_prefix_create(
struct nb_cb_create_args *args)
{
struct interface *ifp;
struct pref64_adv *entry;
struct prefix_ipv6 p;
uint32_t lifetime = PREF64_LIFETIME_AUTO;
if (args->event != NB_EV_APPLY)
return NB_OK;
ifp = nb_running_get_entry(args->dnode, NULL, true);
yang_dnode_get_ipv6p(&p, args->dnode, "prefix");
if (yang_dnode_exists(args->dnode, "lifetime"))
lifetime = yang_dnode_get_uint16(args->dnode, "lifetime");
entry = rtadv_pref64_set(ifp->info, &p, lifetime);
nb_running_set_entry(args->dnode, entry);
return NB_OK;
}
int lib_interface_zebra_ipv6_router_advertisements_pref64_pref64_prefix_destroy(
struct nb_cb_destroy_args *args)
{
struct interface *ifp;
struct pref64_adv *entry;
if (args->event != NB_EV_APPLY)
return NB_OK;
entry = nb_running_unset_entry(args->dnode);
ifp = nb_running_get_entry(args->dnode, NULL, true);
rtadv_pref64_reset(ifp->info, entry);
return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/rdnss/rdnss-address/lifetime
*/
int lib_interface_zebra_ipv6_router_advertisements_pref64_pref64_prefix_lifetime_modify(
struct nb_cb_modify_args *args)
{
struct interface *ifp;
struct pref64_adv *entry;
if (args->event != NB_EV_APPLY)
return NB_OK;
entry = nb_running_get_entry(args->dnode, NULL, true);
ifp = nb_running_get_entry(lyd_parent(lyd_parent(args->dnode)), NULL, true);
rtadv_pref64_update(ifp->info, entry, yang_dnode_get_uint16(args->dnode, NULL));
return NB_OK;
}
int lib_interface_zebra_ipv6_router_advertisements_pref64_pref64_prefix_lifetime_destroy(
struct nb_cb_destroy_args *args)
{
struct interface *ifp;
struct pref64_adv *entry;
if (args->event != NB_EV_APPLY)
return NB_OK;
entry = nb_running_get_entry(args->dnode, NULL, true);
ifp = nb_running_get_entry(lyd_parent(lyd_parent(args->dnode)), NULL, true);
rtadv_pref64_update(ifp->info, entry, PREF64_LIFETIME_AUTO);
return NB_OK;
}
#endif /* defined(HAVE_RTADV) */
#if HAVE_BFDD == 0
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/ptm-enable
*/
int lib_interface_zebra_ptm_enable_modify(struct nb_cb_modify_args *args)
{
struct interface *ifp;
bool ptm;
if (args->event != NB_EV_APPLY)
return NB_OK;
ifp = nb_running_get_entry(args->dnode, NULL, true);
ptm = yang_dnode_get_bool(args->dnode, NULL);
if (ptm)
zebra_if_ptm_enable(ifp);
else
zebra_if_ptm_disable(ifp);
return NB_OK;
}
#endif
/*
* XPath: /frr-vrf:lib/vrf/frr-zebra:zebra/router-id
*/
int lib_vrf_zebra_router_id_modify(struct nb_cb_modify_args *args)
{
struct vrf *vrf;
struct prefix p;
if (args->event != NB_EV_APPLY)
return NB_OK;
vrf = nb_running_get_entry(args->dnode, NULL, true);
yang_dnode_get_ipv4p(&p, args->dnode, NULL);
router_id_set(AFI_IP, &p, vrf->info);
return NB_OK;
}
int lib_vrf_zebra_router_id_destroy(struct nb_cb_destroy_args *args)
{
struct vrf *vrf;
struct prefix p;
if (args->event != NB_EV_APPLY)
return NB_OK;
vrf = nb_running_get_entry(args->dnode, NULL, true);
memset(&p, 0, sizeof(p));
p.family = AF_INET;
router_id_set(AFI_IP, &p, vrf->info);
return NB_OK;
}
/*
* XPath: /frr-vrf:lib/vrf/frr-zebra:zebra/ipv6-router-id
*/
int lib_vrf_zebra_ipv6_router_id_modify(struct nb_cb_modify_args *args)
{
struct vrf *vrf;
struct prefix p;
if (args->event != NB_EV_APPLY)
return NB_OK;
vrf = nb_running_get_entry(args->dnode, NULL, true);
yang_dnode_get_ipv6p(&p, args->dnode, NULL);
router_id_set(AFI_IP6, &p, vrf->info);
return NB_OK;
}
int lib_vrf_zebra_ipv6_router_id_destroy(struct nb_cb_destroy_args *args)
{
struct vrf *vrf;
struct prefix p;
if (args->event != NB_EV_APPLY)
return NB_OK;
vrf = nb_running_get_entry(args->dnode, NULL, true);
memset(&p, 0, sizeof(p));
p.family = AF_INET6;
router_id_set(AFI_IP6, &p, vrf->info);
return NB_OK;
}
/*
* XPath: /frr-vrf:lib/vrf/frr-zebra:zebra/filter-protocol
*/
int lib_vrf_zebra_filter_protocol_create(struct nb_cb_create_args *args)
{
const char *proto = yang_dnode_get_string(args->dnode, "protocol");
int rtype;
rtype = proto_name2num(proto);
if (args->event == NB_EV_VALIDATE)
if (rtype < 0) {
snprintfrr(args->errmsg, args->errmsg_len,
"invalid protocol name \"%s\"", proto);
return NB_ERR_VALIDATION;
}
/* the creation finishes in the apply_finish callback */
return NB_OK;
}
int lib_vrf_zebra_filter_protocol_destroy(struct nb_cb_destroy_args *args)
{
struct vrf *vrf;
const char *afi_safi = yang_dnode_get_string(args->dnode, "afi-safi");
const char *proto = yang_dnode_get_string(args->dnode, "protocol");
const char *rmap = yang_dnode_get_string(args->dnode, "route-map");
afi_t afi;
safi_t safi;
int rtype;
yang_afi_safi_identity2value(afi_safi, &afi, &safi);
rtype = proto_name2num(proto);
/* deleting an existing entry, it can't be invalid */
assert(rtype >= 0);
if (args->event != NB_EV_APPLY)
return NB_OK;
vrf = nb_running_get_entry(args->dnode, NULL, true);
ip_protocol_rm_del(vrf->info, rmap, rtype, afi, safi);
return NB_OK;
}
void lib_vrf_zebra_filter_protocol_apply_finish(
struct nb_cb_apply_finish_args *args)
{
struct vrf *vrf;
const char *afi_safi = yang_dnode_get_string(args->dnode, "afi-safi");
const char *proto = yang_dnode_get_string(args->dnode, "protocol");
const char *rmap = yang_dnode_get_string(args->dnode, "route-map");
afi_t afi;
safi_t safi;
int rtype;
yang_afi_safi_identity2value(afi_safi, &afi, &safi);
rtype = proto_name2num(proto);
/* finishing apply for a validated entry, it can't be invalid */
assert(rtype >= 0);
vrf = nb_running_get_entry(args->dnode, NULL, true);
ip_protocol_rm_add(vrf->info, rmap, rtype, afi, safi);
}
/*
* XPath: /frr-vrf:lib/vrf/frr-zebra:zebra/filter-protocol/route-map
*/
int lib_vrf_zebra_filter_protocol_route_map_modify(struct nb_cb_modify_args *args)
{
/* the update is done in the apply_finish callback */
return NB_OK;
}
/*
* XPath: /frr-vrf:lib/vrf/frr-zebra:zebra/filter-nht
*/
int lib_vrf_zebra_filter_nht_create(struct nb_cb_create_args *args)
{
const char *afi_safi = yang_dnode_get_string(args->dnode, "afi-safi");
const char *proto = yang_dnode_get_string(args->dnode, "protocol");
afi_t afi;
safi_t safi;
int rtype;
yang_afi_safi_identity2value(afi_safi, &afi, &safi);
if (strcasecmp(proto, "any") == 0)
rtype = ZEBRA_ROUTE_MAX;
else
rtype = proto_name2num(proto);
if (args->event == NB_EV_VALIDATE) {
if (rtype < 0) {
snprintfrr(args->errmsg, args->errmsg_len,
"invalid protocol name \"%s\"", proto);
return NB_ERR_VALIDATION;
}
if (safi != SAFI_UNICAST) {
snprintfrr(args->errmsg, args->errmsg_len,
"only SAFI unicast is supported");
return NB_ERR_VALIDATION;
}
}
/* the creation finishes in the apply_finish callback */
return NB_OK;
}
int lib_vrf_zebra_filter_nht_destroy(struct nb_cb_destroy_args *args)
{
struct vrf *vrf;
const char *afi_safi = yang_dnode_get_string(args->dnode, "afi-safi");
const char *proto = yang_dnode_get_string(args->dnode, "protocol");
const char *rmap = yang_dnode_get_string(args->dnode, "route-map");
afi_t afi;
safi_t safi;
int rtype;
yang_afi_safi_identity2value(afi_safi, &afi, &safi);
if (strcasecmp(proto, "any") == 0)
rtype = ZEBRA_ROUTE_MAX;
else
rtype = proto_name2num(proto);
/* deleting an existing entry, it can't be invalid */
assert(rtype >= 0);
assert(safi == SAFI_UNICAST);
if (args->event != NB_EV_APPLY)
return NB_OK;
vrf = nb_running_get_entry(args->dnode, NULL, true);
ip_nht_rm_del(vrf->info, rmap, rtype, afi);
return NB_OK;
}
void lib_vrf_zebra_filter_nht_apply_finish(struct nb_cb_apply_finish_args *args)
{
struct vrf *vrf;
const char *afi_safi = yang_dnode_get_string(args->dnode, "afi-safi");
const char *proto = yang_dnode_get_string(args->dnode, "protocol");
const char *rmap = yang_dnode_get_string(args->dnode, "route-map");
afi_t afi;
safi_t safi;
int rtype;
yang_afi_safi_identity2value(afi_safi, &afi, &safi);
if (strcasecmp(proto, "any") == 0)
rtype = ZEBRA_ROUTE_MAX;
else
rtype = proto_name2num(proto);
/* finishing apply for an existing entry, it can't be invalid */
assert(rtype >= 0);
assert(safi == SAFI_UNICAST);
vrf = nb_running_get_entry(args->dnode, NULL, true);
ip_nht_rm_add(vrf->info, rmap, rtype, afi);
}
/*
* XPath: /frr-vrf:lib/vrf/frr-zebra:zebra/filter-nht/route-map
*/
int lib_vrf_zebra_filter_nht_route_map_modify(struct nb_cb_modify_args *args)
{
/* the update is done in the apply_finish callback */
return NB_OK;
}
/*
* XPath: /frr-vrf:lib/vrf/frr-zebra:zebra/resolve-via-default
*/
int lib_vrf_zebra_resolve_via_default_modify(struct nb_cb_modify_args *args)
{
struct vrf *vrf;
struct zebra_vrf *zvrf;
bool resolve_via_default;
if (args->event != NB_EV_APPLY)
return NB_OK;
vrf = nb_running_get_entry(args->dnode, NULL, true);
zvrf = vrf->info;
resolve_via_default = yang_dnode_get_bool(args->dnode, NULL);
if (zvrf->zebra_rnh_ip_default_route == resolve_via_default)
return NB_OK;
zvrf->zebra_rnh_ip_default_route = resolve_via_default;
zebra_evaluate_rnh(zvrf, AFI_IP, 0, NULL, SAFI_UNICAST);
return NB_OK;
}
int lib_vrf_zebra_resolve_via_default_destroy(struct nb_cb_destroy_args *args)
{
struct vrf *vrf;
struct zebra_vrf *zvrf;
bool resolve_via_default;
if (args->event != NB_EV_APPLY)
return NB_OK;
vrf = nb_running_get_entry(args->dnode, NULL, true);
zvrf = vrf->info;
resolve_via_default = DFLT_ZEBRA_IP_NHT_RESOLVE_VIA_DEFAULT;
if (zvrf->zebra_rnh_ip_default_route == resolve_via_default)
return NB_OK;
zvrf->zebra_rnh_ip_default_route = resolve_via_default;
zebra_evaluate_rnh(zvrf, AFI_IP, 0, NULL, SAFI_UNICAST);
return NB_OK;
}
/*
* XPath: /frr-vrf:lib/vrf/frr-zebra:zebra/ipv6-resolve-via-default
*/
int lib_vrf_zebra_ipv6_resolve_via_default_modify(struct nb_cb_modify_args *args)
{
struct vrf *vrf;
struct zebra_vrf *zvrf;
bool resolve_via_default;
if (args->event != NB_EV_APPLY)
return NB_OK;
vrf = nb_running_get_entry(args->dnode, NULL, true);
zvrf = vrf->info;
resolve_via_default = yang_dnode_get_bool(args->dnode, NULL);
if (zvrf->zebra_rnh_ipv6_default_route == resolve_via_default)
return NB_OK;
zvrf->zebra_rnh_ipv6_default_route = resolve_via_default;
zebra_evaluate_rnh(zvrf, AFI_IP6, 0, NULL, SAFI_UNICAST);
return NB_OK;
}
int lib_vrf_zebra_ipv6_resolve_via_default_destroy(struct nb_cb_destroy_args *args)
{
struct vrf *vrf;
struct zebra_vrf *zvrf;
bool resolve_via_default;
if (args->event != NB_EV_APPLY)
return NB_OK;
vrf = nb_running_get_entry(args->dnode, NULL, true);
zvrf = vrf->info;
resolve_via_default = DFLT_ZEBRA_IP_NHT_RESOLVE_VIA_DEFAULT;
if (zvrf->zebra_rnh_ipv6_default_route == resolve_via_default)
return NB_OK;
zvrf->zebra_rnh_ipv6_default_route = resolve_via_default;
zebra_evaluate_rnh(zvrf, AFI_IP6, 0, NULL, SAFI_UNICAST);
return NB_OK;
}
/*
* XPath: /frr-vrf:lib/vrf/frr-zebra:zebra/netns/table-range
*/
static int table_range_validate(uint32_t start, uint32_t end, char *errmsg,
size_t errmsg_len)
{
#if defined(GNU_LINUX)
if ((start >= RT_TABLE_ID_COMPAT && start <= RT_TABLE_ID_LOCAL) ||
(end >= RT_TABLE_ID_COMPAT && end <= RT_TABLE_ID_LOCAL)) {
snprintfrr(errmsg, errmsg_len,
"Values forbidden in range [%u;%u]",
RT_TABLE_ID_COMPAT, RT_TABLE_ID_LOCAL);
return NB_ERR_VALIDATION;
}
if (start < RT_TABLE_ID_COMPAT && end > RT_TABLE_ID_LOCAL) {
snprintfrr(errmsg, errmsg_len,
"Range overlaps range [%u;%u] forbidden",
RT_TABLE_ID_COMPAT, RT_TABLE_ID_LOCAL);
return NB_ERR_VALIDATION;
}
#endif
return NB_OK;
}
int lib_vrf_zebra_netns_table_range_create(struct nb_cb_create_args *args)
{
struct vrf *vrf;
uint32_t start, end;
const char *vrf_name;
start = yang_dnode_get_uint32(args->dnode, "start");
end = yang_dnode_get_uint32(args->dnode, "end");
if (args->event == NB_EV_VALIDATE) {
vrf_name = yang_dnode_get_string(args->dnode, "../../../name");
if (!vrf_is_backend_netns() &&
strcmp(vrf_name, VRF_DEFAULT_NAME)) {
snprintfrr(args->errmsg, args->errmsg_len,
"Configuration is not available in non-default VRFs when using VRF-lite backend.");
return NB_ERR_VALIDATION;
}
return table_range_validate(start, end, args->errmsg,
args->errmsg_len);
}
if (args->event != NB_EV_APPLY)
return NB_OK;
vrf = nb_running_get_entry(args->dnode, NULL, true);
table_manager_range(true, vrf->info, start, end);
return NB_OK;
}
int lib_vrf_zebra_netns_table_range_destroy(struct nb_cb_destroy_args *args)
{
struct vrf *vrf;
if (args->event != NB_EV_APPLY)
return NB_OK;
vrf = nb_running_get_entry(args->dnode, NULL, true);
table_manager_range(false, vrf->info, 0, 0);
return NB_OK;
}
/*
* XPath: /frr-vrf:lib/vrf/frr-zebra:zebra/netns/table-range/start
*/
int lib_vrf_zebra_netns_table_range_start_modify(struct nb_cb_modify_args *args)
{
struct vrf *vrf;
uint32_t start, end;
start = yang_dnode_get_uint32(args->dnode, NULL);
end = yang_dnode_get_uint32(args->dnode, "../end");
if (args->event == NB_EV_VALIDATE)
return table_range_validate(start, end, args->errmsg,
args->errmsg_len);
if (args->event != NB_EV_APPLY)
return NB_OK;
vrf = nb_running_get_entry(args->dnode, NULL, true);
table_manager_range(true, vrf->info, start, end);
return NB_OK;
}
/*
* XPath: /frr-vrf:lib/vrf/frr-zebra:zebra/netns/table-range/end
*/
int lib_vrf_zebra_netns_table_range_end_modify(struct nb_cb_modify_args *args)
{
struct vrf *vrf;
uint32_t start, end;
start = yang_dnode_get_uint32(args->dnode, "../start");
end = yang_dnode_get_uint32(args->dnode, NULL);
if (args->event == NB_EV_VALIDATE)
return table_range_validate(start, end, args->errmsg,
args->errmsg_len);
if (args->event != NB_EV_APPLY)
return NB_OK;
vrf = nb_running_get_entry(args->dnode, NULL, true);
table_manager_range(true, vrf->info, start, end);
return NB_OK;
}
/*
* XPath: /frr-vrf:lib/vrf/frr-zebra:zebra/mpls/fec-nexthop-resolution
*/
int lib_vrf_zebra_mpls_fec_nexthop_resolution_modify(
struct nb_cb_modify_args *args)
{
struct vrf *vrf;
struct zebra_vrf *zvrf;
bool fec_nexthop_resolution;
if (args->event != NB_EV_APPLY)
return NB_OK;
vrf = nb_running_get_entry(args->dnode, NULL, true);
zvrf = vrf->info;
fec_nexthop_resolution = yang_dnode_get_bool(args->dnode, NULL);
if (zvrf->zebra_mpls_fec_nexthop_resolution == fec_nexthop_resolution)
return NB_OK;
zvrf->zebra_mpls_fec_nexthop_resolution = fec_nexthop_resolution;
zebra_mpls_fec_nexthop_resolution_update(zvrf);
return NB_OK;
}
int lib_vrf_zebra_mpls_fec_nexthop_resolution_destroy(
struct nb_cb_destroy_args *args)
{
struct vrf *vrf;
struct zebra_vrf *zvrf;
bool fec_nexthop_resolution;
if (args->event != NB_EV_APPLY)
return NB_OK;
vrf = nb_running_get_entry(args->dnode, NULL, true);
zvrf = vrf->info;
fec_nexthop_resolution = DFLT_ZEBRA_IP_NHT_RESOLVE_VIA_DEFAULT;
if (zvrf->zebra_mpls_fec_nexthop_resolution == fec_nexthop_resolution)
return NB_OK;
zvrf->zebra_mpls_fec_nexthop_resolution = fec_nexthop_resolution;
zebra_mpls_fec_nexthop_resolution_update(zvrf);
return NB_OK;
}
/*
* XPath: /frr-vrf:lib/vrf/frr-zebra:zebra/l3vni-id
*/
int lib_vrf_zebra_l3vni_id_modify(struct nb_cb_modify_args *args)
{
struct vrf *vrf;
vni_t vni = 0;
bool pfx_only = false;
uint32_t count;
vni = yang_dnode_get_uint32(args->dnode, NULL);
switch (args->event) {
case NB_EV_PREPARE:
case NB_EV_ABORT:
return NB_OK;
case NB_EV_VALIDATE:
count = yang_dnode_count(args->dnode,
"/frr-vrf:lib/vrf/frr-zebra:zebra[l3vni-id='%u']",
vni);
if (count > 1) {
snprintfrr(args->errmsg, args->errmsg_len,
"vni %u is already mapped to another vrf",
vni);
return NB_ERR_VALIDATION;
}
break;
case NB_EV_APPLY:
vrf = nb_running_get_entry(args->dnode, NULL, true);
pfx_only = yang_dnode_get_bool(args->dnode, "../prefix-only");
zebra_vxlan_process_vrf_vni_cmd(vrf->info, vni,
pfx_only ? 1 : 0, 1);
break;
}
return NB_OK;
}
int lib_vrf_zebra_l3vni_id_destroy(struct nb_cb_destroy_args *args)
{
struct vrf *vrf;
vni_t vni = 0;
switch (args->event) {
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_VALIDATE:
return NB_OK;
case NB_EV_APPLY:
vrf = nb_running_get_entry(args->dnode, NULL, true);
vni = yang_dnode_get_uint32(args->dnode, NULL);
zebra_vxlan_process_vrf_vni_cmd(vrf->info, vni, 0, 0);
break;
}
return NB_OK;
}
/*
* XPath: /frr-vrf:lib/vrf/frr-zebra:zebra/prefix-only
*/
int lib_vrf_zebra_prefix_only_modify(struct nb_cb_modify_args *args)
{
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
/* TODO: implement me. */
break;
}
return NB_OK;
}