T#8134: ACS connectivity issue after bootup

This commit is contained in:
suvendhu 2022-06-06 11:35:21 +05:30 committed by Vivek Kumar Dutta
parent a3be4dd092
commit 23e16013be
11 changed files with 272 additions and 53 deletions

View file

@ -718,17 +718,21 @@ int get_connection_interface()
struct blob_buf b = { 0 };
memset(&b, 0, sizeof(struct blob_buf));
blob_buf_init(&b, 0);
bb_add_string(&b, "interface", cwmp_main.conf.default_wan_iface);
int e = icwmp_ubus_invoke("network.interface", "status", b.head, ubus_network_interface_callback, NULL);
char ubus_obj[100] = {0};
snprintf(ubus_obj, sizeof(ubus_obj), "network.interface.%s", cwmp_main.conf.default_wan_iface);
FREE(cwmp_main.conf.interface);
int e = icwmp_ubus_invoke(ubus_obj, "status", b.head, ubus_network_interface_callback, NULL);
blob_buf_free(&b);
if (e != 0) {
CWMP_LOG(INFO, "Get network interface from network.interface ubus method failed. Ubus err code: %d", e);
CWMP_LOG(INFO, "Get network interface from %s ubus method failed. Ubus err code: %d", ubus_obj, e);
return -1;
}
if (cwmp_main.conf.interface == NULL) {
CWMP_LOG(INFO, "Not able to get the network interface from network.interface ubus method.");
CWMP_LOG(INFO, "Not able to get the network interface from %s ubus method.", ubus_obj);
return -1;
}
return CWMP_OK;

199
config.c
View file

