mirror of
https://github.com/FRRouting/frr.git
synced 2025-04-30 05:27:16 +02:00

When the user modifies an SRv6 SID and then removes all SIDs, staticd crashes: ``` 2025/03/23 08:37:22.691860 STATIC: lib/memory.c:74: mt_count_free(): assertion (mt->n_alloc) failed STATIC: Received signal 6 at 1742715442 (si_addr 0x8200007cf0); aborting... STATIC: zlog_signal+0x390 fcc704a844b8 ffffd7450390 /usr/lib/frr/libfrr.so.0 (mapped at 0xfcc704800000) STATIC: core_handler+0x1f8 fcc704b79990 ffffd7450590 /usr/lib/frr/libfrr.so.0 (mapped at 0xfcc704800000) STATIC: ---- signal ---- STATIC: ? fcc705c008f8 ffffd74507a0 linux-vdso.so.1 (mapped at 0xfcc705c00000) STATIC: pthread_key_delete+0x1a0 fcc70458f1f0 ffffd7451a00 /lib/aarch64-linux-gnu/libc.so.6 (mapped at 0xfcc704510000) STATIC: raise+0x1c fcc70454a67c ffffd7451ad0 /lib/aarch64-linux-gnu/libc.so.6 (mapped at 0xfcc704510000) STATIC: abort+0xe4 fcc704537130 ffffd7451af0 /lib/aarch64-linux-gnu/libc.so.6 (mapped at 0xfcc704510000) STATIC: _zlog_assert_failed+0x3c4 fcc704c407c8 ffffd7451c40 /usr/lib/frr/libfrr.so.0 (mapped at 0xfcc704800000) STATIC: mt_count_free+0x12c fcc704a93c74 ffffd7451dc0 /usr/lib/frr/libfrr.so.0 (mapped at 0xfcc704800000) STATIC: qfree+0x28 fcc704a93fa0 ffffd7451e70 /usr/lib/frr/libfrr.so.0 (mapped at 0xfcc704800000) STATIC: static_srv6_sid_free+0x1c adc1df8fa544 ffffd7451e90 /usr/lib/frr/staticd (mapped at 0xadc1df8a0000) STATIC: delete_static_srv6_sid+0x14 adc1df8faafc ffffd7451eb0 /usr/lib/frr/staticd (mapped at 0xadc1df8a0000) STATIC: list_delete_all_node+0x104 fcc704a60eec ffffd7451ed0 /usr/lib/frr/libfrr.so.0 (mapped at 0xfcc704800000) STATIC: list_delete+0x8c fcc704a61054 ffffd7451f00 /usr/lib/frr/libfrr.so.0 (mapped at 0xfcc704800000) STATIC: static_srv6_cleanup+0x20 adc1df8fabdc ffffd7451f20 /usr/lib/frr/staticd (mapped at 0xadc1df8a0000) STATIC: sigint+0x40 adc1df8be544 ffffd7451f30 /usr/lib/frr/staticd (mapped at 0xadc1df8a0000) STATIC: frr_sigevent_process+0x148 fcc704b79460 ffffd7451f40 /usr/lib/frr/libfrr.so.0 (mapped at 0xfcc704800000) STATIC: event_fetch+0x1c4 fcc704bc0834 ffffd7451f60 /usr/lib/frr/libfrr.so.0 (mapped at 0xfcc704800000) STATIC: frr_run+0x650 fcc704a5d230 ffffd7452080 /usr/lib/frr/libfrr.so.0 (mapped at 0xfcc704800000) STATIC: main+0x1d0 adc1df8be75c ffffd7452270 /usr/lib/frr/staticd (mapped at 0xadc1df8a0000) STATIC: __libc_init_first+0x7c fcc7045373fc ffffd74522b0 /lib/aarch64-linux-gnu/libc.so.6 (mapped at 0xfcc704510000) STATIC: __libc_start_main+0x98 fcc7045374cc ffffd74523c0 /lib/aarch64-linux-gnu/libc.so.6 (mapped at 0xfcc704510000) STATIC: _start+0x30 adc1df8be0f0 ffffd7452420 /usr/lib/frr/staticd (mapped at 0xadc1df8a0000) ``` Tracking this down, the crash occurs because every time we modify a SID, staticd executes some callbacks to modify the SID and finally it calls `apply_finish`, which re-adds the SID to the list `srv6_sids`. This leads to having the same SID multiple times in the `srv6_sids` list. When we delete all SIDs, staticd attempts to deallocate the same SID multiple times, which leads to the crash. This commit fixes the issue by moving the code that adds the SID to the list from the `apply_finish` callback to the `create` callback. This ensures that the SID is inserted into the list only once, when it is created. For all subsequent modifications, the SID is modified but not added to the list. Signed-off-by: Carmine Scarpitta <cscarpit@cisco.com>
1374 lines
36 KiB
C
1374 lines
36 KiB
C
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
/*
|
|
* Copyright (C) 2018 Vmware
|
|
* Vishal Dhingra
|
|
*/
|
|
#include <zebra.h>
|
|
|
|
#include "northbound.h"
|
|
#include "libfrr.h"
|
|
#include "log.h"
|
|
#include "lib_errors.h"
|
|
#include "prefix.h"
|
|
#include "table.h"
|
|
#include "vrf.h"
|
|
#include "nexthop.h"
|
|
#include "srcdest_table.h"
|
|
|
|
#include "static_vrf.h"
|
|
#include "static_routes.h"
|
|
#include "static_nb.h"
|
|
#include "static_zebra.h"
|
|
|
|
#include "static_srv6.h"
|
|
#include "static_debug.h"
|
|
|
|
|
|
static int static_path_list_create(struct nb_cb_create_args *args)
|
|
{
|
|
struct route_node *rn;
|
|
struct static_path *pn;
|
|
const struct lyd_node *vrf_dnode;
|
|
const char *vrf;
|
|
uint8_t distance;
|
|
uint32_t table_id;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
vrf_dnode = yang_dnode_get_parent(args->dnode,
|
|
"control-plane-protocol");
|
|
vrf = yang_dnode_get_string(vrf_dnode, "vrf");
|
|
table_id = yang_dnode_get_uint32(args->dnode, "table-id");
|
|
|
|
/*
|
|
* TableId is not applicable for VRF. Consider the case of
|
|
* l3mdev, there is one uint32_t space to work with.
|
|
* A l3mdev device points at a specific table that it
|
|
* relates to and a set of interfaces it belongs to.
|
|
*/
|
|
if (table_id && (strcmp(vrf, vrf_get_default_name()) != 0)
|
|
&& !vrf_is_backend_netns()) {
|
|
snprintf(
|
|
args->errmsg, args->errmsg_len,
|
|
"%% table param only available when running on netns-based vrfs");
|
|
return NB_ERR_VALIDATION;
|
|
}
|
|
break;
|
|
case NB_EV_ABORT:
|
|
case NB_EV_PREPARE:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
rn = nb_running_get_entry(args->dnode, NULL, true);
|
|
distance = yang_dnode_get_uint8(args->dnode, "distance");
|
|
table_id = yang_dnode_get_uint32(args->dnode, "table-id");
|
|
pn = static_add_path(rn, table_id, distance);
|
|
nb_running_set_entry(args->dnode, pn);
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
static int static_path_list_destroy(struct nb_cb_destroy_args *args)
|
|
{
|
|
struct static_path *pn;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
pn = nb_running_unset_entry(args->dnode);
|
|
static_del_path(pn);
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
static int static_path_list_tag_modify(struct nb_cb_modify_args *args)
|
|
{
|
|
struct static_path *pn;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_ABORT:
|
|
case NB_EV_PREPARE:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
pn = nb_running_get_entry(args->dnode, NULL, true);
|
|
pn->tag = yang_dnode_get_uint32(args->dnode, NULL);
|
|
static_install_path(pn);
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
struct nexthop_iter {
|
|
uint32_t count;
|
|
bool blackhole;
|
|
};
|
|
|
|
static int nexthop_iter_cb(const struct lyd_node *dnode, void *arg)
|
|
{
|
|
struct nexthop_iter *iter = arg;
|
|
enum static_nh_type nh_type;
|
|
|
|
nh_type = yang_dnode_get_enum(dnode, "nh-type");
|
|
|
|
if (nh_type == STATIC_BLACKHOLE)
|
|
iter->blackhole = true;
|
|
|
|
iter->count++;
|
|
|
|
return YANG_ITER_CONTINUE;
|
|
}
|
|
|
|
static bool static_nexthop_create(struct nb_cb_create_args *args)
|
|
{
|
|
const struct lyd_node *pn_dnode;
|
|
struct nexthop_iter iter;
|
|
struct static_path *pn;
|
|
struct ipaddr ipaddr;
|
|
struct static_nexthop *nh;
|
|
enum static_nh_type nh_type;
|
|
const char *ifname;
|
|
const char *nh_vrf;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
ifname = yang_dnode_get_string(args->dnode, "interface");
|
|
if (ifname != NULL) {
|
|
if (strcasecmp(ifname, "Null0") == 0
|
|
|| strcasecmp(ifname, "reject") == 0
|
|
|| strcasecmp(ifname, "blackhole") == 0) {
|
|
snprintf(args->errmsg, args->errmsg_len,
|
|
"%s: Nexthop interface name can not be from reserved keywords(Null0, reject, blackhole)",
|
|
ifname);
|
|
return NB_ERR_VALIDATION;
|
|
}
|
|
}
|
|
|
|
iter.count = 0;
|
|
iter.blackhole = false;
|
|
|
|
pn_dnode = yang_dnode_get_parent(args->dnode, "path-list");
|
|
yang_dnode_iterate(nexthop_iter_cb, &iter, pn_dnode,
|
|
"./frr-nexthops/nexthop");
|
|
|
|
if (iter.blackhole && iter.count > 1) {
|
|
snprintf(
|
|
args->errmsg, args->errmsg_len,
|
|
"Route cannot have blackhole and non-blackhole nexthops simultaneously");
|
|
return NB_ERR_VALIDATION;
|
|
} else if (iter.count > zebra_ecmp_count) {
|
|
snprintf(args->errmsg, args->errmsg_len,
|
|
"Route cannot have more than %d ECMP nexthops",
|
|
zebra_ecmp_count);
|
|
return NB_ERR_VALIDATION;
|
|
}
|
|
break;
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
yang_dnode_get_ip(&ipaddr, args->dnode, "gateway");
|
|
nh_type = yang_dnode_get_enum(args->dnode, "nh-type");
|
|
ifname = yang_dnode_get_string(args->dnode, "interface");
|
|
nh_vrf = yang_dnode_get_string(args->dnode, "vrf");
|
|
pn = nb_running_get_entry(args->dnode, NULL, true);
|
|
|
|
if (strmatch(ifname, "(null)"))
|
|
ifname = "";
|
|
|
|
if (!static_add_nexthop_validate(nh_vrf, nh_type, &ipaddr))
|
|
flog_warn(
|
|
EC_LIB_NB_CB_CONFIG_VALIDATE,
|
|
"Warning!! Local connected address is configured as Gateway IP((%s))",
|
|
yang_dnode_get_string(args->dnode,
|
|
"./gateway"));
|
|
nh = static_add_nexthop(pn, nh_type, &ipaddr, ifname, nh_vrf,
|
|
0);
|
|
nb_running_set_entry(args->dnode, nh);
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
static bool static_nexthop_destroy(struct nb_cb_destroy_args *args)
|
|
{
|
|
struct static_nexthop *nh;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
nh = nb_running_unset_entry(args->dnode);
|
|
static_delete_nexthop(nh);
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
static int nexthop_srv6_segs_stack_entry_create(struct nb_cb_create_args *args)
|
|
{
|
|
struct static_nexthop *nh;
|
|
uint32_t pos;
|
|
uint8_t index;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
nh = nb_running_get_entry(args->dnode, NULL, true);
|
|
pos = yang_get_list_pos(args->dnode);
|
|
if (!pos) {
|
|
flog_warn(EC_LIB_NB_CB_CONFIG_APPLY,
|
|
"libyang returns invalid seg position");
|
|
return NB_ERR;
|
|
}
|
|
/* Mapping to array = list-index -1 */
|
|
index = pos - 1;
|
|
memset(&nh->snh_seg.seg[index], 0, sizeof(struct in6_addr));
|
|
nh->snh_seg.num_segs++;
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
static int nexthop_srv6_segs_stack_entry_destroy(struct nb_cb_destroy_args *args)
|
|
{
|
|
struct static_nexthop *nh;
|
|
uint32_t pos;
|
|
uint8_t index;
|
|
int old_num_segs;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
nh = nb_running_get_entry(args->dnode, NULL, true);
|
|
pos = yang_get_list_pos(args->dnode);
|
|
if (!pos) {
|
|
flog_warn(EC_LIB_NB_CB_CONFIG_APPLY,
|
|
"libyang returns invalid seg position");
|
|
return NB_ERR;
|
|
}
|
|
index = pos - 1;
|
|
old_num_segs = nh->snh_seg.num_segs;
|
|
memset(&nh->snh_seg.seg[index], 0, sizeof(struct in6_addr));
|
|
nh->snh_seg.num_segs--;
|
|
|
|
if (old_num_segs != nh->snh_seg.num_segs)
|
|
nh->state = STATIC_START;
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
static int static_nexthop_srv6_segs_modify(struct nb_cb_modify_args *args)
|
|
{
|
|
struct static_nexthop *nh;
|
|
uint32_t pos;
|
|
uint8_t index;
|
|
struct in6_addr old_seg;
|
|
struct in6_addr cli_seg;
|
|
|
|
nh = nb_running_get_entry(args->dnode, NULL, true);
|
|
pos = yang_get_list_pos(lyd_parent(args->dnode));
|
|
if (!pos) {
|
|
flog_warn(EC_LIB_NB_CB_CONFIG_APPLY,
|
|
"libyang returns invalid seg position");
|
|
return NB_ERR;
|
|
}
|
|
/* Mapping to array = list-index -1 */
|
|
index = pos - 1;
|
|
|
|
old_seg = nh->snh_seg.seg[index];
|
|
yang_dnode_get_ipv6(&cli_seg, args->dnode, NULL);
|
|
|
|
memcpy(&nh->snh_seg.seg[index], &cli_seg, sizeof(struct in6_addr));
|
|
|
|
if (memcmp(&old_seg, &nh->snh_seg.seg[index],
|
|
sizeof(struct in6_addr)) != 0)
|
|
nh->state = STATIC_START;
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
static int nexthop_mpls_label_stack_entry_create(struct nb_cb_create_args *args)
|
|
{
|
|
struct static_nexthop *nh;
|
|
uint32_t pos;
|
|
uint8_t index;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
if (!mpls_enabled) {
|
|
snprintf(
|
|
args->errmsg, args->errmsg_len,
|
|
"%% MPLS not turned on in kernel ignoring static route");
|
|
return NB_ERR_VALIDATION;
|
|
}
|
|
break;
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
nh = nb_running_get_entry(args->dnode, NULL, true);
|
|
pos = yang_get_list_pos(args->dnode);
|
|
if (!pos) {
|
|
flog_warn(EC_LIB_NB_CB_CONFIG_APPLY,
|
|
"libyang returns invalid label position");
|
|
return NB_ERR;
|
|
}
|
|
/* Mapping to array = list-index -1 */
|
|
index = pos - 1;
|
|
nh->snh_label.label[index] = 0;
|
|
nh->snh_label.num_labels++;
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
static int
|
|
nexthop_mpls_label_stack_entry_destroy(struct nb_cb_destroy_args *args)
|
|
{
|
|
struct static_nexthop *nh;
|
|
uint32_t pos;
|
|
uint8_t index;
|
|
uint old_num_labels;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
nh = nb_running_get_entry(args->dnode, NULL, true);
|
|
pos = yang_get_list_pos(args->dnode);
|
|
if (!pos) {
|
|
flog_warn(EC_LIB_NB_CB_CONFIG_APPLY,
|
|
"libyang returns invalid label position");
|
|
return NB_ERR;
|
|
}
|
|
index = pos - 1;
|
|
old_num_labels = nh->snh_label.num_labels;
|
|
nh->snh_label.label[index] = 0;
|
|
nh->snh_label.num_labels--;
|
|
|
|
if (old_num_labels != nh->snh_label.num_labels)
|
|
nh->state = STATIC_START;
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
static int static_nexthop_mpls_label_modify(struct nb_cb_modify_args *args)
|
|
{
|
|
struct static_nexthop *nh;
|
|
uint32_t pos;
|
|
uint8_t index;
|
|
mpls_label_t old_label;
|
|
|
|
nh = nb_running_get_entry(args->dnode, NULL, true);
|
|
pos = yang_get_list_pos(lyd_parent(args->dnode));
|
|
if (!pos) {
|
|
flog_warn(EC_LIB_NB_CB_CONFIG_APPLY,
|
|
"libyang returns invalid label position");
|
|
return NB_ERR;
|
|
}
|
|
/* Mapping to array = list-index -1 */
|
|
index = pos - 1;
|
|
|
|
old_label = nh->snh_label.label[index];
|
|
nh->snh_label.label[index] = yang_dnode_get_uint32(args->dnode, NULL);
|
|
|
|
if (old_label != nh->snh_label.label[index])
|
|
nh->state = STATIC_START;
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
static int static_nexthop_onlink_modify(struct nb_cb_modify_args *args)
|
|
{
|
|
struct static_nexthop *nh;
|
|
enum static_nh_type nh_type;
|
|
bool old_onlink;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
nh_type = yang_dnode_get_enum(args->dnode, "../nh-type");
|
|
if ((nh_type != STATIC_IPV4_GATEWAY_IFNAME)
|
|
&& (nh_type != STATIC_IPV6_GATEWAY_IFNAME)) {
|
|
snprintf(
|
|
args->errmsg, args->errmsg_len,
|
|
"nexthop type is not the ipv4 or ipv6 interface type");
|
|
return NB_ERR_VALIDATION;
|
|
}
|
|
break;
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
nh = nb_running_get_entry(args->dnode, NULL, true);
|
|
old_onlink = nh->onlink;
|
|
nh->onlink = yang_dnode_get_bool(args->dnode, NULL);
|
|
|
|
if (old_onlink != nh->onlink)
|
|
nh->state = STATIC_START;
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
static int static_nexthop_color_modify(struct nb_cb_modify_args *args)
|
|
{
|
|
struct static_nexthop *nh;
|
|
uint32_t old_color;
|
|
|
|
nh = nb_running_get_entry(args->dnode, NULL, true);
|
|
old_color = nh->color;
|
|
nh->color = yang_dnode_get_uint32(args->dnode, NULL);
|
|
|
|
if (old_color != nh->color)
|
|
nh->state = STATIC_START;
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
static int static_nexthop_color_destroy(struct nb_cb_destroy_args *args)
|
|
{
|
|
struct static_nexthop *nh;
|
|
uint32_t old_color;
|
|
|
|
nh = nb_running_get_entry(args->dnode, NULL, true);
|
|
old_color = nh->color;
|
|
nh->color = 0;
|
|
|
|
if (old_color != nh->color)
|
|
nh->state = STATIC_START;
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
static int static_nexthop_bh_type_modify(struct nb_cb_modify_args *args)
|
|
{
|
|
struct static_nexthop *nh;
|
|
enum static_nh_type nh_type;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
nh_type = yang_dnode_get_enum(args->dnode, "../nh-type");
|
|
if (nh_type != STATIC_BLACKHOLE) {
|
|
snprintf(args->errmsg, args->errmsg_len,
|
|
"nexthop type is not the blackhole type");
|
|
return NB_ERR_VALIDATION;
|
|
}
|
|
break;
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
nh = nb_running_get_entry(args->dnode, NULL, true);
|
|
nh->bh_type = yang_dnode_get_enum(args->dnode, NULL);
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
void routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_apply_finish(
|
|
struct nb_cb_apply_finish_args *args)
|
|
{
|
|
struct static_nexthop *nh;
|
|
|
|
nh = nb_running_get_entry(args->dnode, NULL, true);
|
|
|
|
static_install_nexthop(nh);
|
|
}
|
|
|
|
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_pre_validate(
|
|
struct nb_cb_pre_validate_args *args)
|
|
{
|
|
const struct lyd_node *mls_dnode;
|
|
uint32_t count;
|
|
|
|
mls_dnode = yang_dnode_get(args->dnode, "mpls-label-stack");
|
|
count = yang_get_list_elements_count(lyd_child(mls_dnode));
|
|
|
|
if (count > MPLS_MAX_LABELS) {
|
|
snprintf(args->errmsg, args->errmsg_len,
|
|
"Too many labels, Enter %d or fewer",
|
|
MPLS_MAX_LABELS);
|
|
return NB_ERR_VALIDATION;
|
|
}
|
|
return NB_OK;
|
|
}
|
|
|
|
int routing_control_plane_protocols_name_validate(
|
|
struct nb_cb_create_args *args)
|
|
{
|
|
const char *name;
|
|
|
|
name = yang_dnode_get_string(args->dnode, "name");
|
|
if (!strmatch(name, "staticd")) {
|
|
snprintf(args->errmsg, args->errmsg_len,
|
|
"static routing supports only one instance with name staticd");
|
|
return NB_ERR_VALIDATION;
|
|
}
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath:
|
|
* /frr-routing:routing/control-plane-protocols/control-plane-protocol
|
|
*/
|
|
int routing_control_plane_protocols_staticd_create(struct nb_cb_create_args *args)
|
|
{
|
|
struct static_vrf *svrf;
|
|
const char *vrf;
|
|
|
|
vrf = yang_dnode_get_string(args->dnode, "vrf");
|
|
svrf = static_vrf_alloc(vrf);
|
|
nb_running_set_entry(args->dnode, svrf);
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
int routing_control_plane_protocols_staticd_destroy(
|
|
struct nb_cb_destroy_args *args)
|
|
{
|
|
struct static_vrf *svrf;
|
|
struct route_table *stable;
|
|
struct route_node *rn;
|
|
afi_t afi;
|
|
safi_t safi;
|
|
|
|
svrf = nb_running_unset_entry(args->dnode);
|
|
|
|
FOREACH_AFI_SAFI (afi, safi) {
|
|
stable = svrf->stable[afi][safi];
|
|
if (!stable)
|
|
continue;
|
|
|
|
for (rn = route_top(stable); rn; rn = srcdest_route_next(rn))
|
|
static_del_route(rn);
|
|
}
|
|
|
|
static_vrf_free(svrf);
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath:
|
|
* /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list
|
|
*/
|
|
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_create(
|
|
struct nb_cb_create_args *args)
|
|
{
|
|
struct static_vrf *svrf;
|
|
struct route_node *rn;
|
|
const struct lyd_node *vrf_dnode;
|
|
struct prefix prefix, src_prefix, *src_p;
|
|
const char *afi_safi;
|
|
afi_t prefix_afi;
|
|
afi_t afi;
|
|
safi_t safi;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
yang_dnode_get_prefix(&prefix, args->dnode, "prefix");
|
|
yang_dnode_get_prefix(&src_prefix, args->dnode, "src-prefix");
|
|
src_p = src_prefix.prefixlen ? &src_prefix : NULL;
|
|
afi_safi = yang_dnode_get_string(args->dnode, "afi-safi");
|
|
yang_afi_safi_identity2value(afi_safi, &afi, &safi);
|
|
prefix_afi = family2afi(prefix.family);
|
|
if (afi != prefix_afi) {
|
|
flog_warn(
|
|
EC_LIB_NB_CB_CONFIG_VALIDATE,
|
|
"route node %s creation failed",
|
|
yang_dnode_get_string(args->dnode, "prefix"));
|
|
return NB_ERR_VALIDATION;
|
|
}
|
|
|
|
if (src_p && afi != AFI_IP6) {
|
|
flog_warn(EC_LIB_NB_CB_CONFIG_VALIDATE,
|
|
"invalid use of IPv6 dst-src prefix %s on %s",
|
|
yang_dnode_get_string(args->dnode, "src-prefix"),
|
|
yang_dnode_get_string(args->dnode, "prefix"));
|
|
return NB_ERR_VALIDATION;
|
|
}
|
|
break;
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
vrf_dnode = yang_dnode_get_parent(args->dnode,
|
|
"control-plane-protocol");
|
|
svrf = nb_running_get_entry(vrf_dnode, NULL, true);
|
|
|
|
yang_dnode_get_prefix(&prefix, args->dnode, "prefix");
|
|
yang_dnode_get_prefix(&src_prefix, args->dnode, "src-prefix");
|
|
src_p = src_prefix.prefixlen ? &src_prefix : NULL;
|
|
afi_safi = yang_dnode_get_string(args->dnode, "afi-safi");
|
|
yang_afi_safi_identity2value(afi_safi, &afi, &safi);
|
|
|
|
rn = static_add_route(afi, safi, &prefix, (struct prefix_ipv6 *)src_p, svrf);
|
|
if (!svrf->vrf || svrf->vrf->vrf_id == VRF_UNKNOWN)
|
|
snprintf(
|
|
args->errmsg, args->errmsg_len,
|
|
"Static Route to %s not installed currently because dependent config not fully available",
|
|
yang_dnode_get_string(args->dnode, "prefix"));
|
|
nb_running_set_entry(args->dnode, rn);
|
|
break;
|
|
}
|
|
return NB_OK;
|
|
}
|
|
|
|
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_destroy(
|
|
struct nb_cb_destroy_args *args)
|
|
{
|
|
struct route_node *rn;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
rn = nb_running_unset_entry(args->dnode);
|
|
static_del_route(rn);
|
|
break;
|
|
}
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath:
|
|
* /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list
|
|
*/
|
|
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_create(
|
|
struct nb_cb_create_args *args)
|
|
{
|
|
return static_path_list_create(args);
|
|
}
|
|
|
|
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_destroy(
|
|
struct nb_cb_destroy_args *args)
|
|
{
|
|
return static_path_list_destroy(args);
|
|
}
|
|
|
|
/*
|
|
* XPath:
|
|
* /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/tag
|
|
*/
|
|
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_tag_modify(
|
|
struct nb_cb_modify_args *args)
|
|
{
|
|
return static_path_list_tag_modify(args);
|
|
}
|
|
|
|
/*
|
|
* XPath:
|
|
* /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop
|
|
*/
|
|
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_create(
|
|
struct nb_cb_create_args *args)
|
|
{
|
|
return static_nexthop_create(args);
|
|
}
|
|
|
|
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_destroy(
|
|
struct nb_cb_destroy_args *args)
|
|
{
|
|
return static_nexthop_destroy(args);
|
|
}
|
|
|
|
/*
|
|
* XPath:
|
|
* /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/bh-type
|
|
*/
|
|
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_bh_type_modify(
|
|
struct nb_cb_modify_args *args)
|
|
{
|
|
return static_nexthop_bh_type_modify(args);
|
|
}
|
|
|
|
/*
|
|
* XPath:
|
|
* /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/onlink
|
|
*/
|
|
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_onlink_modify(
|
|
struct nb_cb_modify_args *args)
|
|
{
|
|
return static_nexthop_onlink_modify(args);
|
|
}
|
|
|
|
/*
|
|
* XPath:
|
|
* /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/srte-color
|
|
*/
|
|
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_color_modify(
|
|
struct nb_cb_modify_args *args)
|
|
{
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
if (static_nexthop_color_modify(args) != NB_OK)
|
|
return NB_ERR;
|
|
|
|
break;
|
|
}
|
|
return NB_OK;
|
|
}
|
|
|
|
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_color_destroy(
|
|
struct nb_cb_destroy_args *args)
|
|
{
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
if (static_nexthop_color_destroy(args) != NB_OK)
|
|
return NB_ERR;
|
|
break;
|
|
}
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath:
|
|
* /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/srv6-segs-stack/entry
|
|
*/
|
|
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_srv6_segs_stack_entry_create(
|
|
struct nb_cb_create_args *args)
|
|
{
|
|
return nexthop_srv6_segs_stack_entry_create(args);
|
|
}
|
|
|
|
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_srv6_segs_stack_entry_destroy(
|
|
struct nb_cb_destroy_args *args)
|
|
{
|
|
return nexthop_srv6_segs_stack_entry_destroy(args);
|
|
}
|
|
|
|
/*
|
|
* XPath:
|
|
* /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/srv6-segs-stack/entry/seg
|
|
*/
|
|
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_srv6_segs_stack_entry_seg_modify(
|
|
struct nb_cb_modify_args *args)
|
|
{
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
if (static_nexthop_srv6_segs_modify(args) != NB_OK)
|
|
return NB_ERR;
|
|
break;
|
|
}
|
|
return NB_OK;
|
|
}
|
|
|
|
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_srv6_segs_stack_entry_seg_destroy(
|
|
struct nb_cb_destroy_args *args)
|
|
{
|
|
/*
|
|
* No operation is required in this call back.
|
|
* nexthop_srv6_segs_stack_entry_destroy() will take care
|
|
* to reset the seg vaue.
|
|
*/
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
case NB_EV_APPLY:
|
|
break;
|
|
}
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath:
|
|
* /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/mpls-label-stack/entry
|
|
*/
|
|
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_create(
|
|
struct nb_cb_create_args *args)
|
|
{
|
|
return nexthop_mpls_label_stack_entry_create(args);
|
|
}
|
|
|
|
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_destroy(
|
|
struct nb_cb_destroy_args *args)
|
|
{
|
|
return nexthop_mpls_label_stack_entry_destroy(args);
|
|
}
|
|
|
|
/*
|
|
* XPath:
|
|
* /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/mpls-label-stack/entry/label
|
|
*/
|
|
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_label_modify(
|
|
struct nb_cb_modify_args *args)
|
|
{
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
if (static_nexthop_mpls_label_modify(args) != NB_OK)
|
|
return NB_ERR;
|
|
break;
|
|
}
|
|
return NB_OK;
|
|
}
|
|
|
|
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_label_destroy(
|
|
struct nb_cb_destroy_args *args)
|
|
{
|
|
/*
|
|
* No operation is required in this call back.
|
|
* nexthop_mpls_label_stack_entry_destroy() will take care
|
|
* to reset the label vaue.
|
|
*/
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
case NB_EV_APPLY:
|
|
break;
|
|
}
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath:
|
|
* /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/mpls-label-stack/entry/ttl
|
|
*/
|
|
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_ttl_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:
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_ttl_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:
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath:
|
|
* /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/mpls-label-stack/entry/traffic-class
|
|
*/
|
|
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_traffic_class_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:
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_traffic_class_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:
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath:
|
|
* /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/bfd-monitoring
|
|
*/
|
|
int route_next_hop_bfd_create(struct nb_cb_create_args *args)
|
|
{
|
|
struct static_nexthop *sn;
|
|
|
|
if (args->event != NB_EV_APPLY)
|
|
return NB_OK;
|
|
|
|
sn = nb_running_get_entry(args->dnode, NULL, true);
|
|
static_next_hop_bfd_monitor_enable(sn, args->dnode);
|
|
return NB_OK;
|
|
}
|
|
|
|
int route_next_hop_bfd_destroy(struct nb_cb_destroy_args *args)
|
|
{
|
|
struct static_nexthop *sn;
|
|
|
|
if (args->event != NB_EV_APPLY)
|
|
return NB_OK;
|
|
|
|
sn = nb_running_get_entry(args->dnode, NULL, true);
|
|
static_next_hop_bfd_monitor_disable(sn);
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath:
|
|
* /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/bfd-monitoring/source
|
|
*/
|
|
int route_next_hop_bfd_source_modify(struct nb_cb_modify_args *args)
|
|
{
|
|
struct static_nexthop *sn;
|
|
struct ipaddr source;
|
|
|
|
if (args->event != NB_EV_APPLY)
|
|
return NB_OK;
|
|
|
|
sn = nb_running_get_entry(args->dnode, NULL, true);
|
|
yang_dnode_get_ip(&source, args->dnode, NULL);
|
|
static_next_hop_bfd_source(sn, &source);
|
|
return NB_OK;
|
|
}
|
|
|
|
int route_next_hop_bfd_source_destroy(struct nb_cb_destroy_args *args)
|
|
{
|
|
struct static_nexthop *sn;
|
|
|
|
if (args->event != NB_EV_APPLY)
|
|
return NB_OK;
|
|
|
|
sn = nb_running_get_entry(args->dnode, NULL, true);
|
|
static_next_hop_bfd_auto_source(sn);
|
|
|
|
/* NHT information are needed by BFD to automatically find the source
|
|
*
|
|
* Force zebra to resend the information to BFD by unregistering and
|
|
* registering again NHT. The (...)/frr-nexthops/nexthop northbound
|
|
* apply_finish function will trigger a call to static_install_nexthop()
|
|
* that does a call to static_zebra_nht_register(nh, true);
|
|
* static_zebra_nht_register(sn, false);
|
|
*/
|
|
static_zebra_nht_register(sn, false);
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath:
|
|
* /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/bfd-monitoring/multi-hop
|
|
*/
|
|
int route_next_hop_bfd_multi_hop_modify(struct nb_cb_modify_args *args)
|
|
{
|
|
struct static_nexthop *sn;
|
|
|
|
if (args->event != NB_EV_APPLY)
|
|
return NB_OK;
|
|
|
|
sn = nb_running_get_entry(args->dnode, NULL, true);
|
|
static_next_hop_bfd_multi_hop(sn,
|
|
yang_dnode_get_bool(args->dnode, NULL));
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath:
|
|
* /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/bfd-monitoring/profile
|
|
*/
|
|
int route_next_hop_bfd_profile_modify(struct nb_cb_modify_args *args)
|
|
{
|
|
struct static_nexthop *sn;
|
|
|
|
if (args->event != NB_EV_APPLY)
|
|
return NB_OK;
|
|
|
|
sn = nb_running_get_entry(args->dnode, NULL, true);
|
|
static_next_hop_bfd_profile(sn,
|
|
yang_dnode_get_string(args->dnode, NULL));
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
int route_next_hop_bfd_profile_destroy(struct nb_cb_destroy_args *args)
|
|
{
|
|
struct static_nexthop *sn;
|
|
|
|
if (args->event != NB_EV_APPLY)
|
|
return NB_OK;
|
|
|
|
sn = nb_running_get_entry(args->dnode, NULL, true);
|
|
static_next_hop_bfd_profile(sn, NULL);
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath:
|
|
* /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/segment-routing
|
|
*/
|
|
int routing_control_plane_protocols_control_plane_protocol_staticd_segment_routing_create(
|
|
struct nb_cb_create_args *args)
|
|
{
|
|
return NB_OK;
|
|
}
|
|
|
|
int routing_control_plane_protocols_control_plane_protocol_staticd_segment_routing_destroy(
|
|
struct nb_cb_destroy_args *args)
|
|
{
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath:
|
|
* /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/segment-routing/srv6
|
|
*/
|
|
int routing_control_plane_protocols_control_plane_protocol_staticd_segment_routing_srv6_create(
|
|
struct nb_cb_create_args *args)
|
|
{
|
|
return NB_OK;
|
|
}
|
|
|
|
int routing_control_plane_protocols_control_plane_protocol_staticd_segment_routing_srv6_destroy(
|
|
struct nb_cb_destroy_args *args)
|
|
{
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath:
|
|
* /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/segment-routing/srv6/static-sids
|
|
*/
|
|
int routing_control_plane_protocols_control_plane_protocol_staticd_segment_routing_srv6_local_sids_create(
|
|
struct nb_cb_create_args *args)
|
|
{
|
|
return NB_OK;
|
|
}
|
|
|
|
int routing_control_plane_protocols_control_plane_protocol_staticd_segment_routing_srv6_local_sids_destroy(
|
|
struct nb_cb_destroy_args *args)
|
|
{
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath:
|
|
* /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/segment-routing/srv6/locators/locator/static-sids/sid
|
|
*/
|
|
int routing_control_plane_protocols_control_plane_protocol_staticd_segment_routing_srv6_local_sids_sid_create(
|
|
struct nb_cb_create_args *args)
|
|
{
|
|
struct static_srv6_sid *sid;
|
|
struct prefix_ipv6 sid_value;
|
|
|
|
if (args->event != NB_EV_APPLY)
|
|
return NB_OK;
|
|
|
|
yang_dnode_get_ipv6p(&sid_value, args->dnode, "sid");
|
|
sid = static_srv6_sid_alloc(&sid_value);
|
|
nb_running_set_entry(args->dnode, sid);
|
|
listnode_add(srv6_sids, sid);
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
int routing_control_plane_protocols_control_plane_protocol_staticd_segment_routing_srv6_local_sids_sid_destroy(
|
|
struct nb_cb_destroy_args *args)
|
|
{
|
|
struct static_srv6_sid *sid;
|
|
|
|
if (args->event != NB_EV_APPLY)
|
|
return NB_OK;
|
|
|
|
sid = nb_running_unset_entry(args->dnode);
|
|
listnode_delete(srv6_sids, sid);
|
|
static_srv6_sid_del(sid);
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
void routing_control_plane_protocols_control_plane_protocol_staticd_segment_routing_srv6_local_sids_sid_apply_finish(
|
|
struct nb_cb_apply_finish_args *args)
|
|
{
|
|
struct static_srv6_sid *sid;
|
|
struct static_srv6_locator *locator;
|
|
|
|
sid = nb_running_get_entry(args->dnode, NULL, true);
|
|
|
|
locator = static_srv6_locator_lookup(sid->locator_name);
|
|
if (!locator) {
|
|
DEBUGD(&static_dbg_srv6,
|
|
"%s: Locator %s not found, trying to get locator information from zebra",
|
|
__func__, sid->locator_name);
|
|
static_zebra_srv6_manager_get_locator(sid->locator_name);
|
|
return;
|
|
}
|
|
|
|
sid->locator = locator;
|
|
|
|
static_zebra_request_srv6_sid(sid);
|
|
}
|
|
|
|
/*
|
|
* XPath:
|
|
* /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/segment-routing/srv6/locators/locator/static-sids/sid/behavior
|
|
*/
|
|
int routing_control_plane_protocols_control_plane_protocol_staticd_segment_routing_srv6_local_sids_sid_behavior_modify(
|
|
struct nb_cb_modify_args *args)
|
|
{
|
|
struct static_srv6_sid *sid;
|
|
|
|
if (args->event != NB_EV_APPLY)
|
|
return NB_OK;
|
|
|
|
sid = nb_running_get_entry(args->dnode, NULL, true);
|
|
|
|
/* Release and uninstall existing SID, if any, before requesting the new one */
|
|
if (CHECK_FLAG(sid->flags, STATIC_FLAG_SRV6_SID_VALID)) {
|
|
static_zebra_release_srv6_sid(sid);
|
|
UNSET_FLAG(sid->flags, STATIC_FLAG_SRV6_SID_VALID);
|
|
}
|
|
|
|
if (CHECK_FLAG(sid->flags, STATIC_FLAG_SRV6_SID_SENT_TO_ZEBRA)) {
|
|
static_zebra_srv6_sid_uninstall(sid);
|
|
UNSET_FLAG(sid->flags, STATIC_FLAG_SRV6_SID_SENT_TO_ZEBRA);
|
|
}
|
|
|
|
sid->behavior = yang_dnode_get_enum(args->dnode, "../behavior");
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
int routing_control_plane_protocols_control_plane_protocol_staticd_segment_routing_srv6_local_sids_sid_behavior_destroy(
|
|
struct nb_cb_destroy_args *args)
|
|
{
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath:
|
|
* /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/segment-routing/srv6/locators/locator/static-sids/sid/vrf-name
|
|
*/
|
|
int routing_control_plane_protocols_control_plane_protocol_staticd_segment_routing_srv6_local_sids_sid_vrf_name_modify(
|
|
struct nb_cb_modify_args *args)
|
|
{
|
|
struct static_srv6_sid *sid;
|
|
const char *vrf_name;
|
|
|
|
if (args->event != NB_EV_APPLY)
|
|
return NB_OK;
|
|
|
|
sid = nb_running_get_entry(args->dnode, NULL, true);
|
|
|
|
/* Release and uninstall existing SID, if any, before requesting the new one */
|
|
if (CHECK_FLAG(sid->flags, STATIC_FLAG_SRV6_SID_VALID)) {
|
|
static_zebra_release_srv6_sid(sid);
|
|
UNSET_FLAG(sid->flags, STATIC_FLAG_SRV6_SID_VALID);
|
|
}
|
|
|
|
if (CHECK_FLAG(sid->flags, STATIC_FLAG_SRV6_SID_SENT_TO_ZEBRA)) {
|
|
static_zebra_srv6_sid_uninstall(sid);
|
|
UNSET_FLAG(sid->flags, STATIC_FLAG_SRV6_SID_SENT_TO_ZEBRA);
|
|
}
|
|
|
|
vrf_name = yang_dnode_get_string(args->dnode, "../vrf-name");
|
|
snprintf(sid->attributes.vrf_name, sizeof(sid->attributes.vrf_name), "%s", vrf_name);
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
int routing_control_plane_protocols_control_plane_protocol_staticd_segment_routing_srv6_local_sids_sid_vrf_name_destroy(
|
|
struct nb_cb_destroy_args *args)
|
|
{
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath:
|
|
* /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/segment-routing/srv6/locators/locator/static-sids/sid/paths
|
|
*/
|
|
int routing_control_plane_protocols_control_plane_protocol_staticd_segment_routing_srv6_local_sids_sid_paths_create(
|
|
struct nb_cb_create_args *args)
|
|
{
|
|
/* Actual setting is done in apply_finish */
|
|
return NB_OK;
|
|
}
|
|
|
|
int routing_control_plane_protocols_control_plane_protocol_staticd_segment_routing_srv6_local_sids_sid_paths_destroy(
|
|
struct nb_cb_destroy_args *args)
|
|
{
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath:
|
|
* /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/segment-routing/srv6/locators/locator/static-sids/sid/paths/interface
|
|
*/
|
|
int routing_control_plane_protocols_control_plane_protocol_staticd_segment_routing_srv6_local_sids_sid_paths_interface_modify(
|
|
struct nb_cb_modify_args *args)
|
|
{
|
|
struct static_srv6_sid *sid;
|
|
const char *ifname;
|
|
|
|
if (args->event != NB_EV_APPLY)
|
|
return NB_OK;
|
|
|
|
sid = nb_running_get_entry(args->dnode, NULL, true);
|
|
|
|
/* Release and uninstall existing SID, if any, before requesting the new one */
|
|
if (CHECK_FLAG(sid->flags, STATIC_FLAG_SRV6_SID_VALID)) {
|
|
static_zebra_release_srv6_sid(sid);
|
|
UNSET_FLAG(sid->flags, STATIC_FLAG_SRV6_SID_VALID);
|
|
}
|
|
|
|
if (CHECK_FLAG(sid->flags, STATIC_FLAG_SRV6_SID_SENT_TO_ZEBRA)) {
|
|
static_zebra_srv6_sid_uninstall(sid);
|
|
UNSET_FLAG(sid->flags, STATIC_FLAG_SRV6_SID_SENT_TO_ZEBRA);
|
|
}
|
|
|
|
ifname = yang_dnode_get_string(args->dnode, "../interface");
|
|
snprintf(sid->attributes.ifname, sizeof(sid->attributes.ifname), "%s", ifname);
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
int routing_control_plane_protocols_control_plane_protocol_staticd_segment_routing_srv6_local_sids_sid_paths_interface_destroy(
|
|
struct nb_cb_destroy_args *args)
|
|
{
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath:
|
|
* /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/segment-routing/srv6/locators/locator/static-sids/sid/paths/next-hop
|
|
*/
|
|
int routing_control_plane_protocols_control_plane_protocol_staticd_segment_routing_srv6_local_sids_sid_paths_next_hop_modify(
|
|
struct nb_cb_modify_args *args)
|
|
{
|
|
struct static_srv6_sid *sid;
|
|
struct ipaddr nexthop;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
yang_dnode_get_ip(&nexthop, args->dnode, "../next-hop");
|
|
if (!IS_IPADDR_V6(&nexthop)) {
|
|
snprintf(args->errmsg, args->errmsg_len,
|
|
"%% Nexthop must be an IPv6 address");
|
|
return NB_ERR_VALIDATION;
|
|
}
|
|
break;
|
|
case NB_EV_ABORT:
|
|
case NB_EV_PREPARE:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
sid = nb_running_get_entry(args->dnode, NULL, true);
|
|
|
|
/* Release and uninstall existing SID, if any, before requesting the new one */
|
|
if (CHECK_FLAG(sid->flags, STATIC_FLAG_SRV6_SID_VALID)) {
|
|
static_zebra_release_srv6_sid(sid);
|
|
UNSET_FLAG(sid->flags, STATIC_FLAG_SRV6_SID_VALID);
|
|
}
|
|
|
|
if (CHECK_FLAG(sid->flags, STATIC_FLAG_SRV6_SID_SENT_TO_ZEBRA)) {
|
|
static_zebra_srv6_sid_uninstall(sid);
|
|
UNSET_FLAG(sid->flags, STATIC_FLAG_SRV6_SID_SENT_TO_ZEBRA);
|
|
}
|
|
|
|
yang_dnode_get_ip(&nexthop, args->dnode, "../next-hop");
|
|
sid->attributes.nh6 = nexthop.ipaddr_v6;
|
|
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
int routing_control_plane_protocols_control_plane_protocol_staticd_segment_routing_srv6_local_sids_sid_paths_next_hop_destroy(
|
|
struct nb_cb_destroy_args *args)
|
|
{
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath:
|
|
* /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/segment-routing/srv6/locators/locator/static-sids/sid/vrf-name
|
|
*/
|
|
int routing_control_plane_protocols_control_plane_protocol_staticd_segment_routing_srv6_local_sids_sid_locator_name_modify(
|
|
struct nb_cb_modify_args *args)
|
|
{
|
|
struct static_srv6_sid *sid;
|
|
const char *loc_name;
|
|
|
|
if (args->event != NB_EV_APPLY)
|
|
return NB_OK;
|
|
|
|
sid = nb_running_get_entry(args->dnode, NULL, true);
|
|
|
|
/* Release and uninstall existing SID, if any, before requesting the new one */
|
|
if (CHECK_FLAG(sid->flags, STATIC_FLAG_SRV6_SID_VALID)) {
|
|
static_zebra_release_srv6_sid(sid);
|
|
UNSET_FLAG(sid->flags, STATIC_FLAG_SRV6_SID_VALID);
|
|
}
|
|
|
|
if (CHECK_FLAG(sid->flags, STATIC_FLAG_SRV6_SID_SENT_TO_ZEBRA)) {
|
|
static_zebra_srv6_sid_uninstall(sid);
|
|
UNSET_FLAG(sid->flags, STATIC_FLAG_SRV6_SID_SENT_TO_ZEBRA);
|
|
}
|
|
|
|
loc_name = yang_dnode_get_string(args->dnode, "../locator-name");
|
|
snprintf(sid->locator_name, sizeof(sid->locator_name), "%s", loc_name);
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
int routing_control_plane_protocols_control_plane_protocol_staticd_segment_routing_srv6_local_sids_sid_locator_name_destroy(
|
|
struct nb_cb_destroy_args *args)
|
|
{
|
|
return NB_OK;
|
|
}
|