[Feature][T8TSK-105][wifi] add enableGBW for specific mac client

Change-Id: Ie7476afb128a8a26fab0044ff17ce7bb6613124b
diff --git a/lib/liblynq-wifi6/libwifi6.c b/lib/liblynq-wifi6/libwifi6.c
index 5ea342a..78c756e 100755
--- a/lib/liblynq-wifi6/libwifi6.c
+++ b/lib/liblynq-wifi6/libwifi6.c
@@ -62,6 +62,13 @@
 
 static struct wpa_ctrl * g_lynq_wpa_ctrl[2] = {0};
 
+//you.chen add for tv-box start
+volatile int g_gbw_enabled = 0;
+char * g_gbw_mac = NULL;
+pthread_t g_gbw_watcher_pid = 0;
+static int startGBW();
+static int stopGBW();
+//you.chen add for tv-box end
 
 typedef struct __curr_status_info {
     ap_info_s *ap;
@@ -152,15 +159,28 @@
         if (!wpa_ctrl_recv(lynq_wpa_ctrl, msg_notify, &len)) {
             msg_notify[len+1] = '\0';
             printf("ap------> %s\n", msg_notify);
-            if (g_ap_callback_func == NULL) {
-                continue;
-            }
+//you.chen change for tv-box start
             if (strstr(msg_notify, "AP-STA-DISCONNECTED") != NULL) {
-                g_ap_callback_func(g_ap_callback_priv, LYNQ_WIFI_STATUS_DISCONNECT);
+                if (g_ap_callback_func != NULL)
+                    g_ap_callback_func(g_ap_callback_priv, LYNQ_WIFI_STATUS_DISCONNECT);
+                if (g_gbw_enabled == 1 && g_gbw_mac != NULL) {
+                    printf("disconect %d, %s ,%s\n", g_gbw_enabled, g_gbw_mac, strstr(msg_notify, (const char*)g_gbw_mac));
+                    if (strstr(msg_notify, (const char*)g_gbw_mac) != NULL) {
+                        stopGBW();
+                    }
+                }
             }
             else if (strstr(msg_notify, "AP-STA-CONNECTED") != NULL) {
-                g_ap_callback_func(g_ap_callback_priv, LYNQ_WIFI_STATUS_CONNECT);
+                if (g_ap_callback_func != NULL)
+                    g_ap_callback_func(g_ap_callback_priv, LYNQ_WIFI_STATUS_CONNECT);
+                if (g_gbw_enabled == 1 && g_gbw_mac != NULL) {
+                    printf("conect %d, %s ,%s\n", g_gbw_enabled, g_gbw_mac, strstr(msg_notify, (const char*)g_gbw_mac));
+                    if (strstr(msg_notify, (const char*)g_gbw_mac) != NULL) {
+                        startGBW();
+                    }
+                }
             }
+//you.chen add for tv-box end
         } // end if (!wpa_ctrl_recv(lynq_wpa_ctrl, msg_notify, &len))
     } // end while (g_ap_watcher_stop_flag == 0)
     if (lynq_wpa_ctrl != NULL) {
@@ -2569,3 +2589,259 @@
 
     return 0;
 }
