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_loop
*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
*)EVENT_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
*)EVENT_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
*)EVENT_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
*)EVENT_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(EVENT_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
);
745 case MGMTD_FE_CONN_WRITE
:
746 event_add_write(client_ctx
->tm
, mgmt_fe_client_write
,
747 client_ctx
, client_ctx
->conn_fd
,
748 &client_ctx
->conn_write_ev
);
750 case MGMTD_FE_PROC_MSG
:
751 tv
.tv_usec
= MGMTD_FE_MSG_PROC_DELAY_USEC
;
752 event_add_timer_tv(client_ctx
->tm
,
753 mgmt_fe_client_proc_msgbufs
, client_ctx
,
754 &tv
, &client_ctx
->msg_proc_ev
);
756 case MGMTD_FE_CONN_WRITES_ON
:
757 event_add_timer_msec(
758 client_ctx
->tm
, mgmt_fe_client_resume_writes
,
759 client_ctx
, MGMTD_FE_MSG_WRITE_DELAY_MSEC
,
760 &client_ctx
->conn_writes_on
);
762 case MGMTD_FE_SERVER
:
763 assert(!"mgmt_fe_client_ctx_post_event called incorrectly");
768 static void mgmt_fe_client_schedule_conn_retry(
769 struct mgmt_fe_client_ctx
*client_ctx
, unsigned long intvl_secs
)
772 "Scheduling MGMTD Frontend server connection retry after %lu seconds",
774 event_add_timer(client_ctx
->tm
, mgmt_fe_client_conn_timeout
,
775 (void *)client_ctx
, intvl_secs
,
776 &client_ctx
->conn_retry_tmr
);
780 * Initialize library and try connecting with MGMTD.
782 uintptr_t mgmt_fe_client_lib_init(struct mgmt_fe_client_params
*params
,
783 struct event_loop
*master_thread
)
785 assert(master_thread
&& params
&& strlen(params
->name
)
786 && !mgmt_fe_client_ctx
.tm
);
788 mgmt_fe_client_ctx
.tm
= master_thread
;
789 memcpy(&mgmt_fe_client_ctx
.client_params
, params
,
790 sizeof(mgmt_fe_client_ctx
.client_params
));
791 if (!mgmt_fe_client_ctx
.client_params
.conn_retry_intvl_sec
)
792 mgmt_fe_client_ctx
.client_params
.conn_retry_intvl_sec
=
793 MGMTD_FE_DEFAULT_CONN_RETRY_INTVL_SEC
;
795 mgmt_msg_init(&mgmt_fe_client_ctx
.mstate
, MGMTD_FE_MAX_NUM_MSG_PROC
,
796 MGMTD_FE_MAX_NUM_MSG_WRITE
, MGMTD_FE_MSG_MAX_LEN
,
799 mgmt_sessions_init(&mgmt_fe_client_ctx
.client_sessions
);
801 /* Start trying to connect to MGMTD frontend server immediately */
802 mgmt_fe_client_schedule_conn_retry(&mgmt_fe_client_ctx
, 1);
804 MGMTD_FE_CLIENT_DBG("Initialized client '%s'", params
->name
);
806 return (uintptr_t)&mgmt_fe_client_ctx
;
810 * Create a new Session for a Frontend Client connection.
812 enum mgmt_result
mgmt_fe_create_client_session(uintptr_t lib_hndl
,
816 struct mgmt_fe_client_ctx
*client_ctx
;
817 struct mgmt_fe_client_session
*session
;
819 client_ctx
= (struct mgmt_fe_client_ctx
*)lib_hndl
;
821 return MGMTD_INVALID_PARAM
;
823 session
= XCALLOC(MTYPE_MGMTD_FE_SESSION
,
824 sizeof(struct mgmt_fe_client_session
));
826 session
->user_ctx
= user_ctx
;
827 session
->client_id
= client_id
;
828 session
->client_ctx
= client_ctx
;
829 session
->session_id
= 0;
831 if (mgmt_fe_send_session_req(client_ctx
, session
, true) != 0) {
832 XFREE(MTYPE_MGMTD_FE_SESSION
, session
);
833 return MGMTD_INTERNAL_ERROR
;
835 mgmt_sessions_add_tail(&client_ctx
->client_sessions
, session
);
837 return MGMTD_SUCCESS
;
841 * Delete an existing Session for a Frontend Client connection.
843 enum mgmt_result
mgmt_fe_destroy_client_session(uintptr_t lib_hndl
,
846 struct mgmt_fe_client_ctx
*client_ctx
;
847 struct mgmt_fe_client_session
*session
;
849 client_ctx
= (struct mgmt_fe_client_ctx
*)lib_hndl
;
851 return MGMTD_INVALID_PARAM
;
853 session
= mgmt_fe_find_session_by_client_id(client_ctx
, client_id
);
854 if (!session
|| session
->client_ctx
!= client_ctx
)
855 return MGMTD_INVALID_PARAM
;
857 if (session
->session_id
&&
858 mgmt_fe_send_session_req(client_ctx
, session
, false) != 0)
860 "Failed to send session destroy request for the session-id %lu",
861 (unsigned long)session
->session_id
);
863 mgmt_sessions_del(&client_ctx
->client_sessions
, session
);
864 XFREE(MTYPE_MGMTD_FE_SESSION
, session
);
866 return MGMTD_SUCCESS
;
869 static void mgmt_fe_destroy_client_sessions(uintptr_t lib_hndl
)
871 struct mgmt_fe_client_ctx
*client_ctx
;
872 struct mgmt_fe_client_session
*session
;
874 client_ctx
= (struct mgmt_fe_client_ctx
*)lib_hndl
;
878 FOREACH_SESSION_IN_LIST (client_ctx
, session
)
879 mgmt_fe_destroy_client_session(lib_hndl
, session
->client_id
);
883 * Send UN/LOCK_DS_REQ to MGMTD for a specific Datastore DS.
885 enum mgmt_result
mgmt_fe_lock_ds(uintptr_t lib_hndl
, uintptr_t session_id
,
886 uint64_t req_id
, Mgmtd__DatastoreId ds_id
,
889 struct mgmt_fe_client_ctx
*client_ctx
;
890 struct mgmt_fe_client_session
*session
;
892 client_ctx
= (struct mgmt_fe_client_ctx
*)lib_hndl
;
894 return MGMTD_INVALID_PARAM
;
896 session
= (struct mgmt_fe_client_session
*)session_id
;
897 if (!session
|| session
->client_ctx
!= client_ctx
)
898 return MGMTD_INVALID_PARAM
;
900 if (mgmt_fe_send_lockds_req(client_ctx
, session
, lock_ds
, req_id
,
903 return MGMTD_INTERNAL_ERROR
;
905 return MGMTD_SUCCESS
;
909 * Send SET_CONFIG_REQ to MGMTD for one or more config data(s).
912 mgmt_fe_set_config_data(uintptr_t lib_hndl
, uintptr_t session_id
,
913 uint64_t req_id
, Mgmtd__DatastoreId ds_id
,
914 Mgmtd__YangCfgDataReq
**config_req
, int num_reqs
,
915 bool implicit_commit
, Mgmtd__DatastoreId dst_ds_id
)
917 struct mgmt_fe_client_ctx
*client_ctx
;
918 struct mgmt_fe_client_session
*session
;
920 client_ctx
= (struct mgmt_fe_client_ctx
*)lib_hndl
;
922 return MGMTD_INVALID_PARAM
;
924 session
= (struct mgmt_fe_client_session
*)session_id
;
925 if (!session
|| session
->client_ctx
!= client_ctx
)
926 return MGMTD_INVALID_PARAM
;
928 if (mgmt_fe_send_setcfg_req(client_ctx
, session
, req_id
, ds_id
,
929 config_req
, num_reqs
, implicit_commit
,
932 return MGMTD_INTERNAL_ERROR
;
934 return MGMTD_SUCCESS
;
938 * Send SET_CONFIG_REQ to MGMTD for one or more config data(s).
940 enum mgmt_result
mgmt_fe_commit_config_data(uintptr_t lib_hndl
,
941 uintptr_t session_id
,
943 Mgmtd__DatastoreId src_ds_id
,
944 Mgmtd__DatastoreId dst_ds_id
,
945 bool validate_only
, bool abort
)
947 struct mgmt_fe_client_ctx
*client_ctx
;
948 struct mgmt_fe_client_session
*session
;
950 client_ctx
= (struct mgmt_fe_client_ctx
*)lib_hndl
;
952 return MGMTD_INVALID_PARAM
;
954 session
= (struct mgmt_fe_client_session
*)session_id
;
955 if (!session
|| session
->client_ctx
!= client_ctx
)
956 return MGMTD_INVALID_PARAM
;
958 if (mgmt_fe_send_commitcfg_req(client_ctx
, session
, req_id
, src_ds_id
,
959 dst_ds_id
, validate_only
, abort
)
961 return MGMTD_INTERNAL_ERROR
;
963 return MGMTD_SUCCESS
;
967 * Send GET_CONFIG_REQ to MGMTD for one or more config data item(s).
970 mgmt_fe_get_config_data(uintptr_t lib_hndl
, uintptr_t session_id
,
971 uint64_t req_id
, Mgmtd__DatastoreId ds_id
,
972 Mgmtd__YangGetDataReq
* data_req
[], int num_reqs
)
974 struct mgmt_fe_client_ctx
*client_ctx
;
975 struct mgmt_fe_client_session
*session
;
977 client_ctx
= (struct mgmt_fe_client_ctx
*)lib_hndl
;
979 return MGMTD_INVALID_PARAM
;
981 session
= (struct mgmt_fe_client_session
*)session_id
;
982 if (!session
|| session
->client_ctx
!= client_ctx
)
983 return MGMTD_INVALID_PARAM
;
985 if (mgmt_fe_send_getcfg_req(client_ctx
, session
, req_id
, ds_id
,
988 return MGMTD_INTERNAL_ERROR
;
990 return MGMTD_SUCCESS
;
994 * Send GET_DATA_REQ to MGMTD for one or more config data item(s).
996 enum mgmt_result
mgmt_fe_get_data(uintptr_t lib_hndl
, uintptr_t session_id
,
997 uint64_t req_id
, Mgmtd__DatastoreId ds_id
,
998 Mgmtd__YangGetDataReq
* data_req
[],
1001 struct mgmt_fe_client_ctx
*client_ctx
;
1002 struct mgmt_fe_client_session
*session
;
1004 client_ctx
= (struct mgmt_fe_client_ctx
*)lib_hndl
;
1006 return MGMTD_INVALID_PARAM
;
1008 session
= (struct mgmt_fe_client_session
*)session_id
;
1009 if (!session
|| session
->client_ctx
!= client_ctx
)
1010 return MGMTD_INVALID_PARAM
;
1012 if (mgmt_fe_send_getdata_req(client_ctx
, session
, req_id
, ds_id
,
1015 return MGMTD_INTERNAL_ERROR
;
1017 return MGMTD_SUCCESS
;
1021 * Send NOTIFY_REGISTER_REQ to MGMTD daemon.
1024 mgmt_fe_register_yang_notify(uintptr_t lib_hndl
, uintptr_t session_id
,
1025 uint64_t req_id
, Mgmtd__DatastoreId ds_id
,
1027 Mgmtd__YangDataXPath
* data_req
[],
1030 struct mgmt_fe_client_ctx
*client_ctx
;
1031 struct mgmt_fe_client_session
*session
;
1033 client_ctx
= (struct mgmt_fe_client_ctx
*)lib_hndl
;
1035 return MGMTD_INVALID_PARAM
;
1037 session
= (struct mgmt_fe_client_session
*)session_id
;
1038 if (!session
|| session
->client_ctx
!= client_ctx
)
1039 return MGMTD_INVALID_PARAM
;
1041 if (mgmt_fe_send_regnotify_req(client_ctx
, session
, req_id
, ds_id
,
1042 register_req
, data_req
, num_reqs
)
1044 return MGMTD_INTERNAL_ERROR
;
1046 return MGMTD_SUCCESS
;
1050 * Destroy library and cleanup everything.
1052 void mgmt_fe_client_lib_destroy(uintptr_t lib_hndl
)
1054 struct mgmt_fe_client_ctx
*client_ctx
;
1056 client_ctx
= (struct mgmt_fe_client_ctx
*)lib_hndl
;
1059 MGMTD_FE_CLIENT_DBG("Destroying MGMTD Frontend Client '%s'",
1060 client_ctx
->client_params
.name
);
1062 mgmt_fe_server_disconnect(client_ctx
, false);
1064 mgmt_fe_destroy_client_sessions(lib_hndl
);
1066 EVENT_OFF(client_ctx
->conn_retry_tmr
);
1067 EVENT_OFF(client_ctx
->conn_read_ev
);
1068 EVENT_OFF(client_ctx
->conn_write_ev
);
1069 EVENT_OFF(client_ctx
->conn_writes_on
);
1070 EVENT_OFF(client_ctx
->msg_proc_ev
);
1071 mgmt_msg_destroy(&client_ctx
->mstate
);