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 <chaitanya.kiran@netexperience.com>
This commit is contained in:
Chaitanya Godavarthi
2021-05-19 22:25:53 -04:00
committed by Rick Sommerville
parent ebaa9b25ce
commit 53ad416396
7 changed files with 131 additions and 103 deletions

View File

@@ -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))

View File

@@ -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
}

View File

@@ -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;

View File

@@ -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,

View File

@@ -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;

View File

@@ -0,0 +1,7 @@
#!/bin/sh
if="$(uci get network.wan.ifname)"
[ "$(cat /sys/class/net/"${if}"/carrier)" = 0 ] && {
return 0
}
return 1

View File

@@ -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);