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>
12 #include "mgmt_fe_client.h"
19 #include "lib/mgmt_fe_client_clippy.c"
21 #define MGMTD_FE_CLIENT_DBG(fmt, ...) \
22 DEBUGD(&mgmt_dbg_fe_client, "%s:" fmt, __func__, ##__VA_ARGS__)
23 #define MGMTD_FE_CLIENT_ERR(fmt, ...) \
24 zlog_err("%s: ERROR: " fmt, __func__, ##__VA_ARGS__)
25 #define MGMTD_DBG_FE_CLIENT_CHECK() \
26 DEBUG_MODE_CHECK(&mgmt_dbg_fe_client, DEBUG_MODE_ALL)
28 struct mgmt_fe_client_ctx
;
30 PREDECL_LIST(mgmt_sessions
);
32 struct mgmt_fe_client_session
{
35 struct mgmt_fe_client_ctx
*client_ctx
;
38 struct mgmt_sessions_item list_linkage
;
41 DECLARE_LIST(mgmt_sessions
, struct mgmt_fe_client_session
, list_linkage
);
43 DEFINE_MTYPE_STATIC(LIB
, MGMTD_FE_SESSION
, "MGMTD Frontend session");
45 struct mgmt_fe_client_ctx
{
47 struct event_loop
*tm
;
48 struct event
*conn_retry_tmr
;
49 struct event
*conn_read_ev
;
50 struct event
*conn_write_ev
;
51 struct event
*conn_writes_on
;
52 struct event
*msg_proc_ev
;
55 struct mgmt_msg_state mstate
;
57 struct mgmt_fe_client_params client_params
;
59 struct mgmt_sessions_head client_sessions
;
62 #define MGMTD_FE_CLIENT_FLAGS_WRITES_OFF (1U << 0)
64 #define FOREACH_SESSION_IN_LIST(client_ctx, session) \
65 frr_each_safe (mgmt_sessions, &(client_ctx)->client_sessions, (session))
67 struct debug mgmt_dbg_fe_client
= {0, "Management frontend client operations"};
69 static struct mgmt_fe_client_ctx mgmt_fe_client_ctx
= {
73 /* Forward declarations */
75 mgmt_fe_client_register_event(struct mgmt_fe_client_ctx
*client_ctx
,
76 enum mgmt_fe_event event
);
77 static void mgmt_fe_client_schedule_conn_retry(
78 struct mgmt_fe_client_ctx
*client_ctx
, unsigned long intvl_secs
);
80 static struct mgmt_fe_client_session
*
81 mgmt_fe_find_session_by_client_id(struct mgmt_fe_client_ctx
*client_ctx
,
84 struct mgmt_fe_client_session
*session
;
86 FOREACH_SESSION_IN_LIST (client_ctx
, session
) {
87 if (session
->client_id
== client_id
) {
89 "Found session %p for client-id %llu.", session
,
90 (unsigned long long)client_id
);
98 static struct mgmt_fe_client_session
*
99 mgmt_fe_find_session_by_session_id(struct mgmt_fe_client_ctx
*client_ctx
,
102 struct mgmt_fe_client_session
*session
;
104 FOREACH_SESSION_IN_LIST (client_ctx
, session
) {
105 if (session
->session_id
== session_id
) {
107 "Found session %p for session-id %llu.",
108 session
, (unsigned long long)session_id
);
117 mgmt_fe_server_disconnect(struct mgmt_fe_client_ctx
*client_ctx
,
120 if (client_ctx
->conn_fd
!= -1) {
121 close(client_ctx
->conn_fd
);
122 client_ctx
->conn_fd
= -1;
126 mgmt_fe_client_schedule_conn_retry(
128 client_ctx
->client_params
.conn_retry_intvl_sec
);
132 mgmt_fe_client_sched_msg_write(struct mgmt_fe_client_ctx
*client_ctx
)
134 if (!CHECK_FLAG(client_ctx
->flags
, MGMTD_FE_CLIENT_FLAGS_WRITES_OFF
))
135 mgmt_fe_client_register_event(client_ctx
,
136 MGMTD_FE_CONN_WRITE
);
140 mgmt_fe_client_writes_on(struct mgmt_fe_client_ctx
*client_ctx
)
142 MGMTD_FE_CLIENT_DBG("Resume writing msgs");
143 UNSET_FLAG(client_ctx
->flags
, MGMTD_FE_CLIENT_FLAGS_WRITES_OFF
);
144 mgmt_fe_client_sched_msg_write(client_ctx
);
148 mgmt_fe_client_writes_off(struct mgmt_fe_client_ctx
*client_ctx
)
150 SET_FLAG(client_ctx
->flags
, MGMTD_FE_CLIENT_FLAGS_WRITES_OFF
);
151 MGMTD_FE_CLIENT_DBG("Paused writing msgs");
154 static int mgmt_fe_client_send_msg(struct mgmt_fe_client_ctx
*client_ctx
,
155 Mgmtd__FeMessage
*fe_msg
)
157 /* users current expect this to fail here */
158 if (client_ctx
->conn_fd
== -1) {
159 MGMTD_FE_CLIENT_DBG("can't send message on closed connection");
163 int rv
= mgmt_msg_send_msg(
164 &client_ctx
->mstate
, fe_msg
,
165 mgmtd__fe_message__get_packed_size(fe_msg
),
166 (size_t(*)(void *, void *))mgmtd__fe_message__pack
,
167 MGMTD_DBG_FE_CLIENT_CHECK());
168 mgmt_fe_client_sched_msg_write(client_ctx
);
172 static void mgmt_fe_client_write(struct event
*thread
)
174 struct mgmt_fe_client_ctx
*client_ctx
;
175 enum mgmt_msg_wsched rv
;
177 client_ctx
= (struct mgmt_fe_client_ctx
*)EVENT_ARG(thread
);
178 rv
= mgmt_msg_write(&client_ctx
->mstate
, client_ctx
->conn_fd
,
179 MGMTD_DBG_FE_CLIENT_CHECK());
180 if (rv
== MSW_SCHED_STREAM
)
181 mgmt_fe_client_register_event(client_ctx
, MGMTD_FE_CONN_WRITE
);
182 else if (rv
== MSW_DISCONNECT
)
183 mgmt_fe_server_disconnect(client_ctx
, true);
184 else if (rv
== MSW_SCHED_WRITES_OFF
) {
185 mgmt_fe_client_writes_off(client_ctx
);
186 mgmt_fe_client_register_event(client_ctx
,
187 MGMTD_FE_CONN_WRITES_ON
);
189 assert(rv
== MSW_SCHED_NONE
);
192 static void mgmt_fe_client_resume_writes(struct event
*thread
)
194 struct mgmt_fe_client_ctx
*client_ctx
;
196 client_ctx
= (struct mgmt_fe_client_ctx
*)EVENT_ARG(thread
);
197 assert(client_ctx
&& client_ctx
->conn_fd
!= -1);
199 mgmt_fe_client_writes_on(client_ctx
);
203 mgmt_fe_send_register_req(struct mgmt_fe_client_ctx
*client_ctx
)
205 Mgmtd__FeMessage fe_msg
;
206 Mgmtd__FeRegisterReq rgstr_req
;
208 mgmtd__fe_register_req__init(&rgstr_req
);
209 rgstr_req
.client_name
= client_ctx
->client_params
.name
;
211 mgmtd__fe_message__init(&fe_msg
);
212 fe_msg
.message_case
= MGMTD__FE_MESSAGE__MESSAGE_REGISTER_REQ
;
213 fe_msg
.register_req
= &rgstr_req
;
216 "Sending REGISTER_REQ message to MGMTD Frontend server");
218 return mgmt_fe_client_send_msg(client_ctx
, &fe_msg
);
222 mgmt_fe_send_session_req(struct mgmt_fe_client_ctx
*client_ctx
,
223 struct mgmt_fe_client_session
*session
,
226 Mgmtd__FeMessage fe_msg
;
227 Mgmtd__FeSessionReq sess_req
;
229 mgmtd__fe_session_req__init(&sess_req
);
230 sess_req
.create
= create
;
232 sess_req
.id_case
= MGMTD__FE_SESSION_REQ__ID_CLIENT_CONN_ID
;
233 sess_req
.client_conn_id
= session
->client_id
;
235 sess_req
.id_case
= MGMTD__FE_SESSION_REQ__ID_SESSION_ID
;
236 sess_req
.session_id
= session
->session_id
;
239 mgmtd__fe_message__init(&fe_msg
);
240 fe_msg
.message_case
= MGMTD__FE_MESSAGE__MESSAGE_SESSION_REQ
;
241 fe_msg
.session_req
= &sess_req
;
244 "Sending SESSION_REQ message for %s session %llu to MGMTD Frontend server",
245 create
? "creating" : "destroying",
246 (unsigned long long)session
->client_id
);
248 return mgmt_fe_client_send_msg(client_ctx
, &fe_msg
);
252 mgmt_fe_send_lockds_req(struct mgmt_fe_client_ctx
*client_ctx
,
253 struct mgmt_fe_client_session
*session
, bool lock
,
254 uint64_t req_id
, Mgmtd__DatastoreId ds_id
)
257 Mgmtd__FeMessage fe_msg
;
258 Mgmtd__FeLockDsReq lockds_req
;
260 mgmtd__fe_lock_ds_req__init(&lockds_req
);
261 lockds_req
.session_id
= session
->session_id
;
262 lockds_req
.req_id
= req_id
;
263 lockds_req
.ds_id
= ds_id
;
264 lockds_req
.lock
= lock
;
266 mgmtd__fe_message__init(&fe_msg
);
267 fe_msg
.message_case
= MGMTD__FE_MESSAGE__MESSAGE_LOCKDS_REQ
;
268 fe_msg
.lockds_req
= &lockds_req
;
271 "Sending %sLOCK_REQ message for Ds:%d session %llu to MGMTD Frontend server",
272 lock
? "" : "UN", ds_id
,
273 (unsigned long long)session
->client_id
);
275 return mgmt_fe_client_send_msg(client_ctx
, &fe_msg
);
279 mgmt_fe_send_setcfg_req(struct mgmt_fe_client_ctx
*client_ctx
,
280 struct mgmt_fe_client_session
*session
,
281 uint64_t req_id
, Mgmtd__DatastoreId ds_id
,
282 Mgmtd__YangCfgDataReq
**data_req
, int num_data_reqs
,
283 bool implicit_commit
, Mgmtd__DatastoreId dst_ds_id
)
286 Mgmtd__FeMessage fe_msg
;
287 Mgmtd__FeSetConfigReq setcfg_req
;
289 mgmtd__fe_set_config_req__init(&setcfg_req
);
290 setcfg_req
.session_id
= session
->session_id
;
291 setcfg_req
.ds_id
= ds_id
;
292 setcfg_req
.req_id
= req_id
;
293 setcfg_req
.data
= data_req
;
294 setcfg_req
.n_data
= (size_t)num_data_reqs
;
295 setcfg_req
.implicit_commit
= implicit_commit
;
296 setcfg_req
.commit_ds_id
= dst_ds_id
;
298 mgmtd__fe_message__init(&fe_msg
);
299 fe_msg
.message_case
= MGMTD__FE_MESSAGE__MESSAGE_SETCFG_REQ
;
300 fe_msg
.setcfg_req
= &setcfg_req
;
303 "Sending SET_CONFIG_REQ message for Ds:%d session %llu (#xpaths:%d) to MGMTD Frontend server",
304 ds_id
, (unsigned long long)session
->client_id
, num_data_reqs
);
306 return mgmt_fe_client_send_msg(client_ctx
, &fe_msg
);
309 static int mgmt_fe_send_commitcfg_req(struct mgmt_fe_client_ctx
*client_ctx
,
310 struct mgmt_fe_client_session
*session
,
312 Mgmtd__DatastoreId src_ds_id
,
313 Mgmtd__DatastoreId dest_ds_id
,
314 bool validate_only
, bool abort
)
317 Mgmtd__FeMessage fe_msg
;
318 Mgmtd__FeCommitConfigReq commitcfg_req
;
320 mgmtd__fe_commit_config_req__init(&commitcfg_req
);
321 commitcfg_req
.session_id
= session
->session_id
;
322 commitcfg_req
.src_ds_id
= src_ds_id
;
323 commitcfg_req
.dst_ds_id
= dest_ds_id
;
324 commitcfg_req
.req_id
= req_id
;
325 commitcfg_req
.validate_only
= validate_only
;
326 commitcfg_req
.abort
= abort
;
328 mgmtd__fe_message__init(&fe_msg
);
329 fe_msg
.message_case
= MGMTD__FE_MESSAGE__MESSAGE_COMMCFG_REQ
;
330 fe_msg
.commcfg_req
= &commitcfg_req
;
333 "Sending COMMIT_CONFIG_REQ message for Src-Ds:%d, Dst-Ds:%d session %llu to MGMTD Frontend server",
334 src_ds_id
, dest_ds_id
, (unsigned long long)session
->client_id
);
336 return mgmt_fe_client_send_msg(client_ctx
, &fe_msg
);
340 mgmt_fe_send_getcfg_req(struct mgmt_fe_client_ctx
*client_ctx
,
341 struct mgmt_fe_client_session
*session
,
342 uint64_t req_id
, Mgmtd__DatastoreId ds_id
,
343 Mgmtd__YangGetDataReq
* data_req
[],
347 Mgmtd__FeMessage fe_msg
;
348 Mgmtd__FeGetConfigReq getcfg_req
;
350 mgmtd__fe_get_config_req__init(&getcfg_req
);
351 getcfg_req
.session_id
= session
->session_id
;
352 getcfg_req
.ds_id
= ds_id
;
353 getcfg_req
.req_id
= req_id
;
354 getcfg_req
.data
= data_req
;
355 getcfg_req
.n_data
= (size_t)num_data_reqs
;
357 mgmtd__fe_message__init(&fe_msg
);
358 fe_msg
.message_case
= MGMTD__FE_MESSAGE__MESSAGE_GETCFG_REQ
;
359 fe_msg
.getcfg_req
= &getcfg_req
;
362 "Sending GET_CONFIG_REQ message for Ds:%d session %llu (#xpaths:%d) to MGMTD Frontend server",
363 ds_id
, (unsigned long long)session
->client_id
, num_data_reqs
);
365 return mgmt_fe_client_send_msg(client_ctx
, &fe_msg
);
369 mgmt_fe_send_getdata_req(struct mgmt_fe_client_ctx
*client_ctx
,
370 struct mgmt_fe_client_session
*session
,
371 uint64_t req_id
, Mgmtd__DatastoreId ds_id
,
372 Mgmtd__YangGetDataReq
* data_req
[],
376 Mgmtd__FeMessage fe_msg
;
377 Mgmtd__FeGetDataReq getdata_req
;
379 mgmtd__fe_get_data_req__init(&getdata_req
);
380 getdata_req
.session_id
= session
->session_id
;
381 getdata_req
.ds_id
= ds_id
;
382 getdata_req
.req_id
= req_id
;
383 getdata_req
.data
= data_req
;
384 getdata_req
.n_data
= (size_t)num_data_reqs
;
386 mgmtd__fe_message__init(&fe_msg
);
387 fe_msg
.message_case
= MGMTD__FE_MESSAGE__MESSAGE_GETDATA_REQ
;
388 fe_msg
.getdata_req
= &getdata_req
;
391 "Sending GET_CONFIG_REQ message for Ds:%d session %llu (#xpaths:%d) to MGMTD Frontend server",
392 ds_id
, (unsigned long long)session
->client_id
, num_data_reqs
);
394 return mgmt_fe_client_send_msg(client_ctx
, &fe_msg
);
397 static int mgmt_fe_send_regnotify_req(
398 struct mgmt_fe_client_ctx
*client_ctx
,
399 struct mgmt_fe_client_session
*session
, uint64_t req_id
,
400 Mgmtd__DatastoreId ds_id
, bool register_req
,
401 Mgmtd__YangDataXPath
* data_req
[], int num_data_reqs
)
404 Mgmtd__FeMessage fe_msg
;
405 Mgmtd__FeRegisterNotifyReq regntfy_req
;
407 mgmtd__fe_register_notify_req__init(®ntfy_req
);
408 regntfy_req
.session_id
= session
->session_id
;
409 regntfy_req
.ds_id
= ds_id
;
410 regntfy_req
.register_req
= register_req
;
411 regntfy_req
.data_xpath
= data_req
;
412 regntfy_req
.n_data_xpath
= (size_t)num_data_reqs
;
414 mgmtd__fe_message__init(&fe_msg
);
415 fe_msg
.message_case
= MGMTD__FE_MESSAGE__MESSAGE_REGNOTIFY_REQ
;
416 fe_msg
.regnotify_req
= ®ntfy_req
;
418 return mgmt_fe_client_send_msg(client_ctx
, &fe_msg
);
422 mgmt_fe_client_handle_msg(struct mgmt_fe_client_ctx
*client_ctx
,
423 Mgmtd__FeMessage
*fe_msg
)
425 struct mgmt_fe_client_session
*session
= NULL
;
428 * protobuf-c adds a max size enum with an internal, and changing by
429 * version, name; cast to an int to avoid unhandled enum warnings
431 switch ((int)fe_msg
->message_case
) {
432 case MGMTD__FE_MESSAGE__MESSAGE_SESSION_REPLY
:
433 if (fe_msg
->session_reply
->create
434 && fe_msg
->session_reply
->has_client_conn_id
) {
436 "Got Session Create Reply Msg for client-id %llu with session-id: %llu.",
438 fe_msg
->session_reply
->client_conn_id
,
440 fe_msg
->session_reply
->session_id
);
442 session
= mgmt_fe_find_session_by_client_id(
444 fe_msg
->session_reply
->client_conn_id
);
446 if (session
&& fe_msg
->session_reply
->success
) {
448 "Session Create for client-id %llu successful.",
450 fe_msg
->session_reply
452 session
->session_id
=
453 fe_msg
->session_reply
->session_id
;
456 "Session Create for client-id %llu failed.",
458 fe_msg
->session_reply
461 } else if (!fe_msg
->session_reply
->create
) {
463 "Got Session Destroy Reply Msg for session-id %llu",
465 fe_msg
->session_reply
->session_id
);
467 session
= mgmt_fe_find_session_by_session_id(
468 client_ctx
, fe_msg
->session_req
->session_id
);
471 if (session
&& session
->client_ctx
472 && session
->client_ctx
->client_params
473 .client_session_notify
)
474 (*session
->client_ctx
->client_params
475 .client_session_notify
)(
476 (uintptr_t)client_ctx
,
477 client_ctx
->client_params
.user_data
,
479 fe_msg
->session_reply
->create
,
480 fe_msg
->session_reply
->success
,
481 (uintptr_t)session
, session
->user_ctx
);
483 case MGMTD__FE_MESSAGE__MESSAGE_LOCKDS_REPLY
:
485 "Got LockDs Reply Msg for session-id %llu",
487 fe_msg
->lockds_reply
->session_id
);
488 session
= mgmt_fe_find_session_by_session_id(
489 client_ctx
, fe_msg
->lockds_reply
->session_id
);
491 if (session
&& session
->client_ctx
492 && session
->client_ctx
->client_params
494 (*session
->client_ctx
->client_params
496 (uintptr_t)client_ctx
,
497 client_ctx
->client_params
.user_data
,
498 session
->client_id
, (uintptr_t)session
,
500 fe_msg
->lockds_reply
->req_id
,
501 fe_msg
->lockds_reply
->lock
,
502 fe_msg
->lockds_reply
->success
,
503 fe_msg
->lockds_reply
->ds_id
,
504 fe_msg
->lockds_reply
->error_if_any
);
506 case MGMTD__FE_MESSAGE__MESSAGE_SETCFG_REPLY
:
508 "Got Set Config Reply Msg for session-id %llu",
510 fe_msg
->setcfg_reply
->session_id
);
512 session
= mgmt_fe_find_session_by_session_id(
513 client_ctx
, fe_msg
->setcfg_reply
->session_id
);
515 if (session
&& session
->client_ctx
516 && session
->client_ctx
->client_params
518 (*session
->client_ctx
->client_params
520 (uintptr_t)client_ctx
,
521 client_ctx
->client_params
.user_data
,
522 session
->client_id
, (uintptr_t)session
,
524 fe_msg
->setcfg_reply
->req_id
,
525 fe_msg
->setcfg_reply
->success
,
526 fe_msg
->setcfg_reply
->ds_id
,
527 fe_msg
->setcfg_reply
->error_if_any
);
529 case MGMTD__FE_MESSAGE__MESSAGE_COMMCFG_REPLY
:
531 "Got Commit Config Reply Msg for session-id %llu",
533 fe_msg
->commcfg_reply
->session_id
);
535 session
= mgmt_fe_find_session_by_session_id(
536 client_ctx
, fe_msg
->commcfg_reply
->session_id
);
538 if (session
&& session
->client_ctx
539 && session
->client_ctx
->client_params
540 .commit_config_notify
)
541 (*session
->client_ctx
->client_params
542 .commit_config_notify
)(
543 (uintptr_t)client_ctx
,
544 client_ctx
->client_params
.user_data
,
545 session
->client_id
, (uintptr_t)session
,
547 fe_msg
->commcfg_reply
->req_id
,
548 fe_msg
->commcfg_reply
->success
,
549 fe_msg
->commcfg_reply
->src_ds_id
,
550 fe_msg
->commcfg_reply
->dst_ds_id
,
551 fe_msg
->commcfg_reply
->validate_only
,
552 fe_msg
->commcfg_reply
->error_if_any
);
554 case MGMTD__FE_MESSAGE__MESSAGE_GETCFG_REPLY
:
556 "Got Get Config Reply Msg for session-id %llu",
558 fe_msg
->getcfg_reply
->session_id
);
560 session
= mgmt_fe_find_session_by_session_id(
561 client_ctx
, fe_msg
->getcfg_reply
->session_id
);
563 if (session
&& session
->client_ctx
564 && session
->client_ctx
->client_params
566 (*session
->client_ctx
->client_params
568 (uintptr_t)client_ctx
,
569 client_ctx
->client_params
.user_data
,
570 session
->client_id
, (uintptr_t)session
,
572 fe_msg
->getcfg_reply
->req_id
,
573 fe_msg
->getcfg_reply
->success
,
574 fe_msg
->getcfg_reply
->ds_id
,
575 fe_msg
->getcfg_reply
->data
576 ? fe_msg
->getcfg_reply
->data
->data
578 fe_msg
->getcfg_reply
->data
579 ? fe_msg
->getcfg_reply
->data
->n_data
581 fe_msg
->getcfg_reply
->data
582 ? fe_msg
->getcfg_reply
->data
585 fe_msg
->getcfg_reply
->error_if_any
);
587 case MGMTD__FE_MESSAGE__MESSAGE_GETDATA_REPLY
:
589 "Got Get Data Reply Msg for session-id %llu",
591 fe_msg
->getdata_reply
->session_id
);
593 session
= mgmt_fe_find_session_by_session_id(
594 client_ctx
, fe_msg
->getdata_reply
->session_id
);
596 if (session
&& session
->client_ctx
597 && session
->client_ctx
->client_params
599 (*session
->client_ctx
->client_params
601 (uintptr_t)client_ctx
,
602 client_ctx
->client_params
.user_data
,
603 session
->client_id
, (uintptr_t)session
,
605 fe_msg
->getdata_reply
->req_id
,
606 fe_msg
->getdata_reply
->success
,
607 fe_msg
->getdata_reply
->ds_id
,
608 fe_msg
->getdata_reply
->data
609 ? fe_msg
->getdata_reply
->data
->data
611 fe_msg
->getdata_reply
->data
612 ? fe_msg
->getdata_reply
->data
615 fe_msg
->getdata_reply
->data
616 ? fe_msg
->getdata_reply
->data
619 fe_msg
->getdata_reply
->error_if_any
);
621 case MGMTD__FE_MESSAGE__MESSAGE_NOTIFY_DATA_REQ
:
622 case MGMTD__FE_MESSAGE__MESSAGE_REGNOTIFY_REQ
:
624 * TODO: Add handling code in future.
628 * NOTE: The following messages are always sent from Frontend
629 * clients to MGMTd only and/or need not be handled here.
631 case MGMTD__FE_MESSAGE__MESSAGE_REGISTER_REQ
:
632 case MGMTD__FE_MESSAGE__MESSAGE_SESSION_REQ
:
633 case MGMTD__FE_MESSAGE__MESSAGE_LOCKDS_REQ
:
634 case MGMTD__FE_MESSAGE__MESSAGE_SETCFG_REQ
:
635 case MGMTD__FE_MESSAGE__MESSAGE_COMMCFG_REQ
:
636 case MGMTD__FE_MESSAGE__MESSAGE_GETCFG_REQ
:
637 case MGMTD__FE_MESSAGE__MESSAGE_GETDATA_REQ
:
638 case MGMTD__FE_MESSAGE__MESSAGE__NOT_SET
:
641 * A 'default' case is being added contrary to the
642 * FRR code guidelines to take care of build
643 * failures on certain build systems (courtesy of
644 * the proto-c package).
652 static void mgmt_fe_client_process_msg(void *user_ctx
, uint8_t *data
,
655 struct mgmt_fe_client_ctx
*client_ctx
= user_ctx
;
656 Mgmtd__FeMessage
*fe_msg
;
658 fe_msg
= mgmtd__fe_message__unpack(NULL
, len
, data
);
660 MGMTD_FE_CLIENT_DBG("Failed to decode %zu bytes from server.",
665 "Decoded %zu bytes of message(msg: %u/%u) from server", len
,
666 fe_msg
->message_case
, fe_msg
->message_case
);
667 (void)mgmt_fe_client_handle_msg(client_ctx
, fe_msg
);
668 mgmtd__fe_message__free_unpacked(fe_msg
, NULL
);
671 static void mgmt_fe_client_proc_msgbufs(struct event
*thread
)
673 struct mgmt_fe_client_ctx
*client_ctx
;
675 client_ctx
= (struct mgmt_fe_client_ctx
*)EVENT_ARG(thread
);
676 if (mgmt_msg_procbufs(&client_ctx
->mstate
, mgmt_fe_client_process_msg
,
677 client_ctx
, MGMTD_DBG_FE_CLIENT_CHECK()))
678 mgmt_fe_client_register_event(client_ctx
, MGMTD_FE_PROC_MSG
);
681 static void mgmt_fe_client_read(struct event
*thread
)
683 struct mgmt_fe_client_ctx
*client_ctx
;
684 enum mgmt_msg_rsched rv
;
686 client_ctx
= (struct mgmt_fe_client_ctx
*)EVENT_ARG(thread
);
688 rv
= mgmt_msg_read(&client_ctx
->mstate
, client_ctx
->conn_fd
,
689 MGMTD_DBG_FE_CLIENT_CHECK());
690 if (rv
== MSR_DISCONNECT
) {
691 mgmt_fe_server_disconnect(client_ctx
, true);
694 if (rv
== MSR_SCHED_BOTH
)
695 mgmt_fe_client_register_event(client_ctx
, MGMTD_FE_PROC_MSG
);
696 mgmt_fe_client_register_event(client_ctx
, MGMTD_FE_CONN_READ
);
699 static void mgmt_fe_server_connect(struct mgmt_fe_client_ctx
*client_ctx
)
701 const char *dbgtag
= MGMTD_DBG_FE_CLIENT_CHECK() ? "FE-client" : NULL
;
703 assert(client_ctx
->conn_fd
== -1);
704 client_ctx
->conn_fd
= mgmt_msg_connect(
705 MGMTD_FE_SERVER_PATH
, MGMTD_SOCKET_FE_SEND_BUF_SIZE
,
706 MGMTD_SOCKET_FE_RECV_BUF_SIZE
, dbgtag
);
708 /* Send REGISTER_REQ message */
709 if (client_ctx
->conn_fd
== -1 ||
710 mgmt_fe_send_register_req(client_ctx
) != 0) {
711 mgmt_fe_server_disconnect(client_ctx
, true);
715 /* Start reading from the socket */
716 mgmt_fe_client_register_event(client_ctx
, MGMTD_FE_CONN_READ
);
718 /* Notify client through registered callback (if any) */
719 if (client_ctx
->client_params
.client_connect_notify
)
720 (void)(*client_ctx
->client_params
.client_connect_notify
)(
721 (uintptr_t)client_ctx
,
722 client_ctx
->client_params
.user_data
, true);
726 static void mgmt_fe_client_conn_timeout(struct event
*thread
)
728 mgmt_fe_server_connect(EVENT_ARG(thread
));
732 mgmt_fe_client_register_event(struct mgmt_fe_client_ctx
*client_ctx
,
733 enum mgmt_fe_event event
)
735 struct timeval tv
= {0};
738 case MGMTD_FE_CONN_READ
:
739 event_add_read(client_ctx
->tm
, mgmt_fe_client_read
,
740 client_ctx
, client_ctx
->conn_fd
,
741 &client_ctx
->conn_read_ev
);
743 case MGMTD_FE_CONN_WRITE
:
744 event_add_write(client_ctx
->tm
, mgmt_fe_client_write
,
745 client_ctx
, client_ctx
->conn_fd
,
746 &client_ctx
->conn_write_ev
);
748 case MGMTD_FE_PROC_MSG
:
749 tv
.tv_usec
= MGMTD_FE_MSG_PROC_DELAY_USEC
;
750 event_add_timer_tv(client_ctx
->tm
,
751 mgmt_fe_client_proc_msgbufs
, client_ctx
,
752 &tv
, &client_ctx
->msg_proc_ev
);
754 case MGMTD_FE_CONN_WRITES_ON
:
755 event_add_timer_msec(
756 client_ctx
->tm
, mgmt_fe_client_resume_writes
,
757 client_ctx
, MGMTD_FE_MSG_WRITE_DELAY_MSEC
,
758 &client_ctx
->conn_writes_on
);
760 case MGMTD_FE_SERVER
:
761 assert(!"mgmt_fe_client_ctx_post_event called incorrectly");
766 static void mgmt_fe_client_schedule_conn_retry(
767 struct mgmt_fe_client_ctx
*client_ctx
, unsigned long intvl_secs
)
770 "Scheduling MGMTD Frontend server connection retry after %lu seconds",
772 event_add_timer(client_ctx
->tm
, mgmt_fe_client_conn_timeout
,
773 (void *)client_ctx
, intvl_secs
,
774 &client_ctx
->conn_retry_tmr
);
777 DEFPY(debug_mgmt_client_fe
, debug_mgmt_client_fe_cmd
,
778 "[no] debug mgmt client frontend",
779 NO_STR DEBUG_STR MGMTD_STR
783 uint32_t mode
= DEBUG_NODE2MODE(vty
->node
);
785 DEBUG_MODE_SET(&mgmt_dbg_fe_client
, mode
, !no
);
790 static void mgmt_debug_client_fe_set_all(uint32_t flags
, bool set
)
792 DEBUG_FLAGS_SET(&mgmt_dbg_fe_client
, flags
, set
);
795 static int mgmt_debug_fe_client_config_write(struct vty
*vty
)
797 if (DEBUG_MODE_CHECK(&mgmt_dbg_fe_client
, DEBUG_MODE_CONF
))
798 vty_out(vty
, "debug mgmt client frontend\n");
803 void mgmt_debug_fe_client_show_debug(struct vty
*vty
)
805 if (MGMTD_DBG_FE_CLIENT_CHECK())
806 vty_out(vty
, "debug mgmt client frontend\n");
809 static struct debug_callbacks mgmt_dbg_fe_client_cbs
= {
810 .debug_set_all
= mgmt_debug_client_fe_set_all
};
812 static struct cmd_node mgmt_dbg_node
= {
813 .name
= "mgmt client frontend",
816 .config_write
= mgmt_debug_fe_client_config_write
,
820 * Initialize library and try connecting with MGMTD.
822 uintptr_t mgmt_fe_client_lib_init(struct mgmt_fe_client_params
*params
,
823 struct event_loop
*master_thread
)
825 assert(master_thread
&& params
&& strlen(params
->name
)
826 && !mgmt_fe_client_ctx
.tm
);
828 mgmt_fe_client_ctx
.tm
= master_thread
;
829 memcpy(&mgmt_fe_client_ctx
.client_params
, params
,
830 sizeof(mgmt_fe_client_ctx
.client_params
));
831 if (!mgmt_fe_client_ctx
.client_params
.conn_retry_intvl_sec
)
832 mgmt_fe_client_ctx
.client_params
.conn_retry_intvl_sec
=
833 MGMTD_FE_DEFAULT_CONN_RETRY_INTVL_SEC
;
835 mgmt_msg_init(&mgmt_fe_client_ctx
.mstate
, MGMTD_FE_MAX_NUM_MSG_PROC
,
836 MGMTD_FE_MAX_NUM_MSG_WRITE
, MGMTD_FE_MSG_MAX_LEN
,
839 mgmt_sessions_init(&mgmt_fe_client_ctx
.client_sessions
);
841 /* Start trying to connect to MGMTD frontend server immediately */
842 mgmt_fe_client_schedule_conn_retry(&mgmt_fe_client_ctx
, 1);
844 MGMTD_FE_CLIENT_DBG("Initialized client '%s'", params
->name
);
846 return (uintptr_t)&mgmt_fe_client_ctx
;
849 void mgmt_fe_client_lib_vty_init(void)
851 debug_init(&mgmt_dbg_fe_client_cbs
);
852 install_node(&mgmt_dbg_node
);
853 install_element(ENABLE_NODE
, &debug_mgmt_client_fe_cmd
);
854 install_element(CONFIG_NODE
, &debug_mgmt_client_fe_cmd
);
858 * Create a new Session for a Frontend Client connection.
860 enum mgmt_result
mgmt_fe_create_client_session(uintptr_t lib_hndl
,
864 struct mgmt_fe_client_ctx
*client_ctx
;
865 struct mgmt_fe_client_session
*session
;
867 client_ctx
= (struct mgmt_fe_client_ctx
*)lib_hndl
;
869 return MGMTD_INVALID_PARAM
;
871 session
= XCALLOC(MTYPE_MGMTD_FE_SESSION
,
872 sizeof(struct mgmt_fe_client_session
));
874 session
->user_ctx
= user_ctx
;
875 session
->client_id
= client_id
;
876 session
->client_ctx
= client_ctx
;
877 session
->session_id
= 0;
879 if (mgmt_fe_send_session_req(client_ctx
, session
, true) != 0) {
880 XFREE(MTYPE_MGMTD_FE_SESSION
, session
);
881 return MGMTD_INTERNAL_ERROR
;
883 mgmt_sessions_add_tail(&client_ctx
->client_sessions
, session
);
885 return MGMTD_SUCCESS
;
889 * Delete an existing Session for a Frontend Client connection.
891 enum mgmt_result
mgmt_fe_destroy_client_session(uintptr_t lib_hndl
,
894 struct mgmt_fe_client_ctx
*client_ctx
;
895 struct mgmt_fe_client_session
*session
;
897 client_ctx
= (struct mgmt_fe_client_ctx
*)lib_hndl
;
899 return MGMTD_INVALID_PARAM
;
901 session
= mgmt_fe_find_session_by_client_id(client_ctx
, client_id
);
902 if (!session
|| session
->client_ctx
!= client_ctx
)
903 return MGMTD_INVALID_PARAM
;
905 if (session
->session_id
&&
906 mgmt_fe_send_session_req(client_ctx
, session
, false) != 0)
908 "Failed to send session destroy request for the session-id %lu",
909 (unsigned long)session
->session_id
);
911 mgmt_sessions_del(&client_ctx
->client_sessions
, session
);
912 XFREE(MTYPE_MGMTD_FE_SESSION
, session
);
914 return MGMTD_SUCCESS
;
917 static void mgmt_fe_destroy_client_sessions(uintptr_t lib_hndl
)
919 struct mgmt_fe_client_ctx
*client_ctx
;
920 struct mgmt_fe_client_session
*session
;
922 client_ctx
= (struct mgmt_fe_client_ctx
*)lib_hndl
;
926 FOREACH_SESSION_IN_LIST (client_ctx
, session
)
927 mgmt_fe_destroy_client_session(lib_hndl
, session
->client_id
);
931 * Send UN/LOCK_DS_REQ to MGMTD for a specific Datastore DS.
933 enum mgmt_result
mgmt_fe_lock_ds(uintptr_t lib_hndl
, uintptr_t session_id
,
934 uint64_t req_id
, Mgmtd__DatastoreId ds_id
,
937 struct mgmt_fe_client_ctx
*client_ctx
;
938 struct mgmt_fe_client_session
*session
;
940 client_ctx
= (struct mgmt_fe_client_ctx
*)lib_hndl
;
942 return MGMTD_INVALID_PARAM
;
944 session
= (struct mgmt_fe_client_session
*)session_id
;
945 if (!session
|| session
->client_ctx
!= client_ctx
)
946 return MGMTD_INVALID_PARAM
;
948 if (mgmt_fe_send_lockds_req(client_ctx
, session
, lock_ds
, req_id
,
951 return MGMTD_INTERNAL_ERROR
;
953 return MGMTD_SUCCESS
;
957 * Send SET_CONFIG_REQ to MGMTD for one or more config data(s).
960 mgmt_fe_set_config_data(uintptr_t lib_hndl
, uintptr_t session_id
,
961 uint64_t req_id
, Mgmtd__DatastoreId ds_id
,
962 Mgmtd__YangCfgDataReq
**config_req
, int num_reqs
,
963 bool implicit_commit
, Mgmtd__DatastoreId dst_ds_id
)
965 struct mgmt_fe_client_ctx
*client_ctx
;
966 struct mgmt_fe_client_session
*session
;
968 client_ctx
= (struct mgmt_fe_client_ctx
*)lib_hndl
;
970 return MGMTD_INVALID_PARAM
;
972 session
= (struct mgmt_fe_client_session
*)session_id
;
973 if (!session
|| session
->client_ctx
!= client_ctx
)
974 return MGMTD_INVALID_PARAM
;
976 if (mgmt_fe_send_setcfg_req(client_ctx
, session
, req_id
, ds_id
,
977 config_req
, num_reqs
, implicit_commit
,
980 return MGMTD_INTERNAL_ERROR
;
982 return MGMTD_SUCCESS
;
986 * Send SET_CONFIG_REQ to MGMTD for one or more config data(s).
988 enum mgmt_result
mgmt_fe_commit_config_data(uintptr_t lib_hndl
,
989 uintptr_t session_id
,
991 Mgmtd__DatastoreId src_ds_id
,
992 Mgmtd__DatastoreId dst_ds_id
,
993 bool validate_only
, bool abort
)
995 struct mgmt_fe_client_ctx
*client_ctx
;
996 struct mgmt_fe_client_session
*session
;
998 client_ctx
= (struct mgmt_fe_client_ctx
*)lib_hndl
;
1000 return MGMTD_INVALID_PARAM
;
1002 session
= (struct mgmt_fe_client_session
*)session_id
;
1003 if (!session
|| session
->client_ctx
!= client_ctx
)
1004 return MGMTD_INVALID_PARAM
;
1006 if (mgmt_fe_send_commitcfg_req(client_ctx
, session
, req_id
, src_ds_id
,
1007 dst_ds_id
, validate_only
, abort
)
1009 return MGMTD_INTERNAL_ERROR
;
1011 return MGMTD_SUCCESS
;
1015 * Send GET_CONFIG_REQ to MGMTD for one or more config data item(s).
1018 mgmt_fe_get_config_data(uintptr_t lib_hndl
, uintptr_t session_id
,
1019 uint64_t req_id
, Mgmtd__DatastoreId ds_id
,
1020 Mgmtd__YangGetDataReq
* data_req
[], int num_reqs
)
1022 struct mgmt_fe_client_ctx
*client_ctx
;
1023 struct mgmt_fe_client_session
*session
;
1025 client_ctx
= (struct mgmt_fe_client_ctx
*)lib_hndl
;
1027 return MGMTD_INVALID_PARAM
;
1029 session
= (struct mgmt_fe_client_session
*)session_id
;
1030 if (!session
|| session
->client_ctx
!= client_ctx
)
1031 return MGMTD_INVALID_PARAM
;
1033 if (mgmt_fe_send_getcfg_req(client_ctx
, session
, req_id
, ds_id
,
1036 return MGMTD_INTERNAL_ERROR
;
1038 return MGMTD_SUCCESS
;
1042 * Send GET_DATA_REQ to MGMTD for one or more config data item(s).
1044 enum mgmt_result
mgmt_fe_get_data(uintptr_t lib_hndl
, uintptr_t session_id
,
1045 uint64_t req_id
, Mgmtd__DatastoreId ds_id
,
1046 Mgmtd__YangGetDataReq
* data_req
[],
1049 struct mgmt_fe_client_ctx
*client_ctx
;
1050 struct mgmt_fe_client_session
*session
;
1052 client_ctx
= (struct mgmt_fe_client_ctx
*)lib_hndl
;
1054 return MGMTD_INVALID_PARAM
;
1056 session
= (struct mgmt_fe_client_session
*)session_id
;
1057 if (!session
|| session
->client_ctx
!= client_ctx
)
1058 return MGMTD_INVALID_PARAM
;
1060 if (mgmt_fe_send_getdata_req(client_ctx
, session
, req_id
, ds_id
,
1063 return MGMTD_INTERNAL_ERROR
;
1065 return MGMTD_SUCCESS
;
1069 * Send NOTIFY_REGISTER_REQ to MGMTD daemon.
1072 mgmt_fe_register_yang_notify(uintptr_t lib_hndl
, uintptr_t session_id
,
1073 uint64_t req_id
, Mgmtd__DatastoreId ds_id
,
1075 Mgmtd__YangDataXPath
* data_req
[],
1078 struct mgmt_fe_client_ctx
*client_ctx
;
1079 struct mgmt_fe_client_session
*session
;
1081 client_ctx
= (struct mgmt_fe_client_ctx
*)lib_hndl
;
1083 return MGMTD_INVALID_PARAM
;
1085 session
= (struct mgmt_fe_client_session
*)session_id
;
1086 if (!session
|| session
->client_ctx
!= client_ctx
)
1087 return MGMTD_INVALID_PARAM
;
1089 if (mgmt_fe_send_regnotify_req(client_ctx
, session
, req_id
, ds_id
,
1090 register_req
, data_req
, num_reqs
)
1092 return MGMTD_INTERNAL_ERROR
;
1094 return MGMTD_SUCCESS
;
1098 * Destroy library and cleanup everything.
1100 void mgmt_fe_client_lib_destroy(uintptr_t lib_hndl
)
1102 struct mgmt_fe_client_ctx
*client_ctx
;
1104 client_ctx
= (struct mgmt_fe_client_ctx
*)lib_hndl
;
1107 MGMTD_FE_CLIENT_DBG("Destroying MGMTD Frontend Client '%s'",
1108 client_ctx
->client_params
.name
);
1110 mgmt_fe_server_disconnect(client_ctx
, false);
1112 mgmt_fe_destroy_client_sessions(lib_hndl
);
1114 EVENT_OFF(client_ctx
->conn_retry_tmr
);
1115 EVENT_OFF(client_ctx
->conn_read_ev
);
1116 EVENT_OFF(client_ctx
->conn_write_ev
);
1117 EVENT_OFF(client_ctx
->conn_writes_on
);
1118 EVENT_OFF(client_ctx
->msg_proc_ev
);
1119 mgmt_msg_destroy(&client_ctx
->mstate
);