mirror of
https://dev.iopsys.eu/bbf/bbfdm.git
synced 2025-12-10 07:44:39 +01:00
Added a mechanism to recover blacklisted services
This commit is contained in:
parent
4bfeedf7bc
commit
22cc348d27
5 changed files with 152 additions and 9 deletions
|
|
@ -15,6 +15,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
#include <libubus.h>
|
#include <libubus.h>
|
||||||
#include <libubox/blobmsg_json.h>
|
#include <libubox/blobmsg_json.h>
|
||||||
|
|
@ -24,9 +25,123 @@
|
||||||
#include "get.h"
|
#include "get.h"
|
||||||
#include "cli.h"
|
#include "cli.h"
|
||||||
|
|
||||||
|
struct ubus_context g_ubus_ctx = {0};
|
||||||
|
|
||||||
extern struct list_head registered_services;
|
extern struct list_head registered_services;
|
||||||
extern int g_log_level;
|
extern int g_log_level;
|
||||||
|
|
||||||
|
static void schedule_blacklisted_service_recovery(struct ubus_context *ctx);
|
||||||
|
|
||||||
|
static void blacklisted_recovery_timer_cb(struct uloop_timeout *timeout __attribute__((unused)))
|
||||||
|
{
|
||||||
|
schedule_blacklisted_service_recovery(&g_ubus_ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct uloop_timeout blacklisted_recovery_timer = {
|
||||||
|
.cb = blacklisted_recovery_timer_cb
|
||||||
|
};
|
||||||
|
|
||||||
|
struct service_request_tracker {
|
||||||
|
struct ubus_context *ubus_ctx;
|
||||||
|
service_entry_t *service;
|
||||||
|
struct ubus_request async_request;
|
||||||
|
struct uloop_timeout timeout;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void service_request_timeout(struct uloop_timeout *timeout)
|
||||||
|
{
|
||||||
|
struct service_request_tracker *tracker = container_of(timeout, struct service_request_tracker, timeout);
|
||||||
|
if (tracker == NULL) {
|
||||||
|
BBFDM_ERR("Timeout occurred but tracker is not defined");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BBFDM_ERR("Timeout occurred for request: '%s get'", tracker->service ? tracker->service->name : "unknown");
|
||||||
|
ubus_abort_request(tracker->ubus_ctx, &tracker->async_request);
|
||||||
|
BBFDM_FREE(tracker);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
if (tracker == NULL) {
|
||||||
|
BBFDM_ERR("Request completed but tracker is not defined");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BBFDM_DEBUG("Request completed for '%s get' with status: '%d'", tracker->service ? tracker->service->name : "", ret);
|
||||||
|
uloop_timeout_cancel(&tracker->timeout);
|
||||||
|
|
||||||
|
if (tracker->service && ret == UBUS_STATUS_OK) {
|
||||||
|
tracker->service->is_blacklisted = false;
|
||||||
|
tracker->service->consecutive_timeouts = 0;
|
||||||
|
BBFDM_INFO("Recovered blacklisted service: '%s'", tracker->service->name);
|
||||||
|
} else {
|
||||||
|
BBFDM_DEBUG("Service '%s' still unreachable", tracker->service ? tracker->service->name : "unknown");
|
||||||
|
}
|
||||||
|
|
||||||
|
BBFDM_FREE(tracker);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void verify_service(struct ubus_context *ubus_ctx, service_entry_t *service)
|
||||||
|
{
|
||||||
|
struct blob_buf req_buf = {0};
|
||||||
|
uint32_t id = 0;
|
||||||
|
|
||||||
|
if (!ubus_ctx || !service || !service->name) {
|
||||||
|
BBFDM_ERR("Invalid arguments");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ubus_lookup_id(ubus_ctx, service->name, &id)) {
|
||||||
|
BBFDM_ERR("Failed to lookup object: %s", service->name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct service_request_tracker *tracker = (struct service_request_tracker *)calloc(1, sizeof(struct service_request_tracker));
|
||||||
|
if (!tracker) {
|
||||||
|
BBFDM_ERR("Failed to allocate memory for request tracker");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
tracker->ubus_ctx = ubus_ctx;
|
||||||
|
tracker->service = service;
|
||||||
|
|
||||||
|
tracker->timeout.cb = service_request_timeout;
|
||||||
|
uloop_timeout_set(&tracker->timeout, SERVICE_CALL_TIMEOUT);
|
||||||
|
|
||||||
|
memset(&req_buf, 0, sizeof(struct blob_buf));
|
||||||
|
blob_buf_init(&req_buf, 0);
|
||||||
|
|
||||||
|
blobmsg_add_string(&req_buf, "path", BBFDM_ROOT_OBJECT);
|
||||||
|
|
||||||
|
if (ubus_invoke_async(ubus_ctx, id, "get", req_buf.head, &tracker->async_request)) {
|
||||||
|
BBFDM_ERR("Failed to invoke async method for object: '%s get'", service->name);
|
||||||
|
uloop_timeout_cancel(&tracker->timeout);
|
||||||
|
BBFDM_FREE(tracker);
|
||||||
|
} else {
|
||||||
|
tracker->async_request.complete_cb = service_request_complete;
|
||||||
|
ubus_complete_request_async(ubus_ctx, &tracker->async_request);
|
||||||
|
}
|
||||||
|
|
||||||
|
blob_buf_free(&req_buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void schedule_blacklisted_service_recovery(struct ubus_context *ubus_ctx)
|
||||||
|
{
|
||||||
|
service_entry_t *service = NULL;
|
||||||
|
|
||||||
|
list_for_each_entry(service, ®istered_services, list) {
|
||||||
|
if (service->is_blacklisted) {
|
||||||
|
verify_service(ubus_ctx, service);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int next_check_time = rand_in_range(30, 60) * 1000;
|
||||||
|
BBFDM_DEBUG("Next blacklisted service recovery scheduled in %d msecs", next_check_time);
|
||||||
|
uloop_timeout_set(&blacklisted_recovery_timer, next_check_time);
|
||||||
|
}
|
||||||
|
|
||||||
static void bbfdm_ubus_add_event_cb(struct ubus_context *ctx, struct ubus_event_handler *ev __attribute__((unused)),
|
static void bbfdm_ubus_add_event_cb(struct ubus_context *ctx, struct ubus_event_handler *ev __attribute__((unused)),
|
||||||
const char *type, struct blob_attr *msg)
|
const char *type, struct blob_attr *msg)
|
||||||
{
|
{
|
||||||
|
|
@ -295,7 +410,6 @@ static void usage(char *prog)
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
struct ubus_context ubus_ctx = {0};
|
|
||||||
struct ubus_event_handler add_event = {
|
struct ubus_event_handler add_event = {
|
||||||
.cb = bbfdm_ubus_add_event_cb,
|
.cb = bbfdm_ubus_add_event_cb,
|
||||||
};
|
};
|
||||||
|
|
@ -334,39 +448,43 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
setlogmask(LOG_UPTO(g_log_level));
|
setlogmask(LOG_UPTO(g_log_level));
|
||||||
|
|
||||||
err = ubus_connect_ctx(&ubus_ctx, NULL);
|
init_rand_seed(); // Seed the random number generator
|
||||||
|
|
||||||
|
err = ubus_connect_ctx(&g_ubus_ctx, NULL);
|
||||||
if (err != UBUS_STATUS_OK) {
|
if (err != UBUS_STATUS_OK) {
|
||||||
BBFDM_ERR("Failed to connect to ubus");
|
BBFDM_ERR("Failed to connect to ubus");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
uloop_init();
|
uloop_init();
|
||||||
ubus_add_uloop(&ubus_ctx);
|
ubus_add_uloop(&g_ubus_ctx);
|
||||||
|
|
||||||
err = register_services(&ubus_ctx);
|
err = register_services(&g_ubus_ctx);
|
||||||
if (err) {
|
if (err) {
|
||||||
BBFDM_ERR("Failed to load micro-services");
|
BBFDM_ERR("Failed to load micro-services");
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = ubus_add_object(&ubus_ctx, &bbfdm_object);
|
err = ubus_add_object(&g_ubus_ctx, &bbfdm_object);
|
||||||
if (err != UBUS_STATUS_OK) {
|
if (err != UBUS_STATUS_OK) {
|
||||||
BBFDM_ERR("Failed to add ubus object: %s", ubus_strerror(err));
|
BBFDM_ERR("Failed to add ubus object: %s", ubus_strerror(err));
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ubus_register_event_handler(&ubus_ctx, &add_event, "ubus.object.add"))
|
if (ubus_register_event_handler(&g_ubus_ctx, &add_event, "ubus.object.add"))
|
||||||
goto end;
|
goto end;
|
||||||
|
|
||||||
|
schedule_blacklisted_service_recovery(&g_ubus_ctx);
|
||||||
|
|
||||||
BBFDM_INFO("Waiting on uloop....");
|
BBFDM_INFO("Waiting on uloop....");
|
||||||
uloop_run();
|
uloop_run();
|
||||||
|
|
||||||
end:
|
end:
|
||||||
BBFDM_DEBUG("BBFDMD exits");
|
BBFDM_DEBUG("BBFDMD exits");
|
||||||
ubus_unregister_event_handler(&ubus_ctx, &add_event);
|
ubus_unregister_event_handler(&g_ubus_ctx, &add_event);
|
||||||
unregister_services();
|
unregister_services();
|
||||||
uloop_done();
|
uloop_done();
|
||||||
ubus_shutdown(&ubus_ctx);
|
ubus_shutdown(&g_ubus_ctx);
|
||||||
|
|
||||||
closelog();
|
closelog();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,27 @@
|
||||||
|
|
||||||
int g_log_level = LOG_ERR;
|
int g_log_level = LOG_ERR;
|
||||||
|
|
||||||
|
void init_rand_seed(void)
|
||||||
|
{
|
||||||
|
srandom((unsigned int)time(NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
int rand_in_range(int min, int max)
|
||||||
|
{
|
||||||
|
int range;
|
||||||
|
|
||||||
|
if (min >= max)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (min == (max - 1))
|
||||||
|
return min;
|
||||||
|
|
||||||
|
range = max - min;
|
||||||
|
|
||||||
|
return min + ((int)(((double)range) * ((double)random()) /
|
||||||
|
(((double)RAND_MAX) + 1.0)));
|
||||||
|
}
|
||||||
|
|
||||||
unsigned int get_proto_type(const char *proto)
|
unsigned int get_proto_type(const char *proto)
|
||||||
{
|
{
|
||||||
int type = BBFDMD_BOTH;
|
int type = BBFDMD_BOTH;
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,9 @@ enum bbfdmd_type_enum {
|
||||||
BBFDMD_BOTH = BBFDMD_CWMP | BBFDMD_USP,
|
BBFDMD_BOTH = BBFDMD_CWMP | BBFDMD_USP,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void init_rand_seed(void);
|
||||||
|
int rand_in_range(int min, int max);
|
||||||
|
|
||||||
unsigned int get_proto_type(const char *proto);
|
unsigned int get_proto_type(const char *proto);
|
||||||
|
|
||||||
void fill_optional_input(struct blob_attr *msg, unsigned int *proto, bool *raw_format);
|
void fill_optional_input(struct blob_attr *msg, unsigned int *proto, bool *raw_format);
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,7 @@ int main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
bbfdm_ubus_set_log_level(log_level);
|
bbfdm_ubus_set_log_level(log_level);
|
||||||
|
bbfdm_ubus_load_data_model(NULL);
|
||||||
|
|
||||||
openlog(bbfdm_ctx.config.service_name, LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1);
|
openlog(bbfdm_ctx.config.service_name, LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -767,7 +767,7 @@ int bbfdm_print_data_model_schema(struct bbfdm_context *bbfdm_ctx, const enum bb
|
||||||
bbf_cleanup(&bbf_ctx);
|
bbf_cleanup(&bbf_ctx);
|
||||||
|
|
||||||
bbfdm_ctx_cleanup(bbfdm_ctx);
|
bbfdm_ctx_cleanup(bbfdm_ctx);
|
||||||
return 0;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
int bbfdm_ubus_regiter_init(struct bbfdm_context *bbfdm_ctx)
|
int bbfdm_ubus_regiter_init(struct bbfdm_context *bbfdm_ctx)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue