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.",
113 session
, (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
,
278 (unsigned long long)session
->client_id
);
280 return mgmt_fe_client_send_msg(client_ctx
, &fe_msg
);
284 mgmt_fe_send_setcfg_req(struct mgmt_fe_client_ctx
*client_ctx
,
285 struct mgmt_fe_client_session
*session
,
286 uint64_t req_id
, Mgmtd__DatastoreId ds_id
,
287 Mgmtd__YangCfgDataReq
**data_req
, int num_data_reqs
,
288 bool implicit_commit
, Mgmtd__DatastoreId dst_ds_id
)
291 Mgmtd__FeMessage fe_msg
;
292 Mgmtd__FeSetConfigReq setcfg_req
;
294 mgmtd__fe_set_config_req__init(&setcfg_req
);
295 setcfg_req
.session_id
= session
->session_id
;
296 setcfg_req
.ds_id
= ds_id
;
297 setcfg_req
.req_id
= req_id
;
298 setcfg_req
.data
= data_req
;
299 setcfg_req
.n_data
= (size_t)num_data_reqs
;
300 setcfg_req
.implicit_commit
= implicit_commit
;
301 setcfg_req
.commit_ds_id
= dst_ds_id
;
303 mgmtd__fe_message__init(&fe_msg
);
304 fe_msg
.message_case
= MGMTD__FE_MESSAGE__MESSAGE_SETCFG_REQ
;
305 fe_msg
.setcfg_req
= &setcfg_req
;
308 "Sending SET_CONFIG_REQ message for Ds:%d session %llu (#xpaths:%d) to MGMTD Frontend server",
309 ds_id
, (unsigned long long)session
->client_id
, num_data_reqs
);
311 return mgmt_fe_client_send_msg(client_ctx
, &fe_msg
);
314 static int mgmt_fe_send_commitcfg_req(struct mgmt_fe_client_ctx
*client_ctx
,
315 struct mgmt_fe_client_session
*session
,
317 Mgmtd__DatastoreId src_ds_id
,
318 Mgmtd__DatastoreId dest_ds_id
,
319 bool validate_only
, bool abort
)
322 Mgmtd__FeMessage fe_msg
;
323 Mgmtd__FeCommitConfigReq commitcfg_req
;
325 mgmtd__fe_commit_config_req__init(&commitcfg_req
);
326 commitcfg_req
.session_id
= session
->session_id
;
327 commitcfg_req
.src_ds_id
= src_ds_id
;
328 commitcfg_req
.dst_ds_id
= dest_ds_id
;
329 commitcfg_req
.req_id
= req_id
;
330 commitcfg_req
.validate_only
= validate_only
;
331 commitcfg_req
.abort
= abort
;
333 mgmtd__fe_message__init(&fe_msg
);
334 fe_msg
.message_case
= MGMTD__FE_MESSAGE__MESSAGE_COMMCFG_REQ
;
335 fe_msg
.commcfg_req
= &commitcfg_req
;
338 "Sending COMMIT_CONFIG_REQ message for Src-Ds:%d, Dst-Ds:%d session %llu to MGMTD Frontend server",
339 src_ds_id
, dest_ds_id
, (unsigned long long)session
->client_id
);
341 return mgmt_fe_client_send_msg(client_ctx
, &fe_msg
);
345 mgmt_fe_send_getcfg_req(struct mgmt_fe_client_ctx
*client_ctx
,
346 struct mgmt_fe_client_session
*session
,
347 uint64_t req_id
, Mgmtd__DatastoreId ds_id
,
348 Mgmtd__YangGetDataReq
* data_req
[],
352 Mgmtd__FeMessage fe_msg
;
353 Mgmtd__FeGetConfigReq getcfg_req
;
355 mgmtd__fe_get_config_req__init(&getcfg_req
);
356 getcfg_req
.session_id
= session
->session_id
;
357 getcfg_req
.ds_id
= ds_id
;
358 getcfg_req
.req_id
= req_id
;
359 getcfg_req
.data
= data_req
;
360 getcfg_req
.n_data
= (size_t)num_data_reqs
;
362 mgmtd__fe_message__init(&fe_msg
);
363 fe_msg
.message_case
= MGMTD__FE_MESSAGE__MESSAGE_GETCFG_REQ
;
364 fe_msg
.getcfg_req
= &getcfg_req
;
367 "Sending GET_CONFIG_REQ message for Ds:%d session %llu (#xpaths:%d) to MGMTD Frontend server",
368 ds_id
, (unsigned long long)session
->client_id
, num_data_reqs
);
370 return mgmt_fe_client_send_msg(client_ctx
, &fe_msg
);
374 mgmt_fe_send_getdata_req(struct mgmt_fe_client_ctx
*client_ctx
,
375 struct mgmt_fe_client_session
*session
,
376 uint64_t req_id
, Mgmtd__DatastoreId ds_id
,
377 Mgmtd__YangGetDataReq
* data_req
[],
381 Mgmtd__FeMessage fe_msg
;
382 Mgmtd__FeGetDataReq getdata_req
;
384 mgmtd__fe_get_data_req__init(&getdata_req
);
385 getdata_req
.session_id
= session
->session_id
;
386 getdata_req
.ds_id
= ds_id
;
387 getdata_req
.req_id
= req_id
;
388 getdata_req
.data
= data_req
;
389 getdata_req
.n_data
= (size_t)num_data_reqs
;
391 mgmtd__fe_message__init(&fe_msg
);
392 fe_msg
.message_case
= MGMTD__FE_MESSAGE__MESSAGE_GETDATA_REQ
;
393 fe_msg
.getdata_req
= &getdata_req
;
396 "Sending GET_CONFIG_REQ message for Ds:%d session %llu (#xpaths:%d) to MGMTD Frontend server",
397 ds_id
, (unsigned long long)session
->client_id
, num_data_reqs
);
399 return mgmt_fe_client_send_msg(client_ctx
, &fe_msg
);
402 static int mgmt_fe_send_regnotify_req(
403 struct mgmt_fe_client_ctx
*client_ctx
,
404 struct mgmt_fe_client_session
*session
, uint64_t req_id
,
405 Mgmtd__DatastoreId ds_id
, bool register_req
,
406 Mgmtd__YangDataXPath
* data_req
[], int num_data_reqs
)
409 Mgmtd__FeMessage fe_msg
;
410 Mgmtd__FeRegisterNotifyReq regntfy_req
;
412 mgmtd__fe_register_notify_req__init(®ntfy_req
);
413 regntfy_req
.session_id
= session
->session_id
;
414 regntfy_req
.ds_id
= ds_id
;
415 regntfy_req
.register_req
= register_req
;
416 regntfy_req
.data_xpath
= data_req
;
417 regntfy_req
.n_data_xpath
= (size_t)num_data_reqs
;
419 mgmtd__fe_message__init(&fe_msg
);
420 fe_msg
.message_case
= MGMTD__FE_MESSAGE__MESSAGE_REGNOTIFY_REQ
;
421 fe_msg
.regnotify_req
= ®ntfy_req
;
423 return mgmt_fe_client_send_msg(client_ctx
, &fe_msg
);
427 mgmt_fe_client_handle_msg(struct mgmt_fe_client_ctx
*client_ctx
,
428 Mgmtd__FeMessage
*fe_msg
)
430 struct mgmt_fe_client_session
*session
= NULL
;
433 * protobuf-c adds a max size enum with an internal, and changing by
434 * version, name; cast to an int to avoid unhandled enum warnings
436 switch ((int)fe_msg
->message_case
) {
437 case MGMTD__FE_MESSAGE__MESSAGE_SESSION_REPLY
:
438 if (fe_msg
->session_reply
->create
439 && fe_msg
->session_reply
->has_client_conn_id
) {
441 "Got Session Create Reply Msg for client-id %llu with session-id: %llu.",
443 fe_msg
->session_reply
->client_conn_id
,
445 fe_msg
->session_reply
->session_id
);
447 session
= mgmt_fe_find_session_by_client_id(
449 fe_msg
->session_reply
->client_conn_id
);
451 if (session
&& fe_msg
->session_reply
->success
) {
453 "Session Create for client-id %llu successful.",
455 fe_msg
->session_reply
457 session
->session_id
=
458 fe_msg
->session_reply
->session_id
;
461 "Session Create for client-id %llu failed.",
463 fe_msg
->session_reply
466 } else if (!fe_msg
->session_reply
->create
) {
468 "Got Session Destroy Reply Msg for session-id %llu",
470 fe_msg
->session_reply
->session_id
);
472 session
= mgmt_fe_find_session_by_session_id(
473 client_ctx
, fe_msg
->session_req
->session_id
);
476 if (session
&& session
->client_ctx
477 && session
->client_ctx
->client_params
478 .client_session_notify
)
479 (*session
->client_ctx
->client_params
480 .client_session_notify
)(
481 (uintptr_t)client_ctx
,
482 client_ctx
->client_params
.user_data
,
484 fe_msg
->session_reply
->create
,
485 fe_msg
->session_reply
->success
,
486 (uintptr_t)session
, session
->user_ctx
);
488 case MGMTD__FE_MESSAGE__MESSAGE_LOCKDS_REPLY
:
490 "Got LockDs Reply Msg for session-id %llu",
492 fe_msg
->lockds_reply
->session_id
);
493 session
= mgmt_fe_find_session_by_session_id(
494 client_ctx
, fe_msg
->lockds_reply
->session_id
);
496 if (session
&& session
->client_ctx
497 && session
->client_ctx
->client_params
499 (*session
->client_ctx
->client_params
501 (uintptr_t)client_ctx
,
502 client_ctx
->client_params
.user_data
,
503 session
->client_id
, (uintptr_t)session
,
505 fe_msg
->lockds_reply
->req_id
,
506 fe_msg
->lockds_reply
->lock
,
507 fe_msg
->lockds_reply
->success
,
508 fe_msg
->lockds_reply
->ds_id
,
509 fe_msg
->lockds_reply
->error_if_any
);
511 case MGMTD__FE_MESSAGE__MESSAGE_SETCFG_REPLY
:
513 "Got Set Config Reply Msg for session-id %llu",
515 fe_msg
->setcfg_reply
->session_id
);
517 session
= mgmt_fe_find_session_by_session_id(
518 client_ctx
, fe_msg
->setcfg_reply
->session_id
);
520 if (session
&& session
->client_ctx
521 && session
->client_ctx
->client_params
523 (*session
->client_ctx
->client_params
525 (uintptr_t)client_ctx
,
526 client_ctx
->client_params
.user_data
,
527 session
->client_id
, (uintptr_t)session
,
529 fe_msg
->setcfg_reply
->req_id
,
530 fe_msg
->setcfg_reply
->success
,
531 fe_msg
->setcfg_reply
->ds_id
,
532 fe_msg
->setcfg_reply
->error_if_any
);
534 case MGMTD__FE_MESSAGE__MESSAGE_COMMCFG_REPLY
:
536 "Got Commit Config Reply Msg for session-id %llu",
538 fe_msg
->commcfg_reply
->session_id
);
540 session
= mgmt_fe_find_session_by_session_id(
541 client_ctx
, fe_msg
->commcfg_reply
->session_id
);
543 if (session
&& session
->client_ctx
544 && session
->client_ctx
->client_params
545 .commit_config_notify
)
546 (*session
->client_ctx
->client_params
547 .commit_config_notify
)(
548 (uintptr_t)client_ctx
,
549 client_ctx
->client_params
.user_data
,
550 session
->client_id
, (uintptr_t)session
,
552 fe_msg
->commcfg_reply
->req_id
,
553 fe_msg
->commcfg_reply
->success
,
554 fe_msg
->commcfg_reply
->src_ds_id
,
555 fe_msg
->commcfg_reply
->dst_ds_id
,
556 fe_msg
->commcfg_reply
->validate_only
,
557 fe_msg
->commcfg_reply
->error_if_any
);
559 case MGMTD__FE_MESSAGE__MESSAGE_GETCFG_REPLY
:
561 "Got Get Config Reply Msg for session-id %llu",
563 fe_msg
->getcfg_reply
->session_id
);
565 session
= mgmt_fe_find_session_by_session_id(
566 client_ctx
, fe_msg
->getcfg_reply
->session_id
);
568 if (session
&& session
->client_ctx
569 && session
->client_ctx
->client_params
571 (*session
->client_ctx
->client_params
573 (uintptr_t)client_ctx
,
574 client_ctx
->client_params
.user_data
,
575 session
->client_id
, (uintptr_t)session
,
577 fe_msg
->getcfg_reply
->req_id
,
578 fe_msg
->getcfg_reply
->success
,
579 fe_msg
->getcfg_reply
->ds_id
,
580 fe_msg
->getcfg_reply
->data
581 ? fe_msg
->getcfg_reply
->data
->data
583 fe_msg
->getcfg_reply
->data
584 ? fe_msg
->getcfg_reply
->data
->n_data
586 fe_msg
->getcfg_reply
->data
587 ? fe_msg
->getcfg_reply
->data
590 fe_msg
->getcfg_reply
->error_if_any
);
592 case MGMTD__FE_MESSAGE__MESSAGE_GETDATA_REPLY
:
594 "Got Get Data Reply Msg for session-id %llu",
596 fe_msg
->getdata_reply
->session_id
);
598 session
= mgmt_fe_find_session_by_session_id(
599 client_ctx
, fe_msg
->getdata_reply
->session_id
);
601 if (session
&& session
->client_ctx
602 && session
->client_ctx
->client_params
604 (*session
->client_ctx
->client_params
606 (uintptr_t)client_ctx
,
607 client_ctx
->client_params
.user_data
,
608 session
->client_id
, (uintptr_t)session
,
610 fe_msg
->getdata_reply
->req_id
,
611 fe_msg
->getdata_reply
->success
,
612 fe_msg
->getdata_reply
->ds_id
,
613 fe_msg
->getdata_reply
->data
614 ? fe_msg
->getdata_reply
->data
->data
616 fe_msg
->getdata_reply
->data
617 ? fe_msg
->getdata_reply
->data
620 fe_msg
->getdata_reply
->data
621 ? fe_msg
->getdata_reply
->data
624 fe_msg
->getdata_reply
->error_if_any
);
626 case MGMTD__FE_MESSAGE__MESSAGE_NOTIFY_DATA_REQ
:
627 case MGMTD__FE_MESSAGE__MESSAGE_REGNOTIFY_REQ
:
629 * TODO: Add handling code in future.
633 * NOTE: The following messages are always sent from Frontend
634 * clients to MGMTd only and/or need not be handled here.
636 case MGMTD__FE_MESSAGE__MESSAGE_REGISTER_REQ
:
637 case MGMTD__FE_MESSAGE__MESSAGE_SESSION_REQ
:
638 case MGMTD__FE_MESSAGE__MESSAGE_LOCKDS_REQ
:
639 case MGMTD__FE_MESSAGE__MESSAGE_SETCFG_REQ
:
640 case MGMTD__FE_MESSAGE__MESSAGE_COMMCFG_REQ
:
641 case MGMTD__FE_MESSAGE__MESSAGE_GETCFG_REQ
:
642 case MGMTD__FE_MESSAGE__MESSAGE_GETDATA_REQ
:
643 case MGMTD__FE_MESSAGE__MESSAGE__NOT_SET
:
646 * A 'default' case is being added contrary to the
647 * FRR code guidelines to take care of build
648 * failures on certain build systems (courtesy of
649 * the proto-c package).
657 static void mgmt_fe_client_process_msg(void *user_ctx
, uint8_t *data
,
660 struct mgmt_fe_client_ctx
*client_ctx
= user_ctx
;
661 Mgmtd__FeMessage
*fe_msg
;
663 fe_msg
= mgmtd__fe_message__unpack(NULL
, len
, data
);
665 MGMTD_FE_CLIENT_DBG("Failed to decode %zu bytes from server.",
670 "Decoded %zu bytes of message(msg: %u/%u) from server", len
,
671 fe_msg
->message_case
, fe_msg
->message_case
);
672 (void)mgmt_fe_client_handle_msg(client_ctx
, fe_msg
);
673 mgmtd__fe_message__free_unpacked(fe_msg
, NULL
);
676 static void mgmt_fe_client_proc_msgbufs(struct event
*thread
)
678 struct mgmt_fe_client_ctx
*client_ctx
;
680 client_ctx
= (struct mgmt_fe_client_ctx
*)EVENT_ARG(thread
);
681 if (mgmt_msg_procbufs(&client_ctx
->mstate
, mgmt_fe_client_process_msg
,
682 client_ctx
, mgmt_debug_fe_client
))
683 mgmt_fe_client_register_event(client_ctx
, MGMTD_FE_PROC_MSG
);
686 static void mgmt_fe_client_read(struct event
*thread
)
688 struct mgmt_fe_client_ctx
*client_ctx
;
689 enum mgmt_msg_rsched rv
;
691 client_ctx
= (struct mgmt_fe_client_ctx
*)EVENT_ARG(thread
);
693 rv
= mgmt_msg_read(&client_ctx
->mstate
, client_ctx
->conn_fd
,
694 mgmt_debug_fe_client
);
695 if (rv
== MSR_DISCONNECT
) {
696 mgmt_fe_server_disconnect(client_ctx
, true);
699 if (rv
== MSR_SCHED_BOTH
)
700 mgmt_fe_client_register_event(client_ctx
, MGMTD_FE_PROC_MSG
);
701 mgmt_fe_client_register_event(client_ctx
, MGMTD_FE_CONN_READ
);
704 static void mgmt_fe_server_connect(struct mgmt_fe_client_ctx
*client_ctx
)
706 const char *dbgtag
= mgmt_debug_fe_client
? "FE-client" : NULL
;
708 assert(client_ctx
->conn_fd
== -1);
709 client_ctx
->conn_fd
= mgmt_msg_connect(
710 MGMTD_FE_SERVER_PATH
, MGMTD_SOCKET_FE_SEND_BUF_SIZE
,
711 MGMTD_SOCKET_FE_RECV_BUF_SIZE
, dbgtag
);
713 /* Send REGISTER_REQ message */
714 if (client_ctx
->conn_fd
== -1 ||
715 mgmt_fe_send_register_req(client_ctx
) != 0) {
716 mgmt_fe_server_disconnect(client_ctx
, true);
720 /* Start reading from the socket */
721 mgmt_fe_client_register_event(client_ctx
, MGMTD_FE_CONN_READ
);
723 /* Notify client through registered callback (if any) */
724 if (client_ctx
->client_params
.client_connect_notify
)
725 (void)(*client_ctx
->client_params
.client_connect_notify
)(
726 (uintptr_t)client_ctx
,
727 client_ctx
->client_params
.user_data
, true);
731 static void mgmt_fe_client_conn_timeout(struct event
*thread
)
733 mgmt_fe_server_connect(EVENT_ARG(thread
));
737 mgmt_fe_client_register_event(struct mgmt_fe_client_ctx
*client_ctx
,
738 enum mgmt_fe_event event
)
740 struct timeval tv
= {0};
743 case MGMTD_FE_CONN_READ
:
744 event_add_read(client_ctx
->tm
, mgmt_fe_client_read
,
745 client_ctx
, client_ctx
->conn_fd
,
746 &client_ctx
->conn_read_ev
);
748 case MGMTD_FE_CONN_WRITE
:
749 event_add_write(client_ctx
->tm
, mgmt_fe_client_write
,
750 client_ctx
, client_ctx
->conn_fd
,
751 &client_ctx
->conn_write_ev
);
753 case MGMTD_FE_PROC_MSG
:
754 tv
.tv_usec
= MGMTD_FE_MSG_PROC_DELAY_USEC
;
755 event_add_timer_tv(client_ctx
->tm
,
756 mgmt_fe_client_proc_msgbufs
, client_ctx
,
757 &tv
, &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
);
765 case MGMTD_FE_SERVER
:
766 assert(!"mgmt_fe_client_ctx_post_event called incorrectly");
771 static void mgmt_fe_client_schedule_conn_retry(
772 struct mgmt_fe_client_ctx
*client_ctx
, unsigned long intvl_secs
)
775 "Scheduling MGMTD Frontend server connection retry after %lu seconds",
777 event_add_timer(client_ctx
->tm
, mgmt_fe_client_conn_timeout
,
778 (void *)client_ctx
, intvl_secs
,
779 &client_ctx
->conn_retry_tmr
);
783 * Initialize library and try connecting with MGMTD.
785 uintptr_t mgmt_fe_client_lib_init(struct mgmt_fe_client_params
*params
,
786 struct event_loop
*master_thread
)
788 assert(master_thread
&& params
&& strlen(params
->name
)
789 && !mgmt_fe_client_ctx
.tm
);
791 mgmt_fe_client_ctx
.tm
= master_thread
;
792 memcpy(&mgmt_fe_client_ctx
.client_params
, params
,
793 sizeof(mgmt_fe_client_ctx
.client_params
));
794 if (!mgmt_fe_client_ctx
.client_params
.conn_retry_intvl_sec
)
795 mgmt_fe_client_ctx
.client_params
.conn_retry_intvl_sec
=
796 MGMTD_FE_DEFAULT_CONN_RETRY_INTVL_SEC
;
798 mgmt_msg_init(&mgmt_fe_client_ctx
.mstate
, MGMTD_FE_MAX_NUM_MSG_PROC
,
799 MGMTD_FE_MAX_NUM_MSG_WRITE
, MGMTD_FE_MSG_MAX_LEN
,
802 mgmt_sessions_init(&mgmt_fe_client_ctx
.client_sessions
);
804 /* Start trying to connect to MGMTD frontend server immediately */
805 mgmt_fe_client_schedule_conn_retry(&mgmt_fe_client_ctx
, 1);
807 MGMTD_FE_CLIENT_DBG("Initialized client '%s'", params
->name
);
809 return (uintptr_t)&mgmt_fe_client_ctx
;
813 * Create a new Session for a Frontend Client connection.
815 enum mgmt_result
mgmt_fe_create_client_session(uintptr_t lib_hndl
,
819 struct mgmt_fe_client_ctx
*client_ctx
;
820 struct mgmt_fe_client_session
*session
;
822 client_ctx
= (struct mgmt_fe_client_ctx
*)lib_hndl
;
824 return MGMTD_INVALID_PARAM
;
826 session
= XCALLOC(MTYPE_MGMTD_FE_SESSION
,
827 sizeof(struct mgmt_fe_client_session
));
829 session
->user_ctx
= user_ctx
;
830 session
->client_id
= client_id
;
831 session
->client_ctx
= client_ctx
;
832 session
->session_id
= 0;
834 if (mgmt_fe_send_session_req(client_ctx
, session
, true) != 0) {
835 XFREE(MTYPE_MGMTD_FE_SESSION
, session
);
836 return MGMTD_INTERNAL_ERROR
;
838 mgmt_sessions_add_tail(&client_ctx
->client_sessions
, session
);
840 return MGMTD_SUCCESS
;
844 * Delete an existing Session for a Frontend Client connection.
846 enum mgmt_result
mgmt_fe_destroy_client_session(uintptr_t lib_hndl
,
849 struct mgmt_fe_client_ctx
*client_ctx
;
850 struct mgmt_fe_client_session
*session
;
852 client_ctx
= (struct mgmt_fe_client_ctx
*)lib_hndl
;
854 return MGMTD_INVALID_PARAM
;
856 session
= mgmt_fe_find_session_by_client_id(client_ctx
, client_id
);
857 if (!session
|| session
->client_ctx
!= client_ctx
)
858 return MGMTD_INVALID_PARAM
;
860 if (session
->session_id
&&
861 mgmt_fe_send_session_req(client_ctx
, session
, false) != 0)
863 "Failed to send session destroy request for the session-id %lu",
864 (unsigned long)session
->session_id
);
866 mgmt_sessions_del(&client_ctx
->client_sessions
, session
);
867 XFREE(MTYPE_MGMTD_FE_SESSION
, session
);
869 return MGMTD_SUCCESS
;
872 static void mgmt_fe_destroy_client_sessions(uintptr_t lib_hndl
)
874 struct mgmt_fe_client_ctx
*client_ctx
;
875 struct mgmt_fe_client_session
*session
;
877 client_ctx
= (struct mgmt_fe_client_ctx
*)lib_hndl
;
881 FOREACH_SESSION_IN_LIST (client_ctx
, session
)
882 mgmt_fe_destroy_client_session(lib_hndl
, session
->client_id
);
886 * Send UN/LOCK_DS_REQ to MGMTD for a specific Datastore DS.
888 enum mgmt_result
mgmt_fe_lock_ds(uintptr_t lib_hndl
, uintptr_t session_id
,
889 uint64_t req_id
, Mgmtd__DatastoreId ds_id
,
892 struct mgmt_fe_client_ctx
*client_ctx
;
893 struct mgmt_fe_client_session
*session
;
895 client_ctx
= (struct mgmt_fe_client_ctx
*)lib_hndl
;
897 return MGMTD_INVALID_PARAM
;
899 session
= (struct mgmt_fe_client_session
*)session_id
;
900 if (!session
|| session
->client_ctx
!= client_ctx
)
901 return MGMTD_INVALID_PARAM
;
903 if (mgmt_fe_send_lockds_req(client_ctx
, session
, lock_ds
, req_id
,
906 return MGMTD_INTERNAL_ERROR
;
908 return MGMTD_SUCCESS
;
912 * Send SET_CONFIG_REQ to MGMTD for one or more config data(s).
915 mgmt_fe_set_config_data(uintptr_t lib_hndl
, uintptr_t session_id
,
916 uint64_t req_id
, Mgmtd__DatastoreId ds_id
,
917 Mgmtd__YangCfgDataReq
**config_req
, int num_reqs
,
918 bool implicit_commit
, Mgmtd__DatastoreId dst_ds_id
)
920 struct mgmt_fe_client_ctx
*client_ctx
;
921 struct mgmt_fe_client_session
*session
;
923 client_ctx
= (struct mgmt_fe_client_ctx
*)lib_hndl
;
925 return MGMTD_INVALID_PARAM
;
927 session
= (struct mgmt_fe_client_session
*)session_id
;
928 if (!session
|| session
->client_ctx
!= client_ctx
)
929 return MGMTD_INVALID_PARAM
;
931 if (mgmt_fe_send_setcfg_req(client_ctx
, session
, req_id
, ds_id
,
932 config_req
, num_reqs
, implicit_commit
,
935 return MGMTD_INTERNAL_ERROR
;
937 return MGMTD_SUCCESS
;
941 * Send SET_CONFIG_REQ to MGMTD for one or more config data(s).
943 enum mgmt_result
mgmt_fe_commit_config_data(uintptr_t lib_hndl
,
944 uintptr_t session_id
,
946 Mgmtd__DatastoreId src_ds_id
,
947 Mgmtd__DatastoreId dst_ds_id
,
948 bool validate_only
, bool abort
)
950 struct mgmt_fe_client_ctx
*client_ctx
;
951 struct mgmt_fe_client_session
*session
;
953 client_ctx
= (struct mgmt_fe_client_ctx
*)lib_hndl
;
955 return MGMTD_INVALID_PARAM
;
957 session
= (struct mgmt_fe_client_session
*)session_id
;
958 if (!session
|| session
->client_ctx
!= client_ctx
)
959 return MGMTD_INVALID_PARAM
;
961 if (mgmt_fe_send_commitcfg_req(client_ctx
, session
, req_id
, src_ds_id
,
962 dst_ds_id
, validate_only
, abort
)
964 return MGMTD_INTERNAL_ERROR
;
966 return MGMTD_SUCCESS
;
970 * Send GET_CONFIG_REQ to MGMTD for one or more config data item(s).
973 mgmt_fe_get_config_data(uintptr_t lib_hndl
, uintptr_t session_id
,
974 uint64_t req_id
, Mgmtd__DatastoreId ds_id
,
975 Mgmtd__YangGetDataReq
* data_req
[], int num_reqs
)
977 struct mgmt_fe_client_ctx
*client_ctx
;
978 struct mgmt_fe_client_session
*session
;
980 client_ctx
= (struct mgmt_fe_client_ctx
*)lib_hndl
;
982 return MGMTD_INVALID_PARAM
;
984 session
= (struct mgmt_fe_client_session
*)session_id
;
985 if (!session
|| session
->client_ctx
!= client_ctx
)
986 return MGMTD_INVALID_PARAM
;
988 if (mgmt_fe_send_getcfg_req(client_ctx
, session
, req_id
, ds_id
,
991 return MGMTD_INTERNAL_ERROR
;
993 return MGMTD_SUCCESS
;
997 * Send GET_DATA_REQ to MGMTD for one or more config data item(s).
999 enum mgmt_result
mgmt_fe_get_data(uintptr_t lib_hndl
, uintptr_t session_id
,
1000 uint64_t req_id
, Mgmtd__DatastoreId ds_id
,
1001 Mgmtd__YangGetDataReq
* data_req
[],
1004 struct mgmt_fe_client_ctx
*client_ctx
;
1005 struct mgmt_fe_client_session
*session
;
1007 client_ctx
= (struct mgmt_fe_client_ctx
*)lib_hndl
;
1009 return MGMTD_INVALID_PARAM
;
1011 session
= (struct mgmt_fe_client_session
*)session_id
;
1012 if (!session
|| session
->client_ctx
!= client_ctx
)
1013 return MGMTD_INVALID_PARAM
;
1015 if (mgmt_fe_send_getdata_req(client_ctx
, session
, req_id
, ds_id
,
1018 return MGMTD_INTERNAL_ERROR
;
1020 return MGMTD_SUCCESS
;
1024 * Send NOTIFY_REGISTER_REQ to MGMTD daemon.
1027 mgmt_fe_register_yang_notify(uintptr_t lib_hndl
, uintptr_t session_id
,
1028 uint64_t req_id
, Mgmtd__DatastoreId ds_id
,
1030 Mgmtd__YangDataXPath
* data_req
[],
1033 struct mgmt_fe_client_ctx
*client_ctx
;
1034 struct mgmt_fe_client_session
*session
;
1036 client_ctx
= (struct mgmt_fe_client_ctx
*)lib_hndl
;
1038 return MGMTD_INVALID_PARAM
;
1040 session
= (struct mgmt_fe_client_session
*)session_id
;
1041 if (!session
|| session
->client_ctx
!= client_ctx
)
1042 return MGMTD_INVALID_PARAM
;
1044 if (mgmt_fe_send_regnotify_req(client_ctx
, session
, req_id
, ds_id
,
1045 register_req
, data_req
, num_reqs
)
1047 return MGMTD_INTERNAL_ERROR
;
1049 return MGMTD_SUCCESS
;
1053 * Destroy library and cleanup everything.
1055 void mgmt_fe_client_lib_destroy(uintptr_t lib_hndl
)
1057 struct mgmt_fe_client_ctx
*client_ctx
;
1059 client_ctx
= (struct mgmt_fe_client_ctx
*)lib_hndl
;
1062 MGMTD_FE_CLIENT_DBG("Destroying MGMTD Frontend Client '%s'",
1063 client_ctx
->client_params
.name
);
1065 mgmt_fe_server_disconnect(client_ctx
, false);
1067 mgmt_fe_destroy_client_sessions(lib_hndl
);
1069 EVENT_OFF(client_ctx
->conn_retry_tmr
);
1070 EVENT_OFF(client_ctx
->conn_read_ev
);
1071 EVENT_OFF(client_ctx
->conn_write_ev
);
1072 EVENT_OFF(client_ctx
->conn_writes_on
);
1073 EVENT_OFF(client_ctx
->msg_proc_ev
);
1074 mgmt_msg_destroy(&client_ctx
->mstate
);