From 9203246714aa04a5c8440c55ad407e1c2b0e47b8 Mon Sep 17 00:00:00 2001
From: "nevadita.chatterjee" <nevadita.chatterjee@iopsys.eu>
Date: Wed, 8 Sep 2021 15:20:38 +0530
Subject: [PATCH] mapagent:init according to config preference

---
 src/agent.c     |  49 ++++++++++++++--
 src/agent.h     |   7 ++-
 src/agent_map.c | 146 ++++++++++++++++++++++++++++++++++--------------
 src/config.c    |   4 +-
 4 files changed, 157 insertions(+), 49 deletions(-)

diff --git a/src/agent.c b/src/agent.c
index 8d8347185..3fb6cbfd1 100644
--- a/src/agent.c
+++ b/src/agent.c
@@ -3392,10 +3392,46 @@ int agent_fill_channel_preference_default(struct wifi_radio_element *radio)
         }
 }
 
+int agent_switch_according_to_pref(struct agent *a)
+{
+        uint32_t channel = 0;
+        uint32_t opclass = 0;
+        int ret = 0 , l = 0;
+	struct wifi_radio_element *radio;
+
+	trace("agent: %s: --->\n", __func__);
+
+	for (l = 0; l < a->num_radios; l++) {
+                radio = a->radios + l;
+
+	        ret = agent_get_highest_preference(radio, radio->current_opclass, &channel,
+                                                &opclass);
+        	/* The operating class channel preference has been set
+         	* now we want to switch the channel to the max preference */
+		trace("agent: %s: opclass is %d channel is %d--->\n", __func__, opclass, channel);
+		if ((radio->current_opclass == opclass) && (radio->current_channel == channel))
+				continue;
+         	if (channel != 0 && opclass != 0 ) {
+                	ret = agent_channel_switch(a, radio->macaddr, channel, opclass);
+                	if (ret == -1) {
+
+                        	/*Here we need to set the default preference for all the
+                         	* channels in that operating class also set the response code as rejected*/
+                         //	agent_set_channel_preference_to_default(radio);
+			}
+		}
+        }
+        return 0;
+}
+
+
 static void parse_radio(struct ubus_request *req, int type,
 		struct blob_attr *msg)
 {
-	struct wifi_radio_element *re = (struct wifi_radio_element *)req->priv;
+	struct radio_tmp *re_tmp = (struct wifi_radio_element *)req->priv;
+	struct wifi_radio_element *re = re_tmp->r;
+	struct agent *a = re_tmp->a;
+
 	fprintf(stdout, "%s ---> %s\n", __func__, re->name);
 	int rem, remm, rem1, j = 0, i  = 0;
 	struct blob_attr *tb[12];
@@ -3531,8 +3567,6 @@ static void parse_radio(struct ubus_request *req, int type,
 				re->scanlist->opclass_scanlist[i].bandwidth = blobmsg_get_u32(data[3]);
 			i++;
 		}
-		//Add the config to preference writing here
-        //	agent_config_opclass(re);
 	}
 	if (tb[6])
 		re->current_opclass = (uint8_t) blobmsg_get_u32(tb[6]);
