]> git.proxmox.com Git - mirror_frr.git/blob - lib/mgmt_fe_client.c
Merge pull request #13649 from donaldsharp/unlock_the_node_or_else
[mirror_frr.git] / lib / mgmt_fe_client.c
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>
9 #include "compiler.h"
10 #include "debug.h"
11 #include "memory.h"
12 #include "libfrr.h"
13 #include "mgmt_fe_client.h"
14 #include "mgmt_msg.h"
15 #include "mgmt_pb.h"
16 #include "network.h"
17 #include "stream.h"
18 #include "sockopt.h"
19
20 #include "lib/mgmt_fe_client_clippy.c"
21
22 PREDECL_LIST(mgmt_sessions);
23
24 struct mgmt_fe_client_session {
25 uint64_t client_id; /* FE client identifies itself with this ID */
26 uint64_t session_id; /* FE adapter identified session with this ID */
27 struct mgmt_fe_client *client;
28 uintptr_t user_ctx;
29
30 struct mgmt_sessions_item list_linkage;
31 };
32
33 DECLARE_LIST(mgmt_sessions, struct mgmt_fe_client_session, list_linkage);
34
35 DEFINE_MTYPE_STATIC(LIB, MGMTD_FE_CLIENT, "frontend client");
36 DEFINE_MTYPE_STATIC(LIB, MGMTD_FE_CLIENT_NAME, "frontend client name");
37 DEFINE_MTYPE_STATIC(LIB, MGMTD_FE_SESSION, "frontend session");
38
39 struct mgmt_fe_client {
40 struct msg_client client;
41 char *name;
42 struct mgmt_fe_client_cbs cbs;
43 uintptr_t user_data;
44 struct mgmt_sessions_head sessions;
45 };
46
47 #define FOREACH_SESSION_IN_LIST(client, session) \
48 frr_each_safe (mgmt_sessions, &(client)->sessions, (session))
49
50 struct debug mgmt_dbg_fe_client = {0, "Management frontend client operations"};
51
52
53 static struct mgmt_fe_client_session *
54 mgmt_fe_find_session_by_client_id(struct mgmt_fe_client *client,
55 uint64_t client_id)
56 {
57 struct mgmt_fe_client_session *session;
58
59 FOREACH_SESSION_IN_LIST (client, session) {
60 if (session->client_id == client_id) {
61 MGMTD_FE_CLIENT_DBG("Found session-id %" PRIu64
62 " using client-id %" PRIu64,
63 session->session_id, client_id);
64 return session;
65 }
66 }
67 MGMTD_FE_CLIENT_DBG("Session not found using client-id %" PRIu64,
68 client_id);
69 return NULL;
70 }
71
72 static struct mgmt_fe_client_session *
73 mgmt_fe_find_session_by_session_id(struct mgmt_fe_client *client,
74 uint64_t session_id)
75 {
76 struct mgmt_fe_client_session *session;
77
78 FOREACH_SESSION_IN_LIST (client, session) {
79 if (session->session_id == session_id) {
80 MGMTD_FE_CLIENT_DBG(
81 "Found session of client-id %" PRIu64
82 " using session-id %" PRIu64,
83 session->client_id, session_id);
84 return session;
85 }
86 }
87 MGMTD_FE_CLIENT_DBG("Session not found using session-id %" PRIu64,
88 session_id);
89 return NULL;
90 }
91
92 static int mgmt_fe_client_send_msg(struct mgmt_fe_client *client,
93 Mgmtd__FeMessage *fe_msg,
94 bool short_circuit_ok)
95 {
96 return msg_conn_send_msg(
97 &client->client.conn, MGMT_MSG_VERSION_PROTOBUF, fe_msg,
98 mgmtd__fe_message__get_packed_size(fe_msg),
99 (size_t(*)(void *, void *))mgmtd__fe_message__pack,
100 short_circuit_ok);
101 }
102
103 static int mgmt_fe_send_register_req(struct mgmt_fe_client *client)
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->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
118 return mgmt_fe_client_send_msg(client, &fe_msg, true);
119 }
120
121 static int mgmt_fe_send_session_req(struct mgmt_fe_client *client,
122 struct mgmt_fe_client_session *session,
123 bool create)
124 {
125 Mgmtd__FeMessage fe_msg;
126 Mgmtd__FeSessionReq sess_req;
127 bool scok;
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;
134 scok = true;
135 } else {
136 sess_req.id_case = MGMTD__FE_SESSION_REQ__ID_SESSION_ID;
137 sess_req.session_id = session->session_id;
138 scok = false;
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(
146 "Sending SESSION_REQ %s message for client-id %" PRIu64,
147 create ? "create" : "destroy", session->client_id);
148
149 return mgmt_fe_client_send_msg(client, &fe_msg, scok);
150 }
151
152 int mgmt_fe_send_lockds_req(struct mgmt_fe_client *client, uint64_t session_id,
153 uint64_t req_id, Mgmtd__DatastoreId ds_id,
154 bool lock)
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);
161 lockds_req.session_id = session_id;
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(
171 "Sending %sLOCK_REQ message for Ds:%d session-id %" PRIu64,
172 lock ? "" : "UN", ds_id, session_id);
173
174 return mgmt_fe_client_send_msg(client, &fe_msg, false);
175 }
176
177 int mgmt_fe_send_setcfg_req(struct mgmt_fe_client *client, uint64_t session_id,
178 uint64_t req_id, Mgmtd__DatastoreId ds_id,
179 Mgmtd__YangCfgDataReq **data_req, int num_data_reqs,
180 bool implicit_commit, Mgmtd__DatastoreId dst_ds_id)
181 {
182 (void)req_id;
183 Mgmtd__FeMessage fe_msg;
184 Mgmtd__FeSetConfigReq setcfg_req;
185
186 mgmtd__fe_set_config_req__init(&setcfg_req);
187 setcfg_req.session_id = session_id;
188 setcfg_req.ds_id = ds_id;
189 setcfg_req.req_id = req_id;
190 setcfg_req.data = data_req;
191 setcfg_req.n_data = (size_t)num_data_reqs;
192 setcfg_req.implicit_commit = implicit_commit;
193 setcfg_req.commit_ds_id = dst_ds_id;
194
195 mgmtd__fe_message__init(&fe_msg);
196 fe_msg.message_case = MGMTD__FE_MESSAGE__MESSAGE_SETCFG_REQ;
197 fe_msg.setcfg_req = &setcfg_req;
198
199 MGMTD_FE_CLIENT_DBG(
200 "Sending SET_CONFIG_REQ message for Ds:%d session-id %" PRIu64
201 " (#xpaths:%d)",
202 ds_id, session_id, num_data_reqs);
203
204 return mgmt_fe_client_send_msg(client, &fe_msg, false);
205 }
206
207 int mgmt_fe_send_commitcfg_req(struct mgmt_fe_client *client,
208 uint64_t session_id, uint64_t req_id,
209 Mgmtd__DatastoreId src_ds_id,
210 Mgmtd__DatastoreId dest_ds_id,
211 bool validate_only, bool abort)
212 {
213 (void)req_id;
214 Mgmtd__FeMessage fe_msg;
215 Mgmtd__FeCommitConfigReq commitcfg_req;
216
217 mgmtd__fe_commit_config_req__init(&commitcfg_req);
218 commitcfg_req.session_id = session_id;
219 commitcfg_req.src_ds_id = src_ds_id;
220 commitcfg_req.dst_ds_id = dest_ds_id;
221 commitcfg_req.req_id = req_id;
222 commitcfg_req.validate_only = validate_only;
223 commitcfg_req.abort = abort;
224
225 mgmtd__fe_message__init(&fe_msg);
226 fe_msg.message_case = MGMTD__FE_MESSAGE__MESSAGE_COMMCFG_REQ;
227 fe_msg.commcfg_req = &commitcfg_req;
228
229 MGMTD_FE_CLIENT_DBG(
230 "Sending COMMIT_CONFIG_REQ message for Src-Ds:%d, Dst-Ds:%d session-id %" PRIu64,
231 src_ds_id, dest_ds_id, session_id);
232
233 return mgmt_fe_client_send_msg(client, &fe_msg, false);
234 }
235
236 int mgmt_fe_send_getcfg_req(struct mgmt_fe_client *client, uint64_t session_id,
237 uint64_t req_id, Mgmtd__DatastoreId ds_id,
238 Mgmtd__YangGetDataReq *data_req[],
239 int num_data_reqs)
240 {
241 (void)req_id;
242 Mgmtd__FeMessage fe_msg;
243 Mgmtd__FeGetConfigReq getcfg_req;
244
245 mgmtd__fe_get_config_req__init(&getcfg_req);
246 getcfg_req.session_id = session_id;
247 getcfg_req.ds_id = ds_id;
248 getcfg_req.req_id = req_id;
249 getcfg_req.data = data_req;
250 getcfg_req.n_data = (size_t)num_data_reqs;
251
252 mgmtd__fe_message__init(&fe_msg);
253 fe_msg.message_case = MGMTD__FE_MESSAGE__MESSAGE_GETCFG_REQ;
254 fe_msg.getcfg_req = &getcfg_req;
255
256 MGMTD_FE_CLIENT_DBG(
257 "Sending GET_CONFIG_REQ message for Ds:%d session-id %" PRIu64
258 " (#xpaths:%d)",
259 ds_id, session_id, num_data_reqs);
260
261 return mgmt_fe_client_send_msg(client, &fe_msg, false);
262 }
263
264 int mgmt_fe_send_getdata_req(struct mgmt_fe_client *client, uint64_t session_id,
265 uint64_t req_id, Mgmtd__DatastoreId ds_id,
266 Mgmtd__YangGetDataReq *data_req[],
267 int num_data_reqs)
268 {
269 (void)req_id;
270 Mgmtd__FeMessage fe_msg;
271 Mgmtd__FeGetDataReq getdata_req;
272
273 mgmtd__fe_get_data_req__init(&getdata_req);
274 getdata_req.session_id = session_id;
275 getdata_req.ds_id = ds_id;
276 getdata_req.req_id = req_id;
277 getdata_req.data = data_req;
278 getdata_req.n_data = (size_t)num_data_reqs;
279
280 mgmtd__fe_message__init(&fe_msg);
281 fe_msg.message_case = MGMTD__FE_MESSAGE__MESSAGE_GETDATA_REQ;
282 fe_msg.getdata_req = &getdata_req;
283
284 MGMTD_FE_CLIENT_DBG(
285 "Sending GET_CONFIG_REQ message for Ds:%d session-id %" PRIu64
286 " (#xpaths:%d)",
287 ds_id, session_id, num_data_reqs);
288
289 return mgmt_fe_client_send_msg(client, &fe_msg, false);
290 }
291
292 int mgmt_fe_send_regnotify_req(struct mgmt_fe_client *client,
293 uint64_t session_id, uint64_t req_id,
294 Mgmtd__DatastoreId ds_id, bool register_req,
295 Mgmtd__YangDataXPath *data_req[],
296 int num_data_reqs)
297 {
298 (void)req_id;
299 Mgmtd__FeMessage fe_msg;
300 Mgmtd__FeRegisterNotifyReq regntfy_req;
301
302 mgmtd__fe_register_notify_req__init(&regntfy_req);
303 regntfy_req.session_id = session_id;
304 regntfy_req.ds_id = ds_id;
305 regntfy_req.register_req = register_req;
306 regntfy_req.data_xpath = data_req;
307 regntfy_req.n_data_xpath = (size_t)num_data_reqs;
308
309 mgmtd__fe_message__init(&fe_msg);
310 fe_msg.message_case = MGMTD__FE_MESSAGE__MESSAGE_REGNOTIFY_REQ;
311 fe_msg.regnotify_req = &regntfy_req;
312
313 return mgmt_fe_client_send_msg(client, &fe_msg, false);
314 }
315
316 static int mgmt_fe_client_handle_msg(struct mgmt_fe_client *client,
317 Mgmtd__FeMessage *fe_msg)
318 {
319 struct mgmt_fe_client_session *session = NULL;
320
321 /*
322 * protobuf-c adds a max size enum with an internal, and changing by
323 * version, name; cast to an int to avoid unhandled enum warnings
324 */
325 switch ((int)fe_msg->message_case) {
326 case MGMTD__FE_MESSAGE__MESSAGE_SESSION_REPLY:
327 if (fe_msg->session_reply->create &&
328 fe_msg->session_reply->has_client_conn_id) {
329 MGMTD_FE_CLIENT_DBG(
330 "Got SESSION_REPLY (create) for client-id %" PRIu64
331 " with session-id: %" PRIu64,
332 fe_msg->session_reply->client_conn_id,
333 fe_msg->session_reply->session_id);
334
335 session = mgmt_fe_find_session_by_client_id(
336 client, fe_msg->session_reply->client_conn_id);
337
338 if (session && fe_msg->session_reply->success) {
339 MGMTD_FE_CLIENT_DBG(
340 "Session Created for client-id %" PRIu64,
341 fe_msg->session_reply->client_conn_id);
342 session->session_id =
343 fe_msg->session_reply->session_id;
344 } else {
345 MGMTD_FE_CLIENT_ERR(
346 "Session Create failed for client-id %" PRIu64,
347 fe_msg->session_reply->client_conn_id);
348 }
349 } else if (!fe_msg->session_reply->create) {
350 MGMTD_FE_CLIENT_DBG(
351 "Got SESSION_REPLY (destroy) for session-id %" PRIu64,
352 fe_msg->session_reply->session_id);
353
354 session = mgmt_fe_find_session_by_session_id(
355 client, fe_msg->session_req->session_id);
356 }
357
358 /* The session state may be deleted by the callback */
359 if (session && session->client &&
360 session->client->cbs.client_session_notify)
361 (*session->client->cbs.client_session_notify)(
362 client, client->user_data, session->client_id,
363 fe_msg->session_reply->create,
364 fe_msg->session_reply->success,
365 fe_msg->session_reply->session_id,
366 session->user_ctx);
367 break;
368 case MGMTD__FE_MESSAGE__MESSAGE_LOCKDS_REPLY:
369 MGMTD_FE_CLIENT_DBG("Got LOCKDS_REPLY for session-id %" PRIu64,
370 fe_msg->lockds_reply->session_id);
371 session = mgmt_fe_find_session_by_session_id(
372 client, fe_msg->lockds_reply->session_id);
373
374 if (session && session->client &&
375 session->client->cbs.lock_ds_notify)
376 (*session->client->cbs.lock_ds_notify)(
377 client, client->user_data, session->client_id,
378 fe_msg->lockds_reply->session_id,
379 session->user_ctx, fe_msg->lockds_reply->req_id,
380 fe_msg->lockds_reply->lock,
381 fe_msg->lockds_reply->success,
382 fe_msg->lockds_reply->ds_id,
383 fe_msg->lockds_reply->error_if_any);
384 break;
385 case MGMTD__FE_MESSAGE__MESSAGE_SETCFG_REPLY:
386 MGMTD_FE_CLIENT_DBG("Got SETCFG_REPLY for session-id %" PRIu64,
387 fe_msg->setcfg_reply->session_id);
388
389 session = mgmt_fe_find_session_by_session_id(
390 client, fe_msg->setcfg_reply->session_id);
391
392 if (session && session->client &&
393 session->client->cbs.set_config_notify)
394 (*session->client->cbs.set_config_notify)(
395 client, client->user_data, session->client_id,
396 fe_msg->setcfg_reply->session_id,
397 session->user_ctx, fe_msg->setcfg_reply->req_id,
398 fe_msg->setcfg_reply->success,
399 fe_msg->setcfg_reply->ds_id,
400 fe_msg->setcfg_reply->error_if_any);
401 break;
402 case MGMTD__FE_MESSAGE__MESSAGE_COMMCFG_REPLY:
403 MGMTD_FE_CLIENT_DBG("Got COMMCFG_REPLY for session-id %" PRIu64,
404 fe_msg->commcfg_reply->session_id);
405
406 session = mgmt_fe_find_session_by_session_id(
407 client, fe_msg->commcfg_reply->session_id);
408
409 if (session && session->client &&
410 session->client->cbs.commit_config_notify)
411 (*session->client->cbs.commit_config_notify)(
412 client, client->user_data, session->client_id,
413 fe_msg->commcfg_reply->session_id,
414 session->user_ctx,
415 fe_msg->commcfg_reply->req_id,
416 fe_msg->commcfg_reply->success,
417 fe_msg->commcfg_reply->src_ds_id,
418 fe_msg->commcfg_reply->dst_ds_id,
419 fe_msg->commcfg_reply->validate_only,
420 fe_msg->commcfg_reply->error_if_any);
421 break;
422 case MGMTD__FE_MESSAGE__MESSAGE_GETCFG_REPLY:
423 MGMTD_FE_CLIENT_DBG("Got GETCFG_REPLY for session-id %" PRIu64,
424 fe_msg->getcfg_reply->session_id);
425
426 session = mgmt_fe_find_session_by_session_id(
427 client, fe_msg->getcfg_reply->session_id);
428
429 if (session && session->client &&
430 session->client->cbs.get_data_notify)
431 (*session->client->cbs.get_data_notify)(
432 client, client->user_data, session->client_id,
433 fe_msg->getcfg_reply->session_id,
434 session->user_ctx, fe_msg->getcfg_reply->req_id,
435 fe_msg->getcfg_reply->success,
436 fe_msg->getcfg_reply->ds_id,
437 fe_msg->getcfg_reply->data
438 ? fe_msg->getcfg_reply->data->data
439 : NULL,
440 fe_msg->getcfg_reply->data
441 ? fe_msg->getcfg_reply->data->n_data
442 : 0,
443 fe_msg->getcfg_reply->data
444 ? fe_msg->getcfg_reply->data->next_indx
445 : 0,
446 fe_msg->getcfg_reply->error_if_any);
447 break;
448 case MGMTD__FE_MESSAGE__MESSAGE_GETDATA_REPLY:
449 MGMTD_FE_CLIENT_DBG("Got GETDATA_REPLY for session-id %" PRIu64,
450 fe_msg->getdata_reply->session_id);
451
452 session = mgmt_fe_find_session_by_session_id(
453 client, fe_msg->getdata_reply->session_id);
454
455 if (session && session->client &&
456 session->client->cbs.get_data_notify)
457 (*session->client->cbs.get_data_notify)(
458 client, client->user_data, session->client_id,
459 fe_msg->getdata_reply->session_id,
460 session->user_ctx,
461 fe_msg->getdata_reply->req_id,
462 fe_msg->getdata_reply->success,
463 fe_msg->getdata_reply->ds_id,
464 fe_msg->getdata_reply->data
465 ? fe_msg->getdata_reply->data->data
466 : NULL,
467 fe_msg->getdata_reply->data
468 ? fe_msg->getdata_reply->data->n_data
469 : 0,
470 fe_msg->getdata_reply->data
471 ? fe_msg->getdata_reply->data->next_indx
472 : 0,
473 fe_msg->getdata_reply->error_if_any);
474 break;
475 case MGMTD__FE_MESSAGE__MESSAGE_NOTIFY_DATA_REQ:
476 case MGMTD__FE_MESSAGE__MESSAGE_REGNOTIFY_REQ:
477 /*
478 * TODO: Add handling code in future.
479 */
480 break;
481 /*
482 * NOTE: The following messages are always sent from Frontend
483 * clients to MGMTd only and/or need not be handled here.
484 */
485 case MGMTD__FE_MESSAGE__MESSAGE_REGISTER_REQ:
486 case MGMTD__FE_MESSAGE__MESSAGE_SESSION_REQ:
487 case MGMTD__FE_MESSAGE__MESSAGE_LOCKDS_REQ:
488 case MGMTD__FE_MESSAGE__MESSAGE_SETCFG_REQ:
489 case MGMTD__FE_MESSAGE__MESSAGE_COMMCFG_REQ:
490 case MGMTD__FE_MESSAGE__MESSAGE_GETCFG_REQ:
491 case MGMTD__FE_MESSAGE__MESSAGE_GETDATA_REQ:
492 case MGMTD__FE_MESSAGE__MESSAGE__NOT_SET:
493 default:
494 /*
495 * A 'default' case is being added contrary to the
496 * FRR code guidelines to take care of build
497 * failures on certain build systems (courtesy of
498 * the proto-c package).
499 */
500 break;
501 }
502
503 return 0;
504 }
505
506 static void mgmt_fe_client_process_msg(uint8_t version, uint8_t *data,
507 size_t len, struct msg_conn *conn)
508 {
509 struct mgmt_fe_client *client;
510 struct msg_client *msg_client;
511 Mgmtd__FeMessage *fe_msg;
512
513 msg_client = container_of(conn, struct msg_client, conn);
514 client = container_of(msg_client, struct mgmt_fe_client, client);
515
516 fe_msg = mgmtd__fe_message__unpack(NULL, len, data);
517 if (!fe_msg) {
518 MGMTD_FE_CLIENT_DBG("Failed to decode %zu bytes from server.",
519 len);
520 return;
521 }
522 MGMTD_FE_CLIENT_DBG(
523 "Decoded %zu bytes of message(msg: %u/%u) from server", len,
524 fe_msg->message_case, fe_msg->message_case);
525 (void)mgmt_fe_client_handle_msg(client, fe_msg);
526 mgmtd__fe_message__free_unpacked(fe_msg, NULL);
527 }
528
529 static int _notify_connect_disconnect(struct msg_client *msg_client,
530 bool connected)
531 {
532 struct mgmt_fe_client *client =
533 container_of(msg_client, struct mgmt_fe_client, client);
534 struct mgmt_fe_client_session *session;
535 int ret;
536
537 /* Send REGISTER_REQ message */
538 if (connected) {
539 if ((ret = mgmt_fe_send_register_req(client)) != 0)
540 return ret;
541 }
542
543 /* Walk list of sessions for this FE client deleting them */
544 if (!connected && mgmt_sessions_count(&client->sessions)) {
545 MGMTD_FE_CLIENT_DBG("Cleaning up existing sessions");
546
547 FOREACH_SESSION_IN_LIST (client, session) {
548 assert(session->client);
549
550 /* unlink from list first this avoids double free */
551 mgmt_sessions_del(&client->sessions, session);
552
553 /* notify FE client the session is being deleted */
554 if (session->client->cbs.client_session_notify) {
555 (*session->client->cbs.client_session_notify)(
556 client, client->user_data,
557 session->client_id, false, true,
558 session->session_id, session->user_ctx);
559 }
560
561 XFREE(MTYPE_MGMTD_FE_SESSION, session);
562 }
563 }
564
565 /* Notify FE client through registered callback (if any). */
566 if (client->cbs.client_connect_notify)
567 (void)(*client->cbs.client_connect_notify)(
568 client, client->user_data, connected);
569 return 0;
570 }
571
572 static int mgmt_fe_client_notify_connect(struct msg_client *client)
573 {
574 return _notify_connect_disconnect(client, true);
575 }
576
577 static int mgmt_fe_client_notify_disconnect(struct msg_conn *conn)
578 {
579 struct msg_client *client = container_of(conn, struct msg_client, conn);
580
581 return _notify_connect_disconnect(client, false);
582 }
583
584
585 DEFPY(debug_mgmt_client_fe, debug_mgmt_client_fe_cmd,
586 "[no] debug mgmt client frontend",
587 NO_STR DEBUG_STR MGMTD_STR
588 "client\n"
589 "frontend\n")
590 {
591 uint32_t mode = DEBUG_NODE2MODE(vty->node);
592
593 DEBUG_MODE_SET(&mgmt_dbg_fe_client, mode, !no);
594
595 return CMD_SUCCESS;
596 }
597
598 static void mgmt_debug_client_fe_set_all(uint32_t flags, bool set)
599 {
600 DEBUG_FLAGS_SET(&mgmt_dbg_fe_client, flags, set);
601 }
602
603 static int mgmt_debug_fe_client_config_write(struct vty *vty)
604 {
605 if (DEBUG_MODE_CHECK(&mgmt_dbg_fe_client, DEBUG_MODE_CONF))
606 vty_out(vty, "debug mgmt client frontend\n");
607
608 return CMD_SUCCESS;
609 }
610
611 void mgmt_debug_fe_client_show_debug(struct vty *vty)
612 {
613 if (MGMTD_DBG_FE_CLIENT_CHECK())
614 vty_out(vty, "debug mgmt client frontend\n");
615 }
616
617 static struct debug_callbacks mgmt_dbg_fe_client_cbs = {
618 .debug_set_all = mgmt_debug_client_fe_set_all};
619
620 static struct cmd_node mgmt_dbg_node = {
621 .name = "mgmt client frontend",
622 .node = DEBUG_NODE,
623 .prompt = "",
624 .config_write = mgmt_debug_fe_client_config_write,
625 };
626
627 /*
628 * Initialize library and try connecting with MGMTD.
629 */
630 struct mgmt_fe_client *mgmt_fe_client_create(const char *client_name,
631 struct mgmt_fe_client_cbs *cbs,
632 uintptr_t user_data,
633 struct event_loop *event_loop)
634 {
635 struct mgmt_fe_client *client =
636 XCALLOC(MTYPE_MGMTD_FE_CLIENT, sizeof(*client));
637
638 client->name = XSTRDUP(MTYPE_MGMTD_FE_CLIENT_NAME, client_name);
639 client->user_data = user_data;
640 if (cbs)
641 client->cbs = *cbs;
642
643 mgmt_sessions_init(&client->sessions);
644
645 msg_client_init(&client->client, event_loop, MGMTD_FE_SERVER_PATH,
646 mgmt_fe_client_notify_connect,
647 mgmt_fe_client_notify_disconnect,
648 mgmt_fe_client_process_msg, MGMTD_FE_MAX_NUM_MSG_PROC,
649 MGMTD_FE_MAX_NUM_MSG_WRITE, MGMTD_FE_MSG_MAX_LEN, true,
650 "FE-client", MGMTD_DBG_FE_CLIENT_CHECK());
651
652 MGMTD_FE_CLIENT_DBG("Initialized client '%s'", client_name);
653
654 return client;
655 }
656
657 void mgmt_fe_client_lib_vty_init(void)
658 {
659 debug_init(&mgmt_dbg_fe_client_cbs);
660 install_node(&mgmt_dbg_node);
661 install_element(ENABLE_NODE, &debug_mgmt_client_fe_cmd);
662 install_element(CONFIG_NODE, &debug_mgmt_client_fe_cmd);
663 }
664
665 uint mgmt_fe_client_session_count(struct mgmt_fe_client *client)
666 {
667 return mgmt_sessions_count(&client->sessions);
668 }
669
670 /*
671 * Create a new Session for a Frontend Client connection.
672 */
673 enum mgmt_result mgmt_fe_create_client_session(struct mgmt_fe_client *client,
674 uint64_t client_id,
675 uintptr_t user_ctx)
676 {
677 struct mgmt_fe_client_session *session;
678
679 session = XCALLOC(MTYPE_MGMTD_FE_SESSION,
680 sizeof(struct mgmt_fe_client_session));
681 assert(session);
682 session->user_ctx = user_ctx;
683 session->client_id = client_id;
684 session->client = client;
685 session->session_id = 0;
686
687 mgmt_sessions_add_tail(&client->sessions, session);
688
689 if (mgmt_fe_send_session_req(client, session, true) != 0) {
690 XFREE(MTYPE_MGMTD_FE_SESSION, session);
691 return MGMTD_INTERNAL_ERROR;
692 }
693
694 return MGMTD_SUCCESS;
695 }
696
697 /*
698 * Delete an existing Session for a Frontend Client connection.
699 */
700 enum mgmt_result mgmt_fe_destroy_client_session(struct mgmt_fe_client *client,
701 uint64_t client_id)
702 {
703 struct mgmt_fe_client_session *session;
704
705 session = mgmt_fe_find_session_by_client_id(client, client_id);
706 if (!session || session->client != client)
707 return MGMTD_INVALID_PARAM;
708
709 if (session->session_id &&
710 mgmt_fe_send_session_req(client, session, false) != 0)
711 MGMTD_FE_CLIENT_ERR(
712 "Failed to send session destroy request for the session-id %" PRIu64,
713 session->session_id);
714
715 mgmt_sessions_del(&client->sessions, session);
716 XFREE(MTYPE_MGMTD_FE_SESSION, session);
717
718 return MGMTD_SUCCESS;
719 }
720
721 /*
722 * Destroy library and cleanup everything.
723 */
724 void mgmt_fe_client_destroy(struct mgmt_fe_client *client)
725 {
726 struct mgmt_fe_client_session *session;
727
728 MGMTD_FE_CLIENT_DBG("Destroying MGMTD Frontend Client '%s'",
729 client->name);
730
731 FOREACH_SESSION_IN_LIST (client, session)
732 mgmt_fe_destroy_client_session(client, session->client_id);
733
734 msg_client_cleanup(&client->client);
735
736 XFREE(MTYPE_MGMTD_FE_CLIENT_NAME, client->name);
737 XFREE(MTYPE_MGMTD_FE_CLIENT, client);
738 }