Skip to content

Commit b6364cd

Browse files
committed
ospf: keep RFC 9129 protocol parents in NB candidate
The converted ietf-ospf config leaves live below the ietf-routing control-plane-protocol list. The legacy router ospf and router ospf6 commands still create daemon instances directly, so they also need to seed and destroy the corresponding RFC 9129 parent list entry in the northbound candidate. Without that parent entry, child writes can apply in the daemon while the candidate tree is missing the list entry that owns them. Register create and destroy callbacks for the OSPFv2 and OSPFv3 control-plane-protocol entries, route the CLI router/no-router lifecycle through those callbacks, and clear pending NB changes after direct daemon teardown. Keep OSPFv3 config-file batching enabled immediately before ospf6_init(), where the converted config wrappers are registered. Share the RFC 9129 control-plane-protocol XPath helpers between module info, backend registration, and CLI wrappers, and use the daemon's existing instance-name helpers instead of repeating default-instance literals. Signed-off-by: Eric Parsonage <eric@eparsonage.com>
1 parent 81da1b9 commit b6364cd

15 files changed

Lines changed: 378 additions & 42 deletions

ospf6d/ospf6_area.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "ospf6_area.h"
2828
#include "ospf6_message.h"
2929
#include "ospf6_neighbor.h"
30+
#include "ospf6_nb.h"
3031
#include "ospf6_interface.h"
3132
#include "ospf6_intra.h"
3233
#include "ospf6_abr.h"
@@ -1296,8 +1297,9 @@ static int ospf6_area_xpath(char *xpath, size_t size, const struct ospf6 *o, uin
12961297

12971298
inet_ntop(AF_INET, &addr, area_id_str, sizeof(area_id_str));
12981299
ret = snprintf(xpath, size,
1299-
"/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-ospf:ospfv3'][name='%s']/ietf-ospf:ospf/areas/area[area-id='%s']%s",
1300-
o->name ? o->name : "default", area_id_str, leaf ? leaf : "");
1300+
OSPF6D_IETF_ROUTING_PROTOCOL_XPATH
1301+
"/ietf-ospf:ospf/areas/area[area-id='%s']%s",
1302+
o->name ? o->name : VRF_DEFAULT_NAME, area_id_str, leaf ? leaf : "");
13011303
if (ret < 0 || (size_t)ret >= size)
13021304
return -1;
13031305

