From bd67afba66da0a9ed020c2dce81c7b826f75eebc Mon Sep 17 00:00:00 2001 From: Suvendhu Hansa Date: Fri, 20 Feb 2026 20:32:52 +0530 Subject: [PATCH] Optimize ram usage by combining dm-services --- bbfdmd/ubus/CMakeLists.txt | 4 + bbfdmd/ubus/bbfdmd.c | 8 + bbfdmd/ubus/service.c | 439 ++++++++++++++++++++++ bbfdmd/ubus/service.h | 1 + dm-service/dm_service.c | 24 +- libbbfdm-api/legacy/CMakeLists.txt | 5 + libbbfdm-api/legacy/dmbbf.h | 19 + libbbfdm-api/legacy/dmentry.c | 8 +- libbbfdm-api/legacy/dmentry.h | 4 +- libbbfdm-api/legacy/dmplugin.c | 10 +- libbbfdm-api/legacy/dmplugin.h | 6 +- libbbfdm-api/legacy/plugin/dotso_plugin.c | 46 ++- libbbfdm-api/legacy/plugin/dotso_plugin.h | 5 +- libbbfdm-ubus/bbfdm-ubus.c | 285 +++++++++++++- libbbfdm-ubus/bbfdm-ubus.h | 28 +- libbbfdm/CMakeLists.txt | 5 + libbbfdm/device.c | 3 + test/cmocka/functional_test_bbfd.c | 4 +- test/cmocka/unit_test_bbfd.c | 4 +- 19 files changed, 846 insertions(+), 62 deletions(-) diff --git a/bbfdmd/ubus/CMakeLists.txt b/bbfdmd/ubus/CMakeLists.txt index b3c0e8fb..555ba4ec 100644 --- a/bbfdmd/ubus/CMakeLists.txt +++ b/bbfdmd/ubus/CMakeLists.txt @@ -6,6 +6,10 @@ ADD_DEFINITIONS(-fstrict-aliasing -Wall -Wextra -Werror -Wformat -Wformat-signed SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -I${CMAKE_SOURCE_DIR}") +if (BBFDM_DM_SERVICE_RAM_OPTIMIZED) + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DBBFDM_DM_SERVICE_RAM_OPTIMIZED") +endif() + FILE(GLOB BBF_SOURCES *.c) ADD_EXECUTABLE(bbfdmd ${BBF_SOURCES}) TARGET_LINK_LIBRARIES(bbfdmd ubus ubox blobmsg_json json-c bbfdm-api-v2) diff --git a/bbfdmd/ubus/bbfdmd.c b/bbfdmd/ubus/bbfdmd.c index 7049cf56..e928e446 100644 --- a/bbfdmd/ubus/bbfdmd.c +++ b/bbfdmd/ubus/bbfdmd.c @@ -468,11 +468,19 @@ int main(int argc, char **argv) uloop_init(); ubus_add_uloop(&g_ubus_ctx); +#ifdef BBFDM_DM_SERVICE_RAM_OPTIMIZED + err = register_suppress_services(&g_ubus_ctx); + if (err) { + BBFDM_ERR("Failed to load micro-services"); + goto end; + } +#else err = register_services(&g_ubus_ctx); if (err) { BBFDM_ERR("Failed to load micro-services"); goto end; } +#endif err = ubus_add_object(&g_ubus_ctx, &bbfdm_object); if (err != UBUS_STATUS_OK) { diff --git a/bbfdmd/ubus/service.c b/bbfdmd/ubus/service.c index a914b654..423fd31f 100644 --- a/bbfdmd/ubus/service.c +++ b/bbfdmd/ubus/service.c @@ -229,6 +229,445 @@ static int compare(const struct dirent **a, const struct dirent **b) return strcasecmp((*a)->d_name, (*b)->d_name); // If lengths are equal, sort alphabetically } +typedef struct { + char **paths; + char **filenames; + size_t count; + size_t capacity; +} file_list_t; + +static int file_list_init(file_list_t *fl, size_t capacity) +{ + fl->paths = calloc(capacity, sizeof(char *)); + fl->filenames = calloc(capacity, sizeof(char *)); + if (!fl->paths || !fl->filenames) { + BBFDM_FREE(fl->paths); + BBFDM_FREE(fl->filenames); + return -1; + } + + fl->count = 0; + fl->capacity = capacity; + return 0; +} + +static int file_list_push(file_list_t *fl, const char *file_path, const char *filename) +{ + if (fl->count >= fl->capacity) { + BBFDM_ERR("file_list_push: capacity exhausted (%zu)", fl->capacity); + return -1; + } + + fl->paths[fl->count] = strdup(file_path); + fl->filenames[fl->count] = strdup(filename); + if (!fl->paths[fl->count] || !fl->filenames[fl->count]) { + BBFDM_FREE(fl->paths[fl->count]); + BBFDM_FREE(fl->filenames[fl->count]); + return -1; + } + + fl->count++; + return 0; +} + +static void file_list_free(file_list_t *fl) +{ + for (size_t i = 0; i < fl->count; i++) { + BBFDM_FREE(fl->paths[i]); + BBFDM_FREE(fl->filenames[i]); + } + + BBFDM_FREE(fl->paths); + BBFDM_FREE(fl->filenames); + memset(fl, 0, sizeof(*fl)); +} + +static bool peek_is_unified(const char *file_path) +{ + json_object *json_root = json_object_from_file(file_path); + if (!json_root) + return false; + + json_object *daemon_config = NULL; + json_object_object_get_ex(json_root, "daemon", &daemon_config); + if (!daemon_config) { + json_object_put(json_root); + return false; + } + + json_object *unified_jobj = NULL; + json_object_object_get_ex(daemon_config, "unified_daemon", &unified_jobj); + bool is_unified = unified_jobj ? json_object_get_boolean(unified_jobj) : false; + + json_object_put(json_root); + return is_unified; +} + +static void fill_from_services(json_object *services_arr, const char *source_name, service_object_t *objects, + size_t *num_objs, size_t total_capacity) +{ + size_t _len = json_object_array_length(services_arr); + for (size_t _j = 0; _j < _len; _j++) { + 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; + + json_object_object_get_ex(_svc, "parent_dm", &_pdm); + json_object_object_get_ex(_svc, "object", &_obj); + json_object_object_get_ex(_svc, "proto", &_proto); + + _pdm_str = _pdm ? json_object_get_string(_pdm) : ""; + _obj_str = _obj ? json_object_get_string(_obj) : ""; + + memset(objects[*num_objs].parent_path, 0, sizeof(objects[*num_objs].parent_path)); + memset(objects[*num_objs].object_name, 0, sizeof(objects[*num_objs].object_name)); + + strncpy(objects[*num_objs].parent_path, _pdm_str, sizeof(objects[*num_objs].parent_path) - 1); + strncpy(objects[*num_objs].object_name, _obj_str, sizeof(objects[*num_objs].object_name) - 1); + if (!strlen(objects[*num_objs].parent_path) || !strlen(objects[*num_objs].object_name)) { + BBFDM_WARNING("Skip empty parent_dm/object in %s", source_name); + continue; + } + + 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; + } + } +} + +static void load_non_unified_services(struct ubus_context *ubus_ctx, file_list_t *fl) +{ + if (fl->count == 0) + return; + + /* Locate core.json in the list and move it to index 0 */ + size_t core_idx = fl->count; + for (size_t i = 0; i < fl->count; i++) { + if (strcmp(fl->filenames[i], "core.json") == 0) { + core_idx = i; + break; + } + } + + if (core_idx == fl->count) { + BBFDM_ERR("core.json not found in non-unified service list – aborting"); + return; + } + + /* Swap core.json to position 0 so the loop below handles it first. */ + if (core_idx != 0) { + char *tmp_path = fl->paths[0]; + fl->paths[0] = fl->paths[core_idx]; + fl->paths[core_idx] = tmp_path; + + char *tmp_name = fl->filenames[0]; + fl->filenames[0] = fl->filenames[core_idx]; + fl->filenames[core_idx] = tmp_name; + } + + /* Load core.json – derive the shared service configuration */ + json_object *core_root = json_object_from_file(fl->paths[0]); + if (!core_root) { + BBFDM_ERR("Failed to read core.json: %s", fl->paths[0]); + return; + } + + json_object *core_daemon = NULL; + json_object_object_get_ex(core_root, "daemon", &core_daemon); + if (!core_daemon) { + BBFDM_ERR("core.json missing 'daemon' object"); + json_object_put(core_root); + return; + } + + json_object *enable_jobj = NULL; + json_object_object_get_ex(core_daemon, "enable", &enable_jobj); + bool enable = enable_jobj ? json_object_get_boolean(enable_jobj) : false; + if (!enable) { + BBFDM_INFO("core service is disabled, Skipping service"); + json_object_put(core_root); + return; + } + + /* Service name is derived from core.json's filename. */ + char service_name[MAX_PATH_LENGTH] = {0}; + const char *core_fname = fl->filenames[0]; + snprintf(service_name, sizeof(service_name), "%s.%.*s", BBFDM_UBUS_OBJECT, (int)(strlen(core_fname) - 5), core_fname); + + struct blob_buf *service_schema = NULL; + fill_service_schema(ubus_ctx, 2000, service_name, &service_schema); + + json_object *proto_jobj = NULL; + json_object_object_get_ex(core_daemon, "proto", &proto_jobj); + int service_proto = get_proto_type(proto_jobj ? json_object_get_string(proto_jobj) : ""); + + json_object *timeout_jobj = NULL; + json_object_object_get_ex(core_daemon, "timeout", &timeout_jobj); + int service_timeout = timeout_jobj ? json_object_get_int(timeout_jobj) : SERVICE_CALL_TIMEOUT; + + /* count the total number of service objects across + * core.json + all enabled peer files so we can allocate once. */ + size_t total_capacity = 0; + + /* Count objects in core.json's services array */ + json_object *core_services = NULL; + json_object_object_get_ex(core_daemon, "services", &core_services); + if (core_services && json_object_get_type(core_services) == json_type_array) + total_capacity += json_object_array_length(core_services); + + /* Count objects from every other enabled file */ + json_object **peer_roots = calloc(fl->count, sizeof(json_object *)); /* index 0 unused */ + if (!peer_roots) { + BBFDM_ERR("Failed to allocate peer_roots"); + json_object_put(core_root); + return; + } + + for (size_t i = 1; i < fl->count; i++) { + json_object *peer_root = json_object_from_file(fl->paths[i]); + if (!peer_root) { + BBFDM_WARNING("Failed to read JSON: %s – skipping", fl->paths[i]); + continue; + } + + json_object *peer_daemon = NULL; + json_object_object_get_ex(peer_root, "daemon", &peer_daemon); + if (!peer_daemon) { + json_object_put(peer_root); + continue; + } + + json_object *enable_jobj = NULL; + json_object_object_get_ex(peer_daemon, "enable", &enable_jobj); + bool enabled = enable_jobj ? json_object_get_boolean(enable_jobj) : false; + if (!enabled) { + BBFDM_INFO("Service '%s' is disabled – skipping", fl->filenames[i]); + json_object_put(peer_root); + continue; + } + + json_object *peer_services = NULL; + json_object_object_get_ex(peer_daemon, "services", &peer_services); + if (peer_services && json_object_get_type(peer_services) == json_type_array) + total_capacity += json_object_array_length(peer_services); + + peer_roots[i] = peer_root; /* retain for the fill pass below */ + } + + if (total_capacity == 0) { + BBFDM_WARNING("No service objects found across non-unified files – skipping"); + for (size_t i = 1; i < fl->count; i++) { + if (peer_roots[i]) + json_object_put(peer_roots[i]); + } + + BBFDM_FREE(peer_roots); + json_object_put(core_root); + return; + } + + service_object_t *objects = calloc(total_capacity, sizeof(service_object_t)); + if (!objects) { + BBFDM_ERR("Failed to allocate service objects"); + for (size_t i = 1; i < fl->count; i++) { + if (peer_roots[i]) + json_object_put(peer_roots[i]); + } + + BBFDM_FREE(peer_roots); + json_object_put(core_root); + return; + } + + /* fill the objects array */ + size_t num_objs = 0; + + /* core.json objects */ + if (core_services && json_object_get_type(core_services) == json_type_array) + fill_from_services(core_services, "core.json", objects, &num_objs, total_capacity); + + /* peer files */ + for (size_t i = 1; i < fl->count; i++) { + if (!peer_roots[i]) + continue; + + json_object *peer_daemon = NULL; + json_object_object_get_ex(peer_roots[i], "daemon", &peer_daemon); + + json_object *peer_services = NULL; + json_object_object_get_ex(peer_daemon, "services", &peer_services); + + if (peer_services && json_object_get_type(peer_services) == json_type_array) + fill_from_services(peer_services, fl->filenames[i], objects, &num_objs, total_capacity); + + json_object_put(peer_roots[i]); + } + + BBFDM_FREE(peer_roots); + json_object_put(core_root); + + /* Register the single merged service entry */ + BBFDM_INFO("Registering non-unified service [%s :: %zu objects]", service_name, num_objs); + add_service_to_list(service_name, service_schema, service_proto, service_timeout, objects, num_objs, false); +} + +static int load_unified_service(struct ubus_context *ubus_ctx, const char *filename, const char *file_path) +{ + size_t num_objs = 0; + + if (!filename || !file_path) { + BBFDM_ERR("Invalid filename or file path"); + return -1; + } + + json_object *json_root = json_object_from_file(file_path); + if (!json_root) { + BBFDM_ERR("Failed to read JSON file: %s", file_path); + return -1; + } + + json_object *daemon_config = NULL; + json_object_object_get_ex(json_root, "daemon", &daemon_config); + if (!daemon_config) { + BBFDM_ERR("Failed to find daemon object in: %s", file_path); + json_object_put(json_root); + 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_INFO("Unified service '%s' is disabled – skipping", filename); + json_object_put(json_root); + return -1; + } + + char service_name[MAX_PATH_LENGTH] = {0}; + snprintf(service_name, sizeof(service_name), "%s.%.*s", BBFDM_UBUS_OBJECT, (int)(strlen(filename) - 5), filename); + + struct blob_buf *service_schema = NULL; + fill_service_schema(ubus_ctx, 2000, service_name, &service_schema); + + 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) : ""); + + json_object *timeout_jobj = NULL; + json_object_object_get_ex(daemon_config, "timeout", &timeout_jobj); + int service_timeout = timeout_jobj ? json_object_get_int(timeout_jobj) : SERVICE_CALL_TIMEOUT; + + json_object *services_array = NULL; + if (!json_object_object_get_ex(daemon_config, "services", &services_array) || + json_object_get_type(services_array) != json_type_array) { + BBFDM_WARNING("No valid 'services' array in: %s", filename); + json_object_put(json_root); + return -1; + } + + size_t service_count = json_object_array_length(services_array); + if (service_count == 0) { + BBFDM_WARNING("Empty 'services' array in unified service '%s'", service_name); + json_object_put(json_root); + return -1; + } + + service_object_t *objects = calloc(service_count, sizeof(service_object_t)); + if (!objects) { + BBFDM_ERR("Failed to allocate memory"); + json_object_put(json_root); + return -1; + } + + for (size_t i = 0; i < service_count; i++) { + json_object *service_obj = json_object_array_get_idx(services_array, i); + json_object *parent_dm = NULL, *object = NULL, *proto = NULL; + + json_object_object_get_ex(service_obj, "parent_dm", &parent_dm); + json_object_object_get_ex(service_obj, "object", &object); + json_object_object_get_ex(service_obj, "proto", &proto); + + snprintf(objects[num_objs].parent_path, sizeof(objects[num_objs].parent_path), "%s", parent_dm ? json_object_get_string(parent_dm) : ""); + snprintf(objects[num_objs].object_name, sizeof(objects[num_objs].object_name), "%s", object ? json_object_get_string(object) : ""); + + if (!strlen(objects[num_objs].parent_path) || !strlen(objects[num_objs].object_name)) { + BBFDM_WARNING("Skip empty parent_dm/object in '%s'", service_name); + continue; + } + + objects[num_objs].protocol = get_proto_type(proto ? json_object_get_string(proto) : ""); + num_objs++; + } + + BBFDM_INFO("Registering unified service [%s :: %zu objects]", service_name, num_objs); + add_service_to_list(service_name, service_schema, service_proto, service_timeout, objects, num_objs, true); + + json_object_put(json_root); + return 0; +} + +int register_suppress_services(struct ubus_context *ubus_ctx) +{ + struct dirent **namelist = NULL; + file_list_t non_unified_list = {0}; + file_list_t unified_list = {0}; + + int num_files = scandir(BBFDM_MICROSERVICE_INPUT_PATH, &namelist, filter, compare); + if (num_files < 0) { + BBFDM_ERR("scandir failed on: %s", BBFDM_MICROSERVICE_INPUT_PATH); + return -1; + } + + if (file_list_init(&non_unified_list, (size_t)num_files) < 0 || file_list_init(&unified_list, (size_t)num_files) < 0) { + BBFDM_ERR("Failed to allocate categorisation lists"); + for (int i = 0; i < num_files; i++) + BBFDM_FREE(namelist[i]); + + BBFDM_FREE(namelist); + + file_list_free(&non_unified_list); + file_list_free(&unified_list); + return -1; + } + + /* categorise every valid JSON file */ + for (int i = 0; i < num_files; i++) { + char file_path[512] = {0}; + snprintf(file_path, sizeof(file_path), "%s/%s", BBFDM_MICROSERVICE_INPUT_PATH, namelist[i]->d_name); + + if (!bbfdm_file_exists(file_path) || !bbfdm_is_regular_file(file_path)) { + BBFDM_FREE(namelist[i]); + continue; + } + + bool is_unified = peek_is_unified(file_path); + file_list_t *target = is_unified ? &unified_list : &non_unified_list; + + if (file_list_push(target, file_path, namelist[i]->d_name) < 0) + BBFDM_ERR("Failed to push '%s' into categorisation list", namelist[i]->d_name); + + BBFDM_FREE(namelist[i]); + } + BBFDM_FREE(namelist); + + /* handle all non-unified files as a single merged service */ + load_non_unified_services(ubus_ctx, &non_unified_list); + + /* handle each unified file as its own independent service */ + for (size_t i = 0; i < unified_list.count; i++) { + if (load_unified_service(ubus_ctx, unified_list.filenames[i], unified_list.paths[i])) + BBFDM_ERR("Failed to load unified service: %s", unified_list.filenames[i]); + } + + file_list_free(&non_unified_list); + file_list_free(&unified_list); + return 0; +} + int register_services(struct ubus_context *ubus_ctx) { struct dirent **namelist; diff --git a/bbfdmd/ubus/service.h b/bbfdmd/ubus/service.h index 42530012..9278e04f 100644 --- a/bbfdmd/ubus/service.h +++ b/bbfdmd/ubus/service.h @@ -32,6 +32,7 @@ typedef struct service_entry { } service_entry_t; int register_services(struct ubus_context *ctx); +int register_suppress_services(struct ubus_context *ubus_ctx); void unregister_services(void); void list_registered_services(struct blob_buf *bb); void fill_service_schema(struct ubus_context *ubus_ctx, int ubus_timeout, const char *service_name, struct blob_buf **service_schema); diff --git a/dm-service/dm_service.c b/dm-service/dm_service.c index fa6375c9..2ae3321d 100644 --- a/dm-service/dm_service.c +++ b/dm-service/dm_service.c @@ -21,6 +21,7 @@ static void usage(char *prog) fprintf(stderr, " -m micro-service name\n"); fprintf(stderr, " -l log verbosity value as per standard syslog\n"); fprintf(stderr, " -d Display the schema data model supported by micro-service\n"); + fprintf(stderr, " -s Reduce memory usage of dm-services\n"); fprintf(stderr, " -h Display this help\n"); fprintf(stderr, "\n"); } @@ -31,10 +32,11 @@ int main(int argc, char **argv) char proc_name[64] = {0}; int log_level = LOG_ERR; int err = 0, ch, dm_type = 0; + bool suppress = false; memset(&bbfdm_ctx, 0, sizeof(struct bbfdm_context)); - while ((ch = getopt(argc, argv, "hdl:m:")) != -1) { + while ((ch = getopt(argc, argv, "hdsl:m:")) != -1) { switch (ch) { case 'm': bbfdm_ubus_set_service_name(&bbfdm_ctx, optarg); @@ -49,6 +51,9 @@ int main(int argc, char **argv) case 'd': dm_type++; break; + case 's': + suppress = true; + break; case 'h': usage(argv[0]); exit(0); @@ -63,7 +68,10 @@ int main(int argc, char **argv) } if (dm_type > 0) { - int res = bbfdm_print_data_model_schema(&bbfdm_ctx, dm_type); + int res = 0; + if (suppress == false) { + res = bbfdm_print_data_model_schema(&bbfdm_ctx, dm_type); + } exit(res); } openlog(bbfdm_ctx.config.service_name, LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1); @@ -71,9 +79,15 @@ int main(int argc, char **argv) bbfdm_ubus_set_log_level(log_level); bbfdm_ubus_load_data_model(NULL); - err = bbfdm_ubus_register_init(&bbfdm_ctx); - if (err != 0) - goto exit; + if (suppress == false) { + err = bbfdm_ubus_register_init(&bbfdm_ctx); + if (err != 0) + goto exit; + } else { + err = bbfdm_ubus_register_suppress_init(&bbfdm_ctx); + if (err != 0) + goto exit; + } // Create process name using service name and prefix "dm_" snprintf(proc_name, sizeof(proc_name), "dm_%s", bbfdm_ctx.config.service_name); diff --git a/libbbfdm-api/legacy/CMakeLists.txt b/libbbfdm-api/legacy/CMakeLists.txt index 6b96c4c2..6ef57bcd 100644 --- a/libbbfdm-api/legacy/CMakeLists.txt +++ b/libbbfdm-api/legacy/CMakeLists.txt @@ -40,3 +40,8 @@ FILE(GLOB libbbfdm-api_include_headers include/*.h) INSTALL(FILES ${libbbfdm-api_include_headers} DESTINATION usr/include ) + +FILE(GLOB libbbfdm-api_plugin_headers plugin/*.h) +INSTALL(FILES ${libbbfdm-api_plugin_headers} + DESTINATION usr/include/libbbfdm-api/legacy/plugin +) diff --git a/libbbfdm-api/legacy/dmbbf.h b/libbbfdm-api/legacy/dmbbf.h index e18ed115..48cd7dec 100644 --- a/libbbfdm-api/legacy/dmbbf.h +++ b/libbbfdm-api/legacy/dmbbf.h @@ -27,6 +27,25 @@ #include "dmmem.h" #include "dmapi.h" +typedef struct bbfdm_config { + struct list_head apply_handlers; + char service_name[32]; // Service name for micro-service identification + char in_name[128]; // Service plugin path + char in_plugin_dir[128]; // Service extra/internal plugin directory path + char out_name[128]; // Ubus name to use +} bbfdm_config_t; + +struct bbfdm_context { + bbfdm_config_t config; + struct ubus_event_handler apply_event; + struct ubus_context *ubus_ctx; + struct ubus_object ubus_obj; + struct list_head event_handlers; + struct list_head changed_uci; + bool internal_ubus_ctx; + char uci_change_proto[10]; +}; + int get_number_of_entries(struct dmctx *ctx, void *data, char *instance, int (*browseinstobj)(struct dmctx *ctx, struct dmnode *node, void *data, char *instance)); // To be removed later!!!!!!!!!!!! char *handle_instance(struct dmctx *dmctx, DMNODE *parent_node, struct uci_section *s, const char *inst_opt, const char *alias_opt); diff --git a/libbbfdm-api/legacy/dmentry.c b/libbbfdm-api/legacy/dmentry.c index 7cd0c889..65924dc4 100644 --- a/libbbfdm-api/legacy/dmentry.c +++ b/libbbfdm-api/legacy/dmentry.c @@ -243,18 +243,18 @@ int bbf_entry_method(struct dmctx *ctx, int cmd) return bbf_fault_map(ctx, fault); } -void bbf_global_init(DMOBJ *dm_entryobj, const char *plugin_path) +void bbf_global_init(DMOBJ *dm_entryobj, struct bbfdm_context *daemon_ctx, const char *plugin_path) { bbfdm_ensure_folder_exists(DATA_MODEL_DB_PATH); dm_dynamic_initmem(&global_memhead); dm_ubus_cache_init(); - load_plugins(dm_entryobj, plugin_path); + load_plugins(dm_entryobj, daemon_ctx, plugin_path); } -void bbf_global_clean(DMOBJ *dm_entryobj) +void bbf_global_clean(DMOBJ *dm_entryobj, struct bbfdm_context *daemon_ctx) { - free_plugins(dm_entryobj); + free_plugins(dm_entryobj, daemon_ctx); dm_ubus_cache_free(); dm_dynamic_cleanmem(&global_memhead); } diff --git a/libbbfdm-api/legacy/dmentry.h b/libbbfdm-api/legacy/dmentry.h index 1d5756b7..a5fc7e2f 100644 --- a/libbbfdm-api/legacy/dmentry.h +++ b/libbbfdm-api/legacy/dmentry.h @@ -25,8 +25,8 @@ int bbf_fault_map(struct dmctx *ctx, int fault); int bbf_entry_method(struct dmctx *ctx, int cmd); -void bbf_global_init(DMOBJ *dm_entryobj, const char *plugin_path); -void bbf_global_clean(DMOBJ *dm_entryobj); +void bbf_global_init(DMOBJ *dm_entryobj, struct bbfdm_context *daemon_ctx, const char *plugin_path); +void bbf_global_clean(DMOBJ *dm_entryobj, struct bbfdm_context *daemon_ctx); int dm_validate_allowed_objects(struct dmctx *ctx, struct dm_reference *reference, char *objects[]); diff --git a/libbbfdm-api/legacy/dmplugin.c b/libbbfdm-api/legacy/dmplugin.c index 212eabb5..7253368e 100644 --- a/libbbfdm-api/legacy/dmplugin.c +++ b/libbbfdm-api/legacy/dmplugin.c @@ -99,7 +99,7 @@ static void dm_check_dynamic_obj(struct list_head *mem_list, DMNODE *parent_node if (parent_node->obj) { if (parent_node->obj->nextdynamicobj) { - for (int i = 0; i < __INDX_DYNAMIC_MAX - 1; i++) { + for (int i = 0; i < __INDX_DYNAMIC_MAX; i++) { struct dm_dynamic_obj *next_dyn_array = parent_node->obj->nextdynamicobj + i; if (next_dyn_array->nextobj) { for (int j = 0; next_dyn_array->nextobj[j]; j++) { @@ -231,7 +231,7 @@ static int compare(const struct dirent **a, const struct dirent **b) return strcasecmp((*a)->d_name, (*b)->d_name); } -void load_plugins(DMOBJ *dm_entryobj, const char *plugin_path) +void load_plugins(DMOBJ *dm_entryobj, struct bbfdm_context *daemon_ctx, const char *plugin_path) { struct dirent **namelist; @@ -253,7 +253,7 @@ void load_plugins(DMOBJ *dm_entryobj, const char *plugin_path) if (DM_LSTRSTR(namelist[i]->d_name, ".json")) { load_json_plugins(dm_entryobj, file_path); } else if (DM_LSTRSTR(namelist[i]->d_name, ".so")) { - load_dotso_plugins(dm_entryobj, file_path); + load_dotso_plugins(dm_entryobj, daemon_ctx, file_path); } FREE(namelist[i]); @@ -262,10 +262,10 @@ void load_plugins(DMOBJ *dm_entryobj, const char *plugin_path) FREE(namelist); } -void free_plugins(DMOBJ *dm_entryobj) +void free_plugins(DMOBJ *dm_entryobj, struct bbfdm_context *daemon_ctx) { free_all_dynamic_nodes(dm_entryobj); free_json_plugins(); - free_dotso_plugins(); + free_dotso_plugins(daemon_ctx); } diff --git a/libbbfdm-api/legacy/dmplugin.h b/libbbfdm-api/legacy/dmplugin.h index 871a3378..7f1bba4b 100644 --- a/libbbfdm-api/legacy/dmplugin.h +++ b/libbbfdm-api/legacy/dmplugin.h @@ -11,6 +11,8 @@ #ifndef __DMPLUGIN_H__ #define __DMPLUGIN_H__ +#include "dmbbf.h" + DMOBJ *find_entry_obj(DMOBJ *entryobj, const char *obj_path); void disable_entry_obj(DMOBJ *entryobj, const char *obj_path, const char *parent_obj, const char *plugin_path); @@ -21,7 +23,7 @@ int get_entry_leaf_idx(DMLEAF *entryleaf); int get_obj_idx(DMOBJ **entryobj); int get_leaf_idx(DMLEAF **entryleaf); -void load_plugins(DMOBJ *dm_entryobj, const char *plugin_path); -void free_plugins(DMOBJ *dm_entryobj); +void load_plugins(DMOBJ *dm_entryobj, struct bbfdm_context *daemon_ctx, const char *plugin_path); +void free_plugins(DMOBJ *dm_entryobj, struct bbfdm_context *daemon_ctx); #endif //__DMPLUGIN_H__ diff --git a/libbbfdm-api/legacy/plugin/dotso_plugin.c b/libbbfdm-api/legacy/plugin/dotso_plugin.c index efed5582..e9ed5b9e 100644 --- a/libbbfdm-api/legacy/plugin/dotso_plugin.c +++ b/libbbfdm-api/legacy/plugin/dotso_plugin.c @@ -32,7 +32,7 @@ static void add_list_loaded_libraries(struct list_head *library_list, void *libr lib->library = library; } -static void free_all_list_open_library(struct list_head *library_list) +static void free_all_list_open_library(struct list_head *library_list, struct bbfdm_context *daemon_ctx) { struct loaded_library *lib = NULL, *tmp = NULL; @@ -40,6 +40,19 @@ static void free_all_list_open_library(struct list_head *library_list) list_del(&lib->list); if (lib->library) { + DM_MAP_OBJ *dynamic_obj = NULL; + + //Dynamic Object + *(void **) (&dynamic_obj) = dlsym(lib->library, "tDynamicObj"); + + if (dynamic_obj) { + // Clean module + for (int i = 0; dynamic_obj[i].path; i++) { + if (dynamic_obj[i].clean_module) + dynamic_obj[i].clean_module(daemon_ctx); + } + } + dlclose(lib->library); lib->library = NULL; } @@ -60,7 +73,7 @@ static void dotso_plugin_disable_requested_entries(DMOBJ *entryobj, DMOBJ *reque disable_entry_leaf(entryobj, requested_leaf->parameter, parent_obj, plugin_path); } -int load_dotso_plugins(DMOBJ *entryobj, const char *plugin_path) +int load_dotso_plugins(DMOBJ *entryobj, struct bbfdm_context *daemon_ctx, const char *plugin_path) { void *handle = dlopen(plugin_path, RTLD_NOW|RTLD_LOCAL); if (!handle) { @@ -130,15 +143,38 @@ int load_dotso_plugins(DMOBJ *entryobj, const char *plugin_path) } if (dynamic_obj[i].init_module) - dynamic_obj[i].init_module(NULL); + dynamic_obj[i].init_module(daemon_ctx); } add_list_loaded_libraries(&loaded_library_list, handle); return 0; } -int free_dotso_plugins(void) +int free_dotso_plugins(struct bbfdm_context *daemon_ctx) { - free_all_list_open_library(&loaded_library_list); + free_all_list_open_library(&loaded_library_list, daemon_ctx); return 0; } + +void perform_dotso_plugin_sync(struct bbfdm_context *bbfdm_ctx) +{ + struct loaded_library *lib = NULL; + struct list_head *library_list = &loaded_library_list; + + list_for_each_entry(lib, library_list, list) { + if (lib->library) { + DM_MAP_OBJ *dynamic_obj = NULL; + + //Dynamic Object + *(void **) (&dynamic_obj) = dlsym(lib->library, "tDynamicObj"); + + if (dynamic_obj) { + // Clean module + for (int i = 0; dynamic_obj[i].path; i++) { + if (dynamic_obj[i].uci_sync_handler) + dynamic_obj[i].uci_sync_handler(bbfdm_ctx); + } + } + } + } +} diff --git a/libbbfdm-api/legacy/plugin/dotso_plugin.h b/libbbfdm-api/legacy/plugin/dotso_plugin.h index 1c8fd6f2..6204851b 100644 --- a/libbbfdm-api/legacy/plugin/dotso_plugin.h +++ b/libbbfdm-api/legacy/plugin/dotso_plugin.h @@ -14,7 +14,8 @@ #include "../dmcommon.h" -int load_dotso_plugins(DMOBJ *entryobj, const char *path); -int free_dotso_plugins(void); +int load_dotso_plugins(DMOBJ *entryobj, struct bbfdm_context *daemon_ctx, const char *path); +int free_dotso_plugins(struct bbfdm_context *daemon_ctx); +void perform_dotso_plugin_sync(struct bbfdm_context *bbfdm_ctx); #endif //__DOTSO_PLUGIN_H__ diff --git a/libbbfdm-ubus/bbfdm-ubus.c b/libbbfdm-ubus/bbfdm-ubus.c index 54e42aa7..8730a26c 100644 --- a/libbbfdm-ubus/bbfdm-ubus.c +++ b/libbbfdm-ubus/bbfdm-ubus.c @@ -36,6 +36,7 @@ // Global variables static void *deamon_lib_handle = NULL; static uint8_t s_log_level = 0xff; +struct list_head supp_modules; static void bbfdm_ctx_init(struct bbfdm_context *bbfdm_ctx) { @@ -46,7 +47,7 @@ static void bbfdm_ctx_init(struct bbfdm_context *bbfdm_ctx) static void bbfdm_ctx_cleanup(struct bbfdm_context *u) { - bbf_global_clean(DEAMON_DM_ROOT_OBJ); + bbf_global_clean(DEAMON_DM_ROOT_OBJ, u); /* DotSo Plugin */ bbfdm_free_dotso_plugin(u, &deamon_lib_handle); @@ -659,21 +660,13 @@ static void free_changed_uci(struct bbfdm_context *bbfdm_ctx) } } -static int load_apply_handlers_from_file(bbfdm_config_t *config) +static int read_apply_handlers_config(const char *serv_config, bbfdm_config_t *config, bool suppress) { - char serv_config[MAX_DM_PATH] = {0}; - - if (config == NULL) { - BBF_ERR("bbfdm_config is null"); + if (DM_STRLEN(serv_config) == 0) { + BBF_ERR("No json file name received"); return -1; } - snprintf(serv_config, sizeof(serv_config), "%s/%s.json", BBFDM_SERVICE_CONFIG_PATH, config->service_name); - if (!bbfdm_file_exists(serv_config) || !bbfdm_is_regular_file(serv_config)) { - BBF_ERR("Config file %s not exists for service %s", serv_config, config->service_name); - return 0; - } - json_object *json_root = json_object_from_file(serv_config); if (!json_root) { BBF_ERR("Failed to read json file %s", serv_config); @@ -688,6 +681,56 @@ static int load_apply_handlers_from_file(bbfdm_config_t *config) return -1; } + if (suppress == true) { + json_object *unified_daemon = NULL; + + json_object_object_get_ex(daemon_config, "unified_daemon", &unified_daemon); + if (!unified_daemon) { + json_object_put(json_root); + return 0; + } + + bool is_unified = json_object_get_boolean(unified_daemon); + if (is_unified == true) { + json_object_put(json_root); + return 0; + } else { + char *tmp = strrchr(serv_config, '/'); + if (tmp == NULL) { + BBFDM_ERR("Failed to extract service name for %s", serv_config); + json_object_put(json_root); + return 0; + } + + char *serv = tmp + 1; + char serv_name[64] = {0}; + + snprintf(serv_name, sizeof(serv_name), "%s", serv); + + int len = strlen(serv_name); + tmp = serv_name + len - 5; + if (strcmp(tmp, ".json") != 0) { + BBFDM_ERR("Service file %s is not ending with .json", serv_config); + json_object_put(json_root); + return 0; + } + + *tmp = '\0'; + + // store this service name + struct supp_module_node *supp_node = (struct supp_module_node *)calloc(1, sizeof(struct supp_module_node)); + if (supp_node == NULL) { + BBFDM_ERR("Failed to allocate memory for service file %s", serv_config); + json_object_put(json_root); + return 0; + } + + INIT_LIST_HEAD(&supp_node->list); + list_add_tail(&supp_node->list, &supp_modules); + supp_node->service = strdup(serv_name); + } + } + json_object *apply_handler = NULL; json_object_object_get_ex(daemon_config, "apply_handler", &apply_handler); if (!apply_handler) { @@ -756,6 +799,60 @@ static int load_apply_handlers_from_file(bbfdm_config_t *config) return 0; } +static int load_apply_handlers_from_file(bbfdm_config_t *config, bool suppress) +{ + char serv_config[MAX_DM_PATH] = {0}; + + if (config == NULL) { + BBF_ERR("bbfdm_config is null"); + return -1; + } + + snprintf(serv_config, sizeof(serv_config), "%s/%s.json", BBFDM_SERVICE_CONFIG_PATH, config->service_name); + if (!bbfdm_file_exists(serv_config) || !bbfdm_is_regular_file(serv_config)) { + BBF_ERR("Config file %s not exists for service %s", serv_config, config->service_name); + return -1; + } + + if (read_apply_handlers_config(serv_config, config, suppress) != 0) { + BBF_ERR("Failed to read apply handlers for service file %s", serv_config); + return -1; + } + + if (suppress == true) { + DIR *dir; + struct dirent *entry; + + dir = opendir(BBFDM_SERVICE_CONFIG_PATH); + if (!dir) { + BBF_ERR("Failed to open service directory %s", BBFDM_SERVICE_CONFIG_PATH); + return -1; + } + + while ((entry = readdir(dir)) != NULL) { + /* Match only regular files ending in .json */ + char plug_config[MAX_DM_PATH] = {0}; + + size_t len = strlen(entry->d_name); + if (len < 5 || strcmp(entry->d_name + len - 5, ".json") != 0) + continue; + + snprintf(plug_config, sizeof(plug_config), "%s/%s", BBFDM_SERVICE_CONFIG_PATH, entry->d_name); + if (!bbfdm_is_regular_file(plug_config) || DM_STRCMP(serv_config, plug_config) == 0) + continue; + + if (read_apply_handlers_config(plug_config, config, suppress) != 0) { + BBF_ERR("Failed to read apply handlers for service file %s", plug_config); + closedir(dir); + return -1; + } + } + + closedir(dir); + } + return 0; +} + static int load_micro_service_config(bbfdm_config_t *config) { char opt_val[MAX_DM_PATH] = {0}; @@ -765,7 +862,7 @@ static int load_micro_service_config(bbfdm_config_t *config) return -1; } - if (load_apply_handlers_from_file(config) != 0) { + if (load_apply_handlers_from_file(config, false) != 0) { BBF_ERR("Failed to load handlers from service file"); return -1; } @@ -794,6 +891,103 @@ static int load_micro_service_config(bbfdm_config_t *config) return 0; } +static int load_micro_service_suppress_config(bbfdm_config_t *config) +{ + char opt_val[MAX_DM_PATH] = {0}; + + if (!config || strlen(config->service_name) == 0) { + BBF_ERR("Invalid input options for service name"); + return -1; + } + + if (load_apply_handlers_from_file(config, true) != 0) { + BBF_ERR("Failed to load handlers from service file"); + return -1; + } + + if (INTERNAL_ROOT_TREE == NULL) { + // This API will only be called with micro-services started with '-m' option + + snprintf(opt_val, MAX_DM_PATH, "%s/%s.so", BBFDM_DEFAULT_MICROSERVICE_MODULE_PATH, config->service_name); + if (!file_exists(opt_val)) { + snprintf(opt_val, MAX_DM_PATH, "%s/%s.json", BBFDM_DEFAULT_MICROSERVICE_MODULE_PATH, config->service_name); + } + + if (!file_exists(opt_val)) { + BBF_ERR("Failed to load service plugin %s opt_val=%s", config->service_name, opt_val); + return -1; + } + + strncpyt(config->in_name, opt_val, sizeof(config->in_name)); + } + + snprintf(opt_val, MAX_DM_PATH, "%s/%s", BBFDM_DEFAULT_MICROSERVICE_MODULE_PATH, config->service_name); + if (folder_exists(opt_val)) { + strncpyt(config->in_plugin_dir, opt_val, sizeof(config->in_plugin_dir)); + } + + return 0; +} + +static int load_micro_service_suppress_data_model(struct bbfdm_context *daemon_ctx) +{ + int err = 0; + + if (INTERNAL_ROOT_TREE) { + BBF_INFO("Loading Data Model Internal plugin (%s)", daemon_ctx->config.service_name); + err = bbfdm_load_internal_plugin(daemon_ctx, INTERNAL_ROOT_TREE, &DEAMON_DM_ROOT_OBJ); + } else { + BBF_INFO("Loading Data Model External plugin (%s)", daemon_ctx->config.service_name); + err = bbfdm_load_external_plugin(daemon_ctx, &deamon_lib_handle, &DEAMON_DM_ROOT_OBJ); + } + + if (err) + return err; + + BBF_INFO("Loading sub-modules %s", daemon_ctx->config.in_plugin_dir); + bbf_global_init(DEAMON_DM_ROOT_OBJ, daemon_ctx, daemon_ctx->config.in_plugin_dir); + + // Load suppressed dm + struct supp_module_node *node = NULL; + list_for_each_entry(node, &supp_modules, list) { + if (DM_STRCMP(daemon_ctx->config.service_name, node->service) == 0) { + // Base service dmtree is already loaded so skip it + continue; + } + + char opt_val[MAX_DM_PATH] = {0}; + + snprintf(opt_val, MAX_DM_PATH, "%s/%s.so", BBFDM_DEFAULT_MICROSERVICE_MODULE_PATH, node->service); + if (!file_exists(opt_val)) { + snprintf(opt_val, MAX_DM_PATH, "%s/%s.json", BBFDM_DEFAULT_MICROSERVICE_MODULE_PATH, node->service); + } + + if (!file_exists(opt_val)) { + BBF_ERR("Failed to load service plugin %s opt_val=%s", node->service, opt_val); + continue; + } + + if (DM_LSTRSTR(opt_val, ".json")) { + load_json_plugins(DEAMON_DM_ROOT_OBJ, opt_val); + } else if (DM_LSTRSTR(opt_val, ".so")) { + load_dotso_plugins(DEAMON_DM_ROOT_OBJ, daemon_ctx, opt_val); + } + + char supp_plug_dir[MAX_DM_PATH] = {0}; + snprintf(supp_plug_dir, MAX_DM_PATH, "%s/%s", BBFDM_DEFAULT_MICROSERVICE_MODULE_PATH, node->service); + if (folder_exists(supp_plug_dir)) { + load_plugins(DEAMON_DM_ROOT_OBJ, daemon_ctx, supp_plug_dir); + } + } + + if (DM_STRLEN(daemon_ctx->config.out_name) == 0) { + BBF_ERR("output name not defined"); + return -1; + } + + return 0; +} + static int load_micro_service_data_model(struct bbfdm_context *daemon_ctx) { int err = 0; @@ -810,7 +1004,7 @@ static int load_micro_service_data_model(struct bbfdm_context *daemon_ctx) return err; BBF_INFO("Loading sub-modules %s", daemon_ctx->config.in_plugin_dir); - bbf_global_init(DEAMON_DM_ROOT_OBJ, daemon_ctx->config.in_plugin_dir); + bbf_global_init(DEAMON_DM_ROOT_OBJ, daemon_ctx, daemon_ctx->config.in_plugin_dir); if (DM_STRLEN(daemon_ctx->config.out_name) == 0) { BBF_ERR("output name not defined"); @@ -897,6 +1091,9 @@ static void perform_uci_sync_op(struct bbfdm_context *bbfdm_ctx) } } + // Now execute sync handlers of loaded plugins + perform_dotso_plugin_sync(bbfdm_ctx); + free_changed_uci(bbfdm_ctx); if (bbfdm_refresh_references(BBFDM_BOTH, bbfdm_ctx->config.out_name)) { @@ -1056,6 +1253,66 @@ int bbfdm_ubus_register_init(struct bbfdm_context *bbfdm_ctx) return register_events_to_ubus(bbfdm_ctx->ubus_ctx, &bbfdm_ctx->event_handlers); } +int bbfdm_ubus_register_suppress_init(struct bbfdm_context *bbfdm_ctx) +{ + int err = 0; + + // Set the logmask with default, if not already set by api + if (s_log_level == 0xff) { + BBF_INFO("Log level not set, setting default value %d", LOG_ERR); + bbfdm_ubus_set_log_level(LOG_ERR); + } + + if (bbfdm_ctx->ubus_ctx == NULL) { + err = bbfdm_ubus_init(bbfdm_ctx); + if (err) { + BBF_ERR("Failed to initialize ubus_ctx internally"); + return err; + } + } + + bbfdm_ctx_init(bbfdm_ctx); + + INIT_LIST_HEAD(&supp_modules); + + err = load_micro_service_suppress_config(&bbfdm_ctx->config); + if (err) { + BBF_ERR("Failed to load micro-service config"); + return err; + } + + err = load_micro_service_suppress_data_model(bbfdm_ctx); + if (err) { + BBF_ERR("Failed to load micro-service data model"); + return err; + } + + struct supp_module_node *node = NULL, *tmp = NULL; + list_for_each_entry_safe(node, tmp, &supp_modules, list) { + list_del(&node->list); + BBFDM_FREE(node->service); + BBFDM_FREE(node); + } + + err = regiter_ubus_object(bbfdm_ctx); + if (err != UBUS_STATUS_OK) + return -1; + + err = bbfdm_refresh_references(BBFDM_BOTH, bbfdm_ctx->config.out_name); + if (err) { + BBF_ERR("Failed to refresh instance data base"); + return -1; + } + + err = register_bbfdm_apply_event(bbfdm_ctx); + if (err) { + BBF_ERR("Failed to register bbfdm apply event"); + return -1; + } + + return register_events_to_ubus(bbfdm_ctx->ubus_ctx, &bbfdm_ctx->event_handlers); +} + int bbfdm_ubus_register_free(struct bbfdm_context *bbfdm_ctx) { if (bbfdm_ctx->ubus_ctx) { diff --git a/libbbfdm-ubus/bbfdm-ubus.h b/libbbfdm-ubus/bbfdm-ubus.h index 8ddc1f0b..b2b0fc57 100644 --- a/libbbfdm-ubus/bbfdm-ubus.h +++ b/libbbfdm-ubus/bbfdm-ubus.h @@ -6,9 +6,17 @@ #include #include "libbbfdm-api/legacy/dmbbf.h" +#include "libbbfdm-api/legacy/dmplugin.h" +#include "libbbfdm-api/legacy/plugin/json_plugin.h" +#include "libbbfdm-api/legacy/plugin/dotso_plugin.h" #define BBFDM_DEFAULT_UBUS_OBJ "bbfdm" +struct supp_module_node { + char *service; + struct list_head list; +}; + struct bbfdm_async_req { struct ubus_context *ctx; struct ubus_request_data req; @@ -21,25 +29,6 @@ struct apply_handler_node { struct list_head list; }; -typedef struct bbfdm_config { - struct list_head apply_handlers; - char service_name[32]; // Service name for micro-service identification - char in_name[128]; // Service plugin path - char in_plugin_dir[128]; // Service extra/internal plugin directory path - char out_name[128]; // Ubus name to use -} bbfdm_config_t; - -struct bbfdm_context { - bbfdm_config_t config; - struct ubus_event_handler apply_event; - struct ubus_context *ubus_ctx; - struct ubus_object ubus_obj; - struct list_head event_handlers; - struct list_head changed_uci; - bool internal_ubus_ctx; - char uci_change_proto[10]; -}; - typedef struct bbfdm_data { struct ubus_context *ctx; struct ubus_object *obj; @@ -50,6 +39,7 @@ typedef struct bbfdm_data { } bbfdm_data_t; int bbfdm_ubus_register_init(struct bbfdm_context *bbfdm_ctx); +int bbfdm_ubus_register_suppress_init(struct bbfdm_context *bbfdm_ctx); int bbfdm_ubus_register_free(struct bbfdm_context *bbfdm_ctx); __attribute__((deprecated("Use bbfdm_ubus_register_init() instead of bbfdm_ubus_regiter_init()"))) diff --git a/libbbfdm/CMakeLists.txt b/libbbfdm/CMakeLists.txt index c2c7fbad..ba4abc0a 100644 --- a/libbbfdm/CMakeLists.txt +++ b/libbbfdm/CMakeLists.txt @@ -5,6 +5,11 @@ PROJECT(libbbfdm) ADD_DEFINITIONS(-Wall -Werror -g3 -D_GNU_SOURCE -DBBF_VENDOR_PREFIX="${BBF_VENDOR_PREFIX}") SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -I${CMAKE_SOURCE_DIR} -I${CMAKE_CURRENT_SOURCE_DIR} -I${CMAKE_SOURCE_DIR}/libbbfdm-api/version-2") + +if (BBFDM_DM_SERVICE_RAM_OPTIMIZED) + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DBBFDM_DM_SERVICE_RAM_OPTIMIZED") +endif() + FILE(GLOB BBF_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.c) ADD_LIBRARY(core SHARED ${BBF_SOURCES}) diff --git a/libbbfdm/device.c b/libbbfdm/device.c index fc898b64..8d062089 100644 --- a/libbbfdm/device.c +++ b/libbbfdm/device.c @@ -126,6 +126,9 @@ DMOBJ tDMRootObj[] = { {"LANConfigSecurity", &DMREAD, NULL, NULL, "file:/etc/config/users", NULL, NULL, NULL, NULL, tLANConfigSecurityParams, NULL, BBFDM_BOTH}, {"Schedules", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tSchedulesObj, tSchedulesParams, NULL, BBFDM_BOTH}, {"Security", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tSecurityObj, tSecurityParams, NULL, BBFDM_CWMP}, +#ifdef BBFDM_DM_SERVICE_RAM_OPTIMIZED +{"Services", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, BBFDM_BOTH}, +#endif {0} }; diff --git a/test/cmocka/functional_test_bbfd.c b/test/cmocka/functional_test_bbfd.c index 5e1cf839..450f60b1 100644 --- a/test/cmocka/functional_test_bbfd.c +++ b/test/cmocka/functional_test_bbfd.c @@ -42,13 +42,13 @@ static int teardown_commit(void **state) static int group_init(void **state) { - bbf_global_init(TR181_ROOT_TREE, "/usr/share/bbfdm/micro_services/core"); + bbf_global_init(TR181_ROOT_TREE, NULL, "/usr/share/bbfdm/micro_services/core"); return 0; } static int group_teardown(void **state) { - bbf_global_clean(TR181_ROOT_TREE); + bbf_global_clean(TR181_ROOT_TREE, NULL); return 0; } diff --git a/test/cmocka/unit_test_bbfd.c b/test/cmocka/unit_test_bbfd.c index 5ebbcbb7..aaa8d354 100644 --- a/test/cmocka/unit_test_bbfd.c +++ b/test/cmocka/unit_test_bbfd.c @@ -54,13 +54,13 @@ static int teardown_revert(void **state) static int group_init(void **state) { - bbf_global_init(TR181_ROOT_TREE, "/usr/share/bbfdm/micro_services/core"); + bbf_global_init(TR181_ROOT_TREE, NULL, "/usr/share/bbfdm/micro_services/core"); return 0; } static int group_teardown(void **state) { - bbf_global_clean(TR181_ROOT_TREE); + bbf_global_clean(TR181_ROOT_TREE, NULL); return 0; }