]> git.proxmox.com Git - mirror_frr.git/blob - mgmtd/mgmt_fe_adapter.c
Merge pull request #13544 from cscarpitta/bugfix/fix-build-error
[mirror_frr.git] / mgmtd / mgmt_fe_adapter.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * MGMTD Frontend Client Connection Adapter
4 *
5 * Copyright (C) 2021 Vmware, Inc.
6 * Pushpasis Sarkar <spushpasis@vmware.com>
7 */
8
9 #include <zebra.h>
10 #include "sockopt.h"
11 #include "network.h"
12 #include "libfrr.h"
13 #include "mgmt_fe_client.h"
14 #include "mgmt_msg.h"
15 #include "mgmt_pb.h"
16 #include "hash.h"
17 #include "jhash.h"
18 #include "mgmtd/mgmt.h"
19 #include "mgmtd/mgmt_memory.h"
20 #include "mgmtd/mgmt_fe_adapter.h"
21
22 #define MGMTD_FE_ADAPTER_DBG(fmt, ...) \
23 DEBUGD(&mgmt_debug_fe, "%s:" fmt, __func__, ##__VA_ARGS__)
24 #define MGMTD_FE_ADAPTER_ERR(fmt, ...) \
25 zlog_err("%s: ERROR: " fmt, __func__, ##__VA_ARGS__)
26
27 #define FOREACH_ADAPTER_IN_LIST(adapter) \
28 frr_each_safe (mgmt_fe_adapters, &mgmt_fe_adapters, (adapter))
29
30 enum mgmt_session_event {
31 MGMTD_FE_SESSION_CFG_TXN_CLNUP = 1,
32 MGMTD_FE_SESSION_SHOW_TXN_CLNUP,
33 };
34
35 struct mgmt_fe_session_ctx {
36 struct mgmt_fe_client_adapter *adapter;
37 uint64_t session_id;
38 uint64_t client_id;
39 uint64_t txn_id;
40 uint64_t cfg_txn_id;
41 uint8_t ds_write_locked[MGMTD_DS_MAX_ID];
42 uint8_t ds_read_locked[MGMTD_DS_MAX_ID];
43 uint8_t ds_locked_implict[MGMTD_DS_MAX_ID];
44 struct event *proc_cfg_txn_clnp;
45 struct event *proc_show_txn_clnp;
46
47 struct mgmt_fe_sessions_item list_linkage;
48 };
49
50 DECLARE_LIST(mgmt_fe_sessions, struct mgmt_fe_session_ctx, list_linkage);
51
52 #define FOREACH_SESSION_IN_LIST(adapter, session) \
53 frr_each_safe (mgmt_fe_sessions, &(adapter)->fe_sessions, (session))
54
55 static struct event_loop *mgmt_fe_adapter_tm;
56 static struct mgmt_master *mgmt_fe_adapter_mm;
57
58 static struct mgmt_fe_adapters_head mgmt_fe_adapters;
59
60 static struct hash *mgmt_fe_sessions;
61 static uint64_t mgmt_fe_next_session_id;
62
63 /* Forward declarations */
64 static void
65 mgmt_fe_adapter_register_event(struct mgmt_fe_client_adapter *adapter,
66 enum mgmt_fe_event event);
67 static void
68 mgmt_fe_adapter_disconnect(struct mgmt_fe_client_adapter *adapter);
69 static void
70 mgmt_fe_session_register_event(struct mgmt_fe_session_ctx *session,
71 enum mgmt_session_event event);
72
73 static int
74 mgmt_fe_session_write_lock_ds(Mgmtd__DatastoreId ds_id,
75 struct mgmt_ds_ctx *ds_ctx,
76 struct mgmt_fe_session_ctx *session)
77 {
78 if (!session->ds_write_locked[ds_id]) {
79 if (mgmt_ds_write_lock(ds_ctx) != 0) {
80 MGMTD_FE_ADAPTER_DBG(
81 "Failed to lock the DS %u for Sessn: %p from %s!",
82 ds_id, session, session->adapter->name);
83 return -1;
84 }
85
86 session->ds_write_locked[ds_id] = true;
87 MGMTD_FE_ADAPTER_DBG(
88 "Write-Locked the DS %u for Sessn: %p from %s!", ds_id,
89 session, session->adapter->name);
90 }
91
92 return 0;
93 }
94
95 static int
96 mgmt_fe_session_read_lock_ds(Mgmtd__DatastoreId ds_id,
97 struct mgmt_ds_ctx *ds_ctx,
98 struct mgmt_fe_session_ctx *session)
99 {
100 if (!session->ds_read_locked[ds_id]) {
101 if (mgmt_ds_read_lock(ds_ctx) != 0) {
102 MGMTD_FE_ADAPTER_DBG(
103 "Failed to lock the DS %u for Sessn: %p from %s!",
104 ds_id, session, session->adapter->name);
105 return -1;
106 }
107
108 session->ds_read_locked[ds_id] = true;
109 MGMTD_FE_ADAPTER_DBG(
110 "Read-Locked the DS %u for Sessn: %p from %s!", ds_id,
111 session, session->adapter->name);
112 }
113
114 return 0;
115 }
116
117 static int mgmt_fe_session_unlock_ds(Mgmtd__DatastoreId ds_id,
118 struct mgmt_ds_ctx *ds_ctx,
119 struct mgmt_fe_session_ctx *session,
120 bool unlock_write, bool unlock_read)
121 {
122 if (unlock_write && session->ds_write_locked[ds_id]) {
123 session->ds_write_locked[ds_id] = false;
124 session->ds_locked_implict[ds_id] = false;
125 if (mgmt_ds_unlock(ds_ctx) != 0) {
126 MGMTD_FE_ADAPTER_DBG(
127 "Failed to unlock the DS %u taken earlier by Sessn: %p from %s!",
128 ds_id, session, session->adapter->name);
129 return -1;
130 }
131
132 MGMTD_FE_ADAPTER_DBG(
133 "Unlocked DS %u write-locked earlier by Sessn: %p from %s",
134 ds_id, session, session->adapter->name);
135 } else if (unlock_read && session->ds_read_locked[ds_id]) {
136 session->ds_read_locked[ds_id] = false;
137 session->ds_locked_implict[ds_id] = false;
138 if (mgmt_ds_unlock(ds_ctx) != 0) {
139 MGMTD_FE_ADAPTER_DBG(
140 "Failed to unlock the DS %u taken earlier by Sessn: %p from %s!",
141 ds_id, session, session->adapter->name);
142 return -1;
143 }
144
145 MGMTD_FE_ADAPTER_DBG(
146 "Unlocked DS %u read-locked earlier by Sessn: %p from %s",
147 ds_id, session, session->adapter->name);
148 }
149
150 return 0;
151 }
152
153 static void
154 mgmt_fe_session_cfg_txn_cleanup(struct mgmt_fe_session_ctx *session)
155 {
156 Mgmtd__DatastoreId ds_id;
157 struct mgmt_ds_ctx *ds_ctx;
158
159 /*
160 * Ensure any uncommitted changes in Candidate DS
161 * is discarded.
162 */
163 mgmt_ds_copy_dss(mm->running_ds, mm->candidate_ds, false);
164
165 for (ds_id = 0; ds_id < MGMTD_DS_MAX_ID; ds_id++) {
166 ds_ctx = mgmt_ds_get_ctx_by_id(mgmt_fe_adapter_mm, ds_id);
167 if (ds_ctx) {
168 if (session->ds_locked_implict[ds_id])
169 mgmt_fe_session_unlock_ds(
170 ds_id, ds_ctx, session, true, false);
171 }
172 }
173
174 /*
175 * Destroy the actual transaction created earlier.
176 */
177 if (session->cfg_txn_id != MGMTD_TXN_ID_NONE)
178 mgmt_destroy_txn(&session->cfg_txn_id);
179 }
180
181 static void
182 mgmt_fe_session_show_txn_cleanup(struct mgmt_fe_session_ctx *session)
183 {
184 Mgmtd__DatastoreId ds_id;
185 struct mgmt_ds_ctx *ds_ctx;
186
187 for (ds_id = 0; ds_id < MGMTD_DS_MAX_ID; ds_id++) {
188 ds_ctx = mgmt_ds_get_ctx_by_id(mgmt_fe_adapter_mm, ds_id);
189 if (ds_ctx) {
190 mgmt_fe_session_unlock_ds(ds_id, ds_ctx, session,
191 false, true);
192 }
193 }
194
195 /*
196 * Destroy the transaction created recently.
197 */
198 if (session->txn_id != MGMTD_TXN_ID_NONE)
199 mgmt_destroy_txn(&session->txn_id);
200 }
201
202 static void
203 mgmt_fe_adapter_compute_set_cfg_timers(struct mgmt_setcfg_stats *setcfg_stats)
204 {
205 setcfg_stats->last_exec_tm = timeval_elapsed(setcfg_stats->last_end,
206 setcfg_stats->last_start);
207 if (setcfg_stats->last_exec_tm > setcfg_stats->max_tm)
208 setcfg_stats->max_tm = setcfg_stats->last_exec_tm;
209
210 if (setcfg_stats->last_exec_tm < setcfg_stats->min_tm)
211 setcfg_stats->min_tm = setcfg_stats->last_exec_tm;
212
213 setcfg_stats->avg_tm =
214 (((setcfg_stats->avg_tm * (setcfg_stats->set_cfg_count - 1))
215 + setcfg_stats->last_exec_tm)
216 / setcfg_stats->set_cfg_count);
217 }
218
219 static void
220 mgmt_fe_session_compute_commit_timers(struct mgmt_commit_stats *cmt_stats)
221 {
222 cmt_stats->last_exec_tm =
223 timeval_elapsed(cmt_stats->last_end, cmt_stats->last_start);
224 if (cmt_stats->last_exec_tm > cmt_stats->max_tm) {
225 cmt_stats->max_tm = cmt_stats->last_exec_tm;
226 cmt_stats->max_batch_cnt = cmt_stats->last_batch_cnt;
227 }
228
229 if (cmt_stats->last_exec_tm < cmt_stats->min_tm) {
230 cmt_stats->min_tm = cmt_stats->last_exec_tm;
231 cmt_stats->min_batch_cnt = cmt_stats->last_batch_cnt;
232 }
233 }
234
235 static void mgmt_fe_cleanup_session(struct mgmt_fe_session_ctx **session)
236 {
237 if ((*session)->adapter) {
238 mgmt_fe_session_cfg_txn_cleanup((*session));
239 mgmt_fe_session_show_txn_cleanup((*session));
240 mgmt_fe_session_unlock_ds(MGMTD_DS_CANDIDATE,
241 mgmt_fe_adapter_mm->candidate_ds,
242 *session, true, true);
243 mgmt_fe_session_unlock_ds(MGMTD_DS_RUNNING,
244 mgmt_fe_adapter_mm->running_ds,
245 *session, true, true);
246
247 mgmt_fe_sessions_del(&(*session)->adapter->fe_sessions,
248 *session);
249 mgmt_fe_adapter_unlock(&(*session)->adapter);
250 }
251
252 hash_release(mgmt_fe_sessions, *session);
253 XFREE(MTYPE_MGMTD_FE_SESSION, *session);
254 *session = NULL;
255 }
256
257 static struct mgmt_fe_session_ctx *
258 mgmt_fe_find_session_by_client_id(struct mgmt_fe_client_adapter *adapter,
259 uint64_t client_id)
260 {
261 struct mgmt_fe_session_ctx *session;
262
263 FOREACH_SESSION_IN_LIST (adapter, session) {
264 if (session->client_id == client_id)
265 return session;
266 }
267
268 return NULL;
269 }
270
271 static unsigned int mgmt_fe_session_hash_key(const void *data)
272 {
273 const struct mgmt_fe_session_ctx *session = data;
274
275 return jhash2((uint32_t *) &session->session_id,
276 sizeof(session->session_id) / sizeof(uint32_t), 0);
277 }
278
279 static bool mgmt_fe_session_hash_cmp(const void *d1, const void *d2)
280 {
281 const struct mgmt_fe_session_ctx *session1 = d1;
282 const struct mgmt_fe_session_ctx *session2 = d2;
283
284 return (session1->session_id == session2->session_id);
285 }
286
287 static void mgmt_fe_session_hash_free(void *data)
288 {
289 struct mgmt_fe_session_ctx *session = data;
290
291 mgmt_fe_cleanup_session(&session);
292 }
293
294 static void mgmt_fe_session_hash_destroy(void)
295 {
296 if (mgmt_fe_sessions == NULL)
297 return;
298
299 hash_clean(mgmt_fe_sessions,
300 mgmt_fe_session_hash_free);
301 hash_free(mgmt_fe_sessions);
302 mgmt_fe_sessions = NULL;
303 }
304
305 static inline struct mgmt_fe_session_ctx *
306 mgmt_session_id2ctx(uint64_t session_id)
307 {
308 struct mgmt_fe_session_ctx key = {0};
309 struct mgmt_fe_session_ctx *session;
310
311 if (!mgmt_fe_sessions)
312 return NULL;
313
314 key.session_id = session_id;
315 session = hash_lookup(mgmt_fe_sessions, &key);
316
317 return session;
318 }
319
320 static struct mgmt_fe_session_ctx *
321 mgmt_fe_create_session(struct mgmt_fe_client_adapter *adapter,
322 uint64_t client_id)
323 {
324 struct mgmt_fe_session_ctx *session;
325
326 session = mgmt_fe_find_session_by_client_id(adapter, client_id);
327 if (session)
328 mgmt_fe_cleanup_session(&session);
329
330 session = XCALLOC(MTYPE_MGMTD_FE_SESSION,
331 sizeof(struct mgmt_fe_session_ctx));
332 assert(session);
333 session->client_id = client_id;
334 session->adapter = adapter;
335 session->txn_id = MGMTD_TXN_ID_NONE;
336 session->cfg_txn_id = MGMTD_TXN_ID_NONE;
337 mgmt_fe_adapter_lock(adapter);
338 mgmt_fe_sessions_add_tail(&adapter->fe_sessions, session);
339 if (!mgmt_fe_next_session_id)
340 mgmt_fe_next_session_id++;
341 session->session_id = mgmt_fe_next_session_id++;
342 hash_get(mgmt_fe_sessions, session, hash_alloc_intern);
343
344 return session;
345 }
346
347 static void
348 mgmt_fe_cleanup_sessions(struct mgmt_fe_client_adapter *adapter)
349 {
350 struct mgmt_fe_session_ctx *session;
351
352 FOREACH_SESSION_IN_LIST (adapter, session)
353 mgmt_fe_cleanup_session(&session);
354 }
355
356 static inline void
357 mgmt_fe_adapter_sched_msg_write(struct mgmt_fe_client_adapter *adapter)
358 {
359 if (!CHECK_FLAG(adapter->flags, MGMTD_FE_ADAPTER_FLAGS_WRITES_OFF))
360 mgmt_fe_adapter_register_event(adapter,
361 MGMTD_FE_CONN_WRITE);
362 }
363
364 static inline void
365 mgmt_fe_adapter_writes_on(struct mgmt_fe_client_adapter *adapter)
366 {
367 MGMTD_FE_ADAPTER_DBG("Resume writing msgs for '%s'", adapter->name);
368 UNSET_FLAG(adapter->flags, MGMTD_FE_ADAPTER_FLAGS_WRITES_OFF);
369 mgmt_fe_adapter_sched_msg_write(adapter);
370 }
371
372 static inline void
373 mgmt_fe_adapter_writes_off(struct mgmt_fe_client_adapter *adapter)
374 {
375 SET_FLAG(adapter->flags, MGMTD_FE_ADAPTER_FLAGS_WRITES_OFF);
376 MGMTD_FE_ADAPTER_DBG("Paused writing msgs for '%s'", adapter->name);
377 }
378
379 static int
380 mgmt_fe_adapter_send_msg(struct mgmt_fe_client_adapter *adapter,
381 Mgmtd__FeMessage *fe_msg)
382 {
383 if (adapter->conn_fd == -1) {
384 MGMTD_FE_ADAPTER_DBG("can't send message on closed connection");
385 return -1;
386 }
387
388 int rv = mgmt_msg_send_msg(
389 &adapter->mstate, fe_msg,
390 mgmtd__fe_message__get_packed_size(fe_msg),
391 (size_t(*)(void *, void *))mgmtd__fe_message__pack,
392 MGMT_DEBUG_FE_CHECK());
393 mgmt_fe_adapter_sched_msg_write(adapter);
394 return rv;
395 }
396
397 static int
398 mgmt_fe_send_session_reply(struct mgmt_fe_client_adapter *adapter,
399 struct mgmt_fe_session_ctx *session,
400 bool create, bool success)
401 {
402 Mgmtd__FeMessage fe_msg;
403 Mgmtd__FeSessionReply session_reply;
404
405 mgmtd__fe_session_reply__init(&session_reply);
406 session_reply.create = create;
407 if (create) {
408 session_reply.has_client_conn_id = 1;
409 session_reply.client_conn_id = session->client_id;
410 }
411 session_reply.session_id = session->session_id;
412 session_reply.success = success;
413
414 mgmtd__fe_message__init(&fe_msg);
415 fe_msg.message_case = MGMTD__FE_MESSAGE__MESSAGE_SESSION_REPLY;
416 fe_msg.session_reply = &session_reply;
417
418 MGMTD_FE_ADAPTER_DBG(
419 "Sending SESSION_REPLY message to MGMTD Frontend client '%s'",
420 adapter->name);
421
422 return mgmt_fe_adapter_send_msg(adapter, &fe_msg);
423 }
424
425 static int mgmt_fe_send_lockds_reply(struct mgmt_fe_session_ctx *session,
426 Mgmtd__DatastoreId ds_id,
427 uint64_t req_id, bool lock_ds,
428 bool success, const char *error_if_any)
429 {
430 Mgmtd__FeMessage fe_msg;
431 Mgmtd__FeLockDsReply lockds_reply;
432
433 assert(session->adapter);
434
435 mgmtd__fe_lock_ds_reply__init(&lockds_reply);
436 lockds_reply.session_id = session->session_id;
437 lockds_reply.ds_id = ds_id;
438 lockds_reply.req_id = req_id;
439 lockds_reply.lock = lock_ds;
440 lockds_reply.success = success;
441 if (error_if_any)
442 lockds_reply.error_if_any = (char *)error_if_any;
443
444 mgmtd__fe_message__init(&fe_msg);
445 fe_msg.message_case = MGMTD__FE_MESSAGE__MESSAGE_LOCKDS_REPLY;
446 fe_msg.lockds_reply = &lockds_reply;
447
448 MGMTD_FE_ADAPTER_DBG(
449 "Sending LOCK_DS_REPLY message to MGMTD Frontend client '%s'",
450 session->adapter->name);
451
452 return mgmt_fe_adapter_send_msg(session->adapter, &fe_msg);
453 }
454
455 static int mgmt_fe_send_setcfg_reply(struct mgmt_fe_session_ctx *session,
456 Mgmtd__DatastoreId ds_id,
457 uint64_t req_id, bool success,
458 const char *error_if_any,
459 bool implicit_commit)
460 {
461 Mgmtd__FeMessage fe_msg;
462 Mgmtd__FeSetConfigReply setcfg_reply;
463
464 assert(session->adapter);
465
466 if (implicit_commit && session->cfg_txn_id)
467 mgmt_fe_session_register_event(
468 session, MGMTD_FE_SESSION_CFG_TXN_CLNUP);
469
470 mgmtd__fe_set_config_reply__init(&setcfg_reply);
471 setcfg_reply.session_id = session->session_id;
472 setcfg_reply.ds_id = ds_id;
473 setcfg_reply.req_id = req_id;
474 setcfg_reply.success = success;
475 if (error_if_any)
476 setcfg_reply.error_if_any = (char *)error_if_any;
477
478 mgmtd__fe_message__init(&fe_msg);
479 fe_msg.message_case = MGMTD__FE_MESSAGE__MESSAGE_SETCFG_REPLY;
480 fe_msg.setcfg_reply = &setcfg_reply;
481
482 MGMTD_FE_ADAPTER_DBG(
483 "Sending SET_CONFIG_REPLY message to MGMTD Frontend client '%s'",
484 session->adapter->name);
485
486 if (implicit_commit) {
487 if (mm->perf_stats_en)
488 gettimeofday(&session->adapter->cmt_stats.last_end,
489 NULL);
490 mgmt_fe_session_compute_commit_timers(
491 &session->adapter->cmt_stats);
492 }
493
494 if (mm->perf_stats_en)
495 gettimeofday(&session->adapter->setcfg_stats.last_end, NULL);
496 mgmt_fe_adapter_compute_set_cfg_timers(&session->adapter->setcfg_stats);
497
498 return mgmt_fe_adapter_send_msg(session->adapter, &fe_msg);
499 }
500
501 static int mgmt_fe_send_commitcfg_reply(
502 struct mgmt_fe_session_ctx *session, Mgmtd__DatastoreId src_ds_id,
503 Mgmtd__DatastoreId dst_ds_id, uint64_t req_id, enum mgmt_result result,
504 bool validate_only, const char *error_if_any)
505 {
506 Mgmtd__FeMessage fe_msg;
507 Mgmtd__FeCommitConfigReply commcfg_reply;
508
509 assert(session->adapter);
510
511 mgmtd__fe_commit_config_reply__init(&commcfg_reply);
512 commcfg_reply.session_id = session->session_id;
513 commcfg_reply.src_ds_id = src_ds_id;
514 commcfg_reply.dst_ds_id = dst_ds_id;
515 commcfg_reply.req_id = req_id;
516 commcfg_reply.success =
517 (result == MGMTD_SUCCESS || result == MGMTD_NO_CFG_CHANGES)
518 ? true
519 : false;
520 commcfg_reply.validate_only = validate_only;
521 if (error_if_any)
522 commcfg_reply.error_if_any = (char *)error_if_any;
523
524 mgmtd__fe_message__init(&fe_msg);
525 fe_msg.message_case = MGMTD__FE_MESSAGE__MESSAGE_COMMCFG_REPLY;
526 fe_msg.commcfg_reply = &commcfg_reply;
527
528 MGMTD_FE_ADAPTER_DBG(
529 "Sending COMMIT_CONFIG_REPLY message to MGMTD Frontend client '%s'",
530 session->adapter->name);
531
532 /*
533 * Cleanup the CONFIG transaction associated with this session.
534 */
535 if (session->cfg_txn_id
536 && ((result == MGMTD_SUCCESS && !validate_only)
537 || (result == MGMTD_NO_CFG_CHANGES)))
538 mgmt_fe_session_register_event(
539 session, MGMTD_FE_SESSION_CFG_TXN_CLNUP);
540
541 if (mm->perf_stats_en)
542 gettimeofday(&session->adapter->cmt_stats.last_end, NULL);
543 mgmt_fe_session_compute_commit_timers(&session->adapter->cmt_stats);
544 return mgmt_fe_adapter_send_msg(session->adapter, &fe_msg);
545 }
546
547 static int mgmt_fe_send_getcfg_reply(struct mgmt_fe_session_ctx *session,
548 Mgmtd__DatastoreId ds_id,
549 uint64_t req_id, bool success,
550 Mgmtd__YangDataReply *data,
551 const char *error_if_any)
552 {
553 Mgmtd__FeMessage fe_msg;
554 Mgmtd__FeGetConfigReply getcfg_reply;
555
556 assert(session->adapter);
557
558 mgmtd__fe_get_config_reply__init(&getcfg_reply);
559 getcfg_reply.session_id = session->session_id;
560 getcfg_reply.ds_id = ds_id;
561 getcfg_reply.req_id = req_id;
562 getcfg_reply.success = success;
563 getcfg_reply.data = data;
564 if (error_if_any)
565 getcfg_reply.error_if_any = (char *)error_if_any;
566
567 mgmtd__fe_message__init(&fe_msg);
568 fe_msg.message_case = MGMTD__FE_MESSAGE__MESSAGE_GETCFG_REPLY;
569 fe_msg.getcfg_reply = &getcfg_reply;
570
571 MGMTD_FE_ADAPTER_DBG(
572 "Sending GET_CONFIG_REPLY message to MGMTD Frontend client '%s'",
573 session->adapter->name);
574
575 /*
576 * Cleanup the SHOW transaction associated with this session.
577 */
578 if (session->txn_id && (!success || (data && data->next_indx < 0)))
579 mgmt_fe_session_register_event(
580 session, MGMTD_FE_SESSION_SHOW_TXN_CLNUP);
581
582 return mgmt_fe_adapter_send_msg(session->adapter, &fe_msg);
583 }
584
585 static int mgmt_fe_send_getdata_reply(struct mgmt_fe_session_ctx *session,
586 Mgmtd__DatastoreId ds_id,
587 uint64_t req_id, bool success,
588 Mgmtd__YangDataReply *data,
589 const char *error_if_any)
590 {
591 Mgmtd__FeMessage fe_msg;
592 Mgmtd__FeGetDataReply getdata_reply;
593
594 assert(session->adapter);
595
596 mgmtd__fe_get_data_reply__init(&getdata_reply);
597 getdata_reply.session_id = session->session_id;
598 getdata_reply.ds_id = ds_id;
599 getdata_reply.req_id = req_id;
600 getdata_reply.success = success;
601 getdata_reply.data = data;
602 if (error_if_any)
603 getdata_reply.error_if_any = (char *)error_if_any;
604
605 mgmtd__fe_message__init(&fe_msg);
606 fe_msg.message_case = MGMTD__FE_MESSAGE__MESSAGE_GETDATA_REPLY;
607 fe_msg.getdata_reply = &getdata_reply;
608
609 MGMTD_FE_ADAPTER_DBG(
610 "Sending GET_DATA_REPLY message to MGMTD Frontend client '%s'",
611 session->adapter->name);
612
613 /*
614 * Cleanup the SHOW transaction associated with this session.
615 */
616 if (session->txn_id && (!success || (data && data->next_indx < 0)))
617 mgmt_fe_session_register_event(
618 session, MGMTD_FE_SESSION_SHOW_TXN_CLNUP);
619
620 return mgmt_fe_adapter_send_msg(session->adapter, &fe_msg);
621 }
622
623 static void mgmt_fe_session_cfg_txn_clnup(struct event *thread)
624 {
625 struct mgmt_fe_session_ctx *session;
626
627 session = (struct mgmt_fe_session_ctx *)EVENT_ARG(thread);
628
629 mgmt_fe_session_cfg_txn_cleanup(session);
630 }
631
632 static void mgmt_fe_session_show_txn_clnup(struct event *thread)
633 {
634 struct mgmt_fe_session_ctx *session;
635
636 session = (struct mgmt_fe_session_ctx *)EVENT_ARG(thread);
637
638 mgmt_fe_session_show_txn_cleanup(session);
639 }
640
641 static void
642 mgmt_fe_session_register_event(struct mgmt_fe_session_ctx *session,
643 enum mgmt_session_event event)
644 {
645 struct timeval tv = {.tv_sec = 0,
646 .tv_usec = MGMTD_FE_MSG_PROC_DELAY_USEC};
647
648 switch (event) {
649 case MGMTD_FE_SESSION_CFG_TXN_CLNUP:
650 event_add_timer_tv(mgmt_fe_adapter_tm,
651 mgmt_fe_session_cfg_txn_clnup, session,
652 &tv, &session->proc_cfg_txn_clnp);
653 break;
654 case MGMTD_FE_SESSION_SHOW_TXN_CLNUP:
655 event_add_timer_tv(mgmt_fe_adapter_tm,
656 mgmt_fe_session_show_txn_clnup, session,
657 &tv, &session->proc_show_txn_clnp);
658 break;
659 }
660 }
661
662 static struct mgmt_fe_client_adapter *
663 mgmt_fe_find_adapter_by_fd(int conn_fd)
664 {
665 struct mgmt_fe_client_adapter *adapter;
666
667 FOREACH_ADAPTER_IN_LIST (adapter) {
668 if (adapter->conn_fd == conn_fd)
669 return adapter;
670 }
671
672 return NULL;
673 }
674
675 static struct mgmt_fe_client_adapter *
676 mgmt_fe_find_adapter_by_name(const char *name)
677 {
678 struct mgmt_fe_client_adapter *adapter;
679
680 FOREACH_ADAPTER_IN_LIST (adapter) {
681 if (!strncmp(adapter->name, name, sizeof(adapter->name)))
682 return adapter;
683 }
684
685 return NULL;
686 }
687
688 static void mgmt_fe_adapter_disconnect(struct mgmt_fe_client_adapter *adapter)
689 {
690 if (adapter->conn_fd >= 0) {
691 close(adapter->conn_fd);
692 adapter->conn_fd = -1;
693 }
694
695 /* TODO: notify about client disconnect for appropriate cleanup */
696 mgmt_fe_cleanup_sessions(adapter);
697 mgmt_fe_sessions_fini(&adapter->fe_sessions);
698 mgmt_fe_adapters_del(&mgmt_fe_adapters, adapter);
699
700 mgmt_fe_adapter_unlock(&adapter);
701 }
702
703 static void
704 mgmt_fe_adapter_cleanup_old_conn(struct mgmt_fe_client_adapter *adapter)
705 {
706 struct mgmt_fe_client_adapter *old;
707
708 FOREACH_ADAPTER_IN_LIST (old) {
709 if (old != adapter &&
710 !strncmp(adapter->name, old->name, sizeof(adapter->name))) {
711 /*
712 * We have a Zombie lingering around
713 */
714 MGMTD_FE_ADAPTER_DBG(
715 "Client '%s' (FD:%d) seems to have reconnected. Removing old connection (FD:%d)!",
716 adapter->name, adapter->conn_fd, old->conn_fd);
717 mgmt_fe_adapter_disconnect(old);
718 }
719 }
720 }
721
722 static void
723 mgmt_fe_cleanup_adapters(void)
724 {
725 struct mgmt_fe_client_adapter *adapter;
726
727 FOREACH_ADAPTER_IN_LIST (adapter) {
728 mgmt_fe_cleanup_sessions(adapter);
729 mgmt_fe_adapter_unlock(&adapter);
730 }
731 }
732
733 static int
734 mgmt_fe_session_handle_lockds_req_msg(struct mgmt_fe_session_ctx *session,
735 Mgmtd__FeLockDsReq *lockds_req)
736 {
737 struct mgmt_ds_ctx *ds_ctx;
738
739 /*
740 * Next check first if the SET_CONFIG_REQ is for Candidate DS
741 * or not. Report failure if its not. MGMTD currently only
742 * supports editing the Candidate DS.
743 */
744 if (lockds_req->ds_id != MGMTD_DS_CANDIDATE) {
745 mgmt_fe_send_lockds_reply(
746 session, lockds_req->ds_id, lockds_req->req_id,
747 lockds_req->lock, false,
748 "Lock/Unlock on datastores other than Candidate DS not permitted!");
749 return -1;
750 }
751
752 ds_ctx =
753 mgmt_ds_get_ctx_by_id(mgmt_fe_adapter_mm, lockds_req->ds_id);
754 if (!ds_ctx) {
755 mgmt_fe_send_lockds_reply(
756 session, lockds_req->ds_id, lockds_req->req_id,
757 lockds_req->lock, false,
758 "Failed to retrieve handle for DS!");
759 return -1;
760 }
761
762 if (lockds_req->lock) {
763 if (mgmt_fe_session_write_lock_ds(lockds_req->ds_id,
764 ds_ctx, session)
765 != 0) {
766 mgmt_fe_send_lockds_reply(
767 session, lockds_req->ds_id, lockds_req->req_id,
768 lockds_req->lock, false,
769 "Lock already taken on DS by another session!");
770 return -1;
771 }
772
773 session->ds_locked_implict[lockds_req->ds_id] = false;
774 } else {
775 if (!session->ds_write_locked[lockds_req->ds_id]) {
776 mgmt_fe_send_lockds_reply(
777 session, lockds_req->ds_id, lockds_req->req_id,
778 lockds_req->lock, false,
779 "Lock on DS was not taken by this session!");
780 return 0;
781 }
782
783 (void)mgmt_fe_session_unlock_ds(lockds_req->ds_id, ds_ctx,
784 session, true, false);
785 }
786
787 if (mgmt_fe_send_lockds_reply(session, lockds_req->ds_id,
788 lockds_req->req_id, lockds_req->lock,
789 true, NULL)
790 != 0) {
791 MGMTD_FE_ADAPTER_DBG(
792 "Failed to send LOCK_DS_REPLY for DS %u Sessn: %p from %s",
793 lockds_req->ds_id, session, session->adapter->name);
794 }
795
796 return 0;
797 }
798
799 static int
800 mgmt_fe_session_handle_setcfg_req_msg(struct mgmt_fe_session_ctx *session,
801 Mgmtd__FeSetConfigReq *setcfg_req)
802 {
803 uint64_t cfg_session_id;
804 struct mgmt_ds_ctx *ds_ctx, *dst_ds_ctx;
805
806 if (mm->perf_stats_en)
807 gettimeofday(&session->adapter->setcfg_stats.last_start, NULL);
808
809 /*
810 * Next check first if the SET_CONFIG_REQ is for Candidate DS
811 * or not. Report failure if its not. MGMTD currently only
812 * supports editing the Candidate DS.
813 */
814 if (setcfg_req->ds_id != MGMTD_DS_CANDIDATE) {
815 mgmt_fe_send_setcfg_reply(
816 session, setcfg_req->ds_id, setcfg_req->req_id, false,
817 "Set-Config on datastores other than Candidate DS not permitted!",
818 setcfg_req->implicit_commit);
819 return 0;
820 }
821
822 /*
823 * Get the DS handle.
824 */
825 ds_ctx =
826 mgmt_ds_get_ctx_by_id(mgmt_fe_adapter_mm, setcfg_req->ds_id);
827 if (!ds_ctx) {
828 mgmt_fe_send_setcfg_reply(
829 session, setcfg_req->ds_id, setcfg_req->req_id, false,
830 "No such DS exists!", setcfg_req->implicit_commit);
831 return 0;
832 }
833
834 if (session->cfg_txn_id == MGMTD_TXN_ID_NONE) {
835 /*
836 * Check first if the current session can run a CONFIG
837 * transaction or not. Report failure if a CONFIG transaction
838 * from another session is already in progress.
839 */
840 cfg_session_id = mgmt_config_txn_in_progress();
841 if (cfg_session_id != MGMTD_SESSION_ID_NONE
842 && cfg_session_id != session->session_id) {
843 mgmt_fe_send_setcfg_reply(
844 session, setcfg_req->ds_id, setcfg_req->req_id,
845 false,
846 "Configuration already in-progress through a different user session!",
847 setcfg_req->implicit_commit);
848 goto mgmt_fe_sess_handle_setcfg_req_failed;
849 }
850
851
852 /*
853 * Try taking write-lock on the requested DS (if not already).
854 */
855 if (!session->ds_write_locked[setcfg_req->ds_id]) {
856 if (mgmt_fe_session_write_lock_ds(setcfg_req->ds_id,
857 ds_ctx, session)
858 != 0) {
859 mgmt_fe_send_setcfg_reply(
860 session, setcfg_req->ds_id,
861 setcfg_req->req_id, false,
862 "Failed to lock the DS!",
863 setcfg_req->implicit_commit);
864 goto mgmt_fe_sess_handle_setcfg_req_failed;
865 }
866
867 session->ds_locked_implict[setcfg_req->ds_id] = true;
868 }
869
870 /*
871 * Start a CONFIG Transaction (if not started already)
872 */
873 session->cfg_txn_id = mgmt_create_txn(session->session_id,
874 MGMTD_TXN_TYPE_CONFIG);
875 if (session->cfg_txn_id == MGMTD_SESSION_ID_NONE) {
876 mgmt_fe_send_setcfg_reply(
877 session, setcfg_req->ds_id, setcfg_req->req_id,
878 false,
879 "Failed to create a Configuration session!",
880 setcfg_req->implicit_commit);
881 goto mgmt_fe_sess_handle_setcfg_req_failed;
882 }
883
884 MGMTD_FE_ADAPTER_DBG(
885 "Created new Config Txn 0x%llx for session %p",
886 (unsigned long long)session->cfg_txn_id, session);
887 } else {
888 MGMTD_FE_ADAPTER_DBG(
889 "Config Txn 0x%llx for session %p already created",
890 (unsigned long long)session->cfg_txn_id, session);
891
892 if (setcfg_req->implicit_commit) {
893 /*
894 * In this scenario need to skip cleanup of the txn,
895 * so setting implicit commit to false.
896 */
897 mgmt_fe_send_setcfg_reply(
898 session, setcfg_req->ds_id, setcfg_req->req_id,
899 false,
900 "A Configuration transaction is already in progress!",
901 false);
902 return 0;
903 }
904 }
905
906 dst_ds_ctx = 0;
907 if (setcfg_req->implicit_commit) {
908 dst_ds_ctx = mgmt_ds_get_ctx_by_id(mgmt_fe_adapter_mm,
909 setcfg_req->commit_ds_id);
910 if (!dst_ds_ctx) {
911 mgmt_fe_send_setcfg_reply(
912 session, setcfg_req->ds_id, setcfg_req->req_id,
913 false, "No such commit DS exists!",
914 setcfg_req->implicit_commit);
915 return 0;
916 }
917 }
918
919 /*
920 * Create the SETConfig request under the transaction.
921 */
922 if (mgmt_txn_send_set_config_req(
923 session->cfg_txn_id, setcfg_req->req_id, setcfg_req->ds_id,
924 ds_ctx, setcfg_req->data, setcfg_req->n_data,
925 setcfg_req->implicit_commit, setcfg_req->commit_ds_id,
926 dst_ds_ctx)
927 != 0) {
928 mgmt_fe_send_setcfg_reply(
929 session, setcfg_req->ds_id, setcfg_req->req_id, false,
930 "Request processing for SET-CONFIG failed!",
931 setcfg_req->implicit_commit);
932 goto mgmt_fe_sess_handle_setcfg_req_failed;
933 }
934
935 return 0;
936
937 mgmt_fe_sess_handle_setcfg_req_failed:
938
939 /*
940 * Delete transaction created recently.
941 */
942 if (session->cfg_txn_id != MGMTD_TXN_ID_NONE)
943 mgmt_destroy_txn(&session->cfg_txn_id);
944 if (ds_ctx && session->ds_write_locked[setcfg_req->ds_id])
945 mgmt_fe_session_unlock_ds(setcfg_req->ds_id, ds_ctx, session,
946 true, false);
947
948 return 0;
949 }
950
951 static int
952 mgmt_fe_session_handle_getcfg_req_msg(struct mgmt_fe_session_ctx *session,
953 Mgmtd__FeGetConfigReq *getcfg_req)
954 {
955 struct mgmt_ds_ctx *ds_ctx;
956
957 /*
958 * Get the DS handle.
959 */
960 ds_ctx =
961 mgmt_ds_get_ctx_by_id(mgmt_fe_adapter_mm, getcfg_req->ds_id);
962 if (!ds_ctx) {
963 mgmt_fe_send_getcfg_reply(session, getcfg_req->ds_id,
964 getcfg_req->req_id, false, NULL,
965 "No such DS exists!");
966 return 0;
967 }
968
969 /*
970 * Next check first if the SET_CONFIG_REQ is for Candidate DS
971 * or not. Report failure if its not. MGMTD currently only
972 * supports editing the Candidate DS.
973 */
974 if (getcfg_req->ds_id != MGMTD_DS_CANDIDATE
975 && getcfg_req->ds_id != MGMTD_DS_RUNNING) {
976 mgmt_fe_send_getcfg_reply(
977 session, getcfg_req->ds_id, getcfg_req->req_id, false,
978 NULL,
979 "Get-Config on datastores other than Candidate or Running DS not permitted!");
980 return 0;
981 }
982
983 if (session->txn_id == MGMTD_TXN_ID_NONE) {
984 /*
985 * Try taking read-lock on the requested DS (if not already
986 * locked). If the DS has already been write-locked by a ongoing
987 * CONFIG transaction we may allow reading the contents of the
988 * same DS.
989 */
990 if (!session->ds_read_locked[getcfg_req->ds_id]
991 && !session->ds_write_locked[getcfg_req->ds_id]) {
992 if (mgmt_fe_session_read_lock_ds(getcfg_req->ds_id,
993 ds_ctx, session)
994 != 0) {
995 mgmt_fe_send_getcfg_reply(
996 session, getcfg_req->ds_id,
997 getcfg_req->req_id, false, NULL,
998 "Failed to lock the DS! Another session might have locked it!");
999 goto mgmt_fe_sess_handle_getcfg_req_failed;
1000 }
1001
1002 session->ds_locked_implict[getcfg_req->ds_id] = true;
1003 }
1004
1005 /*
1006 * Start a SHOW Transaction (if not started already)
1007 */
1008 session->txn_id = mgmt_create_txn(session->session_id,
1009 MGMTD_TXN_TYPE_SHOW);
1010 if (session->txn_id == MGMTD_SESSION_ID_NONE) {
1011 mgmt_fe_send_getcfg_reply(
1012 session, getcfg_req->ds_id, getcfg_req->req_id,
1013 false, NULL,
1014 "Failed to create a Show transaction!");
1015 goto mgmt_fe_sess_handle_getcfg_req_failed;
1016 }
1017
1018 MGMTD_FE_ADAPTER_DBG(
1019 "Created new Show Txn 0x%llx for session %p",
1020 (unsigned long long)session->txn_id, session);
1021 } else {
1022 MGMTD_FE_ADAPTER_DBG(
1023 "Show Txn 0x%llx for session %p already created",
1024 (unsigned long long)session->txn_id, session);
1025 }
1026
1027 /*
1028 * Create a GETConfig request under the transaction.
1029 */
1030 if (mgmt_txn_send_get_config_req(session->txn_id, getcfg_req->req_id,
1031 getcfg_req->ds_id, ds_ctx,
1032 getcfg_req->data, getcfg_req->n_data)
1033 != 0) {
1034 mgmt_fe_send_getcfg_reply(
1035 session, getcfg_req->ds_id, getcfg_req->req_id, false,
1036 NULL, "Request processing for GET-CONFIG failed!");
1037 goto mgmt_fe_sess_handle_getcfg_req_failed;
1038 }
1039
1040 return 0;
1041
1042 mgmt_fe_sess_handle_getcfg_req_failed:
1043
1044 /*
1045 * Destroy the transaction created recently.
1046 */
1047 if (session->txn_id != MGMTD_TXN_ID_NONE)
1048 mgmt_destroy_txn(&session->txn_id);
1049 if (ds_ctx && session->ds_read_locked[getcfg_req->ds_id])
1050 mgmt_fe_session_unlock_ds(getcfg_req->ds_id, ds_ctx, session,
1051 false, true);
1052
1053 return -1;
1054 }
1055
1056 static int
1057 mgmt_fe_session_handle_getdata_req_msg(struct mgmt_fe_session_ctx *session,
1058 Mgmtd__FeGetDataReq *getdata_req)
1059 {
1060 struct mgmt_ds_ctx *ds_ctx;
1061
1062 /*
1063 * Get the DS handle.
1064 */
1065 ds_ctx = mgmt_ds_get_ctx_by_id(mgmt_fe_adapter_mm,
1066 getdata_req->ds_id);
1067 if (!ds_ctx) {
1068 mgmt_fe_send_getdata_reply(session, getdata_req->ds_id,
1069 getdata_req->req_id, false, NULL,
1070 "No such DS exists!");
1071 return 0;
1072 }
1073
1074 if (session->txn_id == MGMTD_TXN_ID_NONE) {
1075 /*
1076 * Try taking read-lock on the requested DS (if not already
1077 * locked). If the DS has already been write-locked by a ongoing
1078 * CONFIG transaction we may allow reading the contents of the
1079 * same DS.
1080 */
1081 if (!session->ds_read_locked[getdata_req->ds_id]
1082 && !session->ds_write_locked[getdata_req->ds_id]) {
1083 if (mgmt_fe_session_read_lock_ds(getdata_req->ds_id,
1084 ds_ctx, session)
1085 != 0) {
1086 mgmt_fe_send_getdata_reply(
1087 session, getdata_req->ds_id,
1088 getdata_req->req_id, false, NULL,
1089 "Failed to lock the DS! Another session might have locked it!");
1090 goto mgmt_fe_sess_handle_getdata_req_failed;
1091 }
1092
1093 session->ds_locked_implict[getdata_req->ds_id] = true;
1094 }
1095
1096 /*
1097 * Start a SHOW Transaction (if not started already)
1098 */
1099 session->txn_id = mgmt_create_txn(session->session_id,
1100 MGMTD_TXN_TYPE_SHOW);
1101 if (session->txn_id == MGMTD_SESSION_ID_NONE) {
1102 mgmt_fe_send_getdata_reply(
1103 session, getdata_req->ds_id,
1104 getdata_req->req_id, false, NULL,
1105 "Failed to create a Show transaction!");
1106 goto mgmt_fe_sess_handle_getdata_req_failed;
1107 }
1108
1109 MGMTD_FE_ADAPTER_DBG(
1110 "Created new Show Txn 0x%llx for session %p",
1111 (unsigned long long)session->txn_id, session);
1112 } else {
1113 MGMTD_FE_ADAPTER_DBG(
1114 "Show Txn 0x%llx for session %p already created",
1115 (unsigned long long)session->txn_id, session);
1116 }
1117
1118 /*
1119 * Create a GETData request under the transaction.
1120 */
1121 if (mgmt_txn_send_get_data_req(session->txn_id, getdata_req->req_id,
1122 getdata_req->ds_id, ds_ctx,
1123 getdata_req->data, getdata_req->n_data)
1124 != 0) {
1125 mgmt_fe_send_getdata_reply(
1126 session, getdata_req->ds_id, getdata_req->req_id, false,
1127 NULL, "Request processing for GET-CONFIG failed!");
1128 goto mgmt_fe_sess_handle_getdata_req_failed;
1129 }
1130
1131 return 0;
1132
1133 mgmt_fe_sess_handle_getdata_req_failed:
1134
1135 /*
1136 * Destroy the transaction created recently.
1137 */
1138 if (session->txn_id != MGMTD_TXN_ID_NONE)
1139 mgmt_destroy_txn(&session->txn_id);
1140
1141 if (ds_ctx && session->ds_read_locked[getdata_req->ds_id])
1142 mgmt_fe_session_unlock_ds(getdata_req->ds_id, ds_ctx,
1143 session, false, true);
1144
1145 return -1;
1146 }
1147
1148 static int mgmt_fe_session_handle_commit_config_req_msg(
1149 struct mgmt_fe_session_ctx *session,
1150 Mgmtd__FeCommitConfigReq *commcfg_req)
1151 {
1152 struct mgmt_ds_ctx *src_ds_ctx, *dst_ds_ctx;
1153
1154 if (mm->perf_stats_en)
1155 gettimeofday(&session->adapter->cmt_stats.last_start, NULL);
1156 session->adapter->cmt_stats.commit_cnt++;
1157 /*
1158 * Get the source DS handle.
1159 */
1160 src_ds_ctx = mgmt_ds_get_ctx_by_id(mgmt_fe_adapter_mm,
1161 commcfg_req->src_ds_id);
1162 if (!src_ds_ctx) {
1163 mgmt_fe_send_commitcfg_reply(
1164 session, commcfg_req->src_ds_id, commcfg_req->dst_ds_id,
1165 commcfg_req->req_id, MGMTD_INTERNAL_ERROR,
1166 commcfg_req->validate_only,
1167 "No such source DS exists!");
1168 return 0;
1169 }
1170
1171 /*
1172 * Get the destination DS handle.
1173 */
1174 dst_ds_ctx = mgmt_ds_get_ctx_by_id(mgmt_fe_adapter_mm,
1175 commcfg_req->dst_ds_id);
1176 if (!dst_ds_ctx) {
1177 mgmt_fe_send_commitcfg_reply(
1178 session, commcfg_req->src_ds_id, commcfg_req->dst_ds_id,
1179 commcfg_req->req_id, MGMTD_INTERNAL_ERROR,
1180 commcfg_req->validate_only,
1181 "No such destination DS exists!");
1182 return 0;
1183 }
1184
1185 /*
1186 * Next check first if the SET_CONFIG_REQ is for Candidate DS
1187 * or not. Report failure if its not. MGMTD currently only
1188 * supports editing the Candidate DS.
1189 */
1190 if (commcfg_req->dst_ds_id != MGMTD_DS_RUNNING) {
1191 mgmt_fe_send_commitcfg_reply(
1192 session, commcfg_req->src_ds_id, commcfg_req->dst_ds_id,
1193 commcfg_req->req_id, MGMTD_INTERNAL_ERROR,
1194 commcfg_req->validate_only,
1195 "Set-Config on datastores other than Running DS not permitted!");
1196 return 0;
1197 }
1198
1199 if (session->cfg_txn_id == MGMTD_TXN_ID_NONE) {
1200 /*
1201 * Start a CONFIG Transaction (if not started already)
1202 */
1203 session->cfg_txn_id = mgmt_create_txn(session->session_id,
1204 MGMTD_TXN_TYPE_CONFIG);
1205 if (session->cfg_txn_id == MGMTD_SESSION_ID_NONE) {
1206 mgmt_fe_send_commitcfg_reply(
1207 session, commcfg_req->src_ds_id,
1208 commcfg_req->dst_ds_id, commcfg_req->req_id,
1209 MGMTD_INTERNAL_ERROR,
1210 commcfg_req->validate_only,
1211 "Failed to create a Configuration session!");
1212 return 0;
1213 }
1214 MGMTD_FE_ADAPTER_DBG("Created txn %" PRIu64
1215 " for session %" PRIu64
1216 " for COMMIT-CFG-REQ",
1217 session->cfg_txn_id, session->session_id);
1218 }
1219
1220
1221 /*
1222 * Try taking write-lock on the destination DS (if not already).
1223 */
1224 if (!session->ds_write_locked[commcfg_req->dst_ds_id]) {
1225 if (mgmt_fe_session_write_lock_ds(commcfg_req->dst_ds_id,
1226 dst_ds_ctx, session)
1227 != 0) {
1228 mgmt_fe_send_commitcfg_reply(
1229 session, commcfg_req->src_ds_id,
1230 commcfg_req->dst_ds_id, commcfg_req->req_id,
1231 MGMTD_DS_LOCK_FAILED,
1232 commcfg_req->validate_only,
1233 "Failed to lock the destination DS!");
1234 return 0;
1235 }
1236
1237 session->ds_locked_implict[commcfg_req->dst_ds_id] = true;
1238 }
1239
1240 /*
1241 * Create COMMITConfig request under the transaction
1242 */
1243 if (mgmt_txn_send_commit_config_req(
1244 session->cfg_txn_id, commcfg_req->req_id,
1245 commcfg_req->src_ds_id, src_ds_ctx, commcfg_req->dst_ds_id,
1246 dst_ds_ctx, commcfg_req->validate_only, commcfg_req->abort,
1247 false)
1248 != 0) {
1249 mgmt_fe_send_commitcfg_reply(
1250 session, commcfg_req->src_ds_id, commcfg_req->dst_ds_id,
1251 commcfg_req->req_id, MGMTD_INTERNAL_ERROR,
1252 commcfg_req->validate_only,
1253 "Request processing for COMMIT-CONFIG failed!");
1254 return 0;
1255 }
1256
1257 return 0;
1258 }
1259
1260 static int
1261 mgmt_fe_adapter_handle_msg(struct mgmt_fe_client_adapter *adapter,
1262 Mgmtd__FeMessage *fe_msg)
1263 {
1264 struct mgmt_fe_session_ctx *session;
1265
1266 /*
1267 * protobuf-c adds a max size enum with an internal, and changing by
1268 * version, name; cast to an int to avoid unhandled enum warnings
1269 */
1270 switch ((int)fe_msg->message_case) {
1271 case MGMTD__FE_MESSAGE__MESSAGE_REGISTER_REQ:
1272 MGMTD_FE_ADAPTER_DBG("Got Register Req Msg from '%s'",
1273 fe_msg->register_req->client_name);
1274
1275 if (strlen(fe_msg->register_req->client_name)) {
1276 strlcpy(adapter->name,
1277 fe_msg->register_req->client_name,
1278 sizeof(adapter->name));
1279 mgmt_fe_adapter_cleanup_old_conn(adapter);
1280 }
1281 break;
1282 case MGMTD__FE_MESSAGE__MESSAGE_SESSION_REQ:
1283 if (fe_msg->session_req->create
1284 && fe_msg->session_req->id_case
1285 == MGMTD__FE_SESSION_REQ__ID_CLIENT_CONN_ID) {
1286 MGMTD_FE_ADAPTER_DBG(
1287 "Got Session Create Req Msg for client-id %llu from '%s'",
1288 (unsigned long long)
1289 fe_msg->session_req->client_conn_id,
1290 adapter->name);
1291
1292 session = mgmt_fe_create_session(
1293 adapter, fe_msg->session_req->client_conn_id);
1294 mgmt_fe_send_session_reply(adapter, session, true,
1295 session ? true : false);
1296 } else if (
1297 !fe_msg->session_req->create
1298 && fe_msg->session_req->id_case
1299 == MGMTD__FE_SESSION_REQ__ID_SESSION_ID) {
1300 MGMTD_FE_ADAPTER_DBG(
1301 "Got Session Destroy Req Msg for session-id %llu from '%s'",
1302 (unsigned long long)
1303 fe_msg->session_req->session_id,
1304 adapter->name);
1305
1306 session = mgmt_session_id2ctx(
1307 fe_msg->session_req->session_id);
1308 mgmt_fe_send_session_reply(adapter, session, false,
1309 true);
1310 mgmt_fe_cleanup_session(&session);
1311 }
1312 break;
1313 case MGMTD__FE_MESSAGE__MESSAGE_LOCKDS_REQ:
1314 session = mgmt_session_id2ctx(
1315 fe_msg->lockds_req->session_id);
1316 MGMTD_FE_ADAPTER_DBG(
1317 "Got %sockDS Req Msg for DS:%d for session-id %llx from '%s'",
1318 fe_msg->lockds_req->lock ? "L" : "Unl",
1319 fe_msg->lockds_req->ds_id,
1320 (unsigned long long)fe_msg->lockds_req->session_id,
1321 adapter->name);
1322 mgmt_fe_session_handle_lockds_req_msg(
1323 session, fe_msg->lockds_req);
1324 break;
1325 case MGMTD__FE_MESSAGE__MESSAGE_SETCFG_REQ:
1326 session = mgmt_session_id2ctx(
1327 fe_msg->setcfg_req->session_id);
1328 session->adapter->setcfg_stats.set_cfg_count++;
1329 MGMTD_FE_ADAPTER_DBG(
1330 "Got Set Config Req Msg (%d Xpaths, Implicit:%c) on DS:%d for session-id %llu from '%s'",
1331 (int)fe_msg->setcfg_req->n_data,
1332 fe_msg->setcfg_req->implicit_commit ? 'T':'F',
1333 fe_msg->setcfg_req->ds_id,
1334 (unsigned long long)fe_msg->setcfg_req->session_id,
1335 adapter->name);
1336
1337 mgmt_fe_session_handle_setcfg_req_msg(
1338 session, fe_msg->setcfg_req);
1339 break;
1340 case MGMTD__FE_MESSAGE__MESSAGE_COMMCFG_REQ:
1341 session = mgmt_session_id2ctx(
1342 fe_msg->commcfg_req->session_id);
1343 MGMTD_FE_ADAPTER_DBG(
1344 "Got Commit Config Req Msg for src-DS:%d dst-DS:%d (Abort:%c) on session-id %llu from '%s'",
1345 fe_msg->commcfg_req->src_ds_id,
1346 fe_msg->commcfg_req->dst_ds_id,
1347 fe_msg->commcfg_req->abort ? 'T':'F',
1348 (unsigned long long)fe_msg->commcfg_req->session_id,
1349 adapter->name);
1350 mgmt_fe_session_handle_commit_config_req_msg(
1351 session, fe_msg->commcfg_req);
1352 break;
1353 case MGMTD__FE_MESSAGE__MESSAGE_GETCFG_REQ:
1354 session = mgmt_session_id2ctx(
1355 fe_msg->getcfg_req->session_id);
1356 MGMTD_FE_ADAPTER_DBG(
1357 "Got Get-Config Req Msg for DS:%d (xpaths: %d) on session-id %llu from '%s'",
1358 fe_msg->getcfg_req->ds_id,
1359 (int)fe_msg->getcfg_req->n_data,
1360 (unsigned long long)fe_msg->getcfg_req->session_id,
1361 adapter->name);
1362 mgmt_fe_session_handle_getcfg_req_msg(
1363 session, fe_msg->getcfg_req);
1364 break;
1365 case MGMTD__FE_MESSAGE__MESSAGE_GETDATA_REQ:
1366 session = mgmt_session_id2ctx(
1367 fe_msg->getdata_req->session_id);
1368 MGMTD_FE_ADAPTER_DBG(
1369 "Got Get-Data Req Msg for DS:%d (xpaths: %d) on session-id %llu from '%s'",
1370 fe_msg->getdata_req->ds_id,
1371 (int)fe_msg->getdata_req->n_data,
1372 (unsigned long long)fe_msg->getdata_req->session_id,
1373 adapter->name);
1374 mgmt_fe_session_handle_getdata_req_msg(
1375 session, fe_msg->getdata_req);
1376 break;
1377 case MGMTD__FE_MESSAGE__MESSAGE_NOTIFY_DATA_REQ:
1378 case MGMTD__FE_MESSAGE__MESSAGE_REGNOTIFY_REQ:
1379 /*
1380 * TODO: Add handling code in future.
1381 */
1382 break;
1383 /*
1384 * NOTE: The following messages are always sent from MGMTD to
1385 * Frontend clients only and/or need not be handled on MGMTd.
1386 */
1387 case MGMTD__FE_MESSAGE__MESSAGE_SESSION_REPLY:
1388 case MGMTD__FE_MESSAGE__MESSAGE_LOCKDS_REPLY:
1389 case MGMTD__FE_MESSAGE__MESSAGE_SETCFG_REPLY:
1390 case MGMTD__FE_MESSAGE__MESSAGE_COMMCFG_REPLY:
1391 case MGMTD__FE_MESSAGE__MESSAGE_GETCFG_REPLY:
1392 case MGMTD__FE_MESSAGE__MESSAGE_GETDATA_REPLY:
1393 case MGMTD__FE_MESSAGE__MESSAGE__NOT_SET:
1394 default:
1395 /*
1396 * A 'default' case is being added contrary to the
1397 * FRR code guidelines to take care of build
1398 * failures on certain build systems (courtesy of
1399 * the proto-c package).
1400 */
1401 break;
1402 }
1403
1404 return 0;
1405 }
1406
1407 static void mgmt_fe_adapter_process_msg(void *user_ctx, uint8_t *data,
1408 size_t len)
1409 {
1410 struct mgmt_fe_client_adapter *adapter = user_ctx;
1411 Mgmtd__FeMessage *fe_msg;
1412
1413 fe_msg = mgmtd__fe_message__unpack(NULL, len, data);
1414 if (!fe_msg) {
1415 MGMTD_FE_ADAPTER_DBG(
1416 "Failed to decode %zu bytes for adapter: %s", len,
1417 adapter->name);
1418 return;
1419 }
1420 MGMTD_FE_ADAPTER_DBG(
1421 "Decoded %zu bytes of message: %u from adapter: %s", len,
1422 fe_msg->message_case, adapter->name);
1423 (void)mgmt_fe_adapter_handle_msg(adapter, fe_msg);
1424 mgmtd__fe_message__free_unpacked(fe_msg, NULL);
1425 }
1426
1427 static void mgmt_fe_adapter_proc_msgbufs(struct event *thread)
1428 {
1429 struct mgmt_fe_client_adapter *adapter = EVENT_ARG(thread);
1430
1431 if (mgmt_msg_procbufs(&adapter->mstate, mgmt_fe_adapter_process_msg,
1432 adapter, MGMT_DEBUG_FE_CHECK()))
1433 mgmt_fe_adapter_register_event(adapter, MGMTD_FE_PROC_MSG);
1434 }
1435
1436 static void mgmt_fe_adapter_read(struct event *thread)
1437 {
1438 struct mgmt_fe_client_adapter *adapter = EVENT_ARG(thread);
1439 enum mgmt_msg_rsched rv;
1440
1441 rv = mgmt_msg_read(&adapter->mstate, adapter->conn_fd,
1442 MGMT_DEBUG_FE_CHECK());
1443 if (rv == MSR_DISCONNECT) {
1444 mgmt_fe_adapter_disconnect(adapter);
1445 return;
1446 }
1447 if (rv == MSR_SCHED_BOTH)
1448 mgmt_fe_adapter_register_event(adapter, MGMTD_FE_PROC_MSG);
1449 mgmt_fe_adapter_register_event(adapter, MGMTD_FE_CONN_READ);
1450 }
1451
1452 static void mgmt_fe_adapter_write(struct event *thread)
1453 {
1454 struct mgmt_fe_client_adapter *adapter = EVENT_ARG(thread);
1455 enum mgmt_msg_wsched rv;
1456
1457 rv = mgmt_msg_write(&adapter->mstate, adapter->conn_fd,
1458 MGMT_DEBUG_FE_CHECK());
1459 if (rv == MSW_SCHED_STREAM)
1460 mgmt_fe_adapter_register_event(adapter, MGMTD_FE_CONN_WRITE);
1461 else if (rv == MSW_DISCONNECT)
1462 mgmt_fe_adapter_disconnect(adapter);
1463 else if (rv == MSW_SCHED_WRITES_OFF) {
1464 mgmt_fe_adapter_writes_off(adapter);
1465 mgmt_fe_adapter_register_event(adapter,
1466 MGMTD_FE_CONN_WRITES_ON);
1467 } else
1468 assert(rv == MSW_SCHED_NONE);
1469 }
1470
1471 static void mgmt_fe_adapter_resume_writes(struct event *thread)
1472 {
1473 struct mgmt_fe_client_adapter *adapter;
1474
1475 adapter = (struct mgmt_fe_client_adapter *)EVENT_ARG(thread);
1476 assert(adapter && adapter->conn_fd != -1);
1477
1478 mgmt_fe_adapter_writes_on(adapter);
1479 }
1480
1481 static void
1482 mgmt_fe_adapter_register_event(struct mgmt_fe_client_adapter *adapter,
1483 enum mgmt_fe_event event)
1484 {
1485 struct timeval tv = {0};
1486
1487 switch (event) {
1488 case MGMTD_FE_CONN_READ:
1489 event_add_read(mgmt_fe_adapter_tm, mgmt_fe_adapter_read,
1490 adapter, adapter->conn_fd, &adapter->conn_read_ev);
1491 break;
1492 case MGMTD_FE_CONN_WRITE:
1493 event_add_write(mgmt_fe_adapter_tm,
1494 mgmt_fe_adapter_write, adapter,
1495 adapter->conn_fd, &adapter->conn_write_ev);
1496 break;
1497 case MGMTD_FE_PROC_MSG:
1498 tv.tv_usec = MGMTD_FE_MSG_PROC_DELAY_USEC;
1499 event_add_timer_tv(mgmt_fe_adapter_tm,
1500 mgmt_fe_adapter_proc_msgbufs, adapter,
1501 &tv, &adapter->proc_msg_ev);
1502 break;
1503 case MGMTD_FE_CONN_WRITES_ON:
1504 event_add_timer_msec(mgmt_fe_adapter_tm,
1505 mgmt_fe_adapter_resume_writes, adapter,
1506 MGMTD_FE_MSG_WRITE_DELAY_MSEC,
1507 &adapter->conn_writes_on);
1508 break;
1509 case MGMTD_FE_SERVER:
1510 assert(!"mgmt_fe_adapter_post_event() called incorrectly");
1511 break;
1512 }
1513 }
1514
1515 void mgmt_fe_adapter_lock(struct mgmt_fe_client_adapter *adapter)
1516 {
1517 adapter->refcount++;
1518 }
1519
1520 extern void
1521 mgmt_fe_adapter_unlock(struct mgmt_fe_client_adapter **adapter)
1522 {
1523 assert(*adapter && (*adapter)->refcount);
1524
1525 (*adapter)->refcount--;
1526 if (!(*adapter)->refcount) {
1527 mgmt_fe_adapters_del(&mgmt_fe_adapters, *adapter);
1528 EVENT_OFF((*adapter)->conn_read_ev);
1529 EVENT_OFF((*adapter)->conn_write_ev);
1530 EVENT_OFF((*adapter)->proc_msg_ev);
1531 EVENT_OFF((*adapter)->conn_writes_on);
1532 mgmt_msg_destroy(&(*adapter)->mstate);
1533 XFREE(MTYPE_MGMTD_FE_ADPATER, *adapter);
1534 }
1535
1536 *adapter = NULL;
1537 }
1538
1539 int mgmt_fe_adapter_init(struct event_loop *tm, struct mgmt_master *mm)
1540 {
1541 if (!mgmt_fe_adapter_tm) {
1542 mgmt_fe_adapter_tm = tm;
1543 mgmt_fe_adapter_mm = mm;
1544 mgmt_fe_adapters_init(&mgmt_fe_adapters);
1545
1546 assert(!mgmt_fe_sessions);
1547 mgmt_fe_sessions = hash_create(mgmt_fe_session_hash_key,
1548 mgmt_fe_session_hash_cmp,
1549 "MGMT Frontend Sessions");
1550 }
1551
1552 return 0;
1553 }
1554
1555 void mgmt_fe_adapter_destroy(void)
1556 {
1557 mgmt_fe_cleanup_adapters();
1558 mgmt_fe_session_hash_destroy();
1559 }
1560
1561 struct mgmt_fe_client_adapter *
1562 mgmt_fe_create_adapter(int conn_fd, union sockunion *from)
1563 {
1564 struct mgmt_fe_client_adapter *adapter = NULL;
1565
1566 adapter = mgmt_fe_find_adapter_by_fd(conn_fd);
1567 if (!adapter) {
1568 adapter = XCALLOC(MTYPE_MGMTD_FE_ADPATER,
1569 sizeof(struct mgmt_fe_client_adapter));
1570 assert(adapter);
1571
1572 adapter->conn_fd = conn_fd;
1573 memcpy(&adapter->conn_su, from, sizeof(adapter->conn_su));
1574 snprintf(adapter->name, sizeof(adapter->name), "Unknown-FD-%d",
1575 adapter->conn_fd);
1576 mgmt_fe_sessions_init(&adapter->fe_sessions);
1577
1578 mgmt_msg_init(&adapter->mstate, MGMTD_FE_MAX_NUM_MSG_PROC,
1579 MGMTD_FE_MAX_NUM_MSG_WRITE, MGMTD_FE_MSG_MAX_LEN,
1580 "FE-adapter");
1581 mgmt_fe_adapter_lock(adapter);
1582
1583 mgmt_fe_adapter_register_event(adapter, MGMTD_FE_CONN_READ);
1584 mgmt_fe_adapters_add_tail(&mgmt_fe_adapters, adapter);
1585
1586 adapter->setcfg_stats.min_tm = ULONG_MAX;
1587 adapter->cmt_stats.min_tm = ULONG_MAX;
1588 MGMTD_FE_ADAPTER_DBG("Added new MGMTD Frontend adapter '%s'",
1589 adapter->name);
1590 }
1591
1592 /* Make client socket non-blocking. */
1593 set_nonblocking(adapter->conn_fd);
1594 setsockopt_so_sendbuf(adapter->conn_fd,
1595 MGMTD_SOCKET_FE_SEND_BUF_SIZE);
1596 setsockopt_so_recvbuf(adapter->conn_fd,
1597 MGMTD_SOCKET_FE_RECV_BUF_SIZE);
1598 return adapter;
1599 }
1600
1601 struct mgmt_fe_client_adapter *mgmt_fe_get_adapter(const char *name)
1602 {
1603 return mgmt_fe_find_adapter_by_name(name);
1604 }
1605
1606 int mgmt_fe_send_set_cfg_reply(uint64_t session_id, uint64_t txn_id,
1607 Mgmtd__DatastoreId ds_id, uint64_t req_id,
1608 enum mgmt_result result,
1609 const char *error_if_any,
1610 bool implicit_commit)
1611 {
1612 struct mgmt_fe_session_ctx *session;
1613
1614 session = mgmt_session_id2ctx(session_id);
1615 if (!session || session->cfg_txn_id != txn_id) {
1616 if (session)
1617 MGMTD_FE_ADAPTER_ERR(
1618 "Txn_id doesnot match, session txn is 0x%llx, current txn 0x%llx",
1619 (unsigned long long)session->cfg_txn_id,
1620 (unsigned long long)txn_id);
1621 return -1;
1622 }
1623
1624 return mgmt_fe_send_setcfg_reply(
1625 session, ds_id, req_id, result == MGMTD_SUCCESS ? true : false,
1626 error_if_any, implicit_commit);
1627 }
1628
1629 int mgmt_fe_send_commit_cfg_reply(uint64_t session_id, uint64_t txn_id,
1630 Mgmtd__DatastoreId src_ds_id,
1631 Mgmtd__DatastoreId dst_ds_id,
1632 uint64_t req_id, bool validate_only,
1633 enum mgmt_result result,
1634 const char *error_if_any)
1635 {
1636 struct mgmt_fe_session_ctx *session;
1637
1638 session = mgmt_session_id2ctx(session_id);
1639 if (!session || session->cfg_txn_id != txn_id)
1640 return -1;
1641
1642 return mgmt_fe_send_commitcfg_reply(session, src_ds_id, dst_ds_id,
1643 req_id, result, validate_only,
1644 error_if_any);
1645 }
1646
1647 int mgmt_fe_send_get_cfg_reply(uint64_t session_id, uint64_t txn_id,
1648 Mgmtd__DatastoreId ds_id, uint64_t req_id,
1649 enum mgmt_result result,
1650 Mgmtd__YangDataReply *data_resp,
1651 const char *error_if_any)
1652 {
1653 struct mgmt_fe_session_ctx *session;
1654
1655 session = mgmt_session_id2ctx(session_id);
1656 if (!session || session->txn_id != txn_id)
1657 return -1;
1658
1659 return mgmt_fe_send_getcfg_reply(session, ds_id, req_id,
1660 result == MGMTD_SUCCESS, data_resp,
1661 error_if_any);
1662 }
1663
1664 int mgmt_fe_send_get_data_reply(uint64_t session_id, uint64_t txn_id,
1665 Mgmtd__DatastoreId ds_id, uint64_t req_id,
1666 enum mgmt_result result,
1667 Mgmtd__YangDataReply *data_resp,
1668 const char *error_if_any)
1669 {
1670 struct mgmt_fe_session_ctx *session;
1671
1672 session = mgmt_session_id2ctx(session_id);
1673 if (!session || session->txn_id != txn_id)
1674 return -1;
1675
1676 return mgmt_fe_send_getdata_reply(session, ds_id, req_id,
1677 result == MGMTD_SUCCESS,
1678 data_resp, error_if_any);
1679 }
1680
1681 int mgmt_fe_send_data_notify(Mgmtd__DatastoreId ds_id,
1682 Mgmtd__YangData * data_resp[], int num_data)
1683 {
1684 /* struct mgmt_fe_session_ctx *session; */
1685
1686 return 0;
1687 }
1688
1689 struct mgmt_setcfg_stats *
1690 mgmt_fe_get_session_setcfg_stats(uint64_t session_id)
1691 {
1692 struct mgmt_fe_session_ctx *session;
1693
1694 session = mgmt_session_id2ctx(session_id);
1695 if (!session || !session->adapter)
1696 return NULL;
1697
1698 return &session->adapter->setcfg_stats;
1699 }
1700
1701 struct mgmt_commit_stats *
1702 mgmt_fe_get_session_commit_stats(uint64_t session_id)
1703 {
1704 struct mgmt_fe_session_ctx *session;
1705
1706 session = mgmt_session_id2ctx(session_id);
1707 if (!session || !session->adapter)
1708 return NULL;
1709
1710 return &session->adapter->cmt_stats;
1711 }
1712
1713 static void
1714 mgmt_fe_adapter_cmt_stats_write(struct vty *vty,
1715 struct mgmt_fe_client_adapter *adapter)
1716 {
1717 char buf[MGMT_LONG_TIME_MAX_LEN];
1718
1719 if (!mm->perf_stats_en)
1720 return;
1721
1722 vty_out(vty, " Num-Commits: \t\t\t%lu\n",
1723 adapter->cmt_stats.commit_cnt);
1724 if (adapter->cmt_stats.commit_cnt > 0) {
1725 if (mm->perf_stats_en)
1726 vty_out(vty, " Max-Commit-Duration: \t\t%lu uSecs\n",
1727 adapter->cmt_stats.max_tm);
1728 vty_out(vty, " Max-Commit-Batch-Size: \t\t%lu\n",
1729 adapter->cmt_stats.max_batch_cnt);
1730 if (mm->perf_stats_en)
1731 vty_out(vty, " Min-Commit-Duration: \t\t%lu uSecs\n",
1732 adapter->cmt_stats.min_tm);
1733 vty_out(vty, " Min-Commit-Batch-Size: \t\t%lu\n",
1734 adapter->cmt_stats.min_batch_cnt);
1735 if (mm->perf_stats_en)
1736 vty_out(vty,
1737 " Last-Commit-Duration: \t\t%lu uSecs\n",
1738 adapter->cmt_stats.last_exec_tm);
1739 vty_out(vty, " Last-Commit-Batch-Size: \t\t%lu\n",
1740 adapter->cmt_stats.last_batch_cnt);
1741 vty_out(vty, " Last-Commit-CfgData-Reqs: \t\t%lu\n",
1742 adapter->cmt_stats.last_num_cfgdata_reqs);
1743 vty_out(vty, " Last-Commit-CfgApply-Reqs: \t\t%lu\n",
1744 adapter->cmt_stats.last_num_apply_reqs);
1745 if (mm->perf_stats_en) {
1746 vty_out(vty, " Last-Commit-Details:\n");
1747 vty_out(vty, " Commit Start: \t\t\t%s\n",
1748 mgmt_realtime_to_string(
1749 &adapter->cmt_stats.last_start, buf,
1750 sizeof(buf)));
1751 #ifdef MGMTD_LOCAL_VALIDATIONS_ENABLED
1752 vty_out(vty, " Config-Validate Start: \t\t%s\n",
1753 mgmt_realtime_to_string(
1754 &adapter->cmt_stats.validate_start, buf,
1755 sizeof(buf)));
1756 #endif
1757 vty_out(vty, " Prep-Config Start: \t\t%s\n",
1758 mgmt_realtime_to_string(
1759 &adapter->cmt_stats.prep_cfg_start, buf,
1760 sizeof(buf)));
1761 vty_out(vty, " Txn-Create Start: \t\t%s\n",
1762 mgmt_realtime_to_string(
1763 &adapter->cmt_stats.txn_create_start,
1764 buf, sizeof(buf)));
1765 vty_out(vty,
1766 #ifdef MGMTD_LOCAL_VALIDATIONS_ENABLED
1767 " Send-Config Start: \t\t%s\n",
1768 #else
1769 " Send-Config-Validate Start: \t%s\n",
1770 #endif
1771 mgmt_realtime_to_string(
1772 &adapter->cmt_stats.send_cfg_start, buf,
1773 sizeof(buf)));
1774 vty_out(vty, " Apply-Config Start: \t\t%s\n",
1775 mgmt_realtime_to_string(
1776 &adapter->cmt_stats.apply_cfg_start,
1777 buf, sizeof(buf)));
1778 vty_out(vty, " Apply-Config End: \t\t%s\n",
1779 mgmt_realtime_to_string(
1780 &adapter->cmt_stats.apply_cfg_end, buf,
1781 sizeof(buf)));
1782 vty_out(vty, " Txn-Delete Start: \t\t%s\n",
1783 mgmt_realtime_to_string(
1784 &adapter->cmt_stats.txn_del_start, buf,
1785 sizeof(buf)));
1786 vty_out(vty, " Commit End: \t\t\t%s\n",
1787 mgmt_realtime_to_string(
1788 &adapter->cmt_stats.last_end, buf,
1789 sizeof(buf)));
1790 }
1791 }
1792 }
1793
1794 static void
1795 mgmt_fe_adapter_setcfg_stats_write(struct vty *vty,
1796 struct mgmt_fe_client_adapter *adapter)
1797 {
1798 char buf[MGMT_LONG_TIME_MAX_LEN];
1799
1800 if (!mm->perf_stats_en)
1801 return;
1802
1803 vty_out(vty, " Num-Set-Cfg: \t\t\t%lu\n",
1804 adapter->setcfg_stats.set_cfg_count);
1805 if (mm->perf_stats_en && adapter->setcfg_stats.set_cfg_count > 0) {
1806 vty_out(vty, " Max-Set-Cfg-Duration: \t\t%lu uSec\n",
1807 adapter->setcfg_stats.max_tm);
1808 vty_out(vty, " Min-Set-Cfg-Duration: \t\t%lu uSec\n",
1809 adapter->setcfg_stats.min_tm);
1810 vty_out(vty, " Avg-Set-Cfg-Duration: \t\t%lu uSec\n",
1811 adapter->setcfg_stats.avg_tm);
1812 vty_out(vty, " Last-Set-Cfg-Details:\n");
1813 vty_out(vty, " Set-Cfg Start: \t\t\t%s\n",
1814 mgmt_realtime_to_string(
1815 &adapter->setcfg_stats.last_start, buf,
1816 sizeof(buf)));
1817 vty_out(vty, " Set-Cfg End: \t\t\t%s\n",
1818 mgmt_realtime_to_string(&adapter->setcfg_stats.last_end,
1819 buf, sizeof(buf)));
1820 }
1821 }
1822
1823 void mgmt_fe_adapter_status_write(struct vty *vty, bool detail)
1824 {
1825 struct mgmt_fe_client_adapter *adapter;
1826 struct mgmt_fe_session_ctx *session;
1827 Mgmtd__DatastoreId ds_id;
1828 bool locked = false;
1829
1830 vty_out(vty, "MGMTD Frontend Adpaters\n");
1831
1832 FOREACH_ADAPTER_IN_LIST (adapter) {
1833 vty_out(vty, " Client: \t\t\t\t%s\n", adapter->name);
1834 vty_out(vty, " Conn-FD: \t\t\t\t%d\n", adapter->conn_fd);
1835 if (detail) {
1836 mgmt_fe_adapter_setcfg_stats_write(vty, adapter);
1837 mgmt_fe_adapter_cmt_stats_write(vty, adapter);
1838 }
1839 vty_out(vty, " Sessions\n");
1840 FOREACH_SESSION_IN_LIST (adapter, session) {
1841 vty_out(vty, " Session: \t\t\t\t%p\n", session);
1842 vty_out(vty, " Client-Id: \t\t\t%llu\n",
1843 (unsigned long long)session->client_id);
1844 vty_out(vty, " Session-Id: \t\t\t%llx\n",
1845 (unsigned long long)session->session_id);
1846 vty_out(vty, " DS-Locks:\n");
1847 FOREACH_MGMTD_DS_ID (ds_id) {
1848 if (session->ds_write_locked[ds_id]
1849 || session->ds_read_locked[ds_id]) {
1850 locked = true;
1851 vty_out(vty,
1852 " %s\t\t\t%s, %s\n",
1853 mgmt_ds_id2name(ds_id),
1854 session->ds_write_locked[ds_id]
1855 ? "Write"
1856 : "Read",
1857 session->ds_locked_implict[ds_id]
1858 ? "Implicit"
1859 : "Explicit");
1860 }
1861 }
1862 if (!locked)
1863 vty_out(vty, " None\n");
1864 }
1865 vty_out(vty, " Total-Sessions: \t\t\t%d\n",
1866 (int)mgmt_fe_sessions_count(&adapter->fe_sessions));
1867 vty_out(vty, " Msg-Recvd: \t\t\t\t%" PRIu64 "\n",
1868 adapter->mstate.nrxm);
1869 vty_out(vty, " Bytes-Recvd: \t\t\t%" PRIu64 "\n",
1870 adapter->mstate.nrxb);
1871 vty_out(vty, " Msg-Sent: \t\t\t\t%" PRIu64 "\n",
1872 adapter->mstate.ntxm);
1873 vty_out(vty, " Bytes-Sent: \t\t\t%" PRIu64 "\n",
1874 adapter->mstate.ntxb);
1875 }
1876 vty_out(vty, " Total: %d\n",
1877 (int)mgmt_fe_adapters_count(&mgmt_fe_adapters));
1878 }
1879
1880 void mgmt_fe_adapter_perf_measurement(struct vty *vty, bool config)
1881 {
1882 mm->perf_stats_en = config;
1883 }
1884
1885 void mgmt_fe_adapter_reset_perf_stats(struct vty *vty)
1886 {
1887 struct mgmt_fe_client_adapter *adapter;
1888 struct mgmt_fe_session_ctx *session;
1889
1890 FOREACH_ADAPTER_IN_LIST (adapter) {
1891 memset(&adapter->setcfg_stats, 0,
1892 sizeof(adapter->setcfg_stats));
1893 FOREACH_SESSION_IN_LIST (adapter, session) {
1894 memset(&adapter->cmt_stats, 0,
1895 sizeof(adapter->cmt_stats));
1896 }
1897 }
1898 }