1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * MGMTD Frontend Client Library api interfaces
4 * Copyright (C) 2021 Vmware, Inc.
5 * Pushpasis Sarkar <spushpasis@vmware.com>
11 #include "mgmt_fe_client.h"
18 #ifdef REDIRECT_DEBUG_TO_STDERR
19 #define MGMTD_FE_CLIENT_DBG(fmt, ...) \
20 fprintf(stderr, "%s: " fmt "\n", __func__, ##__VA_ARGS__)
21 #define MGMTD_FE_CLIENT_ERR(fmt, ...) \
22 fprintf(stderr, "%s: ERROR, " fmt "\n", __func__, ##__VA_ARGS__)
23 #else /* REDIRECT_DEBUG_TO_STDERR */
24 #define MGMTD_FE_CLIENT_DBG(fmt, ...) \
26 if (mgmt_debug_fe_client) \
27 zlog_debug("%s: " fmt, __func__, ##__VA_ARGS__); \
29 #define MGMTD_FE_CLIENT_ERR(fmt, ...) \
30 zlog_err("%s: ERROR: " fmt, __func__, ##__VA_ARGS__)
31 #endif /* REDIRECT_DEBUG_TO_STDERR */
33 struct mgmt_fe_client_ctx
;
35 PREDECL_LIST(mgmt_sessions
);
37 struct mgmt_fe_client_session
{
40 struct mgmt_fe_client_ctx
*client_ctx
;
43 struct mgmt_sessions_item list_linkage
;
46 DECLARE_LIST(mgmt_sessions
, struct mgmt_fe_client_session
, list_linkage
);
48 DEFINE_MTYPE_STATIC(LIB
, MGMTD_FE_SESSION
, "MGMTD Frontend session");
50 struct mgmt_fe_client_ctx
{
52 struct event_master
*tm
;
53 struct event
*conn_retry_tmr
;
54 struct event
*conn_read_ev
;
55 struct event
*conn_write_ev
;
56 struct event
*conn_writes_on
;
57 struct event
*msg_proc_ev
;
60 struct mgmt_msg_state mstate
;
62 struct mgmt_fe_client_params client_params
;
64 struct mgmt_sessions_head client_sessions
;
67 #define MGMTD_FE_CLIENT_FLAGS_WRITES_OFF (1U << 0)
69 #define FOREACH_SESSION_IN_LIST(client_ctx, session) \
70 frr_each_safe (mgmt_sessions, &(client_ctx)->client_sessions, (session))
72 static bool mgmt_debug_fe_client
;
74 static struct mgmt_fe_client_ctx mgmt_fe_client_ctx
= {
78 /* Forward declarations */
80 mgmt_fe_client_register_event(struct mgmt_fe_client_ctx
*client_ctx
,
81 enum mgmt_fe_event event
);
82 static void mgmt_fe_client_schedule_conn_retry(
83 struct mgmt_fe_client_ctx
*client_ctx
, unsigned long intvl_secs
);
85 static struct mgmt_fe_client_session
*
86 mgmt_fe_find_session_by_client_id(struct mgmt_fe_client_ctx
*client_ctx
,
89 struct mgmt_fe_client_session
*session
;
91 FOREACH_SESSION_IN_LIST (client_ctx
, session
) {
92 if (session
->client_id
== client_id
) {
94 "Found session %p for client-id %llu.", session
,
95 (unsigned long long)client_id
);
103 static struct mgmt_fe_client_session
*
104 mgmt_fe_find_session_by_session_id(struct mgmt_fe_client_ctx
*client_ctx
,
107 struct mgmt_fe_client_session
*session
;
109 FOREACH_SESSION_IN_LIST (client_ctx
, session
) {
110 if (session
->session_id
== session_id
) {
112 "Found session %p for session-id %llu.", session
,
113 (unsigned long long)session_id
);
122 mgmt_fe_server_disconnect(struct mgmt_fe_client_ctx
*client_ctx
,
125 if (client_ctx
->conn_fd
!= -1) {
126 close(client_ctx
->conn_fd
);
127 client_ctx
->conn_fd
= -1;
131 mgmt_fe_client_schedule_conn_retry(
133 client_ctx
->client_params
.conn_retry_intvl_sec
);
137 mgmt_fe_client_sched_msg_write(struct mgmt_fe_client_ctx
*client_ctx
)
139 if (!CHECK_FLAG(client_ctx
->flags
, MGMTD_FE_CLIENT_FLAGS_WRITES_OFF
))
140 mgmt_fe_client_register_event(client_ctx
,
141 MGMTD_FE_CONN_WRITE
);
145 mgmt_fe_client_writes_on(struct mgmt_fe_client_ctx
*client_ctx
)
147 MGMTD_FE_CLIENT_DBG("Resume writing msgs");
148 UNSET_FLAG(client_ctx
->flags
, MGMTD_FE_CLIENT_FLAGS_WRITES_OFF
);
149 mgmt_fe_client_sched_msg_write(client_ctx
);
153 mgmt_fe_client_writes_off(struct mgmt_fe_client_ctx
*client_ctx
)
155 SET_FLAG(client_ctx
->flags
, MGMTD_FE_CLIENT_FLAGS_WRITES_OFF
);
156 MGMTD_FE_CLIENT_DBG("Paused writing msgs");
159 static int mgmt_fe_client_send_msg(struct mgmt_fe_client_ctx
*client_ctx
,
160 Mgmtd__FeMessage
*fe_msg
)
162 /* users current expect this to fail here */
163 if (client_ctx
->conn_fd
== -1) {
164 MGMTD_FE_CLIENT_DBG("can't send message on closed connection");
168 int rv
= mgmt_msg_send_msg(
169 &client_ctx
->mstate
, fe_msg
,
170 mgmtd__fe_message__get_packed_size(fe_msg
),
171 (size_t(*)(void *, void *))mgmtd__fe_message__pack
,
172 mgmt_debug_fe_client
);
173 mgmt_fe_client_sched_msg_write(client_ctx
);
177 static void mgmt_fe_client_write(struct event
*thread
)
179 struct mgmt_fe_client_ctx
*client_ctx
;
180 enum mgmt_msg_wsched rv
;
182 client_ctx
= (struct mgmt_fe_client_ctx
*)THREAD_ARG(thread
);
183 rv
= mgmt_msg_write(&client_ctx
->mstate
, client_ctx
->conn_fd
,
184 mgmt_debug_fe_client
);
185 if (rv
== MSW_SCHED_STREAM
)
186 mgmt_fe_client_register_event(client_ctx
, MGMTD_FE_CONN_WRITE
);
187 else if (rv
== MSW_DISCONNECT
)
188 mgmt_fe_server_disconnect(client_ctx
, true);
189 else if (rv
== MSW_SCHED_WRITES_OFF
) {
190 mgmt_fe_client_writes_off(client_ctx
);
191 mgmt_fe_client_register_event(client_ctx
,
192 MGMTD_FE_CONN_WRITES_ON
);
194 assert(rv
== MSW_SCHED_NONE
);
197 static void mgmt_fe_client_resume_writes(struct event
*thread
)
199 struct mgmt_fe_client_ctx
*client_ctx
;
201 client_ctx
= (struct mgmt_fe_client_ctx
*)THREAD_ARG(thread
);
202 assert(client_ctx
&& client_ctx
->conn_fd
!= -1);
204 mgmt_fe_client_writes_on(client_ctx
);
208 mgmt_fe_send_register_req(struct mgmt_fe_client_ctx
*client_ctx
)
210 Mgmtd__FeMessage fe_msg
;
211 Mgmtd__FeRegisterReq rgstr_req
;
213 mgmtd__fe_register_req__init(&rgstr_req
);
214 rgstr_req
.client_name
= client_ctx
->client_params
.name
;
216 mgmtd__fe_message__init(&fe_msg
);
217 fe_msg
.message_case
= MGMTD__FE_MESSAGE__MESSAGE_REGISTER_REQ
;
218 fe_msg
.register_req
= &rgstr_req
;
221 "Sending REGISTER_REQ message to MGMTD Frontend server");
223 return mgmt_fe_client_send_msg(client_ctx
, &fe_msg
);
227 mgmt_fe_send_session_req(struct mgmt_fe_client_ctx
*client_ctx
,
228 struct mgmt_fe_client_session
*session
,
231 Mgmtd__FeMessage fe_msg
;
232 Mgmtd__FeSessionReq sess_req
;
234 mgmtd__fe_session_req__init(&sess_req
);
235 sess_req
.create
= create
;
237 sess_req
.id_case
= MGMTD__FE_SESSION_REQ__ID_CLIENT_CONN_ID
;
238 sess_req
.client_conn_id
= session
->client_id
;
240 sess_req
.id_case
= MGMTD__FE_SESSION_REQ__ID_SESSION_ID
;
241 sess_req
.session_id
= session
->session_id
;
244 mgmtd__fe_message__init(&fe_msg
);
245 fe_msg
.message_case
= MGMTD__FE_MESSAGE__MESSAGE_SESSION_REQ
;
246 fe_msg
.session_req
= &sess_req
;
249 "Sending SESSION_REQ message for %s session %llu to MGMTD Frontend server",
250 create
? "creating" : "destroying",
251 (unsigned long long)session
->client_id
);
253 return mgmt_fe_client_send_msg(client_ctx
, &fe_msg
);
257 mgmt_fe_send_lockds_req(struct mgmt_fe_client_ctx
*client_ctx
,
258 struct mgmt_fe_client_session
*session
, bool lock
,
259 uint64_t req_id
, Mgmtd__DatastoreId ds_id
)
262 Mgmtd__FeMessage fe_msg
;
263 Mgmtd__FeLockDsReq lockds_req
;
265 mgmtd__fe_lock_ds_req__init(&lockds_req
);
266 lockds_req
.session_id
= session
->session_id
;
267 lockds_req
.req_id
= req_id
;
268 lockds_req
.ds_id
= ds_id
;
269 lockds_req
.lock
= lock
;
271 mgmtd__fe_message__init(&fe_msg
);
272 fe_msg
.message_case
= MGMTD__FE_MESSAGE__MESSAGE_LOCKDS_REQ
;
273 fe_msg
.lockds_req
= &lockds_req
;
276 "Sending %sLOCK_REQ message for Ds:%d session %llu to MGMTD Frontend server",
277 lock
? "" : "UN", ds_id
, (unsigned long long)session
->client_id
);
279 return mgmt_fe_client_send_msg(client_ctx
, &fe_msg
);
283 mgmt_fe_send_setcfg_req(struct mgmt_fe_client_ctx
*client_ctx
,
284 struct mgmt_fe_client_session
*session
,
285 uint64_t req_id
, Mgmtd__DatastoreId ds_id
,
286 Mgmtd__YangCfgDataReq
**data_req
, int num_data_reqs
,
287 bool implicit_commit
, Mgmtd__DatastoreId dst_ds_id
)
290 Mgmtd__FeMessage fe_msg
;
291 Mgmtd__FeSetConfigReq setcfg_req
;
293 mgmtd__fe_set_config_req__init(&setcfg_req
);
294 setcfg_req
.session_id
= session
->session_id
;
295 setcfg_req
.ds_id
= ds_id
;
296 setcfg_req
.req_id
= req_id
;
297 setcfg_req
.data
= data_req
;
298 setcfg_req
.n_data
= (size_t)num_data_reqs
;
299 setcfg_req
.implicit_commit
= implicit_commit
;
300 setcfg_req
.commit_ds_id
= dst_ds_id
;
302 mgmtd__fe_message__init(&fe_msg
);
303 fe_msg
.message_case
= MGMTD__FE_MESSAGE__MESSAGE_SETCFG_REQ
;
304 fe_msg
.setcfg_req
= &setcfg_req
;
307 "Sending SET_CONFIG_REQ message for Ds:%d session %llu (#xpaths:%d) to MGMTD Frontend server",
308 ds_id
, (unsigned long long)session
->client_id
, num_data_reqs
);
310 return mgmt_fe_client_send_msg(client_ctx
, &fe_msg
);
314 mgmt_fe_send_commitcfg_req(struct mgmt_fe_client_ctx
*client_ctx
,
315 struct mgmt_fe_client_session
*session
,
316 uint64_t req_id
, Mgmtd__DatastoreId src_ds_id
,
317 Mgmtd__DatastoreId dest_ds_id
, bool validate_only
,
321 Mgmtd__FeMessage fe_msg
;
322 Mgmtd__FeCommitConfigReq commitcfg_req
;
324 mgmtd__fe_commit_config_req__init(&commitcfg_req
);
325 commitcfg_req
.session_id
= session
->session_id
;
326 commitcfg_req
.src_ds_id
= src_ds_id
;
327 commitcfg_req
.dst_ds_id
= dest_ds_id
;
328 commitcfg_req
.req_id
= req_id
;
329 commitcfg_req
.validate_only
= validate_only
;
330 commitcfg_req
.abort
= abort
;
332 mgmtd__fe_message__init(&fe_msg
);
333 fe_msg
.message_case
= MGMTD__FE_MESSAGE__MESSAGE_COMMCFG_REQ
;
334 fe_msg
.commcfg_req
= &commitcfg_req
;
337 "Sending COMMIT_CONFIG_REQ message for Src-Ds:%d, Dst-Ds:%d session %llu to MGMTD Frontend server",
338 src_ds_id
, dest_ds_id
, (unsigned long long)session
->client_id
);
340 return mgmt_fe_client_send_msg(client_ctx
, &fe_msg
);
344 mgmt_fe_send_getcfg_req(struct mgmt_fe_client_ctx
*client_ctx
,
345 struct mgmt_fe_client_session
*session
,
346 uint64_t req_id
, Mgmtd__DatastoreId ds_id
,
347 Mgmtd__YangGetDataReq
* data_req
[],
351 Mgmtd__FeMessage fe_msg
;
352 Mgmtd__FeGetConfigReq getcfg_req
;
354 mgmtd__fe_get_config_req__init(&getcfg_req
);
355 getcfg_req
.session_id
= session
->session_id
;
356 getcfg_req
.ds_id
= ds_id
;
357 getcfg_req
.req_id
= req_id
;
358 getcfg_req
.data
= data_req
;
359 getcfg_req
.n_data
= (size_t)num_data_reqs
;
361 mgmtd__fe_message__init(&fe_msg
);
362 fe_msg
.message_case
= MGMTD__FE_MESSAGE__MESSAGE_GETCFG_REQ
;
363 fe_msg
.getcfg_req
= &getcfg_req
;
366 "Sending GET_CONFIG_REQ message for Ds:%d session %llu (#xpaths:%d) to MGMTD Frontend server",
367 ds_id
, (unsigned long long)session
->client_id
, num_data_reqs
);
369 return mgmt_fe_client_send_msg(client_ctx
, &fe_msg
);
373 mgmt_fe_send_getdata_req(struct mgmt_fe_client_ctx
*client_ctx
,
374 struct mgmt_fe_client_session
*session
,
375 uint64_t req_id
, Mgmtd__DatastoreId ds_id
,
376 Mgmtd__YangGetDataReq
* data_req
[],
380 Mgmtd__FeMessage fe_msg
;
381 Mgmtd__FeGetDataReq getdata_req
;
383 mgmtd__fe_get_data_req__init(&getdata_req
);
384 getdata_req
.session_id
= session
->session_id
;
385 getdata_req
.ds_id
= ds_id
;
386 getdata_req
.req_id
= req_id
;
387 getdata_req
.data
= data_req
;
388 getdata_req
.n_data
= (size_t)num_data_reqs
;
390 mgmtd__fe_message__init(&fe_msg
);
391 fe_msg
.message_case
= MGMTD__FE_MESSAGE__MESSAGE_GETDATA_REQ
;
392 fe_msg
.getdata_req
= &getdata_req
;
395 "Sending GET_CONFIG_REQ message for Ds:%d session %llu (#xpaths:%d) to MGMTD Frontend server",
396 ds_id
, (unsigned long long)session
->client_id
, num_data_reqs
);
398 return mgmt_fe_client_send_msg(client_ctx
, &fe_msg
);
401 static int mgmt_fe_send_regnotify_req(
402 struct mgmt_fe_client_ctx
*client_ctx
,
403 struct mgmt_fe_client_session
*session
, uint64_t req_id
,
404 Mgmtd__DatastoreId ds_id
, bool register_req
,
405 Mgmtd__YangDataXPath
* data_req
[], int num_data_reqs
)
408 Mgmtd__FeMessage fe_msg
;
409 Mgmtd__FeRegisterNotifyReq regntfy_req
;
411 mgmtd__fe_register_notify_req__init(®ntfy_req
);
412 regntfy_req
.session_id
= session
->session_id
;
413 regntfy_req
.ds_id
= ds_id
;
414 regntfy_req
.register_req
= register_req
;
415 regntfy_req
.data_xpath
= data_req
;
416 regntfy_req
.n_data_xpath
= (size_t)num_data_reqs
;
418 mgmtd__fe_message__init(&fe_msg
);
419 fe_msg
.message_case
= MGMTD__FE_MESSAGE__MESSAGE_REGNOTIFY_REQ
;
420 fe_msg
.regnotify_req
= ®ntfy_req
;
422 return mgmt_fe_client_send_msg(client_ctx
, &fe_msg
);
426 mgmt_fe_client_handle_msg(struct mgmt_fe_client_ctx
*client_ctx
,
427 Mgmtd__FeMessage
*fe_msg
)
429 struct mgmt_fe_client_session
*session
= NULL
;
432 * protobuf-c adds a max size enum with an internal, and changing by
433 * version, name; cast to an int to avoid unhandled enum warnings
435 switch ((int)fe_msg
->message_case
) {
436 case MGMTD__FE_MESSAGE__MESSAGE_SESSION_REPLY
:
437 if (fe_msg
->session_reply
->create
438 && fe_msg
->session_reply
->has_client_conn_id
) {
440 "Got Session Create Reply Msg for client-id %llu with session-id: %llu.",
442 fe_msg
->session_reply
->client_conn_id
,
444 fe_msg
->session_reply
->session_id
);
446 session
= mgmt_fe_find_session_by_client_id(
448 fe_msg
->session_reply
->client_conn_id
);
450 if (session
&& fe_msg
->session_reply
->success
) {
452 "Session Create for client-id %llu successful.",
453 (unsigned long long)fe_msg
454 ->session_reply
->client_conn_id
);
455 session
->session_id
=
456 fe_msg
->session_reply
->session_id
;
459 "Session Create for client-id %llu failed.",
460 (unsigned long long)fe_msg
461 ->session_reply
->client_conn_id
);
463 } else if (!fe_msg
->session_reply
->create
) {
465 "Got Session Destroy Reply Msg for session-id %llu",
467 fe_msg
->session_reply
->session_id
);
469 session
= mgmt_fe_find_session_by_session_id(
470 client_ctx
, fe_msg
->session_req
->session_id
);
473 if (session
&& session
->client_ctx
474 && session
->client_ctx
->client_params
475 .client_session_notify
)
476 (*session
->client_ctx
->client_params
477 .client_session_notify
)(
478 (uintptr_t)client_ctx
,
479 client_ctx
->client_params
.user_data
,
481 fe_msg
->session_reply
->create
,
482 fe_msg
->session_reply
->success
,
483 (uintptr_t)session
, session
->user_ctx
);
485 case MGMTD__FE_MESSAGE__MESSAGE_LOCKDS_REPLY
:
487 "Got LockDs Reply Msg for session-id %llu",
489 fe_msg
->lockds_reply
->session_id
);
490 session
= mgmt_fe_find_session_by_session_id(
491 client_ctx
, fe_msg
->lockds_reply
->session_id
);
493 if (session
&& session
->client_ctx
494 && session
->client_ctx
->client_params
496 (*session
->client_ctx
->client_params
498 (uintptr_t)client_ctx
,
499 client_ctx
->client_params
.user_data
,
500 session
->client_id
, (uintptr_t)session
,
502 fe_msg
->lockds_reply
->req_id
,
503 fe_msg
->lockds_reply
->lock
,
504 fe_msg
->lockds_reply
->success
,
505 fe_msg
->lockds_reply
->ds_id
,
506 fe_msg
->lockds_reply
->error_if_any
);
508 case MGMTD__FE_MESSAGE__MESSAGE_SETCFG_REPLY
:
510 "Got Set Config Reply Msg for session-id %llu",
512 fe_msg
->setcfg_reply
->session_id
);
514 session
= mgmt_fe_find_session_by_session_id(
515 client_ctx
, fe_msg
->setcfg_reply
->session_id
);
517 if (session
&& session
->client_ctx
518 && session
->client_ctx
->client_params
520 (*session
->client_ctx
->client_params
522 (uintptr_t)client_ctx
,
523 client_ctx
->client_params
.user_data
,
524 session
->client_id
, (uintptr_t)session
,
526 fe_msg
->setcfg_reply
->req_id
,
527 fe_msg
->setcfg_reply
->success
,
528 fe_msg
->setcfg_reply
->ds_id
,
529 fe_msg
->setcfg_reply
->error_if_any
);
531 case MGMTD__FE_MESSAGE__MESSAGE_COMMCFG_REPLY
:
533 "Got Commit Config Reply Msg for session-id %llu",
535 fe_msg
->commcfg_reply
->session_id
);
537 session
= mgmt_fe_find_session_by_session_id(
538 client_ctx
, fe_msg
->commcfg_reply
->session_id
);
540 if (session
&& session
->client_ctx
541 && session
->client_ctx
->client_params
542 .commit_config_notify
)
543 (*session
->client_ctx
->client_params
544 .commit_config_notify
)(
545 (uintptr_t)client_ctx
,
546 client_ctx
->client_params
.user_data
,
547 session
->client_id
, (uintptr_t)session
,
549 fe_msg
->commcfg_reply
->req_id
,
550 fe_msg
->commcfg_reply
->success
,
551 fe_msg
->commcfg_reply
->src_ds_id
,
552 fe_msg
->commcfg_reply
->dst_ds_id
,
553 fe_msg
->commcfg_reply
->validate_only
,
554 fe_msg
->commcfg_reply
->error_if_any
);
556 case MGMTD__FE_MESSAGE__MESSAGE_GETCFG_REPLY
:
558 "Got Get Config Reply Msg for session-id %llu",
560 fe_msg
->getcfg_reply
->session_id
);
562 session
= mgmt_fe_find_session_by_session_id(
563 client_ctx
, fe_msg
->getcfg_reply
->session_id
);
565 if (session
&& session
->client_ctx
566 && session
->client_ctx
->client_params
568 (*session
->client_ctx
->client_params
570 (uintptr_t)client_ctx
,
571 client_ctx
->client_params
.user_data
,
572 session
->client_id
, (uintptr_t)session
,
574 fe_msg
->getcfg_reply
->req_id
,
575 fe_msg
->getcfg_reply
->success
,
576 fe_msg
->getcfg_reply
->ds_id
,
577 fe_msg
->getcfg_reply
->data
578 ? fe_msg
->getcfg_reply
->data
->data
580 fe_msg
->getcfg_reply
->data
581 ? fe_msg
->getcfg_reply
->data
->n_data
583 fe_msg
->getcfg_reply
->data
584 ? fe_msg
->getcfg_reply
->data
587 fe_msg
->getcfg_reply
->error_if_any
);
589 case MGMTD__FE_MESSAGE__MESSAGE_GETDATA_REPLY
:
591 "Got Get Data Reply Msg for session-id %llu",
593 fe_msg
->getdata_reply
->session_id
);
595 session
= mgmt_fe_find_session_by_session_id(
596 client_ctx
, fe_msg
->getdata_reply
->session_id
);
598 if (session
&& session
->client_ctx
599 && session
->client_ctx
->client_params
601 (*session
->client_ctx
->client_params
603 (uintptr_t)client_ctx
,
604 client_ctx
->client_params
.user_data
,
605 session
->client_id
, (uintptr_t)session
,
607 fe_msg
->getdata_reply
->req_id
,
608 fe_msg
->getdata_reply
->success
,
609 fe_msg
->getdata_reply
->ds_id
,
610 fe_msg
->getdata_reply
->data
611 ? fe_msg
->getdata_reply
->data
->data
613 fe_msg
->getdata_reply
->data
614 ? fe_msg
->getdata_reply
->data
617 fe_msg
->getdata_reply
->data
618 ? fe_msg
->getdata_reply
->data
621 fe_msg
->getdata_reply
->error_if_any
);
623 case MGMTD__FE_MESSAGE__MESSAGE_NOTIFY_DATA_REQ
:
624 case MGMTD__FE_MESSAGE__MESSAGE_REGNOTIFY_REQ
:
626 * TODO: Add handling code in future.
630 * NOTE: The following messages are always sent from Frontend
631 * clients to MGMTd only and/or need not be handled here.
633 case MGMTD__FE_MESSAGE__MESSAGE_REGISTER_REQ
:
634 case MGMTD__FE_MESSAGE__MESSAGE_SESSION_REQ
:
635 case MGMTD__FE_MESSAGE__MESSAGE_LOCKDS_REQ
:
636 case MGMTD__FE_MESSAGE__MESSAGE_SETCFG_REQ
:
637 case MGMTD__FE_MESSAGE__MESSAGE_COMMCFG_REQ
:
638 case MGMTD__FE_MESSAGE__MESSAGE_GETCFG_REQ
:
639 case MGMTD__FE_MESSAGE__MESSAGE_GETDATA_REQ
:
640 case MGMTD__FE_MESSAGE__MESSAGE__NOT_SET
:
643 * A 'default' case is being added contrary to the
644 * FRR code guidelines to take care of build
645 * failures on certain build systems (courtesy of
646 * the proto-c package).
654 static void mgmt_fe_client_process_msg(void *user_ctx
, uint8_t *data
,
657 struct mgmt_fe_client_ctx
*client_ctx
= user_ctx
;
658 Mgmtd__FeMessage
*fe_msg
;
660 fe_msg
= mgmtd__fe_message__unpack(NULL
, len
, data
);
662 MGMTD_FE_CLIENT_DBG("Failed to decode %zu bytes from server.",
667 "Decoded %zu bytes of message(msg: %u/%u) from server", len
,
668 fe_msg
->message_case
, fe_msg
->message_case
);
669 (void)mgmt_fe_client_handle_msg(client_ctx
, fe_msg
);
670 mgmtd__fe_message__free_unpacked(fe_msg
, NULL
);
673 static void mgmt_fe_client_proc_msgbufs(struct event
*thread
)
675 struct mgmt_fe_client_ctx
*client_ctx
;
677 client_ctx
= (struct mgmt_fe_client_ctx
*)THREAD_ARG(thread
);
678 if (mgmt_msg_procbufs(&client_ctx
->mstate
, mgmt_fe_client_process_msg
,
679 client_ctx
, mgmt_debug_fe_client
))
680 mgmt_fe_client_register_event(client_ctx
, MGMTD_FE_PROC_MSG
);
683 static void mgmt_fe_client_read(struct event
*thread
)
685 struct mgmt_fe_client_ctx
*client_ctx
;
686 enum mgmt_msg_rsched rv
;
688 client_ctx
= (struct mgmt_fe_client_ctx
*)THREAD_ARG(thread
);
690 rv
= mgmt_msg_read(&client_ctx
->mstate
, client_ctx
->conn_fd
,
691 mgmt_debug_fe_client
);
692 if (rv
== MSR_DISCONNECT
) {
693 mgmt_fe_server_disconnect(client_ctx
, true);
696 if (rv
== MSR_SCHED_BOTH
)
697 mgmt_fe_client_register_event(client_ctx
, MGMTD_FE_PROC_MSG
);
698 mgmt_fe_client_register_event(client_ctx
, MGMTD_FE_CONN_READ
);
701 static void mgmt_fe_server_connect(struct mgmt_fe_client_ctx
*client_ctx
)
703 const char *dbgtag
= mgmt_debug_fe_client
? "FE-client" : NULL
;
705 assert(client_ctx
->conn_fd
== -1);
706 client_ctx
->conn_fd
= mgmt_msg_connect(
707 MGMTD_FE_SERVER_PATH
, MGMTD_SOCKET_FE_SEND_BUF_SIZE
,
708 MGMTD_SOCKET_FE_RECV_BUF_SIZE
, dbgtag
);
710 /* Send REGISTER_REQ message */
711 if (client_ctx
->conn_fd
== -1 ||
712 mgmt_fe_send_register_req(client_ctx
) != 0) {
713 mgmt_fe_server_disconnect(client_ctx
, true);
717 /* Start reading from the socket */
718 mgmt_fe_client_register_event(client_ctx
, MGMTD_FE_CONN_READ
);
720 /* Notify client through registered callback (if any) */
721 if (client_ctx
->client_params
.client_connect_notify
)
722 (void)(*client_ctx
->client_params
.client_connect_notify
)(
723 (uintptr_t)client_ctx
,
724 client_ctx
->client_params
.user_data
, true);
728 static void mgmt_fe_client_conn_timeout(struct event
*thread
)
730 mgmt_fe_server_connect(THREAD_ARG(thread
));
734 mgmt_fe_client_register_event(struct mgmt_fe_client_ctx
*client_ctx
,
735 enum mgmt_fe_event event
)
737 struct timeval tv
= {0};
740 case MGMTD_FE_CONN_READ
:
741 event_add_read(client_ctx
->tm
, mgmt_fe_client_read
,
742 client_ctx
, client_ctx
->conn_fd
,
743 &client_ctx
->conn_read_ev
);
744 assert(client_ctx
->conn_read_ev
);
746 case MGMTD_FE_CONN_WRITE
:
747 event_add_write(client_ctx
->tm
, mgmt_fe_client_write
,
748 client_ctx
, client_ctx
->conn_fd
,
749 &client_ctx
->conn_write_ev
);
750 assert(client_ctx
->conn_write_ev
);
752 case MGMTD_FE_PROC_MSG
:
753 tv
.tv_usec
= MGMTD_FE_MSG_PROC_DELAY_USEC
;
754 event_add_timer_tv(client_ctx
->tm
,
755 mgmt_fe_client_proc_msgbufs
, client_ctx
,
756 &tv
, &client_ctx
->msg_proc_ev
);
757 assert(client_ctx
->msg_proc_ev
);
759 case MGMTD_FE_CONN_WRITES_ON
:
760 event_add_timer_msec(
761 client_ctx
->tm
, mgmt_fe_client_resume_writes
,
762 client_ctx
, MGMTD_FE_MSG_WRITE_DELAY_MSEC
,
763 &client_ctx
->conn_writes_on
);
764 assert(client_ctx
->conn_writes_on
);
766 case MGMTD_FE_SERVER
:
767 assert(!"mgmt_fe_client_ctx_post_event called incorrectly");
772 static void mgmt_fe_client_schedule_conn_retry(
773 struct mgmt_fe_client_ctx
*client_ctx
, unsigned long intvl_secs
)
776 "Scheduling MGMTD Frontend server connection retry after %lu seconds",
778 event_add_timer(client_ctx
->tm
, mgmt_fe_client_conn_timeout
,
779 (void *)client_ctx
, intvl_secs
,
780 &client_ctx
->conn_retry_tmr
);
784 * Initialize library and try connecting with MGMTD.
786 uintptr_t mgmt_fe_client_lib_init(struct mgmt_fe_client_params
*params
,
787 struct event_master
*master_thread
)
789 assert(master_thread
&& params
&& strlen(params
->name
)
790 && !mgmt_fe_client_ctx
.tm
);
792 mgmt_fe_client_ctx
.tm
= master_thread
;
793 memcpy(&mgmt_fe_client_ctx
.client_params
, params
,
794 sizeof(mgmt_fe_client_ctx
.client_params
));
795 if (!mgmt_fe_client_ctx
.client_params
.conn_retry_intvl_sec
)
796 mgmt_fe_client_ctx
.client_params
.conn_retry_intvl_sec
=
797 MGMTD_FE_DEFAULT_CONN_RETRY_INTVL_SEC
;
799 mgmt_msg_init(&mgmt_fe_client_ctx
.mstate
, MGMTD_FE_MAX_NUM_MSG_PROC
,
800 MGMTD_FE_MAX_NUM_MSG_WRITE
, MGMTD_FE_MSG_MAX_LEN
,
803 mgmt_sessions_init(&mgmt_fe_client_ctx
.client_sessions
);
805 /* Start trying to connect to MGMTD frontend server immediately */
806 mgmt_fe_client_schedule_conn_retry(&mgmt_fe_client_ctx
, 1);
808 MGMTD_FE_CLIENT_DBG("Initialized client '%s'", params
->name
);
810 return (uintptr_t)&mgmt_fe_client_ctx
;
814 * Create a new Session for a Frontend Client connection.
816 enum mgmt_result
mgmt_fe_create_client_session(uintptr_t lib_hndl
,
820 struct mgmt_fe_client_ctx
*client_ctx
;
821 struct mgmt_fe_client_session
*session
;
823 client_ctx
= (struct mgmt_fe_client_ctx
*)lib_hndl
;
825 return MGMTD_INVALID_PARAM
;
827 session
= XCALLOC(MTYPE_MGMTD_FE_SESSION
,
828 sizeof(struct mgmt_fe_client_session
));
830 session
->user_ctx
= user_ctx
;
831 session
->client_id
= client_id
;
832 session
->client_ctx
= client_ctx
;
833 session
->session_id
= 0;
835 if (mgmt_fe_send_session_req(client_ctx
, session
, true) != 0) {
836 XFREE(MTYPE_MGMTD_FE_SESSION
, session
);
837 return MGMTD_INTERNAL_ERROR
;
839 mgmt_sessions_add_tail(&client_ctx
->client_sessions
, session
);
841 return MGMTD_SUCCESS
;
845 * Delete an existing Session for a Frontend Client connection.
847 enum mgmt_result
mgmt_fe_destroy_client_session(uintptr_t lib_hndl
,
850 struct mgmt_fe_client_ctx
*client_ctx
;
851 struct mgmt_fe_client_session
*session
;
853 client_ctx
= (struct mgmt_fe_client_ctx
*)lib_hndl
;
855 return MGMTD_INVALID_PARAM
;
857 session
= mgmt_fe_find_session_by_client_id(client_ctx
, client_id
);
858 if (!session
|| session
->client_ctx
!= client_ctx
)
859 return MGMTD_INVALID_PARAM
;
861 if (session
->session_id
&&
862 mgmt_fe_send_session_req(client_ctx
, session
, false) != 0)
864 "Failed to send session destroy request for the session-id %lu",
865 (unsigned long)session
->session_id
);
867 mgmt_sessions_del(&client_ctx
->client_sessions
, session
);
868 XFREE(MTYPE_MGMTD_FE_SESSION
, session
);
870 return MGMTD_SUCCESS
;
873 static void mgmt_fe_destroy_client_sessions(uintptr_t lib_hndl
)
875 struct mgmt_fe_client_ctx
*client_ctx
;
876 struct mgmt_fe_client_session
*session
;
878 client_ctx
= (struct mgmt_fe_client_ctx
*)lib_hndl
;
882 FOREACH_SESSION_IN_LIST (client_ctx
, session
)
883 mgmt_fe_destroy_client_session(lib_hndl
, session
->client_id
);
887 * Send UN/LOCK_DS_REQ to MGMTD for a specific Datastore DS.
889 enum mgmt_result
mgmt_fe_lock_ds(uintptr_t lib_hndl
, uintptr_t session_id
,
890 uint64_t req_id
, Mgmtd__DatastoreId ds_id
,
893 struct mgmt_fe_client_ctx
*client_ctx
;
894 struct mgmt_fe_client_session
*session
;
896 client_ctx
= (struct mgmt_fe_client_ctx
*)lib_hndl
;
898 return MGMTD_INVALID_PARAM
;
900 session
= (struct mgmt_fe_client_session
*)session_id
;
901 if (!session
|| session
->client_ctx
!= client_ctx
)
902 return MGMTD_INVALID_PARAM
;
904 if (mgmt_fe_send_lockds_req(client_ctx
, session
, lock_ds
, req_id
,
907 return MGMTD_INTERNAL_ERROR
;
909 return MGMTD_SUCCESS
;
913 * Send SET_CONFIG_REQ to MGMTD for one or more config data(s).
916 mgmt_fe_set_config_data(uintptr_t lib_hndl
, uintptr_t session_id
,
917 uint64_t req_id
, Mgmtd__DatastoreId ds_id
,
918 Mgmtd__YangCfgDataReq
**config_req
, int num_reqs
,
919 bool implicit_commit
, Mgmtd__DatastoreId dst_ds_id
)
921 struct mgmt_fe_client_ctx
*client_ctx
;
922 struct mgmt_fe_client_session
*session
;
924 client_ctx
= (struct mgmt_fe_client_ctx
*)lib_hndl
;
926 return MGMTD_INVALID_PARAM
;
928 session
= (struct mgmt_fe_client_session
*)session_id
;
929 if (!session
|| session
->client_ctx
!= client_ctx
)
930 return MGMTD_INVALID_PARAM
;
932 if (mgmt_fe_send_setcfg_req(client_ctx
, session
, req_id
, ds_id
,
933 config_req
, num_reqs
, implicit_commit
,
936 return MGMTD_INTERNAL_ERROR
;
938 return MGMTD_SUCCESS
;
942 * Send SET_CONFIG_REQ to MGMTD for one or more config data(s).
944 enum mgmt_result
mgmt_fe_commit_config_data(uintptr_t lib_hndl
,
945 uintptr_t session_id
,
947 Mgmtd__DatastoreId src_ds_id
,
948 Mgmtd__DatastoreId dst_ds_id
,
949 bool validate_only
, bool abort
)
951 struct mgmt_fe_client_ctx
*client_ctx
;
952 struct mgmt_fe_client_session
*session
;
954 client_ctx
= (struct mgmt_fe_client_ctx
*)lib_hndl
;
956 return MGMTD_INVALID_PARAM
;
958 session
= (struct mgmt_fe_client_session
*)session_id
;
959 if (!session
|| session
->client_ctx
!= client_ctx
)
960 return MGMTD_INVALID_PARAM
;
962 if (mgmt_fe_send_commitcfg_req(client_ctx
, session
, req_id
, src_ds_id
,
963 dst_ds_id
, validate_only
, abort
)
965 return MGMTD_INTERNAL_ERROR
;
967 return MGMTD_SUCCESS
;
971 * Send GET_CONFIG_REQ to MGMTD for one or more config data item(s).
974 mgmt_fe_get_config_data(uintptr_t lib_hndl
, uintptr_t session_id
,
975 uint64_t req_id
, Mgmtd__DatastoreId ds_id
,
976 Mgmtd__YangGetDataReq
* data_req
[], int num_reqs
)
978 struct mgmt_fe_client_ctx
*client_ctx
;
979 struct mgmt_fe_client_session
*session
;
981 client_ctx
= (struct mgmt_fe_client_ctx
*)lib_hndl
;
983 return MGMTD_INVALID_PARAM
;
985 session
= (struct mgmt_fe_client_session
*)session_id
;
986 if (!session
|| session
->client_ctx
!= client_ctx
)
987 return MGMTD_INVALID_PARAM
;
989 if (mgmt_fe_send_getcfg_req(client_ctx
, session
, req_id
, ds_id
,
992 return MGMTD_INTERNAL_ERROR
;
994 return MGMTD_SUCCESS
;
998 * Send GET_DATA_REQ to MGMTD for one or more config data item(s).
1000 enum mgmt_result
mgmt_fe_get_data(uintptr_t lib_hndl
, uintptr_t session_id
,
1001 uint64_t req_id
, Mgmtd__DatastoreId ds_id
,
1002 Mgmtd__YangGetDataReq
* data_req
[],
1005 struct mgmt_fe_client_ctx
*client_ctx
;
1006 struct mgmt_fe_client_session
*session
;
1008 client_ctx
= (struct mgmt_fe_client_ctx
*)lib_hndl
;
1010 return MGMTD_INVALID_PARAM
;
1012 session
= (struct mgmt_fe_client_session
*)session_id
;
1013 if (!session
|| session
->client_ctx
!= client_ctx
)
1014 return MGMTD_INVALID_PARAM
;
1016 if (mgmt_fe_send_getdata_req(client_ctx
, session
, req_id
, ds_id
,
1019 return MGMTD_INTERNAL_ERROR
;
1021 return MGMTD_SUCCESS
;
1025 * Send NOTIFY_REGISTER_REQ to MGMTD daemon.
1028 mgmt_fe_register_yang_notify(uintptr_t lib_hndl
, uintptr_t session_id
,
1029 uint64_t req_id
, Mgmtd__DatastoreId ds_id
,
1031 Mgmtd__YangDataXPath
* data_req
[],
1034 struct mgmt_fe_client_ctx
*client_ctx
;
1035 struct mgmt_fe_client_session
*session
;
1037 client_ctx
= (struct mgmt_fe_client_ctx
*)lib_hndl
;
1039 return MGMTD_INVALID_PARAM
;
1041 session
= (struct mgmt_fe_client_session
*)session_id
;
1042 if (!session
|| session
->client_ctx
!= client_ctx
)
1043 return MGMTD_INVALID_PARAM
;
1045 if (mgmt_fe_send_regnotify_req(client_ctx
, session
, req_id
, ds_id
,
1046 register_req
, data_req
, num_reqs
)
1048 return MGMTD_INTERNAL_ERROR
;
1050 return MGMTD_SUCCESS
;
1054 * Destroy library and cleanup everything.
1056 void mgmt_fe_client_lib_destroy(uintptr_t lib_hndl
)
1058 struct mgmt_fe_client_ctx
*client_ctx
;
1060 client_ctx
= (struct mgmt_fe_client_ctx
*)lib_hndl
;
1063 MGMTD_FE_CLIENT_DBG("Destroying MGMTD Frontend Client '%s'",
1064 client_ctx
->client_params
.name
);
1066 mgmt_fe_server_disconnect(client_ctx
, false);
1068 mgmt_fe_destroy_client_sessions(lib_hndl
);
1070 THREAD_OFF(client_ctx
->conn_retry_tmr
);
1071 THREAD_OFF(client_ctx
->conn_read_ev
);
1072 THREAD_OFF(client_ctx
->conn_write_ev
);
1073 THREAD_OFF(client_ctx
->conn_writes_on
);
1074 THREAD_OFF(client_ctx
->msg_proc_ev
);
1075 mgmt_msg_destroy(&client_ctx
->mstate
);