From 53ad4163969845054e9d83b4e4456deac5e31e13 Mon Sep 17 00:00:00 2001 From: Chaitanya Godavarthi Date: Wed, 19 May 2021 22:25:53 -0400 Subject: [PATCH] wifi-2342 wifi-2343: APC BDR/DR swap fix and monitor cloud connection -Reduced the BDR->DR swap time. -Monitor the cloud connection and start/stop APC based on the connection stability. Signed-off-by: Chaitanya Godavarthi --- feeds/wlan-ap/apc/Makefile | 3 - .../apc/files/etc/hotplug.d/iface/30-apc | 11 -- feeds/wlan-ap/apc/src/src/iface.c | 2 +- feeds/wlan-ap/apc/src/src/neighbor.c | 3 +- feeds/wlan-ap/apc/src/src/ubus.c | 60 +++++-- .../opensync/files/bin/check_wan_link.sh | 7 + .../openwrt/src/lib/target/src/radio.c | 148 +++++++++--------- 7 files changed, 131 insertions(+), 103 deletions(-) delete mode 100644 feeds/wlan-ap/apc/files/etc/hotplug.d/iface/30-apc create mode 100755 feeds/wlan-ap/opensync/files/bin/check_wan_link.sh diff --git a/feeds/wlan-ap/apc/Makefile b/feeds/wlan-ap/apc/Makefile index 9efae2f0e..571bb039c 100644 --- a/feeds/wlan-ap/apc/Makefile +++ b/feeds/wlan-ap/apc/Makefile @@ -38,9 +38,6 @@ define Package/apc/install $(INSTALL_BIN) ./files/apc.init $(1)/etc/init.d/apc $(INSTALL_DIR) $(1)/etc/config $(INSTALL_BIN) ./files/apc.config $(1)/etc/config/apc - $(INSTALL_DIR) $(1)/etc/hotplug.d/iface - $(INSTALL_BIN) ./files/etc/hotplug.d/iface/30-apc $(1)/etc/hotplug.d/iface/30-apc - endef $(eval $(call BuildPackage,apc)) diff --git a/feeds/wlan-ap/apc/files/etc/hotplug.d/iface/30-apc b/feeds/wlan-ap/apc/files/etc/hotplug.d/iface/30-apc deleted file mode 100644 index a2c1700d1..000000000 --- a/feeds/wlan-ap/apc/files/etc/hotplug.d/iface/30-apc +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh -[ wan = "$INTERFACE" ] || exit 0 -[ "$ACTION" = ifup -o "$ACTION" = ifdown ] || exit 0 - -[ ifup = "$ACTION" ] && { - /etc/init.d/apc start -} - -[ ifdown = "$ACTION" ] && { - /etc/init.d/apc stop -} diff --git a/feeds/wlan-ap/apc/src/src/iface.c b/feeds/wlan-ap/apc/src/src/iface.c index d86395299..aee0891c6 100755 --- a/feeds/wlan-ap/apc/src/src/iface.c +++ b/feeds/wlan-ap/apc/src/src/iface.c @@ -168,7 +168,7 @@ void apc_iface_new( void ) ifa->priority = 0x11; ifa->drip = MyIpAddr; ifa->helloint = 4; - ifa->deadint = 16; + ifa->deadint = 12; ifa->waitint = 16; ifa->type = APC_IT_BCAST; diff --git a/feeds/wlan-ap/apc/src/src/neighbor.c b/feeds/wlan-ap/apc/src/src/neighbor.c index b9019c873..1b3c15879 100755 --- a/feeds/wlan-ap/apc/src/src/neighbor.c +++ b/feeds/wlan-ap/apc/src/src/neighbor.c @@ -491,7 +491,8 @@ static void inactivity_timer_hook(struct _timer * tmr) apc_ifa->drip = MyIpAddr; apc_ifa->bdrip = 0; memset(&ApcSpec, 0, sizeof(struct apc_spec)); - WaitingToReelect = 12; + WaitingToReelect = 3; + return; } printf("Inactivity timer expired for nbr %x on %s", n->rid, diff --git a/feeds/wlan-ap/apc/src/src/ubus.c b/feeds/wlan-ap/apc/src/src/ubus.c index ad57113cf..d09f4645e 100644 --- a/feeds/wlan-ap/apc/src/src/ubus.c +++ b/feeds/wlan-ap/apc/src/src/ubus.c @@ -14,10 +14,16 @@ struct ubus_context *ubus_ctx = NULL; static struct blob_buf b; static struct blob_buf nb; -static const char *ubus_path; timer *notify_timer; extern struct apc_iface * apc_ifa; +/* Mandatorily Notify APC_State period */ #define APC_NOTIFY_INTERVAL 10 +/* Check if any change in APC State and notify period */ +#define APC_NOTIFY_CHECK 1 +static ip_addr old_drip; +static ip_addr old_bdrip; +static u8 old_state; +static unsigned int ucount = 0; struct apc_state { char mode[4]; @@ -95,26 +101,44 @@ apc_info_handle(struct ubus_context *ctx, struct ubus_object *obj, } static char apc_mode[APC_MAX_MODE][8] = {"DOWN", "LOOP", "WT", "PTP", "OR", "BDR", "DR"}; -void apc_update_state() +int apc_update_state(void) { struct in_addr dr_addr; struct in_addr bdr_addr; - dr_addr.s_addr = htonl(apc_ifa->drip); - bdr_addr.s_addr = htonl(apc_ifa->bdrip); + ip_addr cur_drip; + ip_addr cur_bdrip; + u8 cur_state; + + cur_drip = apc_ifa->drip; + cur_bdrip = apc_ifa->bdrip; + cur_state = apc_ifa->state; + ucount++; + + if (cur_drip == old_drip && + cur_bdrip == old_bdrip && + cur_state == old_state && ucount < APC_NOTIFY_INTERVAL) { + return -1; + } + + printf("APC State update %u", ucount); + ucount = 0; + + dr_addr.s_addr = htonl(cur_drip); + bdr_addr.s_addr = htonl(cur_bdrip); state.enabled = true; - if ((apc_ifa->state == APC_IS_DR) || - (apc_ifa->state == APC_IS_BACKUP) || - (apc_ifa->state == APC_IS_DROTHER)) { + if ((cur_state == APC_IS_DR) || + (cur_state == APC_IS_BACKUP) || + (cur_state == APC_IS_DROTHER)) { snprintf(state.mode, sizeof(state.mode), "%s", - &apc_mode[apc_ifa->state][0]); + &apc_mode[cur_state][0]); snprintf(state.dr_addr, sizeof(state.dr_addr), "%s", inet_ntoa(dr_addr)); snprintf(state.bdr_addr, sizeof(state.bdr_addr), "%s", inet_ntoa(bdr_addr)); } else if (apc_ifa->state == APC_IS_WAITING) { snprintf(state.mode, sizeof(state.mode), "%s", - &apc_mode[apc_ifa->state][0]); + &apc_mode[cur_state][0]); snprintf(state.dr_addr, sizeof(state.dr_addr), "0.0.0.0"); snprintf(state.bdr_addr, sizeof(state.bdr_addr), "0.0.0.0"); } else { @@ -122,11 +146,21 @@ void apc_update_state() snprintf(state.dr_addr, sizeof(state.dr_addr), "0.0.0.0"); snprintf(state.bdr_addr, sizeof(state.bdr_addr), "0.0.0.0"); } + + old_drip = cur_drip; + old_bdrip = cur_bdrip; + old_state = cur_state; + + return 0; } void apc_send_notification(struct _timer * tmr) { - apc_update_state(); + int ustate = 0; + + ustate = apc_update_state(); + if(ustate != 0) + return; printf("APC send ubus notification\n"); blob_buf_init(&nb, 0); @@ -159,10 +193,10 @@ ubus_init(void) { #endif add_object(&apc_object); notify_timer = tm_new_set(apc_send_notification, NULL, - 0, APC_NOTIFY_INTERVAL); + 0, APC_NOTIFY_CHECK); if (notify_timer) { - printf("APC Start notify timer\n"); - tm_start(notify_timer, APC_NOTIFY_INTERVAL); + printf("APC Start state check and notify timer\n"); + tm_start(notify_timer, APC_NOTIFY_CHECK); } ubus_ctx->connection_lost = ubus_connection_lost; diff --git a/feeds/wlan-ap/opensync/files/bin/check_wan_link.sh b/feeds/wlan-ap/opensync/files/bin/check_wan_link.sh new file mode 100755 index 000000000..ce6d74489 --- /dev/null +++ b/feeds/wlan-ap/opensync/files/bin/check_wan_link.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +if="$(uci get network.wan.ifname)" +[ "$(cat /sys/class/net/"${if}"/carrier)" = 0 ] && { + return 0 +} +return 1 diff --git a/feeds/wlan-ap/opensync/src/platform/openwrt/src/lib/target/src/radio.c b/feeds/wlan-ap/opensync/src/platform/openwrt/src/lib/target/src/radio.c index ac914f4e3..c26e525a5 100755 --- a/feeds/wlan-ap/opensync/src/platform/openwrt/src/lib/target/src/radio.c +++ b/feeds/wlan-ap/opensync/src/platform/openwrt/src/lib/target/src/radio.c @@ -781,12 +781,12 @@ void apc_state_set(struct blob_attr *msg) blobmsg_get_string(tb[APC_ATTR_MODE])); } if (tb[APC_ATTR_DR_ADDR]) { - LOGD("APC br-addr: %s", blobmsg_get_string(tb[APC_ATTR_DR_ADDR])); + LOGD("APC dr-addr: %s", blobmsg_get_string(tb[APC_ATTR_DR_ADDR])); SCHEMA_SET_STR(apc_state.dr_addr, blobmsg_get_string(tb[APC_ATTR_DR_ADDR])); } if (tb[APC_ATTR_BDR_ADDR]) { - LOGD("APC dbr-addr: %s", blobmsg_get_string(tb[APC_ATTR_BDR_ADDR])); + LOGD("APC bdr-addr: %s", blobmsg_get_string(tb[APC_ATTR_BDR_ADDR])); SCHEMA_SET_STR(apc_state.bdr_addr, blobmsg_get_string(tb[APC_ATTR_BDR_ADDR])); } @@ -800,106 +800,106 @@ void apc_state_set(struct blob_attr *msg) } } - LOGD("APC_state Updating"); + LOGI("APC_state Updating: mode: %s, dr-addr: %s bdr-addr: %s", + apc_state.mode, apc_state.dr_addr, apc_state.bdr_addr); + if (!ovsdb_table_update(&table_APC_State, &apc_state)) LOG(ERR, "APC_state: failed to update"); + } static ovsdb_table_t table_Manager; -ev_timer apc_cld_mon_timer; -ev_timer apc_cld_disconn_timer; -ev_timer apc_backoff_timer; -#define APC_CLD_MON_TIME 5 -#define APC_CLD_DISCONN_TIME 60 -#define APC_BKOFF_TIME 60 +static int conn_since = 0; +#define APC_CLOUD_MON_PERIOD 60 + +static void apc_enable(bool flag) { + + SCHEMA_SET_INT(apc_conf.enabled, flag); + if (!ovsdb_table_update(&table_APC_Config, &apc_conf)) { + LOG(ERR, "%s:APC_Config: failed to update", __func__); + return; + } + LOGI("APC %s: %s APC", __func__, flag?"enable":"disable"); + +} static void -apc_cld_mon_cb(struct ev_loop *loop, ev_timer *timer, int revents) +apc_cld_mon_cb(struct schema_Manager *mgr) { - struct schema_APC_State state; - struct schema_Manager mgr; + int i = 0; + conn_since = 0; + struct schema_APC_State apc_state; json_t *where; + int ret = 0; + int link = 1; - where = ovsdb_table_where(&table_APC_State, &state); + where = ovsdb_table_where(&table_APC_State, &apc_state); if (false == ovsdb_table_select_one_where(&table_APC_State, - where, &state)) { + where, &apc_state)) { LOG(ERR, "%s: APC_State read failed", __func__); return; } - /*If not DR and not BDR the dont proceed */ - if ((strncmp(state.mode, "DR", 2) != 0) && - (strncmp(state.mode, "BDR", 3) != 0)) - return; - /*If BDR addr is 0 means its a standalone DR*/ - if ((strncmp(state.bdr_addr, "0.0.0.0", 7) == 0)) - return; - where = ovsdb_table_where(&table_Manager, &mgr); - if (false == ovsdb_table_select_one_where(&table_Manager, - where, &mgr)) { - LOG(ERR, "%s: Manager read failed", __func__); - return; + /*Checks if wan ethernet port is down and disables apc*/ + ret = system("/bin/check_wan_link.sh"); + if (WIFEXITED(ret)) { + LOGI("The return value: %d\n", WEXITSTATUS(ret)); + link = WEXITSTATUS(ret); + if (link == 0) { + apc_enable(false); + return; + } } - if (mgr.is_connected == false) { - if (!ev_is_active(&apc_cld_disconn_timer) && - !ev_is_pending(&apc_cld_disconn_timer)) { - LOGI("%s: START apc_cld_disconn_timer, %s", - __func__, state.mode); - ev_timer_set(&apc_cld_disconn_timer, - APC_CLD_DISCONN_TIME, 0); - ev_timer_start(EV_DEFAULT, &apc_cld_disconn_timer); - } + /*if cloud conn is false then disable apc*/ + if (mgr->is_connected == false) { + apc_enable(false); } else { - if (ev_is_active(&apc_cld_disconn_timer)) { - LOGI("%s: STOP apc_cld_disconn_timer", __func__); - ev_timer_stop(EV_DEFAULT, &apc_cld_disconn_timer); + for(i=0; i < mgr->status_len; i++) { + if(!strncmp(mgr->status_keys[i] , "sec_since_connect", + strlen("sec_since_connect"))) { + conn_since = atoi(mgr->status[i]); + LOGI("conn_since: %d", conn_since); + break; + } + } + + /*if the APC was stopped earlier, start it if connection good + * for atleast 60 secs*/ + if (!apc_state.enabled && conn_since > APC_CLOUD_MON_PERIOD) { + apc_enable(true); } } } -static void -apc_backoff_cb(struct ev_loop *loop, ev_timer *timer, int revents) +/*Monitor the cloud connection*/ +static void callback_Manager(ovsdb_update_monitor_t *mon, + struct schema_Manager *old, + struct schema_Manager *conf) { - LOGI("%s: Enable APC, STOP apc_backoff_timer", __func__); - SCHEMA_SET_INT(apc_conf.enabled, true); - if (!ovsdb_table_update(&table_APC_Config, &apc_conf)) - LOG(ERR, "%s: APC_Config: failed to update", __func__); + switch (mon->mon_type) + { + case OVSDB_UPDATE_NEW: + case OVSDB_UPDATE_MODIFY: + apc_cld_mon_cb(conf); + break; - ev_timer_stop(EV_DEFAULT, &apc_backoff_timer); -} + case OVSDB_UPDATE_DEL: + apc_enable(false); + break; -static void -apc_cld_disconn_cb(struct ev_loop *loop, ev_timer *timer, int revents) -{ - LOGI("%s: Disable APC , START apc_backoff_timer", __func__); - SCHEMA_SET_INT(apc_conf.enabled, false); - if (!ovsdb_table_update(&table_APC_Config, &apc_conf)) { - LOG(ERR, "%s:APC_Config: failed to update", __func__); - ev_timer_stop(EV_DEFAULT, &apc_cld_disconn_timer); - return; + default: + break; } - - ev_timer_set(&apc_backoff_timer, APC_BKOFF_TIME, 0); - ev_timer_start(EV_DEFAULT, &apc_backoff_timer); - - ev_timer_stop(EV_DEFAULT, &apc_cld_disconn_timer); + return; } void cloud_disconn_mon(void) { - ev_init(&apc_cld_mon_timer, apc_cld_mon_cb); - apc_cld_mon_timer.repeat = APC_CLD_MON_TIME; - ev_timer_again(EV_DEFAULT, &apc_cld_mon_timer); - - ev_timer_init(&apc_cld_disconn_timer, apc_cld_disconn_cb, - APC_CLD_DISCONN_TIME, 0); - ev_timer_init(&apc_backoff_timer, apc_backoff_cb, - APC_BKOFF_TIME, 0); - OVSDB_TABLE_INIT_NO_KEY(Manager); + OVSDB_TABLE_MONITOR(Manager, false); } void apc_init() @@ -907,7 +907,8 @@ void apc_init() /* APC Config */ OVSDB_TABLE_INIT_NO_KEY(APC_Config); OVSDB_TABLE_MONITOR(APC_Config, false); - SCHEMA_SET_INT(apc_conf.enabled, true); + /* Disable APC by default, enable when cloud connected*/ + SCHEMA_SET_INT(apc_conf.enabled, false); LOGI("APC state/config Initialize"); if (!ovsdb_table_insert(&table_APC_Config, &apc_conf)) { LOG(ERR, "APC_Config: failed to initialize"); @@ -927,9 +928,8 @@ void apc_init() } /* Cloud connection monitor - if cloud unreachable - * for certain time, disable APC and enable after a - * back-off time. This triggers relection of DR among - * other APs*/ + * for certain time, disable APC and enable after the + * cloud connection becomes stable. */ cloud_disconn_mon(); } @@ -962,12 +962,12 @@ bool target_radio_init(const struct target_radio_ops *ops) OVSDB_TABLE_INIT(Radius_Proxy_Config, _uuid); OVSDB_TABLE_MONITOR(Radius_Proxy_Config, false); - apc_init(); evsched_task(&periodic_task, NULL, EVSCHED_SEC(5)); radio_nl80211_init(); radio_ubus_init(); + apc_init(); clock_gettime(CLOCK_MONOTONIC, &startup_time);