+//you.chen add for tv-box start
+static int exec_cmd(const char *str_cmd, char * str_cmd_ret, size_t max_len) {
+    FILE *fp;
+    //printf("to exec cmd:%s\n", str_cmd);
+    if((fp=popen(str_cmd,"r"))==NULL)
+    {
+        perror("popen error!");
+        return -1;
+    }
+    if((fread(str_cmd_ret,max_len,1,fp))<0)
+    {
+        perror("fread fail!");
+        fclose(fp);
+        return -1;
+    }
+    fclose(fp);
+    return 0;
+}
+
+static int get_netmask_length(const char* mask)
+{
+    int masklen=0, i=0;
+    int netmask=0;
+
+    if(mask == NULL)
+    {
+        return 0;
+    }
+
+    struct in_addr ip_addr;
+    if( inet_aton(mask, &ip_addr) )
+    {
+        netmask = ntohl(ip_addr.s_addr);
+    }else{
+        netmask = 0;
+        return 0;
+    }
+
+    while(0 == (netmask & 0x01) && i<32)
+    {
+        i++;
+        netmask = netmask>>1;
+    }
+    masklen = 32-i;
+    return masklen;
+}
+
+static int get_tether_route_str(char *str_cmd_ret, size_t max_len) {
+    int mask_len;
+    char *p;
+    char tmp[64] = {0};
+    if (exec_cmd("ifconfig tether | grep Mask", str_cmd_ret, max_len) != 0)
+        return -1;
+    p = strstr(str_cmd_ret, "Mask:");
+    if (p == NULL)
+        return -1;
+    mask_len = get_netmask_length(p + 5);
+    if (mask_len == 0)
+        return -1;
+    p = strstr(str_cmd_ret, "inet addr:");
+    if (p == NULL)
+        return -1;
+    strcpy(tmp, p + 10);
+    p = strstr(tmp, " ");
+    if (p != NULL)
+        *p = '\0';
+    sprintf(str_cmd_ret, "%s/%d", tmp, mask_len);
+    return 0;
+}
+
+static void GBWWatchThreadProc() {
+    int i,n, nloop, nmax, ncheckcount, nidlecount;
+    unsigned long long lastAP1Bytes, lastAP2Bytes, currAP1Bytes, currAP2Bytes;
+    unsigned int lastAP1Drop,lastAP2Drop, currAP1Drop, currAP2Drop;
+    unsigned int setAP1Speed, setAP2Speed, lastAP1Speed, lastAP2Speed, currAP1Speed, currAP2Speed,currSetAP1Speed;
+    char *results[16] = {0};
+    char str_cmd[256] = {0};
+    char str_cmd_ret[128] = {0};
+    char dest_ip[32] = {0};
+    lastAP1Bytes = lastAP2Bytes = 0;
+    lastAP1Drop = lastAP2Drop = 0;
+    lastAP1Speed = lastAP2Speed = 0;
+    setAP1Speed = 50;
+    setAP2Speed = 80;
+    nloop = 0;
+    nmax = 6;
+    ncheckcount = nidlecount = 0;
+
+    printf("------gbw thread run\n");
+    sprintf(str_cmd, "ip neigh | grep %s | awk '{print $1}'", g_gbw_mac);
+    while (dest_ip[0] == '\0') {
+        sleep(1);
+        str_cmd_ret[0] = '\0';
+        exec_cmd(str_cmd, str_cmd_ret, sizeof (str_cmd_ret));
+        for(n = 0; n < (int)sizeof(str_cmd_ret) && str_cmd_ret[n] != '\0'; n++) {
+            if (str_cmd_ret[n] == '\n'){
+                str_cmd_ret[n] = '\0';
+                break;
+            }
+        }
+        if (str_cmd_ret[0] != '\0')
+        {
+            strcpy(dest_ip, str_cmd_ret);
+        }
+    }
+
+    system("tc qdisc del dev tether root > /dev/null 2>&1");
+    system("tc qdisc add dev tether root handle 1: htb r2q 1");
+    system("tc class add dev tether parent 1:  classid 1:1  htb rate 50Mbit ceil 70Mbit prio 2 quantum 3000");
+    if (get_tether_route_str(str_cmd_ret, sizeof (str_cmd_ret)) != 0)
+    {
+        printf("not get tether info\n");
+        return;
+    }
+    sprintf(str_cmd, "tc filter add dev tether parent 1: protocol ip prio 16 u32 match ip dst %s flowid 1:1", str_cmd_ret);
+    system(str_cmd);
+    system("tc class add dev tether parent 1:  classid 1:2  htb rate 80Mbit ceil 100Mbit prio 0 quantum 3000000");
+    sprintf(str_cmd, "tc filter add dev tether parent 1: protocol ip prio 1 u32 match ip dst %s flowid 1:2", dest_ip);
+    //printf("----cmd:%s\n", str_cmd);
+    system(str_cmd);
+
+    while (1) {
+        sleep(1);
+        memset(str_cmd, 0, sizeof(str_cmd));
+        if (0 != exec_cmd("tc -s class show dev tether classid 1:1 | grep Sent", str_cmd, sizeof (str_cmd)))
+            continue;
+        //printf("ap1 --- %s\n", str_cmd);
+        n = lynq_split(str_cmd, strlen(str_cmd), ' ', results);
+        if (n > 9) {
+            if (strcmp(results[1], "Sent") == 0) {
+                currAP1Bytes = atoll(results[2]);
+            }
+            if (strcmp(results[6], "(dropped") == 0) {
+                currAP1Drop = atoi(results[7]);
+            }
+        }
+
+        memset(str_cmd, 0, sizeof(str_cmd));
+        if (0 != exec_cmd("tc -s class show dev tether classid 1:2 | grep Sent", str_cmd, sizeof (str_cmd)))
+            continue;
+        //printf("ap2 --- %s\n", str_cmd);
+        n = lynq_split(str_cmd, strlen(str_cmd), ' ', results);
+        if (n > 9) {
+            if (strcmp(results[1], "Sent") == 0) {
+                currAP2Bytes = atoll(results[2]);
+            }
+            if (strcmp(results[6], "(dropped") == 0) {
+                currAP2Drop = atoi(results[7]);
+            }
+        }
+
+        //printf("ap1 %llu- %u, ap2 %llu-%u\n", currAP1Bytes, currAP1Drop, currAP2Bytes, currAP2Drop);
+        if (currAP1Bytes < lastAP1Bytes || currAP2Bytes < lastAP2Bytes) {
+            lastAP1Bytes = currAP1Bytes;
+            lastAP2Bytes = currAP2Bytes;
+            continue;
+        }
+
+        currAP1Speed = (currAP1Bytes - lastAP1Bytes) / 128 / 1024;
+        currAP2Speed = (currAP2Bytes - lastAP2Bytes) / 128 / 1024;
+        //printf("ap1 speed %d mb, ap2 speed %d mb\n", currAP1Speed, currAP2Speed);
+        lastAP1Speed = currAP1Speed;
+        lastAP2Speed = currAP2Speed;
+        lastAP1Bytes = currAP1Bytes;
+        lastAP2Bytes = currAP2Bytes;
+
+        currSetAP1Speed = setAP1Speed;
+        if ((currAP2Speed < 30 && currAP2Speed > 5) && currAP1Speed > 5) {
+            ncheckcount++;
+            if (ncheckcount > 3) {
+                ncheckcount = 0;
+                currSetAP1Speed = 5;
+            }
+        }
+        else {
+            ncheckcount = 0;
+            if (currAP1Speed < 5)
+                nidlecount++;
+            else
+                nidlecount = 0;
+
+        }
+
+        if (nidlecount > 60 ){
+            currSetAP1Speed = 50;
+        }
+
+        if (currSetAP1Speed != setAP1Speed) {
+            setAP1Speed = currSetAP1Speed;
+            sprintf(str_cmd, "tc class replace dev tether parent 1:  classid 1:1  htb rate %dMbit ceil %dMbit prio 2 quantum 3000", setAP1Speed, (int)(setAP1Speed*1.4));
+            //printf("------***change speed: %s\n", str_cmd);
+            system(str_cmd);
+        }
+    }
+}
+
+int enableGBW(const char* mac) {
+    int i,len;
+    char get_ipaddr_cmd[128]={0};
+    ap_info_s *ap;
+    device_info_s * list;
+
+    if (mac == NULL || g_gbw_enabled == 1)
+        return -1;
+    len = strlen(mac);
+    g_gbw_mac = malloc(len + 1);
+    for(i=0;i<len;i++) {
+        if (mac[i] >= 'A' && mac[i] <= 'Z')
+        {
+            g_gbw_mac[i] = 'a' + (mac[i] - 'A');
+        }
+        else
+            g_gbw_mac[i] = mac[i];
+    }
+    g_gbw_mac[i] = '\0';
+    g_gbw_enabled = 1;
+
+    sprintf(get_ipaddr_cmd, "ip neigh | grep %s", g_gbw_mac);
+    if (system(get_ipaddr_cmd) == 0) {
+        //startGBW();
+        if ( 0 ==lynq_get_ap_device_list(1, &ap, &list,&len) ) {
+            for (i=0;i<len;i++) {
+                //printf("--mac:%s, name:%s\n",list[i].sta_mac, list[i].hostname);
+                if (strcmp(g_gbw_mac, list[i].sta_mac) == 0)
+                    startGBW();
+            }
+            free(ap);
+            free(list);
+        }
+    }
+    return 0;
+}
+
+int disableGBW() {
+    stopGBW();
+    free(g_gbw_mac);
+    g_gbw_mac = NULL;
+    g_gbw_enabled = 1;
+    return 0;
+}
+
+static int startGBW() {
+    if (g_gbw_watcher_pid != 0) {
+        stopGBW();
+    }
+    pthread_create(&g_gbw_watcher_pid,NULL,GBWWatchThreadProc,NULL);
+}
+
+static int stopGBW() {
+    void* retval;
+    pthread_cancel(g_gbw_watcher_pid);
+    pthread_join(g_gbw_watcher_pid, &retval);
+    g_gbw_watcher_pid = 0;
+    system("tc qdisc del dev tether root");
+}
+//you.chen add for tv-box end