Fix add/set/del failures with unified dm-services

This commit is contained in:
Suvendhu Hansa 2026-03-06 18:28:43 +05:30 committed by IOPSYS Dev
parent 8f66eefaf2
commit f309a94f82
No known key found for this signature in database
8 changed files with 261 additions and 71 deletions

View file

@ -61,6 +61,44 @@ static void service_request_timeout(struct uloop_timeout *timeout)
BBFDM_FREE(tracker);
}
static void service_result_callback(struct ubus_request *req __attribute__((unused)), int type __attribute__((unused)), struct blob_attr *msg)
{
if (!msg)
return;
struct blob_buf bb = {0};
bool uci_exist = false;
memset(&bb, 0, sizeof(struct blob_buf));
blob_buf_init(&bb, 0);
blobmsg_add_string(&bb, "proto", "both");
blobmsg_add_u8(&bb, "reload", false);
void *array = blobmsg_open_array(&bb, "services");
struct blob_attr *modified_uci = get_modified_uci_array(msg);
if (modified_uci) {
struct blob_attr *attr = NULL;
int remaining = 0;
blobmsg_for_each_attr(attr, modified_uci, remaining) {
char *file = blobmsg_get_string(attr);
if (file && strncmp(file, "/etc/bbfdm/dmmap/", 17) == 0) {
blobmsg_add_string(&bb, NULL, file);
uci_exist = true;
}
}
}
blobmsg_close_array(&bb, array);
if (uci_exist)
BBFDM_UBUS_INVOKE_SYNC("bbf.config", "commit", bb.head, 10000, NULL, NULL);
blob_buf_free(&bb);
}
static void service_request_complete(struct ubus_request *req, int ret)
{
struct service_request_tracker *tracker = container_of(req, struct service_request_tracker, async_request);
@ -120,6 +158,7 @@ static void verify_service(struct ubus_context *ubus_ctx, service_entry_t *servi
uloop_timeout_cancel(&tracker->timeout);
BBFDM_FREE(tracker);
} else {
tracker->async_request.data_cb = service_result_callback;
tracker->async_request.complete_cb = service_request_complete;
ubus_complete_request_async(ubus_ctx, &tracker->async_request);
}

View file

@ -70,6 +70,45 @@ static int bbfdm_ubus_invoke(const char *obj, const char *method, struct blob_at
return rc;
}
static void handle_uci_commit(const char *cmd, struct blob_attr *modified_uci, bool commit)
{
bool uci_exist = false;
if (modified_uci == NULL)
return;
struct blob_buf bb = {0};
memset(&bb, 0, sizeof(struct blob_buf));
blob_buf_init(&bb, 0);
blobmsg_add_string(&bb, "proto", "both");
if (strcmp(cmd, "get") == 0 || strcmp(cmd, "schema") == 0 ||
strcmp(cmd, "instances") == 0 || commit == false) {
blobmsg_add_u8(&bb, "reload", false);
} else {
blobmsg_add_u8(&bb, "reload", true);
}
void *array = blobmsg_open_array(&bb, "services");
struct blob_attr *attr = NULL;
int remaining = 0;
blobmsg_for_each_attr(attr, modified_uci, remaining) {
blobmsg_add_string(&bb, NULL, blobmsg_get_string(attr));
uci_exist = true;
}
blobmsg_close_array(&bb, array);
if (uci_exist)
BBFDM_UBUS_INVOKE_SYNC("bbf.config", commit ? "commit" : "revert", bb.head, 10000, NULL, NULL);
blob_buf_free(&bb);
}
static void __ubus_callback(struct ubus_request *req, int msgtype __attribute__((unused)), struct blob_attr *msg)
{
struct blob_attr *cur = NULL;
@ -89,14 +128,17 @@ static void __ubus_callback(struct ubus_request *req, int msgtype __attribute__(
cli_data_t *cli_data = (cli_data_t *)req->priv;
struct blob_attr *parameters = get_results_array(msg);
struct blob_attr *modified_uci = get_modified_uci_array(msg);
if (parameters == NULL) {
cli_data->ubus_status = false;
handle_uci_commit(cli_data->cmd, modified_uci, false);
return;
}
if (blobmsg_len(parameters) == 0) {
cli_data->ubus_status = true;
handle_uci_commit(cli_data->cmd, modified_uci, true);
return;
}
@ -111,6 +153,7 @@ static void __ubus_callback(struct ubus_request *req, int msgtype __attribute__(
if (tb[3]) {
printf("Fault %u: %s\n", blobmsg_get_u32(tb[3]), tb[6] ? blobmsg_get_string(tb[6]) : "");
cli_data->ubus_status = false;
handle_uci_commit(cli_data->cmd, modified_uci, false);
return;
}
@ -131,6 +174,8 @@ static void __ubus_callback(struct ubus_request *req, int msgtype __attribute__(
cli_data->ubus_status = true;
}
handle_uci_commit(cli_data->cmd, modified_uci, true);
}
static int cli_exec_cmd(cli_data_t *cli_data, const char *path, const char *value)

View file

@ -198,7 +198,7 @@ void run_sync_call(const char *ubus_obj, const char *ubus_method, struct blob_at
BBFDM_FREE(json_str);
}
BBFDM_UBUS_INVOKE_SYNC(ubus_obj, ubus_method, req_buf.head, 5000, sync_callback, bb_response);
BBFDM_UBUS_INVOKE_SYNC(ubus_obj, ubus_method, req_buf.head, 10000, sync_callback, bb_response);
blob_buf_free(&req_buf);
}

View file

@ -319,6 +319,11 @@ static void fill_from_services(json_object *services_arr, const char *source_nam
{
size_t _len = json_object_array_length(services_arr);
for (size_t _j = 0; _j < _len; _j++) {
if (*num_objs >= total_capacity) {
BBFDM_WARNING("Reached object capacity in %s", source_name);
break;
}
json_object *_svc = json_object_array_get_idx(services_arr, _j);
json_object *_pdm = NULL, *_obj = NULL, *_proto = NULL;
const char *_pdm_str, *_obj_str;
@ -343,10 +348,6 @@ static void fill_from_services(json_object *services_arr, const char *source_nam
objects[*num_objs].protocol = get_proto_type(_proto ? json_object_get_string(_proto) : "");
(*num_objs)++;
if (*num_objs >= total_capacity) {
BBFDM_WARNING("Reached object capacity in %s", source_name);
break;
}
}
}

View file

@ -167,6 +167,30 @@ static int plugin_obj_match(DMOBJECT_ARGS)
return FAULT_9005;
}
static int reference_obj_match(DMOBJECT_ARGS)
{
char skip_obj[][64] = { "Device.MQTT.", "Device.LocalAgent.", "Device.USPAgent.", "Device.STOMP." };
for (int i = 0; i < ARRAY_SIZE(skip_obj); i++) {
if (DM_STRSTR(node->current_object, skip_obj[i]) == node->current_object)
return FAULT_9005;
}
if (node->matched)
return 0;
if (!dmctx->inparam_isparam && DM_STRSTR(node->current_object, dmctx->in_param) == node->current_object) {
node->matched++;
dmctx->findparam = 1;
return 0;
}
if (DM_STRSTR(dmctx->in_param, node->current_object) == dmctx->in_param)
return 0;
return FAULT_9005;
}
static int plugin_leaf_match(DMOBJECT_ARGS)
{
if (node->matched)
@ -2483,14 +2507,14 @@ static int mparam_get_references_db(DMPARAM_ARGS)
if (node->is_instanceobj == 0)
return 0;
char full_param[MAX_DM_PATH] = {0};
char *value = dmstrdup("");
snprintf(full_param, sizeof(full_param), "%s%s", node->current_object, leaf->parameter);
(leaf->getvalue)(full_param, dmctx, data, instance, &value);
if (leaf->dm_flags & DM_FLAG_LINKER) {
char full_param[MAX_DM_PATH] = {0};
char *value = dmstrdup("");
snprintf(full_param, sizeof(full_param), "%s%s", node->current_object, leaf->parameter);
(leaf->getvalue)(full_param, dmctx, data, instance, &value);
add_path((struct list_head *)dmctx->addobj_instance, full_param, value);
}
@ -2507,7 +2531,7 @@ int dm_entry_references_db(struct dmctx *ctx)
ctx->inparam_isparam = 0;
ctx->findparam = 1;
ctx->stop = 0;
ctx->checkobj = NULL;
ctx->checkobj = reference_obj_match;
ctx->checkleaf = NULL;
ctx->method_obj = mobj_get_references_db;
ctx->method_param = mparam_get_references_db;

View file

@ -380,11 +380,6 @@ int bbfdm_set_handler(struct ubus_context *ctx, struct ubus_object *obj,
bbf_init(&data.bbf_ctx);
fault = bbfdm_set_value(&data);
if (data.bbf_ctx.dm_type == BBFDM_BOTH) {
bbf_entry_services(data.bbf_ctx.dm_type, (!fault) ? true : false, true);
}
bbf_cleanup(&data.bbf_ctx);
if (!fault) {
@ -496,10 +491,6 @@ int bbfdm_add_handler(struct ubus_context *ctx, struct ubus_object *obj,
}
end:
if (data.bbf_ctx.dm_type == BBFDM_BOTH) {
bbf_entry_services(data.bbf_ctx.dm_type, (!fault) ? true : false, true);
}
bbf_cleanup(&data.bbf_ctx);
if (!fault) {
@ -568,10 +559,6 @@ int bbfdm_del_handler(struct ubus_context *ctx, struct ubus_object *obj,
fault = create_del_response(&data);
if (data.bbf_ctx.dm_type == BBFDM_BOTH) {
bbf_entry_services(data.bbf_ctx.dm_type, (!fault) ? true : false, true);
}
bbf_cleanup(&data.bbf_ctx);
free_path_list(&paths_list);
@ -681,6 +668,15 @@ static int read_apply_handlers_config(const char *serv_config, bbfdm_config_t *c
return -1;
}
json_object *enable_jobj = NULL;
json_object_object_get_ex(daemon_config, "enable", &enable_jobj);
bool enable = enable_jobj ? json_object_get_boolean(enable_jobj) : false;
if (!enable) {
BBFDM_DEBUG("%s is disabled", serv_config);
json_object_put(json_root);
return 0;
}
if (suppress == true) {
json_object *unified_daemon = NULL;
@ -1078,6 +1074,18 @@ int bbfdm_print_data_model_schema(struct bbfdm_context *bbfdm_ctx, const enum bb
return err;
}
static void send_sync_completed(struct bbfdm_context *bbfdm_ctx)
{
struct blob_buf bb = {0};
memset(&bb, 0, sizeof(struct blob_buf));
blob_buf_init(&bb, 0);
blobmsg_add_string(&bb, "service", bbfdm_ctx->config.service_name);
ubus_send_event(bbfdm_ctx->ubus_ctx, "dmservice.sync_complete", bb.head);
blob_buf_free(&bb);
}
static void perform_uci_sync_op(struct bbfdm_context *bbfdm_ctx)
{
DM_MAP_OBJ *dynamic_obj = INTERNAL_ROOT_TREE;
@ -1123,8 +1131,10 @@ static void bbfdm_apply_event_cb(struct ubus_context *ctx __attribute__((unused)
struct blob_attr *tb[2] = {NULL, NULL};
blobmsg_parse(p, 2, tb, blob_data(msg), blob_len(msg));
if (!tb[0] || !tb[1])
if (!tb[0] || !tb[1]) {
send_sync_completed(bbfdm_ctx);
return;
}
const char *proto = blobmsg_get_string(tb[0]);
struct blob_attr *attr = NULL;
@ -1174,6 +1184,8 @@ static void bbfdm_apply_event_cb(struct ubus_context *ctx __attribute__((unused)
snprintf(bbfdm_ctx->uci_change_proto, sizeof(bbfdm_ctx->uci_change_proto), "%s", proto);
perform_uci_sync_op(bbfdm_ctx);
}
send_sync_completed(bbfdm_ctx);
}
static int register_bbfdm_apply_event(struct bbfdm_context *bbfdm_ctx)

View file

@ -19,27 +19,12 @@ void bbfdm_get(bbfdm_data_t *data, int method)
struct pathNode *pn = NULL;
int fault = 0;
LIST_HEAD(temp_list);
if (method == BBF_INSTANCES) {
// referesh reference db
struct dmctx bbf_ctx = {
.in_param = ROOT_NODE,
.dm_type = data->bbf_ctx.dm_type
};
bbf_init(&bbf_ctx);
bbfdm_cmd_exec(&bbf_ctx, BBF_REFERENCES_DB);
list_splice_tail_init(bbf_ctx.modified_uci_head, &temp_list);
bbf_cleanup(&bbf_ctx);
bbfdm_refresh_references(data->bbf_ctx.dm_type, NULL);
}
bbf_init(&data->bbf_ctx);
if (!list_empty(&temp_list)) {
list_splice_tail_init(&temp_list, data->bbf_ctx.modified_uci_head);
}
void *array = blobmsg_open_array(&data->bbf_ctx.bb, "results");
list_for_each_entry(pn, data->plist, list) {
@ -79,10 +64,5 @@ void bbfdm_get(bbfdm_data_t *data, int method)
ubus_send_reply(data->ctx, data->req, data->bbf_ctx.bb.head);
}
// Apply all bbfdm dmmap changes
if (data->bbf_ctx.dm_type == BBFDM_BOTH) {
dmuci_commit_bbfdm();
}
bbf_cleanup(&data->bbf_ctx);
}

View file

@ -58,6 +58,7 @@ struct bbf_config_async_req {
struct ubus_request_data req;
struct uloop_timeout timeout;
struct blob_attr *services;
struct ubus_event_handler sync_ev;
struct config_package package[MAX_PACKAGE_NUM];
struct list_head changed_uci_list;
};
@ -465,12 +466,12 @@ wait:
return false;
}
static void send_bbf_apply_event(int idx, struct list_head *changed_uci_list)
static int send_bbf_apply_event(int idx, struct list_head *changed_uci_list)
{
char protocol[16] = {0};
if (changed_uci_list == NULL || list_empty(changed_uci_list))
return;
return -1;
struct ubus_context *ctx;
struct blob_buf bb = {0};
@ -501,7 +502,7 @@ static void send_bbf_apply_event(int idx, struct list_head *changed_uci_list)
if (ctx == NULL) {
ULOG_ERR("Can't create UBUS context for 'bbfdm.apply' event");
blob_buf_free(&bb);
return;
return -1;
}
ULOG_INFO("Sending bbfdm.apply event");
@ -509,6 +510,8 @@ static void send_bbf_apply_event(int idx, struct list_head *changed_uci_list)
ubus_send_event(ctx, "bbfdm.apply", bb.head);
blob_buf_free(&bb);
ubus_free(ctx);
return 0;
}
static void send_reply(struct ubus_context *ctx, struct ubus_request_data *req, const char *message, const char *description)
@ -523,17 +526,111 @@ static void send_reply(struct ubus_context *ctx, struct ubus_request_data *req,
blob_buf_free(&bb);
}
static void complete_deferred_request(struct bbf_config_async_req *async_req)
static void sync_event_handler(struct ubus_context *ctx, struct ubus_event_handler *ev,
const char *type, struct blob_attr *msg)
{
if (!async_req)
if (msg == NULL || ev == NULL)
return;
struct bbf_config_async_req *async_req = container_of(ev, struct bbf_config_async_req, sync_ev);
if (async_req == NULL)
return;
// validate if the event received from core service
const struct blobmsg_policy p[1] = {
{ "service", BLOBMSG_TYPE_STRING }
};
struct blob_attr *tb[1] = {0};
if (blobmsg_parse(p, 1, tb, blob_data(msg), blob_len(msg)) != 0)
return;
if (!tb[0] || strcmp("core", blobmsg_get_string(tb[0])) != 0) {
return;
}
uloop_timeout_cancel(&(async_req->timeout));
// Send the response
send_reply(async_req->ctx, &async_req->req, "status", "ok");
// Complete the deferred request and send the response
ubus_complete_deferred_request(async_req->ctx, &async_req->req, 0);
ubus_unregister_event_handler(async_req->ctx, &(async_req->sync_ev));
// Free the allocated memory
FREE(async_req->services);
FREE(async_req);
ULOG_INFO("Commit handler exit");
}
static void sync_listen_timeout(struct uloop_timeout *timeout)
{
struct bbf_config_async_req *async_req = container_of(timeout, struct bbf_config_async_req, timeout);
if (async_req == NULL)
return;
ULOG_INFO("Timeout occurred for sync_complete event from core");
// Send the response
send_reply(async_req->ctx, &async_req->req, "status", "ok");
// Complete the deferred request and send the response
ubus_complete_deferred_request(async_req->ctx, &async_req->req, 0);
ubus_unregister_event_handler(async_req->ctx, &(async_req->sync_ev));
// Free the allocated memory
FREE(async_req->services);
FREE(async_req);
ULOG_INFO("Commit handler exit");
}
static void wait_for_sync_complete_event(struct bbf_config_async_req *async_req)
{
if (async_req == NULL)
return;
if (ubus_register_event_handler(async_req->ctx, &(async_req->sync_ev), "dmservice.sync_complete")) {
ULOG_ERR("Failed to register dmservice.sync_complete event handler");
// Send 'bbf.apply' event
send_bbf_apply_event(async_req->idx, &async_req->changed_uci_list);
goto exit;
}
uloop_timeout_set(&(async_req->timeout), 5000);
// Send 'bbf.apply' event
if (0 != send_bbf_apply_event(async_req->idx, &async_req->changed_uci_list)) {
uloop_timeout_cancel(&(async_req->timeout));
ubus_unregister_event_handler(async_req->ctx, &(async_req->sync_ev));
goto exit;
}
return;
exit:
// Send the response
send_reply(async_req->ctx, &async_req->req, "status", "ok");
// Complete the deferred request and send the response
ubus_complete_deferred_request(async_req->ctx, &async_req->req, 0);
// Free the allocated memory
FREE(async_req->services);
FREE(async_req);
ULOG_INFO("Commit handler exit");
}
static void complete_deferred_request(struct bbf_config_async_req *async_req)
{
if (!async_req)
return;
// If any uci is changed externally then add it in bbf.apply event
struct modi_uci_node *node = NULL, *tmp = NULL;
list_for_each_entry_safe(node, tmp, &g_external_changed_uci, list) {
@ -549,17 +646,14 @@ static void complete_deferred_request(struct bbf_config_async_req *async_req)
FREE(node);
}
// Send 'bbf.apply' event
send_bbf_apply_event(async_req->idx, &async_req->changed_uci_list);
// Free the allocated memory
FREE(async_req->services);
FREE(async_req);
// Lets wait for sync_complete from core
async_req->timeout.cb = sync_listen_timeout;
async_req->sync_ev.cb = sync_event_handler;
// Set internal commit to false
g_internal_commit = false;
ULOG_INFO("Commit handler exit");
wait_for_sync_complete_event(async_req);
}
static void end_request_callback(struct uloop_timeout *t)
@ -946,27 +1040,22 @@ static int bbf_config_commit_handler(struct ubus_context *ctx, struct ubus_objec
FREE(node);
}
if (monitor) {
if (monitor && reload) {
ULOG_INFO("Deferring request and setting up async completion");
async_req->idx = idx;
ubus_defer_request(ctx, req, &async_req->req);
async_req->timeout.cb = complete_request_callback;
uloop_timeout_set(&async_req->timeout, 2000);
} else {
ULOG_INFO("Sending immediate success response");
send_reply(ctx, req, "status", "ok");
// Send 'bbf.apply' event
send_bbf_apply_event(idx, changed_uci);
// Free the allocated memory
FREE(async_req->services);
FREE(async_req);
async_req->idx = idx;
ubus_defer_request(ctx, req, &async_req->req);
async_req->timeout.cb = sync_listen_timeout;
async_req->sync_ev.cb = sync_event_handler;
// Set internal commit to false
g_internal_commit = false;
ULOG_INFO("Commit handler exit");
wait_for_sync_complete_event(async_req);
}
return 0;