@@ -3721,6 +3755,8 @@ static void _enumerate_wifi_objects(struct ubus_request *req, int type,
 	struct json_object *radio_array;
 	char *json_str;
 	int i, j, k, len;
+	struct radio_tmp *radio_tmp_param;
+
 
 	json_str = blobmsg_format_json(msg, true);
 	if (!json_str)
@@ -3808,7 +3844,10 @@ static void _enumerate_wifi_objects(struct ubus_request *req, int type,
 		}
 		// On-boot channel scan
 		// ubus call wifi.radio.wl0 status
-		ubus_call_object(a, r_wobj, "status", parse_radio, &a->radios[i]);
+		radio_tmp_param = calloc(0, sizeof(struct radio_tmp ));
+		radio_tmp_param->r = &a->radios[i];
+		radio_tmp_param->a = a;
+		ubus_call_object(a, r_wobj, "status", parse_radio, radio_tmp_param);
 
 		// ubus call wifi.radio.wl0 scan
 		//ubus_call_object(a, r_wobj, "scan", NULL, &a->radios[i]);
@@ -4830,6 +4869,8 @@ int start_agent(void)
 
 	agent_init_interfaces(w);
 
+	agent_switch_according_to_pref(w); /*switch to the channel according to the prefrence*/
+
 	ubus_register_event_handler(ctx, &w->evh, "ethport");
 	ubus_register_event_handler(ctx, &w->evh, "wifi.*");
 	ubus_register_event_handler(ctx, &w->evh, "wps_credentials");
diff --git a/src/agent.h b/src/agent.h
index 56b39a41a..b5ce3945d 100644
--- a/src/agent.h
+++ b/src/agent.h
@@ -192,7 +192,7 @@ struct netif_fh {
 	unsigned char bssid[6];
 	char ssid[33];
 	char standard[32];
-	char radio_name[6];
+	char radio_name[16];
 	bool enabled;
 	bool torndown;
 	int bssload;
@@ -404,6 +404,11 @@ enum acs_state {
 	ACS_ACTIVE
 };
 
+struct radio_tmp {
+  struct agent *a;
+  struct wifi_radio_element *r
+};
+
 struct wifi_radio_element {
 	char name[16];
 	uint8_t macaddr[6];
diff --git a/src/agent_map.c b/src/agent_map.c
index 727d4cdf0..330d9f547 100644
--- a/src/agent_map.c
+++ b/src/agent_map.c
@@ -1936,28 +1936,38 @@ int get_op_class_bw(int op_class)
 	}
 
 }
+
+int agent_set_channel_preference_to_default(struct wifi_radio_element *radio)
+{
+	trace("%s: --->\n", __func__);
+        int found = 0;
+        int pref = 0;
+        int l = 0, ret = 0;
+
+        for (l = 0; l < radio->num_supp_opclass; l++) {
+		int m;
+                for (m = 0; m <radio->supp_opclass[l].
+                   num_supported_channels ; m++) {
+                	trace("channel  %d\n",radio->supp_opclass[l].supp_chanlist[m].channel );
+                        trace("channel preference  %d\n",radio->supp_opclass[l].supp_chanlist[m].pref );
+                        radio->supp_opclass[l].supp_chanlist[m].pref = 0x0f;
+                }
+        }
+
+	return 0;
+}
+
 /*This function return the channel with the highest preference*/
-int agent_get_highest_preference(struct agent *a, uint8_t *radio_id, int op_class_id, int *channel)
+int agent_get_highest_preference(struct wifi_radio_element *radio, uint32_t op_class_id, uint32_t *channel,
+		uint32_t *opclass_to_move)
 {
 	trace("%s: --->\n", __func__);
+
 	int found = 0;
 	int pref = 0;
 	int l = 0, ret = 0;
-	struct wifi_radio_element *radio = NULL;
 
-        trace("\tradio_id: " MACFMT "\n", MAC2STR(radio_id));
-        for (l = 0; l < a->num_radios; l++) {
-                radio = a->radios + l;
-                ret = memcmp(radio->macaddr, radio_id, 6);
-                if (ret == 0) {
-                        found = 1;
-                        break;
-                }
-        }
 
-	if (found == 0)
-		return -1;
-	
 	for (l = 0; l < radio->num_supp_opclass; l++) {
 		if (radio->supp_opclass[l].id == op_class_id) {
 			int m;
@@ -1968,17 +1978,39 @@ int agent_get_highest_preference(struct agent *a, uint8_t *radio_id, int op_clas
 				if (pref <  radio->supp_opclass[l].supp_chanlist[m].pref) {
 					pref = radio->supp_opclass[l].supp_chanlist[m].pref;
 					*channel = radio->supp_opclass[l].supp_chanlist[m].channel;
+					*opclass_to_move = op_class_id;
 				}
 			}
 		}
 	}
+
+	if (pref == 0x0f)
+		return;
+	else {
+		for (l = 0; l < radio->num_supp_opclass; l++) {
+                        int m;
+                        for (m = 0; m <radio->supp_opclass[l].
+                        num_supported_channels ; m++) {
+                        	trace("channel  %d\n",radio->supp_opclass[l].supp_chanlist[m].channel );
+                                trace("channel preference  %d\n",radio->supp_opclass[l].supp_chanlist[m].pref );
+                                if (pref <  radio->supp_opclass[l].supp_chanlist[m].pref) {
+                                        pref = radio->supp_opclass[l].supp_chanlist[m].pref;
+                                        *channel = radio->supp_opclass[l].supp_chanlist[m].channel;
+                                        *opclass_to_move = radio->supp_opclass[l].id;
+					if (pref == 0x0f)
+						return 0;
+				}
+                        }
+                }
+        }
 	trace("channel to which channel needs to switch  %d\n",*channel );
+	return 0;
 }
 
-static int agent_is_radio_backhaul(struct agent *a, uint8_t *radio_id, struct netif_fh *p)
+static int agent_is_radio_backhaul(struct agent *a, uint8_t *radio_id)
 
 {
-//	struct netif_fh *p = NULL;
+	struct netif_fh *p = NULL;
 	const char *radio_name = NULL;
 	int found = 0;
 	int ret = 0;
@@ -2000,12 +2032,12 @@ static int agent_is_radio_backhaul(struct agent *a, uint8_t *radio_id, struct ne
                 if(ret == 0) {
                         trace("I am here %p \n", p->cfg);
                         trace("radio name 51 multi_ap flag is %d\n", p->cfg->multi_ap);
-                //      if (p->cfg->multi_ap != 2)
-                //              continue;
-                //      else {
+                      if (p->cfg->multi_ap != 2)
+                              continue;
+                      else {
                                 found = 1;
                                 break;
-                //      }
+                      }
                 }
         }
 
@@ -2025,11 +2057,10 @@ int agent_channel_switch(struct agent *a, uint8_t *radio_id, int channel, int op
 	int freq = 0;
 	int bandwidth = 0;
 	struct netif_fh *p = NULL;
-//	int found = 0;
+	int found = 0;
 	const char *radio_name = NULL; 
 	trace("channel switch channel %d radio is "MACFMT" \n", channel, MAC2STR(radio_id));
 
-#if 0
 	list_for_each_entry(p, &a->fhlist, list) {
 		struct wifi_radio_element *radio = NULL;
 		
@@ -2045,19 +2076,17 @@ int agent_channel_switch(struct agent *a, uint8_t *radio_id, int channel, int op
 		trace("radio name 4\n");
 		if(ret == 0) {
 			trace("I am here %p \n", p->cfg);
-			//trace("radio name 5 multi_ap flag is %d\n", p->cfg->band);
 			trace("radio name 51 multi_ap flag is %d\n", p->cfg->multi_ap);
-		//	if (p->cfg->multi_ap != 2)
-		//		continue;
-		//	else {
+			if (p->cfg->multi_ap != 2)
+				continue;
+			else {
 				found = 1;
 				break;
-		//	}
+			}
 		}
 	}
-#endif
-	ret = agent_is_radio_backhaul(a, radio_id, p);
-	if (ret != 0)
+
+	if (found != 1)
 		return -1;
 
 	freq = c2f(channel);
@@ -2160,8 +2189,7 @@ int agent_process_channel_pref_tlv(void *agent, struct tlv_channel_pref *p,
 		radio = a->radios + l;
 		match = memcmp(radio->macaddr, radio_id, 6);
 		if (match == 0) {
-			struct netif_fh *p = NULL;
-			ret = agent_is_radio_backhaul(a, radio_id, p);
+			ret = agent_is_radio_backhaul(a, radio_id);
         		if (ret != 0) {
 				err("radio is a backhaul radio\n");
                 		memcpy(channel_resp[*channel_resp_nr].radio_id,
@@ -2250,21 +2278,35 @@ int agent_process_channel_pref_tlv(void *agent, struct tlv_channel_pref *p,
 						}
 					}
 				}
-			//	break;
-		//	}
+			}
+
 			//Here the global operating class channels have been assigned prefernces
 			if(process == 1) {
 				/* Here we need to see that what is the current operating channel
 				 * and that we want to switch to*/
-				int channel = 0;
-				ret = agent_get_highest_preference(a, radio_id, op.class_id, &channel);
+				uint32_t channel = 0;
+				uint32_t opclass = 0;
+			//	ret = agent_get_highest_preference(a, radio_id, radio->current_opclass, &channel,
+			//			&opclass);
+				 ret = agent_get_highest_preference(radio, radio->current_opclass, &channel,
+                                           &opclass);
 				/* The operating class channel preference has been set
 				 * now we want to switch the channel to the max preference */
-				if(channel != 0) {
-					ret = agent_channel_switch(a, radio_id, channel, op.class_id);
+				if (channel != 0 && opclass != 0 ) {
+					ret = agent_channel_switch(a, radio_id, channel, opclass);
 					if (ret == -1) {
+						
 						/*Here we need to set the default preference for all the
 						 * channels in that operating class also set the response code as rejected*/ 
+						agent_set_channel_preference_to_default(radio);
+						 memcpy(channel_resp[*channel_resp_nr].radio_id, radio_id, 6);
+                				/* Here response code is a Reserved code
+                 				 * to decline the request
+                 				 */
+                				channel_resp[*channel_resp_nr].response = 0x04;
+                				*channel_resp_nr = *channel_resp_nr + 1;
+
+                				return ret;
 					}
 					/* Here we need to write the corresponding preference in the
 					 * config file to make preference reboot persistent */
@@ -2273,8 +2315,6 @@ int agent_process_channel_pref_tlv(void *agent, struct tlv_channel_pref *p,
 				}
 				process = 0;
 			}
-		//	break;
-		}
 
 		}
 
@@ -2283,10 +2323,34 @@ int agent_process_channel_pref_tlv(void *agent, struct tlv_channel_pref *p,
 	}
 
 	*channel_resp_nr = *channel_resp_nr + 1;
-
 	return ret;
 }
 
+#if 0
+int agent_switch_according_to_pref(struct wifi_radio_element *radio)
+{
+	uint32_t channel = 0;
+        uint32_t opclass = 0;
+	struct agent *a = this_agent;
+	int ret = 0;
+
+        ret = agent_get_highest_preference(radio, radio->current_opclass, &channel,
+                                                &opclass);
+        /* The operating class channel preference has been set
+         * now we want to switch the channel to the max preference */
+         if (channel != 0 && opclass != 0 ) {
+         	ret = agent_channel_switch(a, radio->macaddr, channel, opclass);
+                if (ret == -1) {
+
+                	/*Here we need to set the default preference for all the
+                         * channels in that operating class also set the response code as rejected*/
+                         agent_set_channel_preference_to_default(radio);
+                }
+	}
+	return 0;
+}
+#endif
+
 int agent_process_transmit_power_tlv(struct agent *a, struct tlv_txpower_limit *p)
 {
 	int l = 0;
diff --git a/src/config.c b/src/config.c
index 063f8af99..2cf5c10a2 100644
--- a/src/config.c
+++ b/src/config.c
@@ -334,8 +334,6 @@ int wifi_set_opclass_preference(char *radio_name, uint32_t opclass_id,
         set_value(ctx, pkg, s, "radio", radio_name, UCI_TYPE_STRING);
         set_value(ctx, pkg, s, "channel", channel_str, UCI_TYPE_LIST);
 
-//        set_value(ctx, pkg, s, "ifname", ifname, UCI_TYPE_STRING);
-
 out:
 	uci_commit(ctx, &pkg, false);
 	uci_unload(ctx, pkg);
@@ -2997,7 +2995,7 @@ static int agent_config_get_opclass(struct  wifi_radio_element *radio,
                         	        	num_supported_channels ; m++) {
                                 		trace("channel %d\n",radio->supp_opclass[l].supp_chanlist[m].channel );
                                 		if (radio->supp_opclass[l].supp_chanlist[m].channel == channel) {
-                                        		trace("I am here NEVA\n");
+                                        		trace("I am here NEVA\n pref %d", pref);
                                         		radio->supp_opclass[l].supp_chanlist[m].pref = pref;
 						}
 					}
-- 
GitLab