ospf6d/ospf6_interface.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "ospf6_abr.h"
3131
#include "ospf6_interface.h"
3232
#include "ospf6_neighbor.h"
33+
#include "ospf6_nb.h"
3334
#include "ospf6_intra.h"
3435
#include "ospf6_spf.h"
3536
#include "ospf6d.h"
@@ -2065,8 +2066,9 @@ static int ospf6_per_iface_xpath(char *xpath, size_t size, const struct interfac
20652066
addr.s_addr = oi->area->area_id;
20662067
inet_ntop(AF_INET, &addr, area_id_str, sizeof(area_id_str));
20672068
ret = snprintf(xpath, size,
2068-
"/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-ospf:ospfv3'][name='%s']/ietf-ospf:ospf/areas/area[area-id='%s']/interfaces/interface[name='%s']%s",
2069-
ospf6->name ? ospf6->name : "default", area_id_str, ifp->name,
2069+
OSPF6D_IETF_ROUTING_PROTOCOL_XPATH
2070+
"/ietf-ospf:ospf/areas/area[area-id='%s']/interfaces/interface[name='%s']%s",
2071+
ospf6->name ? ospf6->name : VRF_DEFAULT_NAME, area_id_str, ifp->name,
20702072
leaf ? leaf : "");
20712073
if (ret < 0 || (size_t)ret >= size)
20722074
return -1;

ospf6d/ospf6_main.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -188,11 +188,11 @@ static const struct frr_yang_module_info *const ospf6d_yang_modules[] = {
188188
* in mgmtd/mgmt_be_adapter.c::mgmt_be_xpath_prefix().
189189
*/
190190
static const char *const ospf6d_oper_xpaths[] = {
191-
"/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-ospf:ospfv3']",
191+
OSPF6D_IETF_ROUTING_PROTOCOL_TYPE_XPATH,
192192
};
193193

194194
static const char *const ospf6d_config_xpaths[] = {
195-
"/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-ospf:ospfv3']",
195+
OSPF6D_IETF_ROUTING_PROTOCOL_TYPE_XPATH,
196196
};
197197

198198
struct mgmt_be_client_cbs ospf6d_be_client_data = {
@@ -288,7 +288,6 @@ int main(int argc, char *argv[], char *envp[])
288288

289289
/* OSPF6 master init. */
290290
ospf6_master_init(frr_init());
291-
cmd_config_file_batching_set(true);
292291

293292
/* thread master */
294293
master = om6->master;
@@ -300,6 +299,7 @@ int main(int argc, char *argv[], char *envp[])
300299
prefix_list_init();
301300

302301
/* initialize ospf6 */
302+
cmd_config_file_batching_set(true);
303303
ospf6_init(master);
304304

305305
/* Configuration processing callback initialization. */

ospf6d/ospf6_nb.c

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,6 @@
77

88
#include "ospf6_nb.h"
99

10-
#define OSPF6D_IETF_ROUTING_CP_XPATH \
11-
"/ietf-routing:routing/control-plane-protocols/" \
12-
"control-plane-protocol"
13-
#define OSPF6D_IETF_OSPF_XPATH \
14-
OSPF6D_IETF_ROUTING_CP_XPATH "/ietf-ospf:ospf"
15-
1610
/* clang-format off */
1711
const struct frr_yang_module_info ospf6d_ietf_routing_info = {
1812
.name = "ietf-routing",
@@ -21,11 +15,14 @@ const struct frr_yang_module_info ospf6d_ietf_routing_info = {
2115
{
2216
.xpath = OSPF6D_IETF_ROUTING_CP_XPATH,
2317
.cbs = {
18+
.create = ospf6d_ietf_routing_control_plane_protocol_create,
19+
.destroy = ospf6d_ietf_routing_control_plane_protocol_destroy,
2420
.get_next = ospf6d_ietf_routing_control_plane_protocol_get_next,
2521
.get_keys = ospf6d_ietf_routing_control_plane_protocol_get_keys,
2622
.lookup_entry =
2723
ospf6d_ietf_routing_control_plane_protocol_lookup_entry,
2824
},
25+
.cfg_opt_in = true,
2926
},
3027
{
3128
.xpath = NULL,

ospf6d/ospf6_nb.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,25 @@
1010

1111
struct ospf6;
1212

13+
#define OSPF6D_IETF_ROUTING_CP_XPATH \
14+
"/ietf-routing:routing/control-plane-protocols/" \
15+
"control-plane-protocol"
16+
#define OSPF6D_IETF_ROUTING_PROTOCOL_TYPE_XPATH \
17+
OSPF6D_IETF_ROUTING_CP_XPATH "[type='ietf-ospf:ospfv3']"
18+
#define OSPF6D_IETF_ROUTING_PROTOCOL_XPATH \
19+
OSPF6D_IETF_ROUTING_PROTOCOL_TYPE_XPATH "[name='%s']"
20+
#define OSPF6D_IETF_OSPF_XPATH \
21+
OSPF6D_IETF_ROUTING_CP_XPATH "/ietf-ospf:ospf"
22+
1323
extern const struct frr_yang_module_info ospf6d_ietf_routing_info;
1424
extern const struct frr_yang_module_info ospf6d_ietf_routing_ospf_deviation_info;
1525
extern const struct frr_yang_module_info ospf6d_ietf_ospf_info;
1626

1727
/* Shared lookup: find an OSPFv3 instance by the ietf-routing instance name. */
1828
struct ospf6 *ospf6d_ietf_ospf_lookup_instance(const char *name);
1929

30+
int ospf6d_ietf_routing_control_plane_protocol_create(struct nb_cb_create_args *args);
31+
int ospf6d_ietf_routing_control_plane_protocol_destroy(struct nb_cb_destroy_args *args);
2032
const void *ospf6d_ietf_routing_control_plane_protocol_get_next(struct nb_cb_get_next_args *args);
2133
int ospf6d_ietf_routing_control_plane_protocol_get_keys(struct nb_cb_get_keys_args *args);
2234
const void *

ospf6d/ospf6_nb_config.c

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
#include "ospf6_message.h"
2121
#include "ospf6_neighbor.h"
2222
#include "ospf6_route.h"
23+
#include "ospf6_tlv.h"
24+
#include "ospf6_gr.h"
2325
#include "ospf6_nb.h"
2426
#include "ospf6_nssa.h"
2527

@@ -42,6 +44,70 @@ static bool ospf6_area_type_is(const char *val, const char *name)
4244
return false;
4345
}
4446

47+
static bool ospf6d_ietf_ospf_type_is(const char *val)
48+
{
49+
return val && (!strcmp(val, "ospfv3") ||
50+
!strcmp(val, "ietf-ospf:ospfv3"));
51+
}
52+
53+
/*
54+
* XPath: /ietf-routing:routing/control-plane-protocols/control-plane-protocol
55+
*
56+
* Keep the IETF routing protocol list present in the local candidate whenever
57+
* the legacy `router ospf6` CLI creates the daemon instance directly. Child
58+
* commands converted to RFC 9129 leaves, such as explicit-router-id, then have
59+
* a real parent list entry to modify during the pending NB commit.
60+
*/
61+
int ospf6d_ietf_routing_control_plane_protocol_create(struct nb_cb_create_args *args)
62+
{
63+
const char *type;
64+
const char *name;
65+
66+
if (args->event != NB_EV_APPLY)
67+
return NB_OK;
68+
69+
type = yang_dnode_get_string(args->dnode, "type");
70+
if (!ospf6d_ietf_ospf_type_is(type))
71+
return NB_OK;
72+
73+
name = yang_dnode_get_string(args->dnode, "name");
74+
if (!name)
75+
name = VRF_DEFAULT_NAME;
76+
77+
if (!ospf6d_ietf_ospf_lookup_instance(name))
78+
ospf6_instance_create(name);
79+
80+
return NB_OK;
81+
}
82+
83+
int ospf6d_ietf_routing_control_plane_protocol_destroy(struct nb_cb_destroy_args *args)
84+
{
85+
const char *type;
86+
const char *name;
87+
struct ospf6 *ospf6;
88+
89+
if (args->event != NB_EV_APPLY)
90+
return NB_OK;
91+
92+
type = yang_dnode_get_string(args->dnode, "type");
93+
if (!ospf6d_ietf_ospf_type_is(type))
94+
return NB_OK;
95+
96+
name = yang_dnode_get_string(args->dnode, "name");
97+
if (!name)
98+
name = VRF_DEFAULT_NAME;
99+
100+
ospf6 = ospf6d_ietf_ospf_lookup_instance(name);
101+
if (!ospf6)
102+
return NB_OK;
103+
104+
if (ospf6->gr_info.restart_support)
105+
ospf6_gr_nvm_delete(ospf6);
106+
ospf6_delete(&ospf6);
107+
108+
return NB_OK;
109+
}
110+
45111
/*
46112
* Look up the OSPFv3 instance corresponding to an ietf-ospf config dnode.
47113
* Walks up to the parent control-plane-protocol list entry to read the

ospf6d/ospf6_nb_state.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ static void *ospf6d_ietf_list_next_data(struct list *list, const void *entry)
6565

6666
static const char *ospf6d_ietf_instance_name(const struct ospf6 *ospf6)
6767
{
68-
return ospf6->name ? ospf6->name : "default";
68+
return ospf6->name ? ospf6->name : VRF_DEFAULT_NAME;
6969
}
7070

7171
struct ospf6 *ospf6d_ietf_ospf_lookup_instance(const char *name)

ospf6d/ospf6_top.c

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "ospf6_area.h"
3131
#include "ospf6_interface.h"
3232
#include "ospf6_neighbor.h"
33+
#include "ospf6_nb.h"
3334
#include "ospf6_network.h"
3435

3536
#include "ospf6_flood.h"
@@ -676,13 +677,21 @@ bool ospf6_router_id_update(struct ospf6 *ospf6, bool init)
676677
return true;
677678
}
678679

680+
static int ospf6_ietf_routing_protocol_xpath(char *xpath, size_t size, const struct ospf6 *ospf6)
681+
{
682+
return snprintf(xpath, size, OSPF6D_IETF_ROUTING_PROTOCOL_XPATH,
683+
ospf6->name ? ospf6->name : VRF_DEFAULT_NAME);
684+
}
685+
679686
/* start ospf6 */
680687
DEFUN_NOSH(router_ospf6, router_ospf6_cmd, "router ospf6 [vrf NAME]",
681688
ROUTER_STR OSPF6_STR VRF_CMD_HELP_STR)
682689
{
683690
struct ospf6 *ospf6;
684691
const char *vrf_name = VRF_DEFAULT_NAME;
692+
char xpath[XPATH_MAXLEN];
685693
int idx_vrf = 0;
694+
int ret;
686695

687696
if (argv_find(argv, argc, "vrf", &idx_vrf)) {
688697
vrf_name = argv[idx_vrf + 1]->arg;
@@ -692,6 +701,12 @@ DEFUN_NOSH(router_ospf6, router_ospf6_cmd, "router ospf6 [vrf NAME]",
692701
if (ospf6 == NULL)
693702
ospf6 = ospf6_instance_create(vrf_name);
694703

704+
ospf6_ietf_routing_protocol_xpath(xpath, sizeof(xpath), ospf6);
705+
nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
706+
ret = nb_cli_apply_changes(vty, NULL);
707+
if (ret != CMD_SUCCESS)
708+
return ret;
709+
695710
/* set current ospf point. */
696711
VTY_PUSH_CONTEXT(OSPF6_NODE, ospf6);
697712

@@ -704,7 +719,9 @@ DEFUN(no_router_ospf6, no_router_ospf6_cmd, "no router ospf6 [vrf NAME]",
704719
{
705720
struct ospf6 *ospf6;
706721
const char *vrf_name = VRF_DEFAULT_NAME;
722+
char xpath[XPATH_MAXLEN];
707723
int idx_vrf = 0;
724+
int ret = CMD_SUCCESS;
708725

709726
if (argv_find(argv, argc, "vrf", &idx_vrf)) {
710727
vrf_name = argv[idx_vrf + 1]->arg;
@@ -714,16 +731,19 @@ DEFUN(no_router_ospf6, no_router_ospf6_cmd, "no router ospf6 [vrf NAME]",
714731
if (ospf6 == NULL)
715732
vty_out(vty, "OSPFv3 is not configured\n");
716733
else {
734+
ospf6_ietf_routing_protocol_xpath(xpath, sizeof(xpath), ospf6);
717735
if (ospf6->gr_info.restart_support)
718736
ospf6_gr_nvm_delete(ospf6);
719737

720738
ospf6_delete(&ospf6);
739+
nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
740+
ret = nb_cli_apply_changes_clear_pending(vty, "%s", xpath);
721741
}
722742

723743
/* return to config node . */
724744
VTY_PUSH_CONTEXT_NULL(CONFIG_NODE);
725745

726-
return CMD_SUCCESS;
746+
return ret;
727747
}
728748

729749
static void ospf6_db_clear(struct ospf6 *ospf6)
@@ -810,8 +830,8 @@ DEFPY (clear_router_ospf6,
810830
static int ospf6_router_id_xpath(char *xpath, size_t size, const struct ospf6 *o)
811831
{
812832
return snprintf(xpath, size,
813-
"/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-ospf:ospfv3'][name='%s']/ietf-ospf:ospf/explicit-router-id",
814-
o->name ? o->name : "default");
833+
OSPF6D_IETF_ROUTING_PROTOCOL_XPATH "/ietf-ospf:ospf/explicit-router-id",
834+
o->name ? o->name : VRF_DEFAULT_NAME);
815835
}
816836

817837
/*

ospfd/ospf_main.c

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -153,15 +153,27 @@ static const struct frr_yang_module_info *const ospfd_yang_modules[] = {
153153
/*
154154
* ospfd and ospf6d both register the RFC 9129 ietf-ospf control-plane-protocol
155155
* subtree. Filter on the `type` list-key so mgmtd dispatches each change to
156-
* the daemon that owns that protocol family. See the predicate-aware matching
157-
* in mgmtd/mgmt_be_adapter.c::mgmt_be_xpath_prefix().
156+
* the daemon that owns that protocol family. In ospfd daemon-instance mode,
157+
* each process narrows this further to its own `name` key so `ospfd-1` and
158+
* `ospfd-2` do not both receive the same YANG edit.
159+
*
160+
* See the predicate-aware matching in
161+
* mgmtd/mgmt_be_adapter.c::mgmt_be_xpath_prefix().
158162
*/
159163
static const char *const ospfd_oper_xpaths[] = {
160-
"/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-ospf:ospfv2']",
164+
OSPFD_IETF_ROUTING_PROTOCOL_TYPE_XPATH,
161165
};
162166

163167
static const char *const ospfd_config_xpaths[] = {
164-
"/ietf-routing:routing/control-plane-protocols/control-plane-protocol[type='ietf-ospf:ospfv2']",
168+
OSPFD_IETF_ROUTING_PROTOCOL_TYPE_XPATH,
169+
};
170+
171+
static char ospfd_instance_xpath[XPATH_MAXLEN];
172+
static const char *const ospfd_instance_oper_xpaths[] = {
173+
ospfd_instance_xpath,
174+
};
175+
static const char *const ospfd_instance_config_xpaths[] = {
176+
ospfd_instance_xpath,
165177
};
166178

167179
struct mgmt_be_client_cbs ospfd_be_client_data = {
@@ -171,6 +183,20 @@ struct mgmt_be_client_cbs ospfd_be_client_data = {
171183
.noper_xpaths = array_size(ospfd_oper_xpaths),
172184
};
173185

186+
static void ospfd_mgmt_be_init(void)
187+
{
188+
if (!ospf_instance)
189+
return;
190+
191+
ospfd_ietf_routing_protocol_instance_xpath(
192+
ospfd_instance_xpath, sizeof(ospfd_instance_xpath),
193+
ospf_instance, VRF_DEFAULT_NAME);
194+
ospfd_be_client_data.config_xpaths = ospfd_instance_config_xpaths;
195+
ospfd_be_client_data.nconfig_xpaths = array_size(ospfd_instance_config_xpaths);
196+
ospfd_be_client_data.oper_xpaths = ospfd_instance_oper_xpaths;
197+
ospfd_be_client_data.noper_xpaths = array_size(ospfd_instance_oper_xpaths);
198+
}
199+
174200
/* actual paths filled in main() */
175201
static char state_path[512];
176202
static char state_compat1_path[512];
@@ -332,6 +358,7 @@ int main(int argc, char **argv)
332358
/* OSPF errors init */
333359
ospf_error_init();
334360

361+
ospfd_mgmt_be_init();
335362
mgmt_be_client = mgmt_be_client_create("ospfd", &ospfd_be_client_data, 0, master);
336363

337364
frr_config_fork();

0 commit comments

Comments
 (0)