@ -15,18 +15,153 @@
#include "config.h"
#include "log.h"
#include "reboot.h"
#include "ubus_utils.h"
#include "ssl_utils.h"
#include "datamodel_interface.h"
#include "heartbeat.h"
pthread_mutex_t mutex_config_load = PTHREAD_MUTEX_INITIALIZER;
static int check_global_config(struct config *conf)
void get_dhcp_vend_info_cb(struct ubus_request *req, int type __attribute__((unused)), struct blob_attr *msg)
{
if (conf->acsurl == NULL) {
conf->acsurl = strdup(DEFAULT_ACSURL);
if (req == NULL || msg == NULL)
return;
char **v_info = (char **)req->priv;
if (v_info == NULL)
return;
struct blob_attr *param;
size_t rem;
enum {
E_VENDOR_INFO,
__E_MAX
};
const struct blobmsg_policy p[__E_MAX] = {
{ "vendorspecinf", BLOBMSG_TYPE_STRING },
};
blobmsg_for_each_attr(param, msg, rem) {
if (strcmp(blobmsg_name(param), "data") == 0) {
struct blob_attr *tb[__E_MAX] = {NULL};
if (blobmsg_parse(p, __E_MAX, tb, blobmsg_data(param), blobmsg_len(param)) != 0) {
return;
}
if (tb[E_VENDOR_INFO]) {
char *info = blobmsg_get_string(tb[E_VENDOR_INFO]);
int len = strlen(info) + 1;
*v_info = (char *)malloc(len);
if (*v_info == NULL)
return;
memset(*v_info, 0, len);
snprintf(*v_info, len, "%s", info);
}
break;
}
}
return CWMP_OK;
return;
}
bool configure_dhcp_options(char *vendspecinf)
{
if (vendspecinf == NULL) {
CWMP_LOG(DEBUG, "No vendor specific info found");
return false;
}
// extract url from vendor info
int len = CWMP_STRLEN(vendspecinf) + 1;
char vend_info[len];
memset(vend_info, 0, len);
snprintf(vend_info, len, "%s", vendspecinf);
if (strncmp(vend_info, "http://", 7) == 0 || strncmp(vend_info, "https://", 8) == 0) {
uci_set_value_by_path(UCI_DHCP_ACS_URL, vend_info, UCI_STANDARD_CONFIG);
CWMP_LOG(DEBUG, "dhcp url: %s", vend_info);
cwmp_commit_package("cwmp", UCI_STANDARD_CONFIG);
return true;
}
bool update_uci = false;
char *temp = strtok(vend_info, " ");
while (temp) {
if (strncmp(temp, "1=", 2) == 0) {
char *pos = temp + 2;
if (CWMP_STRLEN(pos)) {
uci_set_value_by_path(UCI_DHCP_ACS_URL, pos, UCI_STANDARD_CONFIG);
CWMP_LOG(DEBUG, "dhcp url: %s", pos);
update_uci = true;
}
}
if (strncmp(temp, "2=", 2) == 0) {
char *pos = temp + 2;
if (CWMP_STRLEN(pos)) {
uci_set_value_by_path(UCI_DHCP_CPE_PROV_CODE, pos, UCI_STANDARD_CONFIG);
update_uci = true;
}
}
if (strncmp(temp, "3=", 2) == 0) {
char *pos = temp + 2;
if (CWMP_STRLEN(pos)) {
uci_set_value_by_path(UCI_DHCP_ACS_RETRY_MIN_WAIT_INTERVAL, pos, UCI_STANDARD_CONFIG);
update_uci = true;
}
}
if (strncmp(temp, "4=", 2) == 0) {
char *pos = temp + 2;
if (CWMP_STRLEN(pos)) {
uci_set_value_by_path(UCI_DHCP_ACS_RETRY_INTERVAL_MULTIPLIER, pos, UCI_STANDARD_CONFIG);
update_uci = true;
}
}
temp = strtok(NULL, " ");
}
if (update_uci)
cwmp_commit_package("cwmp", UCI_STANDARD_CONFIG);
return update_uci;
}
static void get_dhcp_vendor_info(char *intf)
{
if (intf == NULL)
return;
char ubus_obj[100] = {0};
snprintf(ubus_obj, sizeof(ubus_obj), "network.interface.%s", intf);
struct blob_buf b;
memset(&b, 0, sizeof(struct blob_buf));
blob_buf_init(&b, 0);
for (int i = 0; i < DHCP_OPTION_READ_MAX_RETRY; i++) {
char *vendor_info = NULL;
if (icwmp_ubus_invoke(ubus_obj, "status", b.head, get_dhcp_vend_info_cb, &vendor_info) == 0) {
CWMP_LOG(DEBUG, "vendor info: %s", vendor_info);
if (configure_dhcp_options(vendor_info)) {
FREE(vendor_info);
break;
}
}
FREE(vendor_info);
CWMP_LOG(INFO, "Failed to read dhcp acs url from ifstatus, retry after %d sec.", DHCP_OPTION_READ_INTERVAL);
sleep(DHCP_OPTION_READ_INTERVAL);
}
blob_buf_free(&b);
}
int get_global_config(struct config *conf)
@ -90,22 +225,49 @@ int get_global_config(struct config *conf)
return error;
}
if ((error = uci_get_value(UCI_CPE_DEFAULT_WAN_IFACE, &value)) == CWMP_OK) {
FREE(conf->default_wan_iface);
if (value != NULL) {
conf->default_wan_iface = strdup(value);
FREE(value);
} else {
conf->default_wan_iface = strdup("wan");
}
CWMP_LOG(DEBUG, "CWMP CONFIG - default wan interface: %s", conf->default_wan_iface ? conf->default_wan_iface : "");
} else {
return error;
}
error = uci_get_value(UCI_DHCP_DISCOVERY_PATH, &value);
// now read the vendor info from ifstatus before reading the DHCP_ACS_URL from uci
if (error == CWMP_OK && value != NULL) {
if (strcmp(value, "enable") == 0 && conf->default_wan_iface != NULL) {
get_dhcp_vendor_info(conf->default_wan_iface);
}
}
error2 = uci_get_value(UCI_ACS_URL_PATH, &value2);
error3 = uci_get_value(UCI_DHCP_ACS_URL, &value3);
FREE(conf->acsurl);
if ((((error == CWMP_OK) && (value != NULL) && (strcmp(value, "enable") == 0)) || ((error2 == CWMP_OK) && ((value2 == NULL) || (value2[0] == 0)))) && ((error3 == CWMP_OK) && (value3 != NULL) && (value3[0] != 0))) {
FREE(conf->acsurl);
conf->acsurl = strdup(value3);
} else if ((error2 == CWMP_OK) && (value2 != NULL) && (value2[0] != 0)) {
FREE(conf->acsurl);
conf->acsurl = strdup(value2);
}
CWMP_LOG(DEBUG, "CWMP CONFIG - acs url: %s", conf->acsurl ? conf->acsurl : "");
FREE(value);
FREE(value2);
FREE(value3);
if (conf->acsurl == NULL) {
CWMP_LOG(ERROR, "ACS URL is Null");
return -1;
}
if ((error = uci_get_value(UCI_ACS_USERID_PATH, &value)) == CWMP_OK) {
if (value != NULL) {
FREE(conf->acs_userid);
@ -304,20 +466,6 @@ int get_global_config(struct config *conf)
return error;
}
if ((error = uci_get_value(UCI_CPE_DEFAULT_WAN_IFACE, &value)) == CWMP_OK) {
FREE(conf->default_wan_iface);
if (value != NULL) {
conf->default_wan_iface = strdup(value);
FREE(value);
} else {
conf->default_wan_iface = strdup("wan");
}
CWMP_LOG(DEBUG, "CWMP CONFIG - default wan interface: %s", conf->default_wan_iface ? conf->default_wan_iface : "");
} else {
return error;
}
if ((error = uci_get_value(UCI_CPE_CRPATH_PATH, &value)) == CWMP_OK) {
FREE(conf->connection_request_path);
if (value == NULL)
@ -651,11 +799,14 @@ int global_conf_init(struct cwmp *cwmp)
if ((error = get_global_config(&(cwmp->conf))))
goto end;
if ((error = check_global_config(&(cwmp->conf))))
goto end;
error = get_connection_interface();
while (error != CWMP_OK && thread_end != true) {
usleep(500);
error = get_connection_interface();
}
if ((error = get_connection_interface()))
return -1;
if (error != CWMP_OK)
goto end;
/* Launch reboot methods if needed */
launch_reboot_methods(cwmp);

25
cwmp.c
View file

@ -268,7 +268,11 @@ int run_session_end_func(void)
if (end_session_flag & END_SESSION_RELOAD) {
CWMP_LOG(INFO, "Config reload: end session request");
cwmp_uci_reinit();
cwmp_apply_acs_changes();
if (cwmp_apply_acs_changes() != CWMP_OK) {
// calling exit to avoid race condition
CWMP_LOG(CRITIC, "terminating cwmp service");
exit(0);
}
check_trigger_heartbeat_session();
}
@ -767,8 +771,10 @@ static int cwmp_init(int argc, char **argv, struct cwmp *cwmp)
return error;
cwmp_uci_init();
if ((error = global_conf_init(cwmp)))
if ((error = global_conf_init(cwmp))) {
cwmp_uci_exit();
return error;
}
cwmp_get_deviceid(cwmp);
load_forced_inform_json_file(cwmp);
@ -821,6 +827,8 @@ static void icwmp_signal_handler(int signal_num)
if (signal_num == SIGINT || signal_num == SIGTERM) {
thread_end = true;
CWMP_LOG(INFO, "Received signal %d", signal_num);
if (cwmp_main.session_status.last_status == SESSION_RUNNING)
http_set_timeout();
@ -833,6 +841,8 @@ static void icwmp_signal_handler(int signal_num)
pthread_cond_signal(&threshold_schedule_download);
pthread_cond_signal(&threshold_apply_schedule_download);
pthread_cond_signal(&threshold_upload);
pthread_cond_signal(&threshold_heartbeat_session);
pthread_cond_signal(&threasheld_retry_session);
shutdown(cwmp_main.cr_socket_desc, SHUT_RDWR);
}
@ -883,16 +893,16 @@ int main(int argc, char **argv)
sigaction(SIGINT, &act, 0);
sigaction(SIGTERM, &act, 0);
error = pthread_create(&http_cr_server_thread, NULL, &thread_http_cr_server_listen, NULL);
if (error < 0) {
CWMP_LOG(ERROR, "Error when creating the http connection request server thread!");
}
error = pthread_create(&ubus_thread, NULL, &thread_uloop_run, NULL);
if (error < 0) {
CWMP_LOG(ERROR, "Error when creating the ubus thread!");
}
error = pthread_create(&http_cr_server_thread, NULL, &thread_http_cr_server_listen, NULL);
if (error < 0) {
CWMP_LOG(ERROR, "Error when creating the http connection request server thread!");
}
error = pthread_create(&periodic_event_thread, NULL, &thread_event_periodic, (void *)cwmp);
if (error < 0) {
CWMP_LOG(ERROR, "Error when creating the periodic event thread!");
@ -902,6 +912,7 @@ int main(int argc, char **argv)
if (error < 0) {
CWMP_LOG(ERROR, "Error when creating the periodic check notify thread!");
}
error = pthread_create(&heart_beat_session_thread, NULL, &thread_heartbeat_session, (void *)cwmp);
if (error < 0) {
CWMP_LOG(ERROR, "Error when creating heartbeat session thread!");

View file

@ -21,9 +21,6 @@ supervisorctl status all
echo "Configuring genieacs"
configure_genieacs
echo "Configuring ACS URL"
configure_acs_url
mkdir -p /var/state/icwmpd
echo "Starting icwmpd deamon"

View file

@ -13,6 +13,12 @@ rm -rf /etc/supervisor/conf.d/*.conf
cp ./gitlab-ci/iopsys-supervisord.conf /etc/supervisor/conf.d/
cp -rf ./test/files/* /
echo "set acs url in cwmp uci"
url="http://$(hostname -i):7547"
uci set cwmp.acs.url=$url
uci commit cwmp
echo "Current ACS URL=$url"
# copy schema for validation test
cp -r ./schemas/ubus/*.json /usr/share/rpcd/schemas/

View file

@ -74,18 +74,23 @@ function configure_download_firmware()
echo "Invalid" > /tmp/firmware/invalid_firmware_v1.0.bin
}
function configure_acs_url()
{
url="http://$(hostname -i):7547"
uci set cwmp.acs.url=$url
uci commit cwmp
echo "Current ACS URL=$url"
}
function check_cwmp_status()
{
status=`ubus call tr069 status | jq -r ".cwmp.status"`
if [ $status != "up" ]; then
iter=0
state=0
while [ $iter -lt 10 ]
do
status=`ubus call tr069 status | jq -r ".cwmp.status"`
if [ $status == "up" ]; then
state=1
break
fi
iter=$(( $iter + 1))
sleep 2
done
if [ $state -eq 0 ]; then
echo "icwmpd is not started correctly, (the current status=$status)"
exit 1
fi

View file

@ -51,6 +51,9 @@ void *thread_heartbeat_session(void *v __attribute__((unused)))
sleep(2);
for (;;) {
if (thread_end)
break;
if (cwmp_main.conf.heart_beat_enable) {
heartbeat_interval.tv_sec = time(NULL) + cwmp_main.conf.heartbeat_interval;
pthread_mutex_lock(&mutex_heartbeat);
@ -64,6 +67,9 @@ void *thread_heartbeat_session(void *v __attribute__((unused)))
//continue;
}
if (thread_end)
break;
pthread_mutex_lock(&mutex_heartbeat_session);
struct session *heartbeat_session = NULL;
heartbeat_session = calloc(1, sizeof(struct session));
@ -89,6 +95,7 @@ void *thread_heartbeat_session(void *v __attribute__((unused)))
pthread_mutex_unlock(&mutex_heartbeat);
continue;
}
cwmp_uci_init();
if (heart_beat_session_status.last_status == SESSION_FAILURE)
reload_networking_config();
@ -111,7 +118,8 @@ void *thread_heartbeat_session(void *v __attribute__((unused)))
cwmp_uci_exit();
pthread_mutex_unlock(&(cwmp_main.mutex_session_send));
pthread_mutex_unlock(&mutex_heartbeat);
break;
// Exiting to avoid race conditions
exit(0);
}
if (error || heartbeat_session->error == CWMP_RETRY_SESSION) {
@ -141,9 +149,6 @@ void *thread_heartbeat_session(void *v __attribute__((unused)))
cwmp_uci_exit();
pthread_mutex_unlock(&mutex_heartbeat_session);
pthread_mutex_unlock(&mutex_heartbeat);
if (thread_end)
break;
} else {
pthread_mutex_lock(&mutex_heartbeat);
pthread_cond_wait(&threshold_heartbeat_session, &mutex_heartbeat);

View file

@ -61,6 +61,9 @@
#define UCI_ACS_HEARTBEAT_ENABLE "cwmp.acs.heartbeat_enable"
#define UCI_ACS_HEARTBEAT_INTERVAL "cwmp.acs.heartbeat_interval"
#define UCI_ACS_HEARTBEAT_TIME "cwmp.acs.heartbeat_time"
#define UCI_DHCP_CPE_PROV_CODE "cwmp.cpe.dhcp_provisioning_code"
#define UCI_DHCP_ACS_RETRY_MIN_WAIT_INTERVAL "cwmp.acs.dhcp_retry_min_wait_interval"
#define UCI_DHCP_ACS_RETRY_INTERVAL_MULTIPLIER "cwmp.acs.dhcp_retry_interval_multiplier"
#define UCI_CPE_FIREWALL_RESTART_STATE "cwmp.cpe.firewall_restart"
@ -68,6 +71,8 @@
#define LIB_DB_CONFIG "/lib/db/config"
#define ETC_DB_CONFIG "/etc/board-db/config"
#define VARSTATE_CONFIG "/var/state"
#define DHCP_OPTION_READ_MAX_RETRY 5
#define DHCP_OPTION_READ_INTERVAL 5
#define section_name(s) s ? (s)->e.name : ""
typedef enum uci_config_paths

View file

@ -0,0 +1,14 @@
{
"up": true,
"pending": false,
"available": true,
"autostart": true,
"dynamic": false,
"uptime": 0,
"l3_device": "eth0",
"proto": "dhcp",
"device": "eth0",
"data": {
}
}

View file

@ -0,0 +1,17 @@
#!/bin/sh
. /usr/share/libubox/jshn.sh
case "$1" in
list)
echo '{ "status" : {} }'
;;
call)
case "$2" in
status)
cat /tmp/network.interface.wan.data 2>/dev/null
;;
esac
;;
esac

View file

@ -40,7 +40,11 @@ static int reload_cmd(struct blob_buf *b)
} else {
pthread_mutex_lock(&(cwmp_main.mutex_session_queue));
cwmp_uci_reinit();
cwmp_apply_acs_changes();
if (cwmp_apply_acs_changes() != CWMP_OK) {
// Exiting to avoid any race condition
CWMP_LOG(CRITIC, "cwmp service terminating");
exit(0);
}
pthread_mutex_unlock(&(cwmp_main.mutex_session_queue));
blobmsg_add_u32(b, "status", 0);
blobmsg_add_string(b, "info", "icwmpd config reloaded");