]>
Commit | Line | Data |
---|---|---|
ef43a632 CH |
1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* | |
3 | * MGMTD Frontend Client Library api interfaces | |
4 | * Copyright (C) 2021 Vmware, Inc. | |
5 | * Pushpasis Sarkar <spushpasis@vmware.com> | |
6 | */ | |
7 | ||
8 | #include <zebra.h> | |
9 | #include "memory.h" | |
10 | #include "libfrr.h" | |
11 | #include "mgmt_fe_client.h" | |
f82370b4 | 12 | #include "mgmt_msg.h" |
ef43a632 CH |
13 | #include "mgmt_pb.h" |
14 | #include "network.h" | |
15 | #include "stream.h" | |
16 | #include "sockopt.h" | |
17 | ||
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, ...) \ | |
25 | do { \ | |
26 | if (mgmt_debug_fe_client) \ | |
27 | zlog_debug("%s: " fmt, __func__, ##__VA_ARGS__); \ | |
28 | } while (0) | |
29 | #define MGMTD_FE_CLIENT_ERR(fmt, ...) \ | |
30 | zlog_err("%s: ERROR: " fmt, __func__, ##__VA_ARGS__) | |
31 | #endif /* REDIRECT_DEBUG_TO_STDERR */ | |
32 | ||
33 | struct mgmt_fe_client_ctx; | |
34 | ||
35 | PREDECL_LIST(mgmt_sessions); | |
36 | ||
37 | struct mgmt_fe_client_session { | |
38 | uint64_t client_id; | |
39 | uint64_t session_id; | |
40 | struct mgmt_fe_client_ctx *client_ctx; | |
41 | uintptr_t user_ctx; | |
42 | ||
43 | struct mgmt_sessions_item list_linkage; | |
44 | }; | |
45 | ||
46 | DECLARE_LIST(mgmt_sessions, struct mgmt_fe_client_session, list_linkage); | |
47 | ||
48 | DEFINE_MTYPE_STATIC(LIB, MGMTD_FE_SESSION, "MGMTD Frontend session"); | |
49 | ||
50 | struct mgmt_fe_client_ctx { | |
51 | int conn_fd; | |
52 | struct thread_master *tm; | |
53 | struct thread *conn_retry_tmr; | |
54 | struct thread *conn_read_ev; | |
55 | struct thread *conn_write_ev; | |
56 | struct thread *conn_writes_on; | |
57 | struct thread *msg_proc_ev; | |
58 | uint32_t flags; | |
ef43a632 | 59 | |
f82370b4 | 60 | struct mgmt_msg_state mstate; |
ef43a632 CH |
61 | |
62 | struct mgmt_fe_client_params client_params; | |
63 | ||
64 | struct mgmt_sessions_head client_sessions; | |
65 | }; | |
66 | ||
67 | #define MGMTD_FE_CLIENT_FLAGS_WRITES_OFF (1U << 0) | |
68 | ||
69 | #define FOREACH_SESSION_IN_LIST(client_ctx, session) \ | |
70 | frr_each_safe (mgmt_sessions, &(client_ctx)->client_sessions, (session)) | |
71 | ||
72 | static bool mgmt_debug_fe_client; | |
73 | ||
f82370b4 CH |
74 | static struct mgmt_fe_client_ctx mgmt_fe_client_ctx = { |
75 | .conn_fd = -1, | |
76 | }; | |
ef43a632 CH |
77 | |
78 | /* Forward declarations */ | |
79 | static void | |
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); | |
84 | ||
85 | static struct mgmt_fe_client_session * | |
86 | mgmt_fe_find_session_by_client_id(struct mgmt_fe_client_ctx *client_ctx, | |
87 | uint64_t client_id) | |
88 | { | |
89 | struct mgmt_fe_client_session *session; | |
90 | ||
91 | FOREACH_SESSION_IN_LIST (client_ctx, session) { | |
92 | if (session->client_id == client_id) { | |
93 | MGMTD_FE_CLIENT_DBG( | |
94 | "Found session %p for client-id %llu.", session, | |
95 | (unsigned long long)client_id); | |
96 | return session; | |
97 | } | |
98 | } | |
99 | ||
100 | return NULL; | |
101 | } | |
102 | ||
103 | static struct mgmt_fe_client_session * | |
104 | mgmt_fe_find_session_by_session_id(struct mgmt_fe_client_ctx *client_ctx, | |
105 | uint64_t session_id) | |
106 | { | |
107 | struct mgmt_fe_client_session *session; | |
108 | ||
109 | FOREACH_SESSION_IN_LIST (client_ctx, session) { | |
110 | if (session->session_id == session_id) { | |
111 | MGMTD_FE_CLIENT_DBG( | |
112 | "Found session %p for session-id %llu.", session, | |
113 | (unsigned long long)session_id); | |
114 | return session; | |
115 | } | |
116 | } | |
117 | ||
118 | return NULL; | |
119 | } | |
120 | ||
121 | static void | |
122 | mgmt_fe_server_disconnect(struct mgmt_fe_client_ctx *client_ctx, | |
123 | bool reconnect) | |
124 | { | |
f82370b4 | 125 | if (client_ctx->conn_fd != -1) { |
ef43a632 | 126 | close(client_ctx->conn_fd); |
f82370b4 | 127 | client_ctx->conn_fd = -1; |
ef43a632 CH |
128 | } |
129 | ||
130 | if (reconnect) | |
131 | mgmt_fe_client_schedule_conn_retry( | |
132 | client_ctx, | |
133 | client_ctx->client_params.conn_retry_intvl_sec); | |
134 | } | |
135 | ||
136 | static inline void | |
137 | mgmt_fe_client_sched_msg_write(struct mgmt_fe_client_ctx *client_ctx) | |
138 | { | |
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); | |
142 | } | |
143 | ||
144 | static inline void | |
145 | mgmt_fe_client_writes_on(struct mgmt_fe_client_ctx *client_ctx) | |
146 | { | |
147 | MGMTD_FE_CLIENT_DBG("Resume writing msgs"); | |
148 | UNSET_FLAG(client_ctx->flags, MGMTD_FE_CLIENT_FLAGS_WRITES_OFF); | |
f82370b4 | 149 | mgmt_fe_client_sched_msg_write(client_ctx); |
ef43a632 CH |
150 | } |
151 | ||
152 | static inline void | |
153 | mgmt_fe_client_writes_off(struct mgmt_fe_client_ctx *client_ctx) | |
154 | { | |
155 | SET_FLAG(client_ctx->flags, MGMTD_FE_CLIENT_FLAGS_WRITES_OFF); | |
156 | MGMTD_FE_CLIENT_DBG("Paused writing msgs"); | |
157 | } | |
158 | ||
f82370b4 CH |
159 | static int mgmt_fe_client_send_msg(struct mgmt_fe_client_ctx *client_ctx, |
160 | Mgmtd__FeMessage *fe_msg) | |
ef43a632 | 161 | { |
f82370b4 CH |
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"); | |
ef43a632 CH |
165 | return -1; |
166 | } | |
167 | ||
f82370b4 CH |
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); | |
ef43a632 | 173 | mgmt_fe_client_sched_msg_write(client_ctx); |
f82370b4 | 174 | return rv; |
ef43a632 CH |
175 | } |
176 | ||
177 | static void mgmt_fe_client_write(struct thread *thread) | |
178 | { | |
ef43a632 | 179 | struct mgmt_fe_client_ctx *client_ctx; |
f82370b4 | 180 | enum mgmt_msg_wsched rv; |
ef43a632 CH |
181 | |
182 | client_ctx = (struct mgmt_fe_client_ctx *)THREAD_ARG(thread); | |
f82370b4 CH |
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) { | |
ef43a632 CH |
190 | mgmt_fe_client_writes_off(client_ctx); |
191 | mgmt_fe_client_register_event(client_ctx, | |
f82370b4 CH |
192 | MGMTD_FE_CONN_WRITES_ON); |
193 | } else | |
194 | assert(rv == MSW_SCHED_NONE); | |
ef43a632 CH |
195 | } |
196 | ||
197 | static void mgmt_fe_client_resume_writes(struct thread *thread) | |
198 | { | |
199 | struct mgmt_fe_client_ctx *client_ctx; | |
200 | ||
201 | client_ctx = (struct mgmt_fe_client_ctx *)THREAD_ARG(thread); | |
f82370b4 | 202 | assert(client_ctx && client_ctx->conn_fd != -1); |
ef43a632 CH |
203 | |
204 | mgmt_fe_client_writes_on(client_ctx); | |
205 | } | |
206 | ||
207 | static int | |
208 | mgmt_fe_send_register_req(struct mgmt_fe_client_ctx *client_ctx) | |
209 | { | |
210 | Mgmtd__FeMessage fe_msg; | |
211 | Mgmtd__FeRegisterReq rgstr_req; | |
212 | ||
213 | mgmtd__fe_register_req__init(&rgstr_req); | |
214 | rgstr_req.client_name = client_ctx->client_params.name; | |
215 | ||
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; | |
219 | ||
220 | MGMTD_FE_CLIENT_DBG( | |
221 | "Sending REGISTER_REQ message to MGMTD Frontend server"); | |
222 | ||
223 | return mgmt_fe_client_send_msg(client_ctx, &fe_msg); | |
224 | } | |
225 | ||
226 | static int | |
227 | mgmt_fe_send_session_req(struct mgmt_fe_client_ctx *client_ctx, | |
228 | struct mgmt_fe_client_session *session, | |
229 | bool create) | |
230 | { | |
231 | Mgmtd__FeMessage fe_msg; | |
232 | Mgmtd__FeSessionReq sess_req; | |
233 | ||
234 | mgmtd__fe_session_req__init(&sess_req); | |
235 | sess_req.create = create; | |
236 | if (create) { | |
237 | sess_req.id_case = MGMTD__FE_SESSION_REQ__ID_CLIENT_CONN_ID; | |
238 | sess_req.client_conn_id = session->client_id; | |
239 | } else { | |
240 | sess_req.id_case = MGMTD__FE_SESSION_REQ__ID_SESSION_ID; | |
241 | sess_req.session_id = session->session_id; | |
242 | } | |
243 | ||
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; | |
247 | ||
248 | MGMTD_FE_CLIENT_DBG( | |
249 | "Sending SESSION_REQ message for %s session %llu to MGMTD Frontend server", | |
250 | create ? "creating" : "destroying", | |
251 | (unsigned long long)session->client_id); | |
252 | ||
253 | return mgmt_fe_client_send_msg(client_ctx, &fe_msg); | |
254 | } | |
255 | ||
256 | static int | |
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) | |
260 | { | |
261 | (void)req_id; | |
262 | Mgmtd__FeMessage fe_msg; | |
263 | Mgmtd__FeLockDsReq lockds_req; | |
264 | ||
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; | |
270 | ||
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; | |
274 | ||
275 | MGMTD_FE_CLIENT_DBG( | |
276 | "Sending %sLOCK_REQ message for Ds:%d session %llu to MGMTD Frontend server", | |
277 | lock ? "" : "UN", ds_id, (unsigned long long)session->client_id); | |
278 | ||
279 | return mgmt_fe_client_send_msg(client_ctx, &fe_msg); | |
280 | } | |
281 | ||
282 | static int | |
283 | mgmt_fe_send_setcfg_req(struct mgmt_fe_client_ctx *client_ctx, | |
284 | struct mgmt_fe_client_session *session, | |
285 | uint64_t req_id, Mgmtd__DatastoreId ds_id, | |
286 | Mgmtd__YangCfgDataReq **data_req, int num_data_reqs, | |
287 | bool implicit_commit, Mgmtd__DatastoreId dst_ds_id) | |
288 | { | |
289 | (void)req_id; | |
290 | Mgmtd__FeMessage fe_msg; | |
291 | Mgmtd__FeSetConfigReq setcfg_req; | |
292 | ||
293 | mgmtd__fe_set_config_req__init(&setcfg_req); | |
294 | setcfg_req.session_id = session->session_id; | |
295 | setcfg_req.ds_id = ds_id; | |
296 | setcfg_req.req_id = req_id; | |
297 | setcfg_req.data = data_req; | |
298 | setcfg_req.n_data = (size_t)num_data_reqs; | |
299 | setcfg_req.implicit_commit = implicit_commit; | |
300 | setcfg_req.commit_ds_id = dst_ds_id; | |
301 | ||
302 | mgmtd__fe_message__init(&fe_msg); | |
303 | fe_msg.message_case = MGMTD__FE_MESSAGE__MESSAGE_SETCFG_REQ; | |
304 | fe_msg.setcfg_req = &setcfg_req; | |
305 | ||
306 | MGMTD_FE_CLIENT_DBG( | |
307 | "Sending SET_CONFIG_REQ message for Ds:%d session %llu (#xpaths:%d) to MGMTD Frontend server", | |
308 | ds_id, (unsigned long long)session->client_id, num_data_reqs); | |
309 | ||
310 | return mgmt_fe_client_send_msg(client_ctx, &fe_msg); | |
311 | } | |
312 | ||
313 | static int | |
314 | mgmt_fe_send_commitcfg_req(struct mgmt_fe_client_ctx *client_ctx, | |
315 | struct mgmt_fe_client_session *session, | |
316 | uint64_t req_id, Mgmtd__DatastoreId src_ds_id, | |
317 | Mgmtd__DatastoreId dest_ds_id, bool validate_only, | |
318 | bool abort) | |
319 | { | |
320 | (void)req_id; | |
321 | Mgmtd__FeMessage fe_msg; | |
322 | Mgmtd__FeCommitConfigReq commitcfg_req; | |
323 | ||
324 | mgmtd__fe_commit_config_req__init(&commitcfg_req); | |
325 | commitcfg_req.session_id = session->session_id; | |
326 | commitcfg_req.src_ds_id = src_ds_id; | |
327 | commitcfg_req.dst_ds_id = dest_ds_id; | |
328 | commitcfg_req.req_id = req_id; | |
329 | commitcfg_req.validate_only = validate_only; | |
330 | commitcfg_req.abort = abort; | |
331 | ||
332 | mgmtd__fe_message__init(&fe_msg); | |
333 | fe_msg.message_case = MGMTD__FE_MESSAGE__MESSAGE_COMMCFG_REQ; | |
334 | fe_msg.commcfg_req = &commitcfg_req; | |
335 | ||
336 | MGMTD_FE_CLIENT_DBG( | |
337 | "Sending COMMIT_CONFIG_REQ message for Src-Ds:%d, Dst-Ds:%d session %llu to MGMTD Frontend server", | |
338 | src_ds_id, dest_ds_id, (unsigned long long)session->client_id); | |
339 | ||
340 | return mgmt_fe_client_send_msg(client_ctx, &fe_msg); | |
341 | } | |
342 | ||
343 | static int | |
344 | mgmt_fe_send_getcfg_req(struct mgmt_fe_client_ctx *client_ctx, | |
345 | struct mgmt_fe_client_session *session, | |
346 | uint64_t req_id, Mgmtd__DatastoreId ds_id, | |
347 | Mgmtd__YangGetDataReq * data_req[], | |
348 | int num_data_reqs) | |
349 | { | |
350 | (void)req_id; | |
351 | Mgmtd__FeMessage fe_msg; | |
352 | Mgmtd__FeGetConfigReq getcfg_req; | |
353 | ||
354 | mgmtd__fe_get_config_req__init(&getcfg_req); | |
355 | getcfg_req.session_id = session->session_id; | |
356 | getcfg_req.ds_id = ds_id; | |
357 | getcfg_req.req_id = req_id; | |
358 | getcfg_req.data = data_req; | |
359 | getcfg_req.n_data = (size_t)num_data_reqs; | |
360 | ||
361 | mgmtd__fe_message__init(&fe_msg); | |
362 | fe_msg.message_case = MGMTD__FE_MESSAGE__MESSAGE_GETCFG_REQ; | |
363 | fe_msg.getcfg_req = &getcfg_req; | |
364 | ||
365 | MGMTD_FE_CLIENT_DBG( | |
366 | "Sending GET_CONFIG_REQ message for Ds:%d session %llu (#xpaths:%d) to MGMTD Frontend server", | |
367 | ds_id, (unsigned long long)session->client_id, num_data_reqs); | |
368 | ||
369 | return mgmt_fe_client_send_msg(client_ctx, &fe_msg); | |
370 | } | |
371 | ||
372 | static int | |
373 | mgmt_fe_send_getdata_req(struct mgmt_fe_client_ctx *client_ctx, | |
374 | struct mgmt_fe_client_session *session, | |
375 | uint64_t req_id, Mgmtd__DatastoreId ds_id, | |
376 | Mgmtd__YangGetDataReq * data_req[], | |
377 | int num_data_reqs) | |
378 | { | |
379 | (void)req_id; | |
380 | Mgmtd__FeMessage fe_msg; | |
381 | Mgmtd__FeGetDataReq getdata_req; | |
382 | ||
383 | mgmtd__fe_get_data_req__init(&getdata_req); | |
384 | getdata_req.session_id = session->session_id; | |
385 | getdata_req.ds_id = ds_id; | |
386 | getdata_req.req_id = req_id; | |
387 | getdata_req.data = data_req; | |
388 | getdata_req.n_data = (size_t)num_data_reqs; | |
389 | ||
390 | mgmtd__fe_message__init(&fe_msg); | |
391 | fe_msg.message_case = MGMTD__FE_MESSAGE__MESSAGE_GETDATA_REQ; | |
392 | fe_msg.getdata_req = &getdata_req; | |
393 | ||
394 | MGMTD_FE_CLIENT_DBG( | |
395 | "Sending GET_CONFIG_REQ message for Ds:%d session %llu (#xpaths:%d) to MGMTD Frontend server", | |
396 | ds_id, (unsigned long long)session->client_id, num_data_reqs); | |
397 | ||
398 | return mgmt_fe_client_send_msg(client_ctx, &fe_msg); | |
399 | } | |
400 | ||
401 | static int mgmt_fe_send_regnotify_req( | |
402 | struct mgmt_fe_client_ctx *client_ctx, | |
403 | struct mgmt_fe_client_session *session, uint64_t req_id, | |
404 | Mgmtd__DatastoreId ds_id, bool register_req, | |
405 | Mgmtd__YangDataXPath * data_req[], int num_data_reqs) | |
406 | { | |
407 | (void)req_id; | |
408 | Mgmtd__FeMessage fe_msg; | |
409 | Mgmtd__FeRegisterNotifyReq regntfy_req; | |
410 | ||
411 | mgmtd__fe_register_notify_req__init(®ntfy_req); | |
412 | regntfy_req.session_id = session->session_id; | |
413 | regntfy_req.ds_id = ds_id; | |
414 | regntfy_req.register_req = register_req; | |
415 | regntfy_req.data_xpath = data_req; | |
416 | regntfy_req.n_data_xpath = (size_t)num_data_reqs; | |
417 | ||
418 | mgmtd__fe_message__init(&fe_msg); | |
419 | fe_msg.message_case = MGMTD__FE_MESSAGE__MESSAGE_REGNOTIFY_REQ; | |
420 | fe_msg.regnotify_req = ®ntfy_req; | |
421 | ||
422 | return mgmt_fe_client_send_msg(client_ctx, &fe_msg); | |
423 | } | |
424 | ||
425 | static int | |
426 | mgmt_fe_client_handle_msg(struct mgmt_fe_client_ctx *client_ctx, | |
427 | Mgmtd__FeMessage *fe_msg) | |
428 | { | |
429 | struct mgmt_fe_client_session *session = NULL; | |
430 | ||
0b645fd2 CH |
431 | /* |
432 | * protobuf-c adds a max size enum with an internal, and changing by | |
433 | * version, name; cast to an int to avoid unhandled enum warnings | |
434 | */ | |
435 | switch ((int)fe_msg->message_case) { | |
ef43a632 CH |
436 | case MGMTD__FE_MESSAGE__MESSAGE_SESSION_REPLY: |
437 | if (fe_msg->session_reply->create | |
438 | && fe_msg->session_reply->has_client_conn_id) { | |
439 | MGMTD_FE_CLIENT_DBG( | |
440 | "Got Session Create Reply Msg for client-id %llu with session-id: %llu.", | |
441 | (unsigned long long) | |
442 | fe_msg->session_reply->client_conn_id, | |
443 | (unsigned long long) | |
444 | fe_msg->session_reply->session_id); | |
445 | ||
446 | session = mgmt_fe_find_session_by_client_id( | |
447 | client_ctx, | |
448 | fe_msg->session_reply->client_conn_id); | |
449 | ||
450 | if (session && fe_msg->session_reply->success) { | |
451 | MGMTD_FE_CLIENT_DBG( | |
452 | "Session Create for client-id %llu successful.", | |
453 | (unsigned long long)fe_msg | |
454 | ->session_reply->client_conn_id); | |
455 | session->session_id = | |
456 | fe_msg->session_reply->session_id; | |
457 | } else { | |
458 | MGMTD_FE_CLIENT_ERR( | |
459 | "Session Create for client-id %llu failed.", | |
460 | (unsigned long long)fe_msg | |
461 | ->session_reply->client_conn_id); | |
462 | } | |
463 | } else if (!fe_msg->session_reply->create) { | |
464 | MGMTD_FE_CLIENT_DBG( | |
465 | "Got Session Destroy Reply Msg for session-id %llu", | |
466 | (unsigned long long) | |
467 | fe_msg->session_reply->session_id); | |
468 | ||
469 | session = mgmt_fe_find_session_by_session_id( | |
470 | client_ctx, fe_msg->session_req->session_id); | |
471 | } | |
472 | ||
473 | if (session && session->client_ctx | |
474 | && session->client_ctx->client_params | |
475 | .client_session_notify) | |
476 | (*session->client_ctx->client_params | |
477 | .client_session_notify)( | |
478 | (uintptr_t)client_ctx, | |
479 | client_ctx->client_params.user_data, | |
480 | session->client_id, | |
481 | fe_msg->session_reply->create, | |
482 | fe_msg->session_reply->success, | |
483 | (uintptr_t)session, session->user_ctx); | |
484 | break; | |
485 | case MGMTD__FE_MESSAGE__MESSAGE_LOCKDS_REPLY: | |
486 | MGMTD_FE_CLIENT_DBG( | |
487 | "Got LockDs Reply Msg for session-id %llu", | |
488 | (unsigned long long) | |
489 | fe_msg->lockds_reply->session_id); | |
490 | session = mgmt_fe_find_session_by_session_id( | |
491 | client_ctx, fe_msg->lockds_reply->session_id); | |
492 | ||
493 | if (session && session->client_ctx | |
494 | && session->client_ctx->client_params | |
495 | .lock_ds_notify) | |
496 | (*session->client_ctx->client_params | |
497 | .lock_ds_notify)( | |
498 | (uintptr_t)client_ctx, | |
499 | client_ctx->client_params.user_data, | |
500 | session->client_id, (uintptr_t)session, | |
501 | session->user_ctx, | |
502 | fe_msg->lockds_reply->req_id, | |
503 | fe_msg->lockds_reply->lock, | |
504 | fe_msg->lockds_reply->success, | |
505 | fe_msg->lockds_reply->ds_id, | |
506 | fe_msg->lockds_reply->error_if_any); | |
507 | break; | |
508 | case MGMTD__FE_MESSAGE__MESSAGE_SETCFG_REPLY: | |
509 | MGMTD_FE_CLIENT_DBG( | |
510 | "Got Set Config Reply Msg for session-id %llu", | |
511 | (unsigned long long) | |
512 | fe_msg->setcfg_reply->session_id); | |
513 | ||
514 | session = mgmt_fe_find_session_by_session_id( | |
515 | client_ctx, fe_msg->setcfg_reply->session_id); | |
516 | ||
517 | if (session && session->client_ctx | |
518 | && session->client_ctx->client_params | |
519 | .set_config_notify) | |
520 | (*session->client_ctx->client_params | |
521 | .set_config_notify)( | |
522 | (uintptr_t)client_ctx, | |
523 | client_ctx->client_params.user_data, | |
524 | session->client_id, (uintptr_t)session, | |
525 | session->user_ctx, | |
526 | fe_msg->setcfg_reply->req_id, | |
527 | fe_msg->setcfg_reply->success, | |
528 | fe_msg->setcfg_reply->ds_id, | |
529 | fe_msg->setcfg_reply->error_if_any); | |
530 | break; | |
531 | case MGMTD__FE_MESSAGE__MESSAGE_COMMCFG_REPLY: | |
532 | MGMTD_FE_CLIENT_DBG( | |
533 | "Got Commit Config Reply Msg for session-id %llu", | |
534 | (unsigned long long) | |
535 | fe_msg->commcfg_reply->session_id); | |
536 | ||
537 | session = mgmt_fe_find_session_by_session_id( | |
538 | client_ctx, fe_msg->commcfg_reply->session_id); | |
539 | ||
540 | if (session && session->client_ctx | |
541 | && session->client_ctx->client_params | |
542 | .commit_config_notify) | |
543 | (*session->client_ctx->client_params | |
544 | .commit_config_notify)( | |
545 | (uintptr_t)client_ctx, | |
546 | client_ctx->client_params.user_data, | |
547 | session->client_id, (uintptr_t)session, | |
548 | session->user_ctx, | |
549 | fe_msg->commcfg_reply->req_id, | |
550 | fe_msg->commcfg_reply->success, | |
551 | fe_msg->commcfg_reply->src_ds_id, | |
552 | fe_msg->commcfg_reply->dst_ds_id, | |
553 | fe_msg->commcfg_reply->validate_only, | |
554 | fe_msg->commcfg_reply->error_if_any); | |
555 | break; | |
556 | case MGMTD__FE_MESSAGE__MESSAGE_GETCFG_REPLY: | |
557 | MGMTD_FE_CLIENT_DBG( | |
558 | "Got Get Config Reply Msg for session-id %llu", | |
559 | (unsigned long long) | |
560 | fe_msg->getcfg_reply->session_id); | |
561 | ||
562 | session = mgmt_fe_find_session_by_session_id( | |
563 | client_ctx, fe_msg->getcfg_reply->session_id); | |
564 | ||
565 | if (session && session->client_ctx | |
566 | && session->client_ctx->client_params | |
567 | .get_data_notify) | |
568 | (*session->client_ctx->client_params | |
569 | .get_data_notify)( | |
570 | (uintptr_t)client_ctx, | |
571 | client_ctx->client_params.user_data, | |
572 | session->client_id, (uintptr_t)session, | |
573 | session->user_ctx, | |
574 | fe_msg->getcfg_reply->req_id, | |
575 | fe_msg->getcfg_reply->success, | |
576 | fe_msg->getcfg_reply->ds_id, | |
577 | fe_msg->getcfg_reply->data | |
578 | ? fe_msg->getcfg_reply->data->data | |
579 | : NULL, | |
580 | fe_msg->getcfg_reply->data | |
581 | ? fe_msg->getcfg_reply->data->n_data | |
582 | : 0, | |
583 | fe_msg->getcfg_reply->data | |
584 | ? fe_msg->getcfg_reply->data | |
585 | ->next_indx | |
586 | : 0, | |
587 | fe_msg->getcfg_reply->error_if_any); | |
588 | break; | |
589 | case MGMTD__FE_MESSAGE__MESSAGE_GETDATA_REPLY: | |
590 | MGMTD_FE_CLIENT_DBG( | |
591 | "Got Get Data Reply Msg for session-id %llu", | |
592 | (unsigned long long) | |
593 | fe_msg->getdata_reply->session_id); | |
594 | ||
595 | session = mgmt_fe_find_session_by_session_id( | |
596 | client_ctx, fe_msg->getdata_reply->session_id); | |
597 | ||
598 | if (session && session->client_ctx | |
599 | && session->client_ctx->client_params | |
600 | .get_data_notify) | |
601 | (*session->client_ctx->client_params | |
602 | .get_data_notify)( | |
603 | (uintptr_t)client_ctx, | |
604 | client_ctx->client_params.user_data, | |
605 | session->client_id, (uintptr_t)session, | |
606 | session->user_ctx, | |
607 | fe_msg->getdata_reply->req_id, | |
608 | fe_msg->getdata_reply->success, | |
609 | fe_msg->getdata_reply->ds_id, | |
610 | fe_msg->getdata_reply->data | |
611 | ? fe_msg->getdata_reply->data->data | |
612 | : NULL, | |
613 | fe_msg->getdata_reply->data | |
614 | ? fe_msg->getdata_reply->data | |
615 | ->n_data | |
616 | : 0, | |
617 | fe_msg->getdata_reply->data | |
618 | ? fe_msg->getdata_reply->data | |
619 | ->next_indx | |
620 | : 0, | |
621 | fe_msg->getdata_reply->error_if_any); | |
622 | break; | |
623 | case MGMTD__FE_MESSAGE__MESSAGE_NOTIFY_DATA_REQ: | |
624 | case MGMTD__FE_MESSAGE__MESSAGE_REGNOTIFY_REQ: | |
625 | /* | |
626 | * TODO: Add handling code in future. | |
627 | */ | |
628 | break; | |
629 | /* | |
630 | * NOTE: The following messages are always sent from Frontend | |
631 | * clients to MGMTd only and/or need not be handled here. | |
632 | */ | |
633 | case MGMTD__FE_MESSAGE__MESSAGE_REGISTER_REQ: | |
634 | case MGMTD__FE_MESSAGE__MESSAGE_SESSION_REQ: | |
635 | case MGMTD__FE_MESSAGE__MESSAGE_LOCKDS_REQ: | |
636 | case MGMTD__FE_MESSAGE__MESSAGE_SETCFG_REQ: | |
637 | case MGMTD__FE_MESSAGE__MESSAGE_COMMCFG_REQ: | |
638 | case MGMTD__FE_MESSAGE__MESSAGE_GETCFG_REQ: | |
639 | case MGMTD__FE_MESSAGE__MESSAGE_GETDATA_REQ: | |
640 | case MGMTD__FE_MESSAGE__MESSAGE__NOT_SET: | |
ef43a632 CH |
641 | default: |
642 | /* | |
643 | * A 'default' case is being added contrary to the | |
644 | * FRR code guidelines to take care of build | |
645 | * failures on certain build systems (courtesy of | |
646 | * the proto-c package). | |
647 | */ | |
648 | break; | |
649 | } | |
650 | ||
651 | return 0; | |
652 | } | |
653 | ||
f82370b4 CH |
654 | static void mgmt_fe_client_process_msg(void *user_ctx, uint8_t *data, |
655 | size_t len) | |
ef43a632 | 656 | { |
f82370b4 | 657 | struct mgmt_fe_client_ctx *client_ctx = user_ctx; |
ef43a632 | 658 | Mgmtd__FeMessage *fe_msg; |
ef43a632 | 659 | |
f82370b4 CH |
660 | fe_msg = mgmtd__fe_message__unpack(NULL, len, data); |
661 | if (!fe_msg) { | |
662 | MGMTD_FE_CLIENT_DBG("Failed to decode %zu bytes from server.", | |
663 | len); | |
664 | return; | |
ef43a632 | 665 | } |
f82370b4 CH |
666 | MGMTD_FE_CLIENT_DBG( |
667 | "Decoded %zu bytes of message(msg: %u/%u) from server", len, | |
668 | fe_msg->message_case, fe_msg->message_case); | |
669 | (void)mgmt_fe_client_handle_msg(client_ctx, fe_msg); | |
670 | mgmtd__fe_message__free_unpacked(fe_msg, NULL); | |
ef43a632 CH |
671 | } |
672 | ||
673 | static void mgmt_fe_client_proc_msgbufs(struct thread *thread) | |
674 | { | |
675 | struct mgmt_fe_client_ctx *client_ctx; | |
ef43a632 CH |
676 | |
677 | client_ctx = (struct mgmt_fe_client_ctx *)THREAD_ARG(thread); | |
f82370b4 CH |
678 | if (mgmt_msg_procbufs(&client_ctx->mstate, mgmt_fe_client_process_msg, |
679 | client_ctx, mgmt_debug_fe_client)) | |
680 | mgmt_fe_client_register_event(client_ctx, MGMTD_FE_PROC_MSG); | |
ef43a632 CH |
681 | } |
682 | ||
683 | static void mgmt_fe_client_read(struct thread *thread) | |
684 | { | |
685 | struct mgmt_fe_client_ctx *client_ctx; | |
f82370b4 | 686 | enum mgmt_msg_rsched rv; |
ef43a632 CH |
687 | |
688 | client_ctx = (struct mgmt_fe_client_ctx *)THREAD_ARG(thread); | |
ef43a632 | 689 | |
f82370b4 CH |
690 | rv = mgmt_msg_read(&client_ctx->mstate, client_ctx->conn_fd, |
691 | mgmt_debug_fe_client); | |
692 | if (rv == MSR_DISCONNECT) { | |
693 | mgmt_fe_server_disconnect(client_ctx, true); | |
694 | return; | |
ef43a632 | 695 | } |
f82370b4 CH |
696 | if (rv == MSR_SCHED_BOTH) |
697 | mgmt_fe_client_register_event(client_ctx, MGMTD_FE_PROC_MSG); | |
ef43a632 CH |
698 | mgmt_fe_client_register_event(client_ctx, MGMTD_FE_CONN_READ); |
699 | } | |
700 | ||
f82370b4 | 701 | static void mgmt_fe_server_connect(struct mgmt_fe_client_ctx *client_ctx) |
ef43a632 | 702 | { |
f82370b4 | 703 | const char *dbgtag = mgmt_debug_fe_client ? "FE-client" : NULL; |
ef43a632 | 704 | |
f82370b4 CH |
705 | assert(client_ctx->conn_fd == -1); |
706 | client_ctx->conn_fd = mgmt_msg_connect( | |
707 | MGMTD_FE_SERVER_PATH, MGMTD_SOCKET_FE_SEND_BUF_SIZE, | |
708 | MGMTD_SOCKET_FE_RECV_BUF_SIZE, dbgtag); | |
ef43a632 | 709 | |
f82370b4 CH |
710 | /* Send REGISTER_REQ message */ |
711 | if (client_ctx->conn_fd == -1 || | |
712 | mgmt_fe_send_register_req(client_ctx) != 0) { | |
713 | mgmt_fe_server_disconnect(client_ctx, true); | |
714 | return; | |
ef43a632 CH |
715 | } |
716 | ||
f82370b4 CH |
717 | /* Start reading from the socket */ |
718 | mgmt_fe_client_register_event(client_ctx, MGMTD_FE_CONN_READ); | |
ef43a632 CH |
719 | |
720 | /* Notify client through registered callback (if any) */ | |
721 | if (client_ctx->client_params.client_connect_notify) | |
722 | (void)(*client_ctx->client_params.client_connect_notify)( | |
723 | (uintptr_t)client_ctx, | |
724 | client_ctx->client_params.user_data, true); | |
ef43a632 CH |
725 | } |
726 | ||
f82370b4 | 727 | |
ef43a632 CH |
728 | static void mgmt_fe_client_conn_timeout(struct thread *thread) |
729 | { | |
f82370b4 | 730 | mgmt_fe_server_connect(THREAD_ARG(thread)); |
ef43a632 CH |
731 | } |
732 | ||
733 | static void | |
734 | mgmt_fe_client_register_event(struct mgmt_fe_client_ctx *client_ctx, | |
735 | enum mgmt_fe_event event) | |
736 | { | |
737 | struct timeval tv = {0}; | |
738 | ||
739 | switch (event) { | |
740 | case MGMTD_FE_CONN_READ: | |
741 | thread_add_read(client_ctx->tm, mgmt_fe_client_read, | |
742 | client_ctx, client_ctx->conn_fd, | |
743 | &client_ctx->conn_read_ev); | |
744 | assert(client_ctx->conn_read_ev); | |
745 | break; | |
746 | case MGMTD_FE_CONN_WRITE: | |
747 | thread_add_write(client_ctx->tm, mgmt_fe_client_write, | |
748 | client_ctx, client_ctx->conn_fd, | |
749 | &client_ctx->conn_write_ev); | |
750 | assert(client_ctx->conn_write_ev); | |
751 | break; | |
752 | case MGMTD_FE_PROC_MSG: | |
753 | tv.tv_usec = MGMTD_FE_MSG_PROC_DELAY_USEC; | |
754 | thread_add_timer_tv(client_ctx->tm, | |
755 | mgmt_fe_client_proc_msgbufs, client_ctx, | |
756 | &tv, &client_ctx->msg_proc_ev); | |
757 | assert(client_ctx->msg_proc_ev); | |
758 | break; | |
759 | case MGMTD_FE_CONN_WRITES_ON: | |
760 | thread_add_timer_msec( | |
761 | client_ctx->tm, mgmt_fe_client_resume_writes, | |
762 | client_ctx, MGMTD_FE_MSG_WRITE_DELAY_MSEC, | |
763 | &client_ctx->conn_writes_on); | |
764 | assert(client_ctx->conn_writes_on); | |
765 | break; | |
766 | case MGMTD_FE_SERVER: | |
767 | assert(!"mgmt_fe_client_ctx_post_event called incorrectly"); | |
768 | break; | |
769 | } | |
770 | } | |
771 | ||
772 | static void mgmt_fe_client_schedule_conn_retry( | |
773 | struct mgmt_fe_client_ctx *client_ctx, unsigned long intvl_secs) | |
774 | { | |
775 | MGMTD_FE_CLIENT_DBG( | |
776 | "Scheduling MGMTD Frontend server connection retry after %lu seconds", | |
777 | intvl_secs); | |
778 | thread_add_timer(client_ctx->tm, mgmt_fe_client_conn_timeout, | |
779 | (void *)client_ctx, intvl_secs, | |
780 | &client_ctx->conn_retry_tmr); | |
781 | } | |
782 | ||
783 | /* | |
784 | * Initialize library and try connecting with MGMTD. | |
785 | */ | |
786 | uintptr_t mgmt_fe_client_lib_init(struct mgmt_fe_client_params *params, | |
787 | struct thread_master *master_thread) | |
788 | { | |
789 | assert(master_thread && params && strlen(params->name) | |
790 | && !mgmt_fe_client_ctx.tm); | |
791 | ||
792 | mgmt_fe_client_ctx.tm = master_thread; | |
793 | memcpy(&mgmt_fe_client_ctx.client_params, params, | |
794 | sizeof(mgmt_fe_client_ctx.client_params)); | |
795 | if (!mgmt_fe_client_ctx.client_params.conn_retry_intvl_sec) | |
796 | mgmt_fe_client_ctx.client_params.conn_retry_intvl_sec = | |
797 | MGMTD_FE_DEFAULT_CONN_RETRY_INTVL_SEC; | |
798 | ||
f82370b4 CH |
799 | mgmt_msg_init(&mgmt_fe_client_ctx.mstate, MGMTD_FE_MAX_NUM_MSG_PROC, |
800 | MGMTD_FE_MAX_NUM_MSG_WRITE, MGMTD_FE_MSG_MAX_LEN, | |
801 | "FE-client"); | |
ef43a632 CH |
802 | |
803 | mgmt_sessions_init(&mgmt_fe_client_ctx.client_sessions); | |
804 | ||
805 | /* Start trying to connect to MGMTD frontend server immediately */ | |
806 | mgmt_fe_client_schedule_conn_retry(&mgmt_fe_client_ctx, 1); | |
807 | ||
808 | MGMTD_FE_CLIENT_DBG("Initialized client '%s'", params->name); | |
809 | ||
810 | return (uintptr_t)&mgmt_fe_client_ctx; | |
811 | } | |
812 | ||
813 | /* | |
814 | * Create a new Session for a Frontend Client connection. | |
815 | */ | |
816 | enum mgmt_result mgmt_fe_create_client_session(uintptr_t lib_hndl, | |
817 | uint64_t client_id, | |
818 | uintptr_t user_ctx) | |
819 | { | |
820 | struct mgmt_fe_client_ctx *client_ctx; | |
821 | struct mgmt_fe_client_session *session; | |
822 | ||
823 | client_ctx = (struct mgmt_fe_client_ctx *)lib_hndl; | |
824 | if (!client_ctx) | |
825 | return MGMTD_INVALID_PARAM; | |
826 | ||
827 | session = XCALLOC(MTYPE_MGMTD_FE_SESSION, | |
828 | sizeof(struct mgmt_fe_client_session)); | |
829 | assert(session); | |
830 | session->user_ctx = user_ctx; | |
831 | session->client_id = client_id; | |
832 | session->client_ctx = client_ctx; | |
833 | session->session_id = 0; | |
834 | ||
835 | if (mgmt_fe_send_session_req(client_ctx, session, true) != 0) { | |
836 | XFREE(MTYPE_MGMTD_FE_SESSION, session); | |
837 | return MGMTD_INTERNAL_ERROR; | |
838 | } | |
839 | mgmt_sessions_add_tail(&client_ctx->client_sessions, session); | |
840 | ||
841 | return MGMTD_SUCCESS; | |
842 | } | |
843 | ||
844 | /* | |
845 | * Delete an existing Session for a Frontend Client connection. | |
846 | */ | |
847 | enum mgmt_result mgmt_fe_destroy_client_session(uintptr_t lib_hndl, | |
848 | uint64_t client_id) | |
849 | { | |
850 | struct mgmt_fe_client_ctx *client_ctx; | |
851 | struct mgmt_fe_client_session *session; | |
852 | ||
853 | client_ctx = (struct mgmt_fe_client_ctx *)lib_hndl; | |
854 | if (!client_ctx) | |
855 | return MGMTD_INVALID_PARAM; | |
856 | ||
857 | session = mgmt_fe_find_session_by_client_id(client_ctx, client_id); | |
858 | if (!session || session->client_ctx != client_ctx) | |
859 | return MGMTD_INVALID_PARAM; | |
860 | ||
861 | if (session->session_id && | |
862 | mgmt_fe_send_session_req(client_ctx, session, false) != 0) | |
863 | MGMTD_FE_CLIENT_ERR( | |
864 | "Failed to send session destroy request for the session-id %lu", | |
865 | (unsigned long)session->session_id); | |
866 | ||
867 | mgmt_sessions_del(&client_ctx->client_sessions, session); | |
868 | XFREE(MTYPE_MGMTD_FE_SESSION, session); | |
869 | ||
870 | return MGMTD_SUCCESS; | |
871 | } | |
872 | ||
873 | static void mgmt_fe_destroy_client_sessions(uintptr_t lib_hndl) | |
874 | { | |
875 | struct mgmt_fe_client_ctx *client_ctx; | |
876 | struct mgmt_fe_client_session *session; | |
877 | ||
878 | client_ctx = (struct mgmt_fe_client_ctx *)lib_hndl; | |
879 | if (!client_ctx) | |
880 | return; | |
881 | ||
882 | FOREACH_SESSION_IN_LIST (client_ctx, session) | |
883 | mgmt_fe_destroy_client_session(lib_hndl, session->client_id); | |
884 | } | |
885 | ||
886 | /* | |
887 | * Send UN/LOCK_DS_REQ to MGMTD for a specific Datastore DS. | |
888 | */ | |
889 | enum mgmt_result mgmt_fe_lock_ds(uintptr_t lib_hndl, uintptr_t session_id, | |
890 | uint64_t req_id, Mgmtd__DatastoreId ds_id, | |
891 | bool lock_ds) | |
892 | { | |
893 | struct mgmt_fe_client_ctx *client_ctx; | |
894 | struct mgmt_fe_client_session *session; | |
895 | ||
896 | client_ctx = (struct mgmt_fe_client_ctx *)lib_hndl; | |
897 | if (!client_ctx) | |
898 | return MGMTD_INVALID_PARAM; | |
899 | ||
900 | session = (struct mgmt_fe_client_session *)session_id; | |
901 | if (!session || session->client_ctx != client_ctx) | |
902 | return MGMTD_INVALID_PARAM; | |
903 | ||
904 | if (mgmt_fe_send_lockds_req(client_ctx, session, lock_ds, req_id, | |
905 | ds_id) | |
906 | != 0) | |
907 | return MGMTD_INTERNAL_ERROR; | |
908 | ||
909 | return MGMTD_SUCCESS; | |
910 | } | |
911 | ||
912 | /* | |
913 | * Send SET_CONFIG_REQ to MGMTD for one or more config data(s). | |
914 | */ | |
915 | enum mgmt_result | |
916 | mgmt_fe_set_config_data(uintptr_t lib_hndl, uintptr_t session_id, | |
917 | uint64_t req_id, Mgmtd__DatastoreId ds_id, | |
918 | Mgmtd__YangCfgDataReq **config_req, int num_reqs, | |
919 | bool implicit_commit, Mgmtd__DatastoreId dst_ds_id) | |
920 | { | |
921 | struct mgmt_fe_client_ctx *client_ctx; | |
922 | struct mgmt_fe_client_session *session; | |
923 | ||
924 | client_ctx = (struct mgmt_fe_client_ctx *)lib_hndl; | |
925 | if (!client_ctx) | |
926 | return MGMTD_INVALID_PARAM; | |
927 | ||
928 | session = (struct mgmt_fe_client_session *)session_id; | |
929 | if (!session || session->client_ctx != client_ctx) | |
930 | return MGMTD_INVALID_PARAM; | |
931 | ||
932 | if (mgmt_fe_send_setcfg_req(client_ctx, session, req_id, ds_id, | |
933 | config_req, num_reqs, implicit_commit, | |
934 | dst_ds_id) | |
935 | != 0) | |
936 | return MGMTD_INTERNAL_ERROR; | |
937 | ||
938 | return MGMTD_SUCCESS; | |
939 | } | |
940 | ||
941 | /* | |
942 | * Send SET_CONFIG_REQ to MGMTD for one or more config data(s). | |
943 | */ | |
944 | enum mgmt_result mgmt_fe_commit_config_data(uintptr_t lib_hndl, | |
945 | uintptr_t session_id, | |
946 | uint64_t req_id, | |
947 | Mgmtd__DatastoreId src_ds_id, | |
948 | Mgmtd__DatastoreId dst_ds_id, | |
949 | bool validate_only, bool abort) | |
950 | { | |
951 | struct mgmt_fe_client_ctx *client_ctx; | |
952 | struct mgmt_fe_client_session *session; | |
953 | ||
954 | client_ctx = (struct mgmt_fe_client_ctx *)lib_hndl; | |
955 | if (!client_ctx) | |
956 | return MGMTD_INVALID_PARAM; | |
957 | ||
958 | session = (struct mgmt_fe_client_session *)session_id; | |
959 | if (!session || session->client_ctx != client_ctx) | |
960 | return MGMTD_INVALID_PARAM; | |
961 | ||
962 | if (mgmt_fe_send_commitcfg_req(client_ctx, session, req_id, src_ds_id, | |
963 | dst_ds_id, validate_only, abort) | |
964 | != 0) | |
965 | return MGMTD_INTERNAL_ERROR; | |
966 | ||
967 | return MGMTD_SUCCESS; | |
968 | } | |
969 | ||
970 | /* | |
971 | * Send GET_CONFIG_REQ to MGMTD for one or more config data item(s). | |
972 | */ | |
973 | enum mgmt_result | |
974 | mgmt_fe_get_config_data(uintptr_t lib_hndl, uintptr_t session_id, | |
975 | uint64_t req_id, Mgmtd__DatastoreId ds_id, | |
976 | Mgmtd__YangGetDataReq * data_req[], int num_reqs) | |
977 | { | |
978 | struct mgmt_fe_client_ctx *client_ctx; | |
979 | struct mgmt_fe_client_session *session; | |
980 | ||
981 | client_ctx = (struct mgmt_fe_client_ctx *)lib_hndl; | |
982 | if (!client_ctx) | |
983 | return MGMTD_INVALID_PARAM; | |
984 | ||
985 | session = (struct mgmt_fe_client_session *)session_id; | |
986 | if (!session || session->client_ctx != client_ctx) | |
987 | return MGMTD_INVALID_PARAM; | |
988 | ||
989 | if (mgmt_fe_send_getcfg_req(client_ctx, session, req_id, ds_id, | |
990 | data_req, num_reqs) | |
991 | != 0) | |
992 | return MGMTD_INTERNAL_ERROR; | |
993 | ||
994 | return MGMTD_SUCCESS; | |
995 | } | |
996 | ||
997 | /* | |
998 | * Send GET_DATA_REQ to MGMTD for one or more config data item(s). | |
999 | */ | |
1000 | enum mgmt_result mgmt_fe_get_data(uintptr_t lib_hndl, uintptr_t session_id, | |
1001 | uint64_t req_id, Mgmtd__DatastoreId ds_id, | |
1002 | Mgmtd__YangGetDataReq * data_req[], | |
1003 | int num_reqs) | |
1004 | { | |
1005 | struct mgmt_fe_client_ctx *client_ctx; | |
1006 | struct mgmt_fe_client_session *session; | |
1007 | ||
1008 | client_ctx = (struct mgmt_fe_client_ctx *)lib_hndl; | |
1009 | if (!client_ctx) | |
1010 | return MGMTD_INVALID_PARAM; | |
1011 | ||
1012 | session = (struct mgmt_fe_client_session *)session_id; | |
1013 | if (!session || session->client_ctx != client_ctx) | |
1014 | return MGMTD_INVALID_PARAM; | |
1015 | ||
1016 | if (mgmt_fe_send_getdata_req(client_ctx, session, req_id, ds_id, | |
1017 | data_req, num_reqs) | |
1018 | != 0) | |
1019 | return MGMTD_INTERNAL_ERROR; | |
1020 | ||
1021 | return MGMTD_SUCCESS; | |
1022 | } | |
1023 | ||
1024 | /* | |
1025 | * Send NOTIFY_REGISTER_REQ to MGMTD daemon. | |
1026 | */ | |
1027 | enum mgmt_result | |
1028 | mgmt_fe_register_yang_notify(uintptr_t lib_hndl, uintptr_t session_id, | |
1029 | uint64_t req_id, Mgmtd__DatastoreId ds_id, | |
1030 | bool register_req, | |
1031 | Mgmtd__YangDataXPath * data_req[], | |
1032 | int num_reqs) | |
1033 | { | |
1034 | struct mgmt_fe_client_ctx *client_ctx; | |
1035 | struct mgmt_fe_client_session *session; | |
1036 | ||
1037 | client_ctx = (struct mgmt_fe_client_ctx *)lib_hndl; | |
1038 | if (!client_ctx) | |
1039 | return MGMTD_INVALID_PARAM; | |
1040 | ||
1041 | session = (struct mgmt_fe_client_session *)session_id; | |
1042 | if (!session || session->client_ctx != client_ctx) | |
1043 | return MGMTD_INVALID_PARAM; | |
1044 | ||
1045 | if (mgmt_fe_send_regnotify_req(client_ctx, session, req_id, ds_id, | |
1046 | register_req, data_req, num_reqs) | |
1047 | != 0) | |
1048 | return MGMTD_INTERNAL_ERROR; | |
1049 | ||
1050 | return MGMTD_SUCCESS; | |
1051 | } | |
1052 | ||
1053 | /* | |
1054 | * Destroy library and cleanup everything. | |
1055 | */ | |
1056 | void mgmt_fe_client_lib_destroy(uintptr_t lib_hndl) | |
1057 | { | |
1058 | struct mgmt_fe_client_ctx *client_ctx; | |
1059 | ||
1060 | client_ctx = (struct mgmt_fe_client_ctx *)lib_hndl; | |
1061 | assert(client_ctx); | |
1062 | ||
1063 | MGMTD_FE_CLIENT_DBG("Destroying MGMTD Frontend Client '%s'", | |
1064 | client_ctx->client_params.name); | |
1065 | ||
1066 | mgmt_fe_server_disconnect(client_ctx, false); | |
1067 | ||
ef43a632 CH |
1068 | mgmt_fe_destroy_client_sessions(lib_hndl); |
1069 | ||
1070 | THREAD_OFF(client_ctx->conn_retry_tmr); | |
1071 | THREAD_OFF(client_ctx->conn_read_ev); | |
1072 | THREAD_OFF(client_ctx->conn_write_ev); | |
1073 | THREAD_OFF(client_ctx->conn_writes_on); | |
1074 | THREAD_OFF(client_ctx->msg_proc_ev); | |
f82370b4 | 1075 | mgmt_msg_destroy(&client_ctx->mstate); |
ef43a632 | 1076 | } |