mirror of
https://dev.iopsys.eu/bbf/icwmp.git
synced 2026-01-27 17:17:17 +01:00
Support to apply non-critical services immediately
From icwmp point of view, services which can cause upstream/wan disruption are critical services and these are applied at the end of the sessions. These services are defined in '/etc/icwmpd/critical_services.json'.
This commit is contained in:
parent
dea357d30f
commit
580f923cfc
8 changed files with 165 additions and 36 deletions
149
src/common.c
149
src/common.c
|
|
@ -19,6 +19,7 @@
|
|||
#include <sys/types.h>
|
||||
#include <ifaddrs.h>
|
||||
#include <mxml.h>
|
||||
#include <libubox/blobmsg_json.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "cwmp_cli.h"
|
||||
|
|
@ -31,15 +32,20 @@ bool cwmp_stop = false;
|
|||
unsigned int flashsize = 256000000;
|
||||
struct cwmp *cwmp_main = NULL;
|
||||
struct session_timer_event *global_session_event = NULL;
|
||||
static int nbre_services = 0;
|
||||
static char *list_services[MAX_NBRE_SERVICES] = { 0 };
|
||||
LIST_HEAD(critical_service_list);
|
||||
LIST_HEAD(cwmp_memory_list);
|
||||
LIST_HEAD(services_reload);
|
||||
|
||||
struct cwmp_mem {
|
||||
struct list_head list;
|
||||
char mem[0];
|
||||
};
|
||||
|
||||
struct cwmp_services {
|
||||
struct list_head list;
|
||||
char *service;
|
||||
};
|
||||
|
||||
struct option cwmp_long_options[] = {
|
||||
{ "boot-event", no_argument, NULL, 'b' },
|
||||
{ "get-rpc-methods", no_argument, NULL, 'g' },
|
||||
|
|
@ -645,35 +651,121 @@ void icwmp_cleanmem()
|
|||
/*
|
||||
* Services Management
|
||||
*/
|
||||
void icwmp_init_list_services()
|
||||
void icwmp_init_critical_services()
|
||||
{
|
||||
int i;
|
||||
struct blob_buf bbuf = {0};
|
||||
struct blob_attr *cur = NULL;
|
||||
struct blob_attr *service_list = NULL;
|
||||
int rem = 0;
|
||||
|
||||
nbre_services = 0;
|
||||
for (i = 0; i < MAX_NBRE_SERVICES; i++)
|
||||
list_services[i] = NULL;
|
||||
if (!file_exists(CWMP_CRITICAL_SERVICES))
|
||||
return;
|
||||
|
||||
CWMP_MEMSET(&bbuf, 0, sizeof(struct blob_buf));
|
||||
blob_buf_init(&bbuf, 0);
|
||||
|
||||
if (blobmsg_add_json_from_file(&bbuf, CWMP_CRITICAL_SERVICES) == false) {
|
||||
CWMP_LOG(WARNING, "The file %s is not a valid JSON file", CWMP_CRITICAL_SERVICES);
|
||||
blob_buf_free(&bbuf);
|
||||
return;
|
||||
}
|
||||
|
||||
struct blob_attr *tb_service[1] = {0};
|
||||
const struct blobmsg_policy p_service[1] = {
|
||||
{ "services_list", BLOBMSG_TYPE_ARRAY }
|
||||
};
|
||||
|
||||
blobmsg_parse(p_service, 1, tb_service, blobmsg_data(bbuf.head), blobmsg_len(bbuf.head));
|
||||
if (tb_service[0] == NULL) {
|
||||
CWMP_LOG(WARNING, "The JSON file %s doesn't contain any service", CWMP_CRITICAL_SERVICES);
|
||||
blob_buf_free(&bbuf);
|
||||
return;
|
||||
}
|
||||
|
||||
service_list = tb_service[0];
|
||||
|
||||
blobmsg_for_each_attr(cur, service_list, rem) {
|
||||
if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING)
|
||||
continue;
|
||||
|
||||
char *serv_name = blobmsg_get_string(cur);
|
||||
if (CWMP_STRLEN(serv_name) == 0)
|
||||
continue;
|
||||
|
||||
struct cwmp_services *serv = malloc(sizeof(struct cwmp_services));
|
||||
if (serv == NULL)
|
||||
break;
|
||||
|
||||
serv->service = CWMP_STRDUP(serv_name);
|
||||
list_add(&serv->list, &critical_service_list);
|
||||
}
|
||||
blob_buf_free(&bbuf);
|
||||
}
|
||||
|
||||
void icwmp_free_critical_services()
|
||||
{
|
||||
struct cwmp_services *serv = NULL, *node = NULL;
|
||||
|
||||
list_for_each_entry_safe(serv, node, &critical_service_list, list) {
|
||||
list_del(&serv->list);
|
||||
FREE(serv->service);
|
||||
free(serv);
|
||||
}
|
||||
}
|
||||
|
||||
bool icwmp_critical_service(const char *service)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
if (CWMP_STRLEN(service) == 0 || list_empty(&critical_service_list))
|
||||
return ret;
|
||||
|
||||
struct cwmp_services *serv = NULL;
|
||||
list_for_each_entry(serv, &critical_service_list, list) {
|
||||
if (CWMP_STRCMP(service, serv->service) == 0) {
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int icwmp_add_service(char *service)
|
||||
{
|
||||
if (nbre_services >= MAX_NBRE_SERVICES)
|
||||
if (CWMP_STRLEN(service) == 0)
|
||||
return -1;
|
||||
list_services[nbre_services++] = strdup(service);
|
||||
|
||||
struct cwmp_services *serv = malloc(sizeof(struct cwmp_services));
|
||||
if (serv == NULL)
|
||||
return -1;
|
||||
|
||||
serv->service = CWMP_STRDUP(service);
|
||||
list_add(&serv->list, &services_reload);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void icwmp_free_list_services()
|
||||
{
|
||||
int i = 0;
|
||||
for (i = 0; i < nbre_services; i++) {
|
||||
FREE(list_services[i]);
|
||||
struct cwmp_services *serv = NULL, *node = NULL;
|
||||
|
||||
list_for_each_entry_safe(serv, node, &services_reload, list) {
|
||||
list_del(&serv->list);
|
||||
FREE(serv->service);
|
||||
free(serv);
|
||||
}
|
||||
nbre_services = 0;
|
||||
}
|
||||
|
||||
void icwmp_restart_services()
|
||||
bool end_session_reload_pending()
|
||||
{
|
||||
return !list_empty(&services_reload);
|
||||
}
|
||||
|
||||
void icwmp_restart_services(int type)
|
||||
{
|
||||
struct blob_buf bb = {0};
|
||||
struct cwmp_services *serv = NULL, *node = NULL;
|
||||
|
||||
memset(&bb, 0, sizeof(struct blob_buf));
|
||||
|
||||
|
|
@ -681,16 +773,35 @@ void icwmp_restart_services()
|
|||
|
||||
void *array = blobmsg_open_array(&bb, "services");
|
||||
|
||||
for (int i = 0; i < nbre_services; i++) {
|
||||
if (list_services[i] == NULL)
|
||||
list_for_each_entry_safe(serv, node, &services_reload, list) {
|
||||
if (CWMP_STRLEN(serv->service) == 0) {
|
||||
list_del(&serv->list);
|
||||
FREE(serv->service);
|
||||
free(serv);
|
||||
continue;
|
||||
}
|
||||
|
||||
// If RELOAD_IMMIDIATE then only reload the non-critical services and delete from the list
|
||||
// otherwise reload all services in the list and clear the list
|
||||
if ((type == RELOAD_IMMIDIATE) && (icwmp_critical_service(serv->service) == true)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
CWMP_LOG(DEBUG, "Detected service: %s will be restarted", serv->service);
|
||||
|
||||
if (CWMP_STRCMP(serv->service, "cwmp") == 0) {
|
||||
list_del(&serv->list);
|
||||
FREE(serv->service);
|
||||
free(serv);
|
||||
|
||||
if (CWMP_STRCMP(list_services[i], "cwmp") == 0) {
|
||||
commit_uci_package("cwmp");
|
||||
continue;
|
||||
}
|
||||
|
||||
blobmsg_add_string(&bb, NULL, list_services[i]);
|
||||
blobmsg_add_string(&bb, NULL, serv->service);
|
||||
list_del(&serv->list);
|
||||
FREE(serv->service);
|
||||
free(serv);
|
||||
}
|
||||
|
||||
blobmsg_close_array(&bb, array);
|
||||
|
|
@ -698,8 +809,6 @@ void icwmp_restart_services()
|
|||
icwmp_ubus_invoke("bbf.config", "commit", bb.head, NULL, NULL);
|
||||
|
||||
blob_buf_free(&bb);
|
||||
|
||||
icwmp_free_list_services();
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
16
src/common.h
16
src/common.h
|
|
@ -75,6 +75,7 @@
|
|||
|
||||
#define ICWMP_TMP_PATH "/tmp/icwmp"
|
||||
#define FIREWALL_CWMP "/etc/firewall.cwmp"
|
||||
#define CWMP_CRITICAL_SERVICES "/etc/icwmpd/critical_services.json"
|
||||
#define DM_PPP_INTERFACE_PATH "Device\\.PPP\\.Interface\\."
|
||||
#define DM_IP_INTERFACE_PATH "Device\\.IP\\.Interface\\."
|
||||
#define DEFAULT_CR_TIMEOUT 5 /* In Seconds */
|
||||
|
|
@ -93,6 +94,12 @@ extern struct uloop_timeout retry_session_timer;
|
|||
extern struct list_head intf_reset_list;
|
||||
extern struct list_head force_inform_list;
|
||||
|
||||
enum service_apply_type {
|
||||
RELOAD_END_SESSION,
|
||||
RELOAD_IMMIDIATE,
|
||||
__INVALID_TYPE
|
||||
};
|
||||
|
||||
typedef struct env {
|
||||
unsigned short boot;
|
||||
unsigned short periodic;
|
||||
|
|
@ -647,10 +654,9 @@ char *icwmp_strdup(const char *s);
|
|||
int icwmp_asprintf(char **s, const char *format, ...);
|
||||
void icwmp_free(void *m);
|
||||
void icwmp_cleanmem();
|
||||
void icwmp_init_list_services();
|
||||
int icwmp_add_service(char *service);
|
||||
void icwmp_free_list_services();
|
||||
void icwmp_restart_services();
|
||||
void icwmp_free_list_services(void);
|
||||
void icwmp_restart_services(int type);
|
||||
bool icwmp_validate_string_length(char *arg, int max_length);
|
||||
bool icwmp_validate_boolean_value(char *arg);
|
||||
bool icwmp_validate_unsignedint(char *arg);
|
||||
|
|
@ -687,4 +693,8 @@ void *cwmp_memcpy(void *dst, const void *src, size_t size, const char *origin, i
|
|||
void cwmp_restart_service(struct uloop_timeout *timeout __attribute__((unused)));
|
||||
int regex_replace(char **str, const char *pattern, const char *replace, int *match_count);
|
||||
void stop_service(void);
|
||||
void icwmp_init_critical_services(void);
|
||||
void icwmp_free_critical_services(void);
|
||||
bool end_session_reload_service(const char *service);
|
||||
bool end_session_reload_pending(void);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -263,7 +263,7 @@ static int cwmp_init(void)
|
|||
|
||||
CWMP_LOG(INFO, "STARTING ICWMP with PID :%d", getpid());
|
||||
|
||||
icwmp_init_list_services();
|
||||
icwmp_init_critical_services();
|
||||
|
||||
/* Only One instance should run*/
|
||||
cwmp_main->pid_file = fopen("/var/run/icwmpd.pid", "w+");
|
||||
|
|
@ -335,6 +335,8 @@ static void cwmp_free()
|
|||
icwmp_cleanmem();
|
||||
rpc_exit();
|
||||
clean_cwmp_session_structure();
|
||||
icwmp_free_critical_services();
|
||||
icwmp_free_list_services();
|
||||
FREE(cwmp_main);
|
||||
CWMP_LOG(INFO, "EXIT ICWMP");
|
||||
closelog();
|
||||
|
|
|
|||
|
|
@ -101,7 +101,6 @@ static void ubus_transaction_callback(struct ubus_request *req, int type __attri
|
|||
if (CWMP_STRLEN(service_name) == 0)
|
||||
continue;
|
||||
|
||||
CWMP_LOG(DEBUG, "Detected service: %s will be restarted in the end session", service_name);
|
||||
icwmp_add_service(service_name);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
23
src/rpc.c
23
src/rpc.c
|
|
@ -1130,6 +1130,19 @@ int cwmp_handle_rpc_cpe_set_parameter_values(struct rpc *rpc)
|
|||
cwmp_free_all_xml_data_list(&xml_list_set_param_value);
|
||||
cwmp_free_all_dm_parameter_list(&list_set_param_value);
|
||||
|
||||
if (!cwmp_transaction("commit")) {
|
||||
fault_code = FAULT_CPE_INTERNAL_ERROR;
|
||||
err_msg = "Failed to commit the transaction";
|
||||
goto fault;
|
||||
}
|
||||
|
||||
icwmp_restart_services(RELOAD_IMMIDIATE);
|
||||
|
||||
int status = 0;
|
||||
if (end_session_reload_pending() == true) {
|
||||
status = 1;
|
||||
}
|
||||
|
||||
b = build_top_body_soap_response(cwmp_main->session->tree_out, "SetParameterValues");
|
||||
|
||||
if (!b) {
|
||||
|
|
@ -1138,8 +1151,6 @@ int cwmp_handle_rpc_cpe_set_parameter_values(struct rpc *rpc)
|
|||
goto fault;
|
||||
}
|
||||
|
||||
int status = 1;
|
||||
|
||||
struct xml_data_struct spv_resp_xml_attrs = {.status = &status};
|
||||
fault_code = build_xml_node_data(SOAP_RESP_SPV, b, &spv_resp_xml_attrs);
|
||||
if (fault_code) {
|
||||
|
|
@ -1147,13 +1158,11 @@ int cwmp_handle_rpc_cpe_set_parameter_values(struct rpc *rpc)
|
|||
goto fault;
|
||||
}
|
||||
|
||||
if (!cwmp_transaction("commit")) {
|
||||
fault_code = FAULT_CPE_INTERNAL_ERROR;
|
||||
err_msg = "Failed to commit the transaction";
|
||||
goto fault;
|
||||
cwmp_set_end_session(END_SESSION_SET_NOTIFICATION_UPDATE | END_SESSION_RELOAD);
|
||||
if (status == 1) {
|
||||
cwmp_set_end_session(END_SESSION_RESTART_SERVICES);
|
||||
}
|
||||
|
||||
cwmp_set_end_session(END_SESSION_RESTART_SERVICES | END_SESSION_SET_NOTIFICATION_UPDATE | END_SESSION_RELOAD);
|
||||
return 0;
|
||||
|
||||
fault:
|
||||
|
|
|
|||
|
|
@ -645,7 +645,7 @@ int run_session_end_func(void)
|
|||
|
||||
if (end_session_flag & END_SESSION_RESTART_SERVICES) {
|
||||
CWMP_LOG(INFO, "Restart modified services");
|
||||
icwmp_restart_services();
|
||||
icwmp_restart_services(RELOAD_END_SESSION);
|
||||
}
|
||||
|
||||
if (cwmp_apply_acs_changes() != CWMP_OK) {
|
||||
|
|
|
|||
|
|
@ -299,7 +299,7 @@ static void soap_add_object_message_test(void **state)
|
|||
|
||||
int ret = cwmp_handle_rpc_cpe_add_object(rpc_cpe);
|
||||
assert_int_equal(ret, 0);
|
||||
icwmp_restart_services();
|
||||
icwmp_restart_services(RELOAD_IMMIDIATE);
|
||||
|
||||
env = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND);
|
||||
assert_non_null(env);
|
||||
|
|
@ -451,7 +451,7 @@ static void soap_delete_object_message_test(void **state)
|
|||
|
||||
int ret = cwmp_handle_rpc_cpe_delete_object(rpc_cpe);
|
||||
assert_int_equal(ret, 0);
|
||||
icwmp_restart_services();
|
||||
icwmp_restart_services(RELOAD_IMMIDIATE);
|
||||
|
||||
env = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND);
|
||||
assert_non_null(env);
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ check_ret $?
|
|||
wait_for_session_end
|
||||
check_session "SetParameterValues"
|
||||
get_status=$(print_tag_value "cwmp:SetParameterValuesResponse" "Status")
|
||||
if [ "$get_status" != "1" ]; then
|
||||
if [ "$get_status" != "0" ]; then
|
||||
echo "Error: Set Value doesn't work correctly" >> ./funl-test-debug.log
|
||||
exit 1
|
||||
fi
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue