mirror of
				https://github.com/Telecominfraproject/wlan-ap.git
				synced 2025-10-29 09:32:34 +00:00 
			
		
		
		
	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
					Chaitanya Godavarthi
				
			
				
					committed by
					
						 Rick Sommerville
						Rick Sommerville
					
				
			
			
				
	
			
			
			 Rick Sommerville
						Rick Sommerville
					
				
			
						parent
						
							ebaa9b25ce
						
					
				
				
					commit
					53ad416396
				
			| @@ -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)) | ||||
|   | ||||
| @@ -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 | ||||
| } | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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,  | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
							
								
								
									
										7
									
								
								feeds/wlan-ap/opensync/files/bin/check_wan_link.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										7
									
								
								feeds/wlan-ap/opensync/files/bin/check_wan_link.sh
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| #!/bin/sh | ||||
|  | ||||
| if="$(uci get network.wan.ifname)" | ||||
| [ "$(cat /sys/class/net/"${if}"/carrier)" = 0 ] && { | ||||
| 	return 0 | ||||
| } | ||||
| return 1 | ||||
| @@ -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); | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user