mirror of
https://dev.iopsys.eu/bbf/bbfdm.git
synced 2026-01-27 17:37:17 +01:00
bbfdmd: Prevent repeated async calls to unstable services
This commit is contained in:
parent
cba4ccc25c
commit
d017aa025c
6 changed files with 97 additions and 10 deletions
|
|
@ -27,6 +27,50 @@
|
|||
extern struct list_head registered_services;
|
||||
extern int g_log_level;
|
||||
|
||||
static void bbfdm_ubus_add_event_cb(struct ubus_context *ctx __attribute__((unused)),
|
||||
struct ubus_event_handler *ev __attribute__((unused)),
|
||||
const char *type, struct blob_attr *msg)
|
||||
{
|
||||
const struct blobmsg_policy policy = {
|
||||
"path", BLOBMSG_TYPE_STRING
|
||||
};
|
||||
service_entry_t *service = NULL;
|
||||
struct blob_attr *attr = NULL;
|
||||
bool service_found = false;
|
||||
const char *path;
|
||||
|
||||
if (type && strcmp(type, "ubus.object.add") != 0)
|
||||
return;
|
||||
|
||||
blobmsg_parse(&policy, 1, &attr, blob_data(msg), blob_len(msg));
|
||||
if (!attr)
|
||||
return;
|
||||
|
||||
path = blobmsg_data(attr);
|
||||
|
||||
if (path && strncmp(path, BBFDM_UBUS_OBJECT".", strlen(BBFDM_UBUS_OBJECT) + 1) == 0) {
|
||||
|
||||
BBFDM_ERR("Detected new service registration: '%s'", path);
|
||||
|
||||
list_for_each_entry(service, ®istered_services, list) {
|
||||
// Check if the service is present in the registred services list
|
||||
if (strcmp(service->name, path) == 0) {
|
||||
service->is_blacklisted = false;
|
||||
service->consecutive_timeouts = 0;
|
||||
service_found = true;
|
||||
BBFDM_ERR("Service '%s' found in registry. Resetting blacklist and timeout counters.", path);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!service_found) {
|
||||
BBFDM_ERR("Newly registered service '%s' is not recognized in the registry."
|
||||
" Possible missing configuration JSON file under '%s'.",
|
||||
path, BBFDM_MICROSERVICE_INPUT_PATH);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const struct blobmsg_policy bbfdm_policy[] = {
|
||||
[BBFDM_PATH] = { .name = "path", .type = BLOBMSG_TYPE_STRING },
|
||||
[BBFDM_VALUE] = { .name = "value", .type = BLOBMSG_TYPE_STRING },
|
||||
|
|
@ -72,10 +116,13 @@ static int bbfdm_handler_async(struct ubus_context *ctx, struct ubus_object *obj
|
|||
|
||||
list_for_each_entry(service, ®istered_services, list) {
|
||||
|
||||
if (service->is_blacklisted)
|
||||
continue;
|
||||
|
||||
if (!is_path_match(context->requested_path, requested_proto, service))
|
||||
continue;
|
||||
|
||||
run_async_call(context, service->name, msg);
|
||||
run_async_call(context, service, msg);
|
||||
}
|
||||
|
||||
context->service_list_processed = true;
|
||||
|
|
@ -117,6 +164,9 @@ static int bbfdm_handler_sync(struct ubus_context *ctx, struct ubus_object *obj,
|
|||
|
||||
list_for_each_entry(service, ®istered_services, list) {
|
||||
|
||||
if (service->is_blacklisted)
|
||||
continue;
|
||||
|
||||
if (!is_path_match(requested_path, requested_proto, service))
|
||||
continue;
|
||||
|
||||
|
|
@ -181,6 +231,10 @@ static void usage(char *prog)
|
|||
int main(int argc, char **argv)
|
||||
{
|
||||
struct ubus_context ubus_ctx = {0};
|
||||
struct ubus_event_handler add_event = {
|
||||
.cb = bbfdm_ubus_add_event_cb,
|
||||
};
|
||||
|
||||
char *cli_argv[4] = {0};
|
||||
int err = 0, ch, cli_argc = 0, i;
|
||||
|
||||
|
|
@ -236,11 +290,15 @@ int main(int argc, char **argv)
|
|||
goto end;
|
||||
}
|
||||
|
||||
if (ubus_register_event_handler(&ubus_ctx, &add_event, "ubus.object.add"))
|
||||
goto end;
|
||||
|
||||
BBFDM_INFO("Waiting on uloop....");
|
||||
uloop_run();
|
||||
|
||||
end:
|
||||
BBFDM_DEBUG("BBFDMD exits");
|
||||
ubus_unregister_event_handler(&ubus_ctx, &add_event);
|
||||
unregister_services();
|
||||
uloop_done();
|
||||
ubus_shutdown(&ubus_ctx);
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#define MAX_VALUE_LENGTH 1024 * 4
|
||||
#define SERVICE_CALL_TIMEOUT 10000 // 10 secs
|
||||
#define SERVICE_CALL_OPERATE_TIMEOUT 1800000 // 30 mins
|
||||
#define SERVICE_MAX_CONSECUTIVE_TIMEOUTS 10
|
||||
|
||||
enum bbfdmd_type_enum {
|
||||
BBFDMD_NONE = 0,
|
||||
|
|
|
|||
|
|
@ -321,6 +321,16 @@ static void handle_request_timeout(struct uloop_timeout *timeout)
|
|||
ubus_abort_request(tracker->ctx->ubus_ctx, &tracker->async_request);
|
||||
tracker->ctx->pending_requests--;
|
||||
|
||||
service_entry_t *service = tracker->service;
|
||||
|
||||
if (service) {
|
||||
service->consecutive_timeouts++;
|
||||
if (service->consecutive_timeouts >= SERVICE_MAX_CONSECUTIVE_TIMEOUTS) {
|
||||
service->is_blacklisted = true;
|
||||
BBFDM_ERR("Service '%s' has been blacklisted due to repeated timeouts", service->name);
|
||||
}
|
||||
}
|
||||
|
||||
if (tracker->ctx->pending_requests == 0 && tracker->ctx->service_list_processed) {
|
||||
BBFDM_ERR("All requests completed after timeout");
|
||||
send_response(tracker->ctx);
|
||||
|
|
@ -347,6 +357,9 @@ static void ubus_request_complete(struct ubus_request *req, int ret)
|
|||
uloop_timeout_cancel(&tracker->timeout);
|
||||
tracker->ctx->pending_requests--;
|
||||
|
||||
if (tracker->service && ret == UBUS_STATUS_OK)
|
||||
tracker->service->consecutive_timeouts = 0;
|
||||
|
||||
if (tracker->ctx->pending_requests == 0 && tracker->ctx->service_list_processed) {
|
||||
BBFDM_DEBUG("Result Callback: All requests completed");
|
||||
send_response(tracker->ctx);
|
||||
|
|
@ -355,20 +368,20 @@ static void ubus_request_complete(struct ubus_request *req, int ret)
|
|||
BBFDM_FREE(tracker);
|
||||
}
|
||||
|
||||
void run_async_call(struct async_request_context *ctx, const char *ubus_obj, struct blob_attr *msg)
|
||||
void run_async_call(struct async_request_context *ctx, service_entry_t *service, struct blob_attr *msg)
|
||||
{
|
||||
struct blob_buf req_buf = {0};
|
||||
struct blob_attr *attr = NULL;
|
||||
int remaining = 0;
|
||||
uint32_t id = 0;
|
||||
|
||||
if (!ctx || !ubus_obj || !msg) {
|
||||
if (!ctx || !service || !msg || !service->name) {
|
||||
BBFDM_ERR("Invalid arguments");
|
||||
return;
|
||||
}
|
||||
|
||||
if (ubus_lookup_id(ctx->ubus_ctx, ubus_obj, &id)) {
|
||||
BBFDM_ERR("Failed to lookup object: %s", ubus_obj);
|
||||
if (ubus_lookup_id(ctx->ubus_ctx, service->name, &id)) {
|
||||
BBFDM_ERR("Failed to lookup object: %s", service->name);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -379,6 +392,7 @@ void run_async_call(struct async_request_context *ctx, const char *ubus_obj, str
|
|||
}
|
||||
|
||||
tracker->ctx = ctx;
|
||||
tracker->service = service;
|
||||
ctx->pending_requests++;
|
||||
ctx->path_matched = true;
|
||||
|
||||
|
|
@ -389,14 +403,14 @@ void run_async_call(struct async_request_context *ctx, const char *ubus_obj, str
|
|||
blobmsg_add_field(&req_buf, blobmsg_type(attr), blobmsg_name(attr), blobmsg_data(attr), blobmsg_len(attr));
|
||||
}
|
||||
|
||||
snprintf(tracker->request_name, sizeof(tracker->request_name), "%s->%s", ubus_obj, ctx->ubus_method);
|
||||
snprintf(tracker->request_name, sizeof(tracker->request_name), "%s->%s", service->name, ctx->ubus_method);
|
||||
|
||||
tracker->timeout.cb = handle_request_timeout;
|
||||
uloop_timeout_set(&tracker->timeout, !strcmp(ctx->ubus_method, "operate") ? SERVICE_CALL_OPERATE_TIMEOUT : SERVICE_CALL_TIMEOUT);
|
||||
|
||||
if (g_log_level == LOG_DEBUG) {
|
||||
char *json_str = blobmsg_format_json_indent(req_buf.head, true, -1);
|
||||
BBFDM_DEBUG("### ubus call %s %s '%s' ###", ubus_obj, ctx->ubus_method, json_str);
|
||||
BBFDM_DEBUG("### ubus call %s %s '%s' ###", service->name, ctx->ubus_method, json_str);
|
||||
BBFDM_FREE(json_str);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -41,12 +41,13 @@ struct async_request_context {
|
|||
|
||||
struct ubus_request_tracker {
|
||||
struct async_request_context *ctx;
|
||||
service_entry_t *service;
|
||||
struct ubus_request async_request;
|
||||
struct uloop_timeout timeout;
|
||||
char request_name[128];
|
||||
};
|
||||
|
||||
void run_async_call(struct async_request_context *ctx, const char *ubus_obj, struct blob_attr *msg);
|
||||
void run_async_call(struct async_request_context *ctx, service_entry_t *service, struct blob_attr *msg);
|
||||
void send_response(struct async_request_context *ctx);
|
||||
|
||||
#endif /* BBFDMD_GET_H */
|
||||
|
|
|
|||
|
|
@ -201,24 +201,35 @@ void list_registered_services(struct blob_buf *bb)
|
|||
|
||||
list_for_each_entry(service, ®istered_services, list) {
|
||||
void *table = blobmsg_open_table(bb, NULL);
|
||||
|
||||
blobmsg_add_string(bb, "name", service->name ? service->name : "");
|
||||
blobmsg_add_string(bb, "proto", service->protocol == BBFDMD_USP ? "usp" : service->protocol == BBFDMD_CWMP ? "cwmp" : "both");
|
||||
blobmsg_add_string(bb, "proto",
|
||||
service->protocol == BBFDMD_USP ? "usp" :
|
||||
service->protocol == BBFDMD_CWMP ? "cwmp" : "both");
|
||||
|
||||
blobmsg_add_u8(bb, "unified_daemon", service->is_unified);
|
||||
blobmsg_add_u8(bb, "blacklisted", service->is_blacklisted);
|
||||
|
||||
void *objects_array = blobmsg_open_array(bb, "objects");
|
||||
for (size_t i = 0; i < service->object_count; i++) {
|
||||
void *obj_table = blobmsg_open_table(bb, NULL);
|
||||
blobmsg_add_string(bb, "parent_dm", service->objects[i].parent_path);
|
||||
blobmsg_add_string(bb, "object", service->objects[i].object_name);
|
||||
|
||||
if (service->protocol == BBFDMD_USP) {
|
||||
blobmsg_add_string(bb, "proto", "usp");
|
||||
} else if (service->protocol == BBFDMD_CWMP) {
|
||||
blobmsg_add_string(bb, "proto", "cwmp");
|
||||
} else {
|
||||
blobmsg_add_string(bb, "proto", service->objects[i].protocol == BBFDMD_USP ? "usp" : service->objects[i].protocol == BBFDMD_CWMP ? "cwmp" : "both");
|
||||
blobmsg_add_string(bb, "proto",
|
||||
service->objects[i].protocol == BBFDMD_USP ? "usp" :
|
||||
service->objects[i].protocol == BBFDMD_CWMP ? "cwmp" : "both");
|
||||
}
|
||||
|
||||
blobmsg_close_table(bb, obj_table);
|
||||
}
|
||||
blobmsg_close_array(bb, objects_array);
|
||||
|
||||
blobmsg_close_table(bb, table);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@ typedef struct service_entry {
|
|||
bool is_unified;
|
||||
size_t object_count;
|
||||
service_object_t *objects;
|
||||
int consecutive_timeouts; // Tracks successive timeouts
|
||||
bool is_blacklisted; // Marks if the service is blacklisted
|
||||
} service_entry_t;
|
||||
|
||||
int register_services(struct ubus_context *ctx);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue