]> git.proxmox.com Git - mirror_frr.git/blame - lib/mgmt_fe_client.c
mgmtd: fix reading of config file[s]
[mirror_frr.git] / lib / mgmt_fe_client.c
CommitLineData
ef43a632
CH
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * MGMTD Frontend Client Library api interfaces
4 * Copyright (C) 2021 Vmware, Inc.
5 * Pushpasis Sarkar <spushpasis@vmware.com>
6 */
7
8#include <zebra.h>
070c5e7a 9#include "compiler.h"
cfa0facb 10#include "debug.h"
ef43a632
CH
11#include "memory.h"
12#include "libfrr.h"
13#include "mgmt_fe_client.h"
f82370b4 14#include "mgmt_msg.h"
ef43a632
CH
15#include "mgmt_pb.h"
16#include "network.h"
17#include "stream.h"
18#include "sockopt.h"
19
cfa0facb
CH
20#include "lib/mgmt_fe_client_clippy.c"
21
ef43a632
CH
22struct mgmt_fe_client_ctx;
23
24PREDECL_LIST(mgmt_sessions);
25
26struct mgmt_fe_client_session {
d6665cf6
CH
27 uint64_t client_id; /* FE client identifies itself with this ID */
28 uint64_t session_id; /* FE adapter identified session with this ID */
ef43a632
CH
29 struct mgmt_fe_client_ctx *client_ctx;
30 uintptr_t user_ctx;
31
32 struct mgmt_sessions_item list_linkage;
33};
34
35DECLARE_LIST(mgmt_sessions, struct mgmt_fe_client_session, list_linkage);
36
37DEFINE_MTYPE_STATIC(LIB, MGMTD_FE_SESSION, "MGMTD Frontend session");
38
39struct mgmt_fe_client_ctx {
070c5e7a 40 struct msg_client client;
ef43a632 41 struct mgmt_fe_client_params client_params;
ef43a632
CH
42 struct mgmt_sessions_head client_sessions;
43};
44
ef43a632
CH
45#define FOREACH_SESSION_IN_LIST(client_ctx, session) \
46 frr_each_safe (mgmt_sessions, &(client_ctx)->client_sessions, (session))
47
cfa0facb 48struct debug mgmt_dbg_fe_client = {0, "Management frontend client operations"};
ef43a632 49
f82370b4 50static struct mgmt_fe_client_ctx mgmt_fe_client_ctx = {
070c5e7a 51 .client = {.conn = {.fd = -1}}};
ef43a632
CH
52
53static struct mgmt_fe_client_session *
54mgmt_fe_find_session_by_client_id(struct mgmt_fe_client_ctx *client_ctx,
d6665cf6 55 uint64_t client_id)
ef43a632
CH
56{
57 struct mgmt_fe_client_session *session;
58
59 FOREACH_SESSION_IN_LIST (client_ctx, session) {
60 if (session->client_id == client_id) {
d6665cf6
CH
61 MGMTD_FE_CLIENT_DBG("Found session-id %" PRIu64
62 " using client-id %" PRIu64,
63 session->session_id, client_id);
ef43a632
CH
64 return session;
65 }
66 }
d6665cf6
CH
67 MGMTD_FE_CLIENT_DBG("Session not found using client-id %" PRIu64,
68 client_id);
ef43a632
CH
69 return NULL;
70}
71
72static struct mgmt_fe_client_session *
73mgmt_fe_find_session_by_session_id(struct mgmt_fe_client_ctx *client_ctx,
d6665cf6 74 uint64_t session_id)
ef43a632
CH
75{
76 struct mgmt_fe_client_session *session;
77
78 FOREACH_SESSION_IN_LIST (client_ctx, session) {
79 if (session->session_id == session_id) {
80 MGMTD_FE_CLIENT_DBG(
d6665cf6
CH
81 "Found session of client-id %" PRIu64
82 " using session-id %" PRIu64,
83 session->client_id, session_id);
ef43a632
CH
84 return session;
85 }
86 }
d6665cf6
CH
87 MGMTD_FE_CLIENT_DBG("Session not found using session-id %" PRIu64,
88 session_id);
ef43a632
CH
89 return NULL;
90}
91
f82370b4 92static int mgmt_fe_client_send_msg(struct mgmt_fe_client_ctx *client_ctx,
5f05ff58
CH
93 Mgmtd__FeMessage *fe_msg,
94 bool short_circuit_ok)
ef43a632 95{
070c5e7a
CH
96 return msg_conn_send_msg(
97 &client_ctx->client.conn, MGMT_MSG_VERSION_PROTOBUF, fe_msg,
f82370b4 98 mgmtd__fe_message__get_packed_size(fe_msg),
5f05ff58
CH
99 (size_t(*)(void *, void *))mgmtd__fe_message__pack,
100 short_circuit_ok);
ef43a632
CH
101}
102
d6665cf6 103static int mgmt_fe_send_register_req(struct mgmt_fe_client_ctx *client_ctx)
ef43a632
CH
104{
105 Mgmtd__FeMessage fe_msg;
106 Mgmtd__FeRegisterReq rgstr_req;
107
108 mgmtd__fe_register_req__init(&rgstr_req);
109 rgstr_req.client_name = client_ctx->client_params.name;
110
111 mgmtd__fe_message__init(&fe_msg);
112 fe_msg.message_case = MGMTD__FE_MESSAGE__MESSAGE_REGISTER_REQ;
113 fe_msg.register_req = &rgstr_req;
114
115 MGMTD_FE_CLIENT_DBG(
116 "Sending REGISTER_REQ message to MGMTD Frontend server");
117
5f05ff58 118 return mgmt_fe_client_send_msg(client_ctx, &fe_msg, true);
ef43a632
CH
119}
120
d6665cf6
CH
121static int mgmt_fe_send_session_req(struct mgmt_fe_client_ctx *client_ctx,
122 struct mgmt_fe_client_session *session,
123 bool create)
ef43a632
CH
124{
125 Mgmtd__FeMessage fe_msg;
126 Mgmtd__FeSessionReq sess_req;
5f05ff58 127 bool scok;
ef43a632
CH
128
129 mgmtd__fe_session_req__init(&sess_req);
130 sess_req.create = create;
131 if (create) {
132 sess_req.id_case = MGMTD__FE_SESSION_REQ__ID_CLIENT_CONN_ID;
133 sess_req.client_conn_id = session->client_id;
5f05ff58 134 scok = true;
ef43a632
CH
135 } else {
136 sess_req.id_case = MGMTD__FE_SESSION_REQ__ID_SESSION_ID;
137 sess_req.session_id = session->session_id;
5f05ff58 138 scok = false;
ef43a632
CH
139 }
140
141 mgmtd__fe_message__init(&fe_msg);
142 fe_msg.message_case = MGMTD__FE_MESSAGE__MESSAGE_SESSION_REQ;
143 fe_msg.session_req = &sess_req;
144
145 MGMTD_FE_CLIENT_DBG(
d6665cf6
CH
146 "Sending SESSION_REQ %s message for client-id %" PRIu64,
147 create ? "create" : "destroy", session->client_id);
ef43a632 148
5f05ff58 149 return mgmt_fe_client_send_msg(client_ctx, &fe_msg, scok);
ef43a632
CH
150}
151
d6665cf6
CH
152static int mgmt_fe_send_lockds_req(struct mgmt_fe_client_ctx *client_ctx,
153 uint64_t session_id, bool lock,
154 uint64_t req_id, Mgmtd__DatastoreId ds_id)
ef43a632
CH
155{
156 (void)req_id;
157 Mgmtd__FeMessage fe_msg;
158 Mgmtd__FeLockDsReq lockds_req;
159
160 mgmtd__fe_lock_ds_req__init(&lockds_req);
d6665cf6 161 lockds_req.session_id = session_id;
ef43a632
CH
162 lockds_req.req_id = req_id;
163 lockds_req.ds_id = ds_id;
164 lockds_req.lock = lock;
165
166 mgmtd__fe_message__init(&fe_msg);
167 fe_msg.message_case = MGMTD__FE_MESSAGE__MESSAGE_LOCKDS_REQ;
168 fe_msg.lockds_req = &lockds_req;
169
170 MGMTD_FE_CLIENT_DBG(
d6665cf6
CH
171 "Sending %sLOCK_REQ message for Ds:%d session-id %" PRIu64,
172 lock ? "" : "UN", ds_id, session_id);
ef43a632 173
5f05ff58 174 return mgmt_fe_client_send_msg(client_ctx, &fe_msg, false);
ef43a632
CH
175}
176
d6665cf6
CH
177static int mgmt_fe_send_setcfg_req(struct mgmt_fe_client_ctx *client_ctx,
178 uint64_t session_id, uint64_t req_id,
179 Mgmtd__DatastoreId ds_id,
180 Mgmtd__YangCfgDataReq **data_req,
181 int num_data_reqs, bool implicit_commit,
182 Mgmtd__DatastoreId dst_ds_id)
ef43a632
CH
183{
184 (void)req_id;
185 Mgmtd__FeMessage fe_msg;
186 Mgmtd__FeSetConfigReq setcfg_req;
187
188 mgmtd__fe_set_config_req__init(&setcfg_req);
d6665cf6 189 setcfg_req.session_id = session_id;
ef43a632
CH
190 setcfg_req.ds_id = ds_id;
191 setcfg_req.req_id = req_id;
192 setcfg_req.data = data_req;
193 setcfg_req.n_data = (size_t)num_data_reqs;
194 setcfg_req.implicit_commit = implicit_commit;
195 setcfg_req.commit_ds_id = dst_ds_id;
196
197 mgmtd__fe_message__init(&fe_msg);
198 fe_msg.message_case = MGMTD__FE_MESSAGE__MESSAGE_SETCFG_REQ;
199 fe_msg.setcfg_req = &setcfg_req;
200
201 MGMTD_FE_CLIENT_DBG(
d6665cf6
CH
202 "Sending SET_CONFIG_REQ message for Ds:%d session-id %" PRIu64
203 " (#xpaths:%d)",
204 ds_id, session_id, num_data_reqs);
ef43a632 205
5f05ff58 206 return mgmt_fe_client_send_msg(client_ctx, &fe_msg, false);
ef43a632
CH
207}
208
83b78f43 209static int mgmt_fe_send_commitcfg_req(struct mgmt_fe_client_ctx *client_ctx,
d6665cf6 210 uint64_t session_id, uint64_t req_id,
83b78f43 211 Mgmtd__DatastoreId src_ds_id,
212 Mgmtd__DatastoreId dest_ds_id,
213 bool validate_only, bool abort)
ef43a632
CH
214{
215 (void)req_id;
216 Mgmtd__FeMessage fe_msg;
217 Mgmtd__FeCommitConfigReq commitcfg_req;
218
219 mgmtd__fe_commit_config_req__init(&commitcfg_req);
d6665cf6 220 commitcfg_req.session_id = session_id;
ef43a632
CH
221 commitcfg_req.src_ds_id = src_ds_id;
222 commitcfg_req.dst_ds_id = dest_ds_id;
223 commitcfg_req.req_id = req_id;
224 commitcfg_req.validate_only = validate_only;
225 commitcfg_req.abort = abort;
226
227 mgmtd__fe_message__init(&fe_msg);
228 fe_msg.message_case = MGMTD__FE_MESSAGE__MESSAGE_COMMCFG_REQ;
229 fe_msg.commcfg_req = &commitcfg_req;
230
231 MGMTD_FE_CLIENT_DBG(
d6665cf6
CH
232 "Sending COMMIT_CONFIG_REQ message for Src-Ds:%d, Dst-Ds:%d session-id %" PRIu64,
233 src_ds_id, dest_ds_id, session_id);
ef43a632 234
5f05ff58 235 return mgmt_fe_client_send_msg(client_ctx, &fe_msg, false);
ef43a632
CH
236}
237
d6665cf6
CH
238static int mgmt_fe_send_getcfg_req(struct mgmt_fe_client_ctx *client_ctx,
239 uint64_t session_id, uint64_t req_id,
240 Mgmtd__DatastoreId ds_id,
241 Mgmtd__YangGetDataReq *data_req[],
242 int num_data_reqs)
ef43a632
CH
243{
244 (void)req_id;
245 Mgmtd__FeMessage fe_msg;
246 Mgmtd__FeGetConfigReq getcfg_req;
247
248 mgmtd__fe_get_config_req__init(&getcfg_req);
d6665cf6 249 getcfg_req.session_id = session_id;
ef43a632
CH
250 getcfg_req.ds_id = ds_id;
251 getcfg_req.req_id = req_id;
252 getcfg_req.data = data_req;
253 getcfg_req.n_data = (size_t)num_data_reqs;
254
255 mgmtd__fe_message__init(&fe_msg);
256 fe_msg.message_case = MGMTD__FE_MESSAGE__MESSAGE_GETCFG_REQ;
257 fe_msg.getcfg_req = &getcfg_req;
258
259 MGMTD_FE_CLIENT_DBG(
d6665cf6
CH
260 "Sending GET_CONFIG_REQ message for Ds:%d session-id %" PRIu64
261 " (#xpaths:%d)",
262 ds_id, session_id, num_data_reqs);
ef43a632 263
5f05ff58 264 return mgmt_fe_client_send_msg(client_ctx, &fe_msg, false);
ef43a632
CH
265}
266
d6665cf6
CH
267static int mgmt_fe_send_getdata_req(struct mgmt_fe_client_ctx *client_ctx,
268 uint64_t session_id, uint64_t req_id,
269 Mgmtd__DatastoreId ds_id,
270 Mgmtd__YangGetDataReq *data_req[],
271 int num_data_reqs)
ef43a632
CH
272{
273 (void)req_id;
274 Mgmtd__FeMessage fe_msg;
275 Mgmtd__FeGetDataReq getdata_req;
276
277 mgmtd__fe_get_data_req__init(&getdata_req);
d6665cf6 278 getdata_req.session_id = session_id;
ef43a632
CH
279 getdata_req.ds_id = ds_id;
280 getdata_req.req_id = req_id;
281 getdata_req.data = data_req;
282 getdata_req.n_data = (size_t)num_data_reqs;
283
284 mgmtd__fe_message__init(&fe_msg);
285 fe_msg.message_case = MGMTD__FE_MESSAGE__MESSAGE_GETDATA_REQ;
286 fe_msg.getdata_req = &getdata_req;
287
288 MGMTD_FE_CLIENT_DBG(
d6665cf6
CH
289 "Sending GET_CONFIG_REQ message for Ds:%d session-id %" PRIu64
290 " (#xpaths:%d)",
291 ds_id, session_id, num_data_reqs);
ef43a632 292
5f05ff58 293 return mgmt_fe_client_send_msg(client_ctx, &fe_msg, false);
ef43a632
CH
294}
295
d6665cf6
CH
296static int mgmt_fe_send_regnotify_req(struct mgmt_fe_client_ctx *client_ctx,
297 uint64_t session_id, uint64_t req_id,
298 Mgmtd__DatastoreId ds_id,
299 bool register_req,
300 Mgmtd__YangDataXPath *data_req[],
301 int num_data_reqs)
ef43a632
CH
302{
303 (void)req_id;
304 Mgmtd__FeMessage fe_msg;
305 Mgmtd__FeRegisterNotifyReq regntfy_req;
306
307 mgmtd__fe_register_notify_req__init(&regntfy_req);
d6665cf6 308 regntfy_req.session_id = session_id;
ef43a632
CH
309 regntfy_req.ds_id = ds_id;
310 regntfy_req.register_req = register_req;
311 regntfy_req.data_xpath = data_req;
312 regntfy_req.n_data_xpath = (size_t)num_data_reqs;
313
314 mgmtd__fe_message__init(&fe_msg);
315 fe_msg.message_case = MGMTD__FE_MESSAGE__MESSAGE_REGNOTIFY_REQ;
316 fe_msg.regnotify_req = &regntfy_req;
317
5f05ff58 318 return mgmt_fe_client_send_msg(client_ctx, &fe_msg, false);
ef43a632
CH
319}
320
d6665cf6
CH
321static int mgmt_fe_client_handle_msg(struct mgmt_fe_client_ctx *client_ctx,
322 Mgmtd__FeMessage *fe_msg)
ef43a632
CH
323{
324 struct mgmt_fe_client_session *session = NULL;
325
0b645fd2
CH
326 /*
327 * protobuf-c adds a max size enum with an internal, and changing by
328 * version, name; cast to an int to avoid unhandled enum warnings
329 */
330 switch ((int)fe_msg->message_case) {
ef43a632 331 case MGMTD__FE_MESSAGE__MESSAGE_SESSION_REPLY:
d6665cf6
CH
332 if (fe_msg->session_reply->create &&
333 fe_msg->session_reply->has_client_conn_id) {
ef43a632 334 MGMTD_FE_CLIENT_DBG(
d6665cf6
CH
335 "Got SESSION_REPLY (create) for client-id %" PRIu64
336 " with session-id: %" PRIu64,
337 fe_msg->session_reply->client_conn_id,
338 fe_msg->session_reply->session_id);
ef43a632
CH
339
340 session = mgmt_fe_find_session_by_client_id(
341 client_ctx,
342 fe_msg->session_reply->client_conn_id);
343
344 if (session && fe_msg->session_reply->success) {
345 MGMTD_FE_CLIENT_DBG(
d6665cf6
CH
346 "Session Created for client-id %" PRIu64,
347 fe_msg->session_reply->client_conn_id);
ef43a632
CH
348 session->session_id =
349 fe_msg->session_reply->session_id;
350 } else {
351 MGMTD_FE_CLIENT_ERR(
d6665cf6
CH
352 "Session Create failed for client-id %" PRIu64,
353 fe_msg->session_reply->client_conn_id);
ef43a632
CH
354 }
355 } else if (!fe_msg->session_reply->create) {
356 MGMTD_FE_CLIENT_DBG(
d6665cf6
CH
357 "Got SESSION_REPLY (destroy) for session-id %" PRIu64,
358 fe_msg->session_reply->session_id);
ef43a632
CH
359
360 session = mgmt_fe_find_session_by_session_id(
361 client_ctx, fe_msg->session_req->session_id);
362 }
363
d6665cf6
CH
364 if (session && session->client_ctx &&
365 session->client_ctx->client_params.client_session_notify)
ef43a632
CH
366 (*session->client_ctx->client_params
367 .client_session_notify)(
368 (uintptr_t)client_ctx,
369 client_ctx->client_params.user_data,
370 session->client_id,
371 fe_msg->session_reply->create,
372 fe_msg->session_reply->success,
d6665cf6
CH
373 fe_msg->session_reply->session_id,
374 session->user_ctx);
ef43a632
CH
375 break;
376 case MGMTD__FE_MESSAGE__MESSAGE_LOCKDS_REPLY:
d6665cf6
CH
377 MGMTD_FE_CLIENT_DBG("Got LOCKDS_REPLY for session-id %" PRIu64,
378 fe_msg->lockds_reply->session_id);
ef43a632
CH
379 session = mgmt_fe_find_session_by_session_id(
380 client_ctx, fe_msg->lockds_reply->session_id);
381
d6665cf6
CH
382 if (session && session->client_ctx &&
383 session->client_ctx->client_params.lock_ds_notify)
384 (*session->client_ctx->client_params.lock_ds_notify)(
ef43a632
CH
385 (uintptr_t)client_ctx,
386 client_ctx->client_params.user_data,
d6665cf6
CH
387 session->client_id,
388 fe_msg->lockds_reply->session_id,
389 session->user_ctx, fe_msg->lockds_reply->req_id,
ef43a632
CH
390 fe_msg->lockds_reply->lock,
391 fe_msg->lockds_reply->success,
392 fe_msg->lockds_reply->ds_id,
393 fe_msg->lockds_reply->error_if_any);
394 break;
395 case MGMTD__FE_MESSAGE__MESSAGE_SETCFG_REPLY:
d6665cf6
CH
396 MGMTD_FE_CLIENT_DBG("Got SETCFG_REPLY for session-id %" PRIu64,
397 fe_msg->setcfg_reply->session_id);
ef43a632
CH
398
399 session = mgmt_fe_find_session_by_session_id(
400 client_ctx, fe_msg->setcfg_reply->session_id);
401
d6665cf6
CH
402 if (session && session->client_ctx &&
403 session->client_ctx->client_params.set_config_notify)
404 (*session->client_ctx->client_params.set_config_notify)(
ef43a632
CH
405 (uintptr_t)client_ctx,
406 client_ctx->client_params.user_data,
d6665cf6
CH
407 session->client_id,
408 fe_msg->setcfg_reply->session_id,
409 session->user_ctx, fe_msg->setcfg_reply->req_id,
ef43a632
CH
410 fe_msg->setcfg_reply->success,
411 fe_msg->setcfg_reply->ds_id,
412 fe_msg->setcfg_reply->error_if_any);
413 break;
414 case MGMTD__FE_MESSAGE__MESSAGE_COMMCFG_REPLY:
d6665cf6
CH
415 MGMTD_FE_CLIENT_DBG("Got COMMCFG_REPLY for session-id %" PRIu64,
416 fe_msg->commcfg_reply->session_id);
ef43a632
CH
417
418 session = mgmt_fe_find_session_by_session_id(
419 client_ctx, fe_msg->commcfg_reply->session_id);
420
d6665cf6
CH
421 if (session && session->client_ctx &&
422 session->client_ctx->client_params.commit_config_notify)
ef43a632
CH
423 (*session->client_ctx->client_params
424 .commit_config_notify)(
425 (uintptr_t)client_ctx,
426 client_ctx->client_params.user_data,
d6665cf6
CH
427 session->client_id,
428 fe_msg->commcfg_reply->session_id,
ef43a632
CH
429 session->user_ctx,
430 fe_msg->commcfg_reply->req_id,
431 fe_msg->commcfg_reply->success,
432 fe_msg->commcfg_reply->src_ds_id,
433 fe_msg->commcfg_reply->dst_ds_id,
434 fe_msg->commcfg_reply->validate_only,
435 fe_msg->commcfg_reply->error_if_any);
436 break;
437 case MGMTD__FE_MESSAGE__MESSAGE_GETCFG_REPLY:
d6665cf6
CH
438 MGMTD_FE_CLIENT_DBG("Got GETCFG_REPLY for session-id %" PRIu64,
439 fe_msg->getcfg_reply->session_id);
ef43a632
CH
440
441 session = mgmt_fe_find_session_by_session_id(
442 client_ctx, fe_msg->getcfg_reply->session_id);
443
d6665cf6
CH
444 if (session && session->client_ctx &&
445 session->client_ctx->client_params.get_data_notify)
446 (*session->client_ctx->client_params.get_data_notify)(
ef43a632
CH
447 (uintptr_t)client_ctx,
448 client_ctx->client_params.user_data,
d6665cf6
CH
449 session->client_id,
450 fe_msg->getcfg_reply->session_id,
451 session->user_ctx, fe_msg->getcfg_reply->req_id,
ef43a632
CH
452 fe_msg->getcfg_reply->success,
453 fe_msg->getcfg_reply->ds_id,
454 fe_msg->getcfg_reply->data
455 ? fe_msg->getcfg_reply->data->data
456 : NULL,
457 fe_msg->getcfg_reply->data
458 ? fe_msg->getcfg_reply->data->n_data
459 : 0,
460 fe_msg->getcfg_reply->data
d6665cf6 461 ? fe_msg->getcfg_reply->data->next_indx
ef43a632
CH
462 : 0,
463 fe_msg->getcfg_reply->error_if_any);
464 break;
465 case MGMTD__FE_MESSAGE__MESSAGE_GETDATA_REPLY:
d6665cf6
CH
466 MGMTD_FE_CLIENT_DBG("Got GETDATA_REPLY for session-id %" PRIu64,
467 fe_msg->getdata_reply->session_id);
ef43a632
CH
468
469 session = mgmt_fe_find_session_by_session_id(
470 client_ctx, fe_msg->getdata_reply->session_id);
471
d6665cf6
CH
472 if (session && session->client_ctx &&
473 session->client_ctx->client_params.get_data_notify)
474 (*session->client_ctx->client_params.get_data_notify)(
ef43a632
CH
475 (uintptr_t)client_ctx,
476 client_ctx->client_params.user_data,
d6665cf6
CH
477 session->client_id,
478 fe_msg->getdata_reply->session_id,
ef43a632
CH
479 session->user_ctx,
480 fe_msg->getdata_reply->req_id,
481 fe_msg->getdata_reply->success,
482 fe_msg->getdata_reply->ds_id,
483 fe_msg->getdata_reply->data
484 ? fe_msg->getdata_reply->data->data
485 : NULL,
486 fe_msg->getdata_reply->data
d6665cf6 487 ? fe_msg->getdata_reply->data->n_data
ef43a632
CH
488 : 0,
489 fe_msg->getdata_reply->data
d6665cf6 490 ? fe_msg->getdata_reply->data->next_indx
ef43a632
CH
491 : 0,
492 fe_msg->getdata_reply->error_if_any);
493 break;
494 case MGMTD__FE_MESSAGE__MESSAGE_NOTIFY_DATA_REQ:
495 case MGMTD__FE_MESSAGE__MESSAGE_REGNOTIFY_REQ:
496 /*
497 * TODO: Add handling code in future.
498 */
499 break;
500 /*
501 * NOTE: The following messages are always sent from Frontend
502 * clients to MGMTd only and/or need not be handled here.
503 */
504 case MGMTD__FE_MESSAGE__MESSAGE_REGISTER_REQ:
505 case MGMTD__FE_MESSAGE__MESSAGE_SESSION_REQ:
506 case MGMTD__FE_MESSAGE__MESSAGE_LOCKDS_REQ:
507 case MGMTD__FE_MESSAGE__MESSAGE_SETCFG_REQ:
508 case MGMTD__FE_MESSAGE__MESSAGE_COMMCFG_REQ:
509 case MGMTD__FE_MESSAGE__MESSAGE_GETCFG_REQ:
510 case MGMTD__FE_MESSAGE__MESSAGE_GETDATA_REQ:
511 case MGMTD__FE_MESSAGE__MESSAGE__NOT_SET:
ef43a632
CH
512 default:
513 /*
514 * A 'default' case is being added contrary to the
515 * FRR code guidelines to take care of build
516 * failures on certain build systems (courtesy of
517 * the proto-c package).
518 */
519 break;
520 }
521
522 return 0;
523}
524
070c5e7a
CH
525static void mgmt_fe_client_process_msg(uint8_t version, uint8_t *data,
526 size_t len, struct msg_conn *conn)
ef43a632 527{
070c5e7a
CH
528 struct mgmt_fe_client_ctx *client_ctx;
529 struct msg_client *client;
ef43a632 530 Mgmtd__FeMessage *fe_msg;
ef43a632 531
070c5e7a
CH
532 client = container_of(conn, struct msg_client, conn);
533 client_ctx = container_of(client, struct mgmt_fe_client_ctx, client);
534
f82370b4
CH
535 fe_msg = mgmtd__fe_message__unpack(NULL, len, data);
536 if (!fe_msg) {
537 MGMTD_FE_CLIENT_DBG("Failed to decode %zu bytes from server.",
538 len);
539 return;
ef43a632 540 }
f82370b4
CH
541 MGMTD_FE_CLIENT_DBG(
542 "Decoded %zu bytes of message(msg: %u/%u) from server", len,
543 fe_msg->message_case, fe_msg->message_case);
544 (void)mgmt_fe_client_handle_msg(client_ctx, fe_msg);
545 mgmtd__fe_message__free_unpacked(fe_msg, NULL);
ef43a632
CH
546}
547
070c5e7a 548static int _notify_connect_disconnect(struct msg_client *client, bool connected)
ef43a632 549{
070c5e7a
CH
550 struct mgmt_fe_client_ctx *client_ctx =
551 container_of(client, struct mgmt_fe_client_ctx, client);
552 int ret;
ef43a632 553
f82370b4 554 /* Send REGISTER_REQ message */
070c5e7a
CH
555 if (connected) {
556 if ((ret = mgmt_fe_send_register_req(client_ctx)) != 0)
557 return ret;
ef43a632
CH
558 }
559
070c5e7a 560 /* Notify FE client through registered callback (if any). */
ef43a632
CH
561 if (client_ctx->client_params.client_connect_notify)
562 (void)(*client_ctx->client_params.client_connect_notify)(
563 (uintptr_t)client_ctx,
070c5e7a
CH
564 client_ctx->client_params.user_data, connected);
565 return 0;
ef43a632
CH
566}
567
070c5e7a 568static int mgmt_fe_client_notify_connect(struct msg_client *client)
ef43a632 569{
070c5e7a 570 return _notify_connect_disconnect(client, true);
ef43a632
CH
571}
572
070c5e7a 573static int mgmt_fe_client_notify_disconnect(struct msg_conn *conn)
ef43a632 574{
070c5e7a 575 struct msg_client *client = container_of(conn, struct msg_client, conn);
ef43a632 576
070c5e7a 577 return _notify_connect_disconnect(client, false);
ef43a632
CH
578}
579
ef43a632 580
cfa0facb
CH
581DEFPY(debug_mgmt_client_fe, debug_mgmt_client_fe_cmd,
582 "[no] debug mgmt client frontend",
583 NO_STR DEBUG_STR MGMTD_STR
584 "client\n"
585 "frontend\n")
586{
587 uint32_t mode = DEBUG_NODE2MODE(vty->node);
588
589 DEBUG_MODE_SET(&mgmt_dbg_fe_client, mode, !no);
590
591 return CMD_SUCCESS;
592}
593
594static void mgmt_debug_client_fe_set_all(uint32_t flags, bool set)
595{
596 DEBUG_FLAGS_SET(&mgmt_dbg_fe_client, flags, set);
597}
598
599static int mgmt_debug_fe_client_config_write(struct vty *vty)
600{
601 if (DEBUG_MODE_CHECK(&mgmt_dbg_fe_client, DEBUG_MODE_CONF))
602 vty_out(vty, "debug mgmt client frontend\n");
603
604 return CMD_SUCCESS;
605}
606
607void mgmt_debug_fe_client_show_debug(struct vty *vty)
608{
609 if (MGMTD_DBG_FE_CLIENT_CHECK())
610 vty_out(vty, "debug mgmt client frontend\n");
611}
612
613static struct debug_callbacks mgmt_dbg_fe_client_cbs = {
614 .debug_set_all = mgmt_debug_client_fe_set_all};
615
616static struct cmd_node mgmt_dbg_node = {
617 .name = "mgmt client frontend",
618 .node = DEBUG_NODE,
619 .prompt = "",
620 .config_write = mgmt_debug_fe_client_config_write,
621};
622
ef43a632
CH
623/*
624 * Initialize library and try connecting with MGMTD.
625 */
626uintptr_t mgmt_fe_client_lib_init(struct mgmt_fe_client_params *params,
cd9d0537 627 struct event_loop *master_thread)
ef43a632 628{
070c5e7a
CH
629 /* Don't call twice */
630 assert(!mgmt_fe_client_ctx.client.conn.loop);
ef43a632 631
070c5e7a 632 mgmt_fe_client_ctx.client_params = *params;
ef43a632
CH
633
634 mgmt_sessions_init(&mgmt_fe_client_ctx.client_sessions);
635
070c5e7a
CH
636 msg_client_init(&mgmt_fe_client_ctx.client, master_thread,
637 MGMTD_FE_SERVER_PATH, mgmt_fe_client_notify_connect,
638 mgmt_fe_client_notify_disconnect,
639 mgmt_fe_client_process_msg, MGMTD_FE_MAX_NUM_MSG_PROC,
edafa64c 640 MGMTD_FE_MAX_NUM_MSG_WRITE, MGMTD_FE_MSG_MAX_LEN, true,
070c5e7a 641 "FE-client", MGMTD_DBG_FE_CLIENT_CHECK());
ef43a632
CH
642
643 MGMTD_FE_CLIENT_DBG("Initialized client '%s'", params->name);
644
645 return (uintptr_t)&mgmt_fe_client_ctx;
646}
647
cfa0facb
CH
648void mgmt_fe_client_lib_vty_init(void)
649{
650 debug_init(&mgmt_dbg_fe_client_cbs);
651 install_node(&mgmt_dbg_node);
652 install_element(ENABLE_NODE, &debug_mgmt_client_fe_cmd);
653 install_element(CONFIG_NODE, &debug_mgmt_client_fe_cmd);
654}
655
ef43a632
CH
656/*
657 * Create a new Session for a Frontend Client connection.
658 */
659enum mgmt_result mgmt_fe_create_client_session(uintptr_t lib_hndl,
d6665cf6
CH
660 uint64_t client_id,
661 uintptr_t user_ctx)
ef43a632
CH
662{
663 struct mgmt_fe_client_ctx *client_ctx;
664 struct mgmt_fe_client_session *session;
665
666 client_ctx = (struct mgmt_fe_client_ctx *)lib_hndl;
667 if (!client_ctx)
668 return MGMTD_INVALID_PARAM;
669
670 session = XCALLOC(MTYPE_MGMTD_FE_SESSION,
d6665cf6 671 sizeof(struct mgmt_fe_client_session));
ef43a632
CH
672 assert(session);
673 session->user_ctx = user_ctx;
674 session->client_id = client_id;
675 session->client_ctx = client_ctx;
676 session->session_id = 0;
677
edafa64c
CH
678 mgmt_sessions_add_tail(&client_ctx->client_sessions, session);
679
ef43a632
CH
680 if (mgmt_fe_send_session_req(client_ctx, session, true) != 0) {
681 XFREE(MTYPE_MGMTD_FE_SESSION, session);
682 return MGMTD_INTERNAL_ERROR;
683 }
ef43a632
CH
684
685 return MGMTD_SUCCESS;
686}
687
688/*
689 * Delete an existing Session for a Frontend Client connection.
690 */
691enum mgmt_result mgmt_fe_destroy_client_session(uintptr_t lib_hndl,
692 uint64_t client_id)
693{
694 struct mgmt_fe_client_ctx *client_ctx;
695 struct mgmt_fe_client_session *session;
696
697 client_ctx = (struct mgmt_fe_client_ctx *)lib_hndl;
698 if (!client_ctx)
699 return MGMTD_INVALID_PARAM;
700
701 session = mgmt_fe_find_session_by_client_id(client_ctx, client_id);
702 if (!session || session->client_ctx != client_ctx)
703 return MGMTD_INVALID_PARAM;
704
705 if (session->session_id &&
706 mgmt_fe_send_session_req(client_ctx, session, false) != 0)
707 MGMTD_FE_CLIENT_ERR(
708 "Failed to send session destroy request for the session-id %lu",
709 (unsigned long)session->session_id);
710
711 mgmt_sessions_del(&client_ctx->client_sessions, session);
712 XFREE(MTYPE_MGMTD_FE_SESSION, session);
713
714 return MGMTD_SUCCESS;
715}
716
717static void mgmt_fe_destroy_client_sessions(uintptr_t lib_hndl)
718{
719 struct mgmt_fe_client_ctx *client_ctx;
720 struct mgmt_fe_client_session *session;
721
722 client_ctx = (struct mgmt_fe_client_ctx *)lib_hndl;
723 if (!client_ctx)
724 return;
725
726 FOREACH_SESSION_IN_LIST (client_ctx, session)
727 mgmt_fe_destroy_client_session(lib_hndl, session->client_id);
728}
729
730/*
731 * Send UN/LOCK_DS_REQ to MGMTD for a specific Datastore DS.
732 */
d6665cf6
CH
733enum mgmt_result mgmt_fe_lock_ds(uintptr_t lib_hndl, uint64_t session_id,
734 uint64_t req_id, Mgmtd__DatastoreId ds_id,
735 bool lock_ds)
ef43a632
CH
736{
737 struct mgmt_fe_client_ctx *client_ctx;
ef43a632
CH
738
739 client_ctx = (struct mgmt_fe_client_ctx *)lib_hndl;
740 if (!client_ctx)
741 return MGMTD_INVALID_PARAM;
742
d6665cf6
CH
743 if (mgmt_fe_send_lockds_req(client_ctx, session_id, lock_ds, req_id,
744 ds_id) != 0)
ef43a632
CH
745 return MGMTD_INTERNAL_ERROR;
746
747 return MGMTD_SUCCESS;
748}
749
750/*
751 * Send SET_CONFIG_REQ to MGMTD for one or more config data(s).
752 */
d6665cf6
CH
753enum mgmt_result mgmt_fe_set_config_data(uintptr_t lib_hndl,
754 uint64_t session_id, uint64_t req_id,
755 Mgmtd__DatastoreId ds_id,
756 Mgmtd__YangCfgDataReq **config_req,
757 int num_reqs, bool implicit_commit,
758 Mgmtd__DatastoreId dst_ds_id)
ef43a632
CH
759{
760 struct mgmt_fe_client_ctx *client_ctx;
ef43a632
CH
761
762 client_ctx = (struct mgmt_fe_client_ctx *)lib_hndl;
763 if (!client_ctx)
764 return MGMTD_INVALID_PARAM;
765
d6665cf6
CH
766 if (mgmt_fe_send_setcfg_req(client_ctx, session_id, req_id, ds_id,
767 config_req, num_reqs, implicit_commit,
768 dst_ds_id) != 0)
ef43a632
CH
769 return MGMTD_INTERNAL_ERROR;
770
771 return MGMTD_SUCCESS;
772}
773
774/*
775 * Send SET_CONFIG_REQ to MGMTD for one or more config data(s).
776 */
777enum mgmt_result mgmt_fe_commit_config_data(uintptr_t lib_hndl,
d6665cf6
CH
778 uint64_t session_id,
779 uint64_t req_id,
780 Mgmtd__DatastoreId src_ds_id,
781 Mgmtd__DatastoreId dst_ds_id,
782 bool validate_only, bool abort)
ef43a632
CH
783{
784 struct mgmt_fe_client_ctx *client_ctx;
ef43a632
CH
785
786 client_ctx = (struct mgmt_fe_client_ctx *)lib_hndl;
787 if (!client_ctx)
788 return MGMTD_INVALID_PARAM;
789
d6665cf6
CH
790 if (mgmt_fe_send_commitcfg_req(client_ctx, session_id, req_id,
791 src_ds_id, dst_ds_id, validate_only,
792 abort) != 0)
ef43a632
CH
793 return MGMTD_INTERNAL_ERROR;
794
795 return MGMTD_SUCCESS;
796}
797
798/*
799 * Send GET_CONFIG_REQ to MGMTD for one or more config data item(s).
800 */
d6665cf6
CH
801enum mgmt_result mgmt_fe_get_config_data(uintptr_t lib_hndl,
802 uint64_t session_id, uint64_t req_id,
803 Mgmtd__DatastoreId ds_id,
804 Mgmtd__YangGetDataReq *data_req[],
805 int num_reqs)
ef43a632
CH
806{
807 struct mgmt_fe_client_ctx *client_ctx;
ef43a632
CH
808
809 client_ctx = (struct mgmt_fe_client_ctx *)lib_hndl;
810 if (!client_ctx)
811 return MGMTD_INVALID_PARAM;
812
d6665cf6
CH
813 if (mgmt_fe_send_getcfg_req(client_ctx, session_id, req_id, ds_id,
814 data_req, num_reqs) != 0)
ef43a632
CH
815 return MGMTD_INTERNAL_ERROR;
816
817 return MGMTD_SUCCESS;
818}
819
820/*
821 * Send GET_DATA_REQ to MGMTD for one or more config data item(s).
822 */
d6665cf6
CH
823enum mgmt_result mgmt_fe_get_data(uintptr_t lib_hndl, uint64_t session_id,
824 uint64_t req_id, Mgmtd__DatastoreId ds_id,
825 Mgmtd__YangGetDataReq *data_req[],
826 int num_reqs)
ef43a632
CH
827{
828 struct mgmt_fe_client_ctx *client_ctx;
ef43a632
CH
829
830 client_ctx = (struct mgmt_fe_client_ctx *)lib_hndl;
831 if (!client_ctx)
832 return MGMTD_INVALID_PARAM;
833
d6665cf6
CH
834 if (mgmt_fe_send_getdata_req(client_ctx, session_id, req_id, ds_id,
835 data_req, num_reqs) != 0)
ef43a632
CH
836 return MGMTD_INTERNAL_ERROR;
837
838 return MGMTD_SUCCESS;
839}
840
841/*
842 * Send NOTIFY_REGISTER_REQ to MGMTD daemon.
843 */
844enum mgmt_result
d6665cf6
CH
845mgmt_fe_register_yang_notify(uintptr_t lib_hndl, uint64_t session_id,
846 uint64_t req_id, Mgmtd__DatastoreId ds_id,
847 bool register_req,
848 Mgmtd__YangDataXPath *data_req[], int num_reqs)
ef43a632
CH
849{
850 struct mgmt_fe_client_ctx *client_ctx;
ef43a632
CH
851
852 client_ctx = (struct mgmt_fe_client_ctx *)lib_hndl;
853 if (!client_ctx)
854 return MGMTD_INVALID_PARAM;
855
d6665cf6
CH
856 if (mgmt_fe_send_regnotify_req(client_ctx, session_id, req_id, ds_id,
857 register_req, data_req, num_reqs) != 0)
ef43a632
CH
858 return MGMTD_INTERNAL_ERROR;
859
860 return MGMTD_SUCCESS;
861}
862
863/*
864 * Destroy library and cleanup everything.
865 */
070c5e7a 866void mgmt_fe_client_lib_destroy(void)
ef43a632 867{
070c5e7a 868 struct mgmt_fe_client_ctx *client_ctx = &mgmt_fe_client_ctx;
ef43a632
CH
869
870 MGMTD_FE_CLIENT_DBG("Destroying MGMTD Frontend Client '%s'",
d6665cf6 871 client_ctx->client_params.name);
ef43a632 872
070c5e7a
CH
873 mgmt_fe_destroy_client_sessions((uintptr_t)client_ctx);
874 msg_client_cleanup(&client_ctx->client);
875 memset(client_ctx, 0, sizeof(*client_ctx));
ef43a632 876}