mirror of
https://dev.iopsys.eu/bbf/bbfdm.git
synced 2025-12-09 23:34:38 +01:00
Compare commits
3 commits
366e9a3799
...
d9a2ee6d2d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d9a2ee6d2d | ||
|
|
8f72146f0f | ||
|
|
bb85e2c7df |
7 changed files with 220 additions and 14 deletions
|
|
@ -25,6 +25,19 @@
|
|||
#include "get.h"
|
||||
#include "cli.h"
|
||||
|
||||
/* Policy for services method (optional filter by service name and framework flag) */
|
||||
enum services_attr {
|
||||
SERVICES_NAME,
|
||||
SERVICES_FRAMEWORK_ONLY,
|
||||
__SERVICES_MAX
|
||||
};
|
||||
|
||||
static const struct blobmsg_policy services_policy[] = {
|
||||
[SERVICES_NAME] = { .name = "name", .type = BLOBMSG_TYPE_STRING },
|
||||
[SERVICES_FRAMEWORK_ONLY] = { .name = "dmf_only", .type = BLOBMSG_TYPE_BOOL },
|
||||
};
|
||||
|
||||
|
||||
struct ubus_context g_ubus_ctx = {0};
|
||||
|
||||
extern struct list_head registered_services;
|
||||
|
|
@ -367,16 +380,31 @@ static int bbfdm_handler_sync(struct ubus_context *ctx, struct ubus_object *obj,
|
|||
}
|
||||
|
||||
static int bbfdm_services_handler(struct ubus_context *ctx, struct ubus_object *obj,
|
||||
struct ubus_request_data *req, const char *method, struct blob_attr *msg __attribute__((unused)))
|
||||
struct ubus_request_data *req, const char *method, struct blob_attr *msg __attribute__((unused)))
|
||||
{
|
||||
struct blob_buf bb;
|
||||
struct blob_attr *tb[__SERVICES_MAX] = {0};
|
||||
struct blob_buf bb = {0};
|
||||
|
||||
if (msg)
|
||||
blobmsg_parse(services_policy, __SERVICES_MAX, tb, blob_data(msg), blob_len(msg));
|
||||
|
||||
const char *filter_name = NULL;
|
||||
if (tb[SERVICES_NAME])
|
||||
filter_name = blobmsg_get_string(tb[SERVICES_NAME]);
|
||||
|
||||
bool framework_only = false;
|
||||
if (tb[SERVICES_FRAMEWORK_ONLY])
|
||||
framework_only = blobmsg_get_bool(tb[SERVICES_FRAMEWORK_ONLY]);
|
||||
|
||||
BBFDM_INFO("ubus method|%s|, name|%s|, filter|%s|, framework_only|%d|", method, obj->name, filter_name ? filter_name : "", framework_only);
|
||||
|
||||
|
||||
BBFDM_INFO("ubus method|%s|, name|%s|", method, obj->name);
|
||||
|
||||
memset(&bb, 0, sizeof(struct blob_buf));
|
||||
blob_buf_init(&bb, 0);
|
||||
|
||||
list_registered_services(&bb);
|
||||
list_registered_services(&bb, filter_name, framework_only);
|
||||
|
||||
ubus_send_reply(ctx, req, bb.head);
|
||||
blob_buf_free(&bb);
|
||||
|
|
@ -392,7 +420,7 @@ static struct ubus_method bbfdm_methods[] = {
|
|||
UBUS_METHOD("set", bbfdm_handler_sync, bbfdm_policy),
|
||||
UBUS_METHOD("add", bbfdm_handler_sync, bbfdm_policy),
|
||||
UBUS_METHOD("del", bbfdm_handler_sync, bbfdm_policy),
|
||||
UBUS_METHOD_NOARG("services", bbfdm_services_handler)
|
||||
UBUS_METHOD("services", bbfdm_services_handler, services_policy)
|
||||
};
|
||||
|
||||
static struct ubus_object_type bbfdm_object_type = UBUS_OBJECT_TYPE(BBFDM_UBUS_OBJECT, bbfdm_methods);
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
LIST_HEAD(registered_services);
|
||||
|
||||
static void add_service_to_list(const char *name, struct blob_buf *dm_schema, int service_proto, int service_timeout,
|
||||
service_object_t *objects, size_t count, bool is_unified)
|
||||
service_object_t *objects, size_t count, bool is_unified, bool dm_framework)
|
||||
{
|
||||
service_entry_t *service = NULL;
|
||||
|
||||
|
|
@ -47,6 +47,7 @@ static void add_service_to_list(const char *name, struct blob_buf *dm_schema, in
|
|||
service->objects = objects;
|
||||
service->object_count = count;
|
||||
service->is_unified = is_unified;
|
||||
service->dm_framework = dm_framework;
|
||||
}
|
||||
|
||||
static void receive_schema_result(struct ubus_request *req, int type __attribute__((unused)), struct blob_attr *msg)
|
||||
|
|
@ -153,9 +154,13 @@ static int load_service_from_file(struct ubus_context *ubus_ctx, const char *fil
|
|||
fill_service_schema(ubus_ctx, 2000, service_name, &service_schema);
|
||||
|
||||
json_object *unified_daemon_jobj = NULL;
|
||||
json_object *dm_framework_jobj = NULL;
|
||||
json_object_object_get_ex(daemon_config, "unified_daemon", &unified_daemon_jobj);
|
||||
bool is_unified = unified_daemon_jobj ? json_object_get_boolean(unified_daemon_jobj) : false;
|
||||
|
||||
json_object_object_get_ex(daemon_config, "dm-framework", &dm_framework_jobj);
|
||||
bool dm_framework = dm_framework_jobj ? json_object_get_boolean(dm_framework_jobj) : false;
|
||||
|
||||
json_object *proto_jobj = NULL;
|
||||
json_object_object_get_ex(daemon_config, "proto", &proto_jobj);
|
||||
int service_proto = get_proto_type(proto_jobj ? json_object_get_string(proto_jobj) : "");
|
||||
|
|
@ -204,8 +209,8 @@ static int load_service_from_file(struct ubus_context *ubus_ctx, const char *fil
|
|||
num_objs++;
|
||||
}
|
||||
|
||||
BBFDM_INFO("Registering [%s :: %lu :: %d]", service_name, num_objs, is_unified);
|
||||
add_service_to_list(service_name, service_schema, service_proto, service_timeout, objects, num_objs, is_unified);
|
||||
BBFDM_INFO("Registering [%s :: %lu :: %d :: %d]", service_name, num_objs, is_unified, dm_framework);
|
||||
add_service_to_list(service_name, service_schema, service_proto, service_timeout, objects, num_objs, is_unified, dm_framework);
|
||||
json_object_put(json_root);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -274,7 +279,7 @@ void unregister_services(void)
|
|||
}
|
||||
}
|
||||
|
||||
void list_registered_services(struct blob_buf *bb)
|
||||
void list_registered_services(struct blob_buf *bb, const char *filter_name, bool framework_only)
|
||||
{
|
||||
service_entry_t *service = NULL;
|
||||
|
||||
|
|
@ -284,6 +289,12 @@ void list_registered_services(struct blob_buf *bb)
|
|||
void *array = blobmsg_open_array(bb, "registered_services");
|
||||
|
||||
list_for_each_entry(service, ®istered_services, list) {
|
||||
if (filter_name && strlen(filter_name) > 0 && service->name && strcmp(filter_name, service->name) != 0)
|
||||
continue;
|
||||
|
||||
if (framework_only && !service->dm_framework)
|
||||
continue;
|
||||
|
||||
void *table = blobmsg_open_table(bb, NULL);
|
||||
|
||||
blobmsg_add_string(bb, "name", service->name ? service->name : "");
|
||||
|
|
@ -292,6 +303,7 @@ void list_registered_services(struct blob_buf *bb)
|
|||
service->protocol == BBFDMD_CWMP ? "cwmp" : "both");
|
||||
|
||||
blobmsg_add_u8(bb, "unified_daemon", service->is_unified);
|
||||
blobmsg_add_u8(bb, "dm_framework", service->dm_framework);
|
||||
blobmsg_add_u8(bb, "blacklisted", service->is_blacklisted);
|
||||
blobmsg_add_u32(bb, "timeout", service->timeout);
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ typedef struct service_entry {
|
|||
char *name;
|
||||
enum bbfdmd_type_enum protocol;
|
||||
bool is_unified;
|
||||
bool dm_framework; // Indicates if the service is managed by dm-framework
|
||||
size_t object_count;
|
||||
service_object_t *objects;
|
||||
int timeout; // Ubus timeout used to get data from lower layer
|
||||
|
|
@ -33,7 +34,7 @@ typedef struct service_entry {
|
|||
|
||||
int register_services(struct ubus_context *ctx);
|
||||
void unregister_services(void);
|
||||
void list_registered_services(struct blob_buf *bb);
|
||||
void list_registered_services(struct blob_buf *bb, const char *filter_name, bool framework_only);
|
||||
void fill_service_schema(struct ubus_context *ubus_ctx, int ubus_timeout, const char *service_name, struct blob_buf **service_schema);
|
||||
|
||||
bool service_path_match(const char *requested_path, unsigned int requested_proto, service_entry_t *service);
|
||||
|
|
|
|||
|
|
@ -728,7 +728,14 @@ struct uci_section *create_dmmap_obj(struct dmctx *dmctx, unsigned char instance
|
|||
|
||||
char *curr_instance = NULL;
|
||||
dmuci_get_value_by_section_string(s, "__instance__", &curr_instance);
|
||||
int curr_instance_int = (curr_instance && *curr_instance != '\0') ? DM_STRTOL(curr_instance) : 0;
|
||||
if (DM_STRLEN(curr_instance) == 0) {
|
||||
BBF_ERR("Found section without __instance__ in package: %s, section type: %s section name: %s. Deleting this entry",
|
||||
section_config(s), section_type(s), section_name(s));
|
||||
dmuci_delete_by_section(s, NULL, NULL);
|
||||
continue;
|
||||
}
|
||||
|
||||
int curr_instance_int = DM_STRTOL(curr_instance);
|
||||
if (curr_instance_int > max_instance)
|
||||
max_instance = curr_instance_int;
|
||||
|
||||
|
|
@ -751,19 +758,20 @@ struct uci_section *create_dmmap_obj(struct dmctx *dmctx, unsigned char instance
|
|||
char s_name[64] = {0};
|
||||
int pos = 0;
|
||||
|
||||
dmuci_add_section_bbfdm(obj_file, obj_name, &dmmap_section);
|
||||
|
||||
for (int i = 0; i < instance_level; i++) {
|
||||
dmuci_set_value_by_section(dmmap_section, dmctx->obj_buf[i], dmctx->inst_buf[i]);
|
||||
pos += snprintf(&s_name[pos], sizeof(s_name) - pos, "%s_%s", dmctx->obj_buf[i], dmctx->inst_buf[i]);
|
||||
}
|
||||
|
||||
snprintf(&s_name[pos], sizeof(s_name) - pos, "%s_%s", obj_name, *instance);
|
||||
|
||||
dmuci_rename_section_by_section(dmmap_section, s_name);
|
||||
dmuci_add_named_section_bbfdm(obj_file, obj_name, s_name, &dmmap_section);
|
||||
|
||||
dmuci_set_value_by_section(dmmap_section, "__section_name__", config_sec_name);
|
||||
dmuci_set_value_by_section(dmmap_section, "__instance__", *instance);
|
||||
|
||||
for (int i = 0; i < instance_level; i++) {
|
||||
dmuci_set_value_by_section(dmmap_section, dmctx->obj_buf[i], dmctx->inst_buf[i]);
|
||||
}
|
||||
}
|
||||
|
||||
dmctx->obj_buf[instance_level] = obj_name;
|
||||
|
|
@ -821,6 +829,14 @@ int generic_browse(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, ch
|
|||
char *config_sec_name = NULL;
|
||||
bool is_same_parent = true;
|
||||
|
||||
// skip instances which has no __instance__
|
||||
dmuci_get_value_by_section_string(curr_data.dmmap_section, "__instance__", &instance);
|
||||
if (DM_STRLEN(instance) == 0) {
|
||||
BBF_WARNING("Skipping object with no instance number in package: %s, section type: %s, section name: %s",
|
||||
section_config(curr_data.dmmap_section), section_type(curr_data.dmmap_section), section_name(curr_data.dmmap_section));
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int i = 0; i < parent_node->instance_level; i++) {
|
||||
char *curr_obj_inst = NULL;
|
||||
dmuci_get_value_by_section_string(curr_data.dmmap_section, dmctx->obj_buf[i], &curr_obj_inst);
|
||||
|
|
|
|||
|
|
@ -729,6 +729,7 @@ enum uci_oper_type {
|
|||
UCI_OP_DEL,
|
||||
UCI_OP_RENAME,
|
||||
UCI_OP_REORDER,
|
||||
UCI_OP_ADD_NAMED,
|
||||
__UCI_OP_MAX
|
||||
};
|
||||
|
||||
|
|
@ -761,6 +762,11 @@ static int __uci_perform_op(int operation, bbfdm_uci_op_data *op_data)
|
|||
if (uci_set(op_data->ucictx, &ptr) != UCI_OK)
|
||||
return -1;
|
||||
break;
|
||||
case UCI_OP_ADD_NAMED:
|
||||
if (uci_set(op_data->ucictx, &ptr) != UCI_OK || ptr.s == NULL)
|
||||
return -1;
|
||||
*op_data->s = ptr.s;
|
||||
break;
|
||||
case UCI_OP_ADD_LIST:
|
||||
if (uci_add_list(op_data->ucictx, &ptr) != UCI_OK)
|
||||
return -1;
|
||||
|
|
@ -850,6 +856,31 @@ int dmuci_add_section(const char *package, const char *stype, struct uci_section
|
|||
return __uci_perform_op(UCI_OP_ADD, &conf_data);
|
||||
}
|
||||
|
||||
int dmuci_add_named_section(const char *package, const char *stype, const char *name, struct uci_section **s)
|
||||
{
|
||||
char fname[128];
|
||||
bbfdm_uci_op_data conf_data = {0};
|
||||
|
||||
if (s == NULL)
|
||||
return -1;
|
||||
|
||||
snprintf(fname, sizeof(fname), "%s/%s", uci_ctx->confdir, package);
|
||||
|
||||
if (create_empty_file(fname))
|
||||
return -1;
|
||||
|
||||
*s = NULL;
|
||||
|
||||
conf_data.s = s;
|
||||
conf_data.ucictx = uci_ctx;
|
||||
conf_data.dmctx = get_bbfdm_global_dmctx();
|
||||
conf_data.package = package;
|
||||
conf_data.section = name;
|
||||
conf_data.value = stype;
|
||||
|
||||
return __uci_perform_op(UCI_OP_ADD_NAMED, &conf_data);
|
||||
}
|
||||
|
||||
/**** UCI DELETE by section pointer *****/
|
||||
int dmuci_delete_by_section(struct uci_section *s, const char *option, const char *value)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -219,6 +219,15 @@ int dmuci_add_section_##UCI_PATH(const char *package, const char *stype, struct
|
|||
uci_ctx = save_uci_ctx; \
|
||||
return res; \
|
||||
}\
|
||||
int dmuci_add_named_section_##UCI_PATH(const char *package, const char *stype, const char *name, struct uci_section **s)\
|
||||
{\
|
||||
struct uci_context *save_uci_ctx; \
|
||||
save_uci_ctx = uci_ctx; \
|
||||
uci_ctx = uci_ctx_##UCI_PATH; \
|
||||
int res = dmuci_add_named_section(package, stype, name, s); \
|
||||
uci_ctx = save_uci_ctx; \
|
||||
return res; \
|
||||
}\
|
||||
int dmuci_delete_##UCI_PATH(const char *package, const char *section, const char *option, const char *value) \
|
||||
{\
|
||||
struct uci_context *save_uci_ctx; \
|
||||
|
|
@ -312,6 +321,7 @@ int dmuci_set_value(const char *package, const char *section, const char *option
|
|||
int dmuci_add_list_value(const char *package, const char *section, const char *option, const char *value);
|
||||
int dmuci_del_list_value(const char *package, const char *section, const char *option, const char *value);
|
||||
int dmuci_add_section(const char *package, const char *stype, struct uci_section **s);
|
||||
int dmuci_add_named_section(const char *package, const char *stype, const char *name, struct uci_section **s);
|
||||
int dmuci_delete(const char *package, const char *section, const char *option, const char *value);
|
||||
int dmuci_rename_section(const char *package, const char *section, const char *value);
|
||||
int dmuci_get_value_by_section_string(struct uci_section *s, const char *option, char **value);
|
||||
|
|
@ -333,6 +343,7 @@ int dmuci_set_value_bbfdm(const char *package, const char *section, const char *
|
|||
int dmuci_set_value_by_section_bbfdm(struct uci_section *s, const char *option, const char *value);
|
||||
int dmuci_add_list_value_bbfdm(const char *package, const char *section, const char *option, const char *value);
|
||||
int dmuci_add_section_bbfdm(const char *package, const char *stype, struct uci_section **s);
|
||||
int dmuci_add_named_section_bbfdm(const char *package, const char *stype, const char *name, struct uci_section **s);
|
||||
int dmuci_delete_bbfdm(const char *package, const char *section, const char *option, const char *value);
|
||||
int dmuci_delete_by_section_unnamed_bbfdm(struct uci_section *s, const char *option, const char *value);
|
||||
int dmuci_delete_by_section_bbfdm(struct uci_section *s, const char *option, const char *value);
|
||||
|
|
|
|||
|
|
@ -19,6 +19,110 @@
|
|||
|
||||
#include "utils.h"
|
||||
|
||||
struct trans_ctx {
|
||||
struct ubus_context *ctx;
|
||||
const char *cmd; /* "commit" or "abort" */
|
||||
const char *proto; /* proto from commit/revert input */
|
||||
};
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* DM-framework service transaction helpers */
|
||||
/* ------------------------------------------------------------------ */
|
||||
static void invoke_service_transaction(struct ubus_context *ctx, const char *service_name,
|
||||
const char *cmd, const char *proto)
|
||||
{
|
||||
if (!ctx || !service_name || !cmd)
|
||||
return;
|
||||
|
||||
struct blob_buf bb = {0};
|
||||
|
||||
blob_buf_init(&bb, 0);
|
||||
blobmsg_add_string(&bb, "cmd", cmd);
|
||||
|
||||
if (proto && strlen(proto)) {
|
||||
void *tbl = blobmsg_open_table(&bb, "optional");
|
||||
blobmsg_add_string(&bb, "proto", proto);
|
||||
blobmsg_close_table(&bb, tbl);
|
||||
}
|
||||
|
||||
if (bbf_config_call(ctx, service_name, "transaction", &bb, NULL, NULL)) {
|
||||
ULOG_ERR("Failed '%s' transaction for service '%s'", cmd, service_name);
|
||||
} else {
|
||||
ULOG_INFO("Service '%s' transaction '%s' succeeded", service_name, cmd);
|
||||
}
|
||||
|
||||
blob_buf_free(&bb);
|
||||
}
|
||||
|
||||
/* Callback used when querying bbfdm 'services' */
|
||||
static void services_list_cb(struct ubus_request *req, int type __attribute__((unused)), struct blob_attr *msg)
|
||||
{
|
||||
struct trans_ctx *tctx = (struct trans_ctx *)req->priv;
|
||||
if (!tctx || !msg)
|
||||
return;
|
||||
|
||||
/* Expecting { "registered_services": [ {...}, ... ] } */
|
||||
struct blob_attr *rs_array = NULL;
|
||||
struct blob_attr *cur;
|
||||
int rem = blob_len(msg);
|
||||
|
||||
/* Find the array first */
|
||||
blob_for_each_attr(cur, msg, rem) {
|
||||
if (blobmsg_type(cur) == BLOBMSG_TYPE_ARRAY && strcmp(blobmsg_name(cur), "registered_services") == 0) {
|
||||
rs_array = cur;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!rs_array)
|
||||
return;
|
||||
|
||||
const struct blobmsg_policy pol[] = {
|
||||
{ "name", BLOBMSG_TYPE_STRING },
|
||||
{ "proto", BLOBMSG_TYPE_STRING },
|
||||
};
|
||||
|
||||
struct blob_attr *entry;
|
||||
blobmsg_for_each_attr(entry, rs_array, rem) {
|
||||
struct blob_attr *tb[2] = {0};
|
||||
blobmsg_parse(pol, 2, tb, blobmsg_data(entry), blobmsg_len(entry));
|
||||
|
||||
if (!tb[0])
|
||||
continue;
|
||||
|
||||
const char *sname = blobmsg_get_string(tb[0]);
|
||||
const char *proto = (tctx->proto) ? tctx->proto : "both";
|
||||
ULOG_ERR("Invoking service transaction for service: %s, cmd: %s, proto: %s", sname, tctx->cmd, proto);
|
||||
invoke_service_transaction(tctx->ctx, sname, tctx->cmd, proto);
|
||||
}
|
||||
}
|
||||
|
||||
static void trigger_dfm_service_transactions(struct ubus_context *ctx, const char *cmd, const char *proto)
|
||||
{
|
||||
if (!ctx || !cmd)
|
||||
return;
|
||||
|
||||
ULOG_ERR("Triggering dm-framework service transactions cmd: %s, proto: %s", cmd, proto);
|
||||
|
||||
struct blob_buf bb = {0};
|
||||
blob_buf_init(&bb, 0);
|
||||
blobmsg_add_u8(&bb, "dmf_only", true);
|
||||
|
||||
struct trans_ctx tctx = {
|
||||
.ctx = ctx,
|
||||
.cmd = cmd,
|
||||
.proto = proto,
|
||||
};
|
||||
|
||||
/* Query bbfdm -> services */
|
||||
if (bbf_config_call(ctx, "bbfdm", "services", &bb, services_list_cb, &tctx)) {
|
||||
ULOG_ERR("Failed to retrieve dm-framework services list from bbfdm");
|
||||
}
|
||||
|
||||
blob_buf_free(&bb);
|
||||
}
|
||||
|
||||
#define TIME_TO_WAIT_FOR_RELOAD 5
|
||||
#define MAX_PACKAGE_NUM 256
|
||||
#define MAX_SERVICE_NUM 16
|
||||
|
|
@ -703,6 +807,7 @@ static int bbf_config_commit_handler(struct ubus_context *ctx, struct ubus_objec
|
|||
#endif
|
||||
}
|
||||
|
||||
trigger_dfm_service_transactions(ctx, "commit", tb[SERVICES_PROTO] ? blobmsg_get_string(tb[SERVICES_PROTO]) : "both");
|
||||
struct blob_attr *services = tb[SERVICES_NAME];
|
||||
|
||||
size_t arr_len = (services) ? blobmsg_len(services) : 0;
|
||||
|
|
@ -802,6 +907,8 @@ static int bbf_config_revert_handler(struct ubus_context *ctx, struct ubus_objec
|
|||
ULOG_DEBUG("Protocol index determined as %d for protocol '%s'", idx, proto);
|
||||
}
|
||||
|
||||
trigger_dfm_service_transactions(ctx, "abort", tb[SERVICES_PROTO] ? blobmsg_get_string(tb[SERVICES_PROTO]) : "both");
|
||||
|
||||
struct blob_attr *services = tb[SERVICES_NAME];
|
||||
|
||||
size_t arr_len = (services) ? blobmsg_len(services) : 0;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue