1/*****************************************************************************************************************
2 * Filr Name	: speedtest.c
3 * Description  : modify from ping.c
4 * related file : qosutils.h qosutils.c
5 * Auther       : Wendel Huang
6 * History	: 2006.05.22 	post to WL500gP
7		  2006.07.18 	Post to WL700g, and remove execution message form release version
8		  2006.08.01    Debug the error in MER mode
9 *****************************************************************************************************************/
10#ifdef QOS
11
12#include <stdio.h>
13#include <sys/param.h>
14#include <sys/socket.h>
15#include <sys/file.h>
16#include <sys/time.h>
17#include <sys/times.h>
18#include <sys/signal.h>
19#include <string.h>
20#include <netinet/in.h>
21#include <netinet/ip.h>
22#include <netinet/ip_icmp.h>
23#include <arpa/inet.h>
24#include <netdb.h>
25#include <stdio.h>
26#include <stdlib.h>
27#include <errno.h>
28#include <unistd.h>
29#include <string.h>
30#include <stdlib.h>
31#include <shutils.h>
32
33#include "qosutils.h"
34
35#ifdef WL600g
36#include "asusbcmnvram.h"
37#include "dbapi.h"
38#include "ifcwanapi.h"
39#include "syscall.h"
40#include "bcmadsl.h"	//for ADSL_CONNECTION_INFO
41#else	//WL500gP, WL550gE
42#include "bcmnvram.h"
43#endif
44
45#ifdef WL600g
46extern ADSL_CONNECTION_INFO glbAdslInfo;// global ADSL info variable is declared in syscall.c
47#endif
48
49#define STRUCT_LEN(name)    sizeof(name)/sizeof(name[0])
50#define MAX_BANDWIDTH	15359	// S = (1500-64)*8/1024 (kbits)
51				// S *1000 / (thelta t) * 1.369 (weight) = B
52#define DETECT_FILE "/tmp/detect_ip"
53
54static const int DEFDATALEN = 56;
55static const int MAXIPLEN = 60;
56static const int MAXICMPLEN = 76;
57static const int MAXWAIT = 10;
58static const int ADSLMXLEN =1400;
59static const int HEADOVERHEAD = 42;
60unsigned long int triptime[36];		//14(frame header)+20(ip header)+8(icmp header)
61static int request_time=1;
62
63#define	A(bit)		rcvd_tbl[(bit)>>3]	/* identify byte in array */
64#define	B(bit)		(1 << ((bit) & 0x07))	/* identify bit in byte */
65#define	SET(bit)	(A(bit) |= B(bit))
66#define	CLR(bit)	(A(bit) &= (~B(bit)))
67#define	TST(bit)	(A(bit) & B(bit))
68
69enum { WAN_RATE_SUCCESS, WAN_LINK_FAIL };
70
71struct icmp_map_t{
72	unsigned difference;
73	unsigned rate;
74} icmp_map[] = {
75	{3000, MAX_BANDWIDTH},
76	{1638, 2048},
77	{819, 1024},
78	{600, 640},
79	{410, 512},
80	{204, 256},
81	{102, 128},
82	{51, 64},
83	{27, 33},
84};//difference = rate * 0.8
85
86struct wan_link_rate {
87	unsigned ds;
88	unsigned us;
89};
90
91/* common routines */
92static int in_cksum(unsigned short *buf, int sz)
93{
94	int nleft = sz;
95	int sum = 0;
96	unsigned short *w = buf;
97	unsigned short ans = 0;
98
99	while (nleft > 1) {
100		sum += *w++;
101		nleft -= 2;
102	}
103
104	if (nleft == 1) {
105		*(unsigned char *) (&ans) = *(unsigned char *) w;
106		sum += ans;
107	}
108
109	sum = (sum >> 16) + (sum & 0xFFFF);
110	sum += (sum >> 16);
111	ans = ~sum;
112	return (ans);
113}
114
115static struct sockaddr_in pingaddr;
116static int pingsock = -1;
117int datalen; /* intentionally uninitialized to work around gcc bug */
118
119// brcm: changed default value of pingcount from 0 to 4.
120static long ntransmitted=0, nreceived=0;
121int pingcount=10;
122static int myid;
123static struct timeval tstart, tend;
124
125struct hostent *hostent;
126
127static char gateway_ip[10][30];
128static void sendping();
129static void unpack(char *, int, struct sockaddr_in *);
130static int detect();
131static int pre_ping(const char *host);
132
133/**************************************************************************/
134
135//static void sendping(int junk)
136static void sendping()
137{
138#ifdef QOS_DEBUG
139	printf("	Start of sendping()\n");
140#endif
141	struct icmp *pkt;
142	int i;
143	char packet[datalen + 8];
144
145	pkt = (struct icmp *) packet;
146
147	int repeat = 0;
148	ntransmitted=0;
149	nreceived=0;
150	switch(request_time)
151	{
152		case 1:
153		case 2:
154		case 3:
155			pingcount=9;
156			printf("pingcount:%d\n",pingcount);
157			break;
158		case 4:
159		case 5:
160		case 6:
161			pingcount=15;
162			printf("pingcount:%d\n",pingcount);
163			break;
164		case 7:
165		case 8:
166		case 9:
167			pingcount=29;
168			printf("pingcount:%d\n",pingcount);
169			break;
170		case 10:
171		case 11:
172		case 12:
173			pingcount=54;
174			printf("pingcount:%d\n",pingcount);
175			break;
176		case 13:
177		case 14:
178		case 15:
179			pingcount=70;
180			printf("pingcount:%d\n",pingcount);
181			break;
182		case 16:
183		case 17:
184		case 18:
185			pingcount=72;
186			printf("pingcount:%d\n",pingcount);
187			break;
188		case 19:
189		case 20:
190		case 21:
191			pingcount=74;
192			printf("pingcount:%d\n",pingcount);
193			break;
194		case 22:
195		case 23:
196		case 24:
197			pingcount=76;
198			printf("pingcount:%d\n",pingcount);
199			break;
200		case 25:
201		case 26:
202		case 27:
203			pingcount=78;
204			printf("pingcount:%d\n",pingcount);
205			break;
206		case 28:
207		case 29:
208		case 30:
209			pingcount=80;
210			printf("pingcount:%d\n",pingcount);
211			break;
212		case 31:
213		case 32:
214		case 33:
215			pingcount=82;
216			printf("pingcount:%d\n",pingcount);
217			break;
218		case 34:
219		case 35:
220		case 36:
221			pingcount=84;
222			printf("pingcount:%d\n",pingcount);
223			break;
224		default:
225			printf("pingcount error!\n");
226	}
227	for ( ; repeat<pingcount ; repeat++ ) {
228		int pingsock1;
229		if( (pingsock1=socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0 ) {
230#ifdef QOS_DEBUG
231			printf("	deltatime() ** socket() Error!!\n");
232#endif
233			exit(2);
234		}
235		pkt->icmp_type = ICMP_ECHO;
236		pkt->icmp_code = 0;
237		if(repeat==pingcount-1)
238		{
239			pkt->icmp_cksum = 0;
240		}
241		else
242		{
243			pkt->icmp_cksum = 1;
244		}
245		pkt->icmp_seq = pingcount;
246		pkt->icmp_id = myid;
247		gettimeofday((struct timeval *)pkt->icmp_data, NULL);
248		if(repeat==0)
249		{
250			gettimeofday(&tstart, NULL);
251		}
252		pkt->icmp_cksum = in_cksum((unsigned short *) pkt, sizeof(packet));
253
254		struct timeval tmshow;
255		memcpy(&tmshow, pkt->icmp_data, sizeof(struct timeval));
256
257#ifdef QOS_DEBUG
258		printf("	sendping() ** sequence = %d 	sendtime= %ld\n", pkt->icmp_seq, tmshow.tv_usec);
259#endif
260
261		i = sendto(pingsock1, packet, sizeof(packet), 0, (struct sockaddr *) &pingaddr, sizeof(struct sockaddr_in));
262		//2006.08.01	This is for sending echo-request error in MER mode
263		//printf("	sendping() ** ntransmitted=%ld : sendto = %d\n", ntransmitted, i);
264		//printf("QOS Detecting#%ld : sendto = %d\n", ntransmitted, i);
265		//printf("QOS \n");
266
267#ifdef QOS_DEBUG
268		if(i<0)
269			switch(errno) {
270				case EBADF:
271					printf("EBADF\n");
272				case EFAULT:
273					printf("EFAULT\n");
274				case ENOTSOCK:
275					printf("ENOTSOCK\n");
276				case EINTR:
277					printf("EINTR\n");
278				case EAGAIN:
279					printf("EAGAIN\n");
280				case ENOBUFS:
281					printf("ENOBUFS\n");
282				//case ENOMEN:
283					//printf("ENOMEN\n");
284				case EINVAL:
285					printf("EINVAL\n");
286				default:
287					printf("sendto DNS error\n");
288			}
289#endif
290
291		if ( i<0 || (size_t)i != sizeof(packet) )
292			printf("	sendping() ** sendto Error !!\n");
293		close(pingsock1);
294	}
295}
296
297static void unpack(char *buf, int sz, struct sockaddr_in *from)
298{
299	struct icmp *icmppkt;
300	struct iphdr *iphdr;
301	//struct timeval tv, *tp;
302	struct timeval tv;
303	int hlen;
304	//unsigned long int triptime;
305
306	gettimeofday(&tv, NULL);
307
308	/* check IP header */
309	iphdr = (struct iphdr *) buf;
310	hlen = iphdr->ihl << 2;
311	/* discard if too short */
312	if (sz < ICMP_MINLEN)
313		return;
314
315	sz -= hlen;
316	icmppkt = (struct icmp *) (buf + hlen);
317
318	if (icmppkt->icmp_type == ICMP_ECHOREPLY) {
319
320		if (icmppkt->icmp_id != myid) {
321#ifdef QOS_DEBUG
322	    	    printf("	unpack() ** not my ping !! icmp->icmpid = %d : myid =%d \n", icmppkt->icmp_id, myid);
323#endif
324	    	    return;				/* not our ping */
325		}
326
327	        ++nreceived;
328		if ((tv.tv_usec -= tstart.tv_usec) < 0) {
329			--tv.tv_sec;
330			tv.tv_usec += 1000000;
331		}
332		tv.tv_sec -= tstart.tv_sec;
333
334		triptime[request_time-1] = tv.tv_sec * 1000000 + tv.tv_usec;
335		//nvram_set("qos_ubw_status", "initialing");
336                /*brcm: changed display message to show actually receive data bytes length
337                  rather than ICMP packet length which is ICMP_MINLEN+dataLen */
338#ifdef QOS_DEBUG
339		printf("	unpack() ** new sec = %ld	new usec = %ld\n", tv.tv_sec, tv.tv_usec);
340#endif
341	}
342	else if (icmppkt->icmp_type == ICMP_UNREACH) {
343		    nvram_set("qos_ubw_reason", "Host Unreachable");
344
345#ifdef QOS_DEBUG
346		    printf("	unpack() ** DNS Host Unreachable !!\n");
347#endif
348
349		    nvram_set("qos_ubw_status", "fail");
350	}
351	else {
352		    nvram_set("qos_ubw_status", "fail");
353
354#ifdef QOS_DEBUG
355		    printf("	unpack() ** icmp->type : %d\n", icmppkt->icmp_type);
356#endif
357	}
358}
359
360static int pre_ping(const char *host)
361{
362	int package=60;
363	char packet[package+MAXIPLEN+MAXICMPLEN];
364	unsigned long int ul_hostip;
365	struct timeval socktv;
366	myid = getpid() & 0xFFFF;
367
368	if( (pingsock=socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0 )
369	{
370		return 0;
371	}
372
373	socktv.tv_sec = 5;
374	socktv.tv_usec = 0;
375	setsockopt(pingsock, SOL_SOCKET, SO_RCVTIMEO, &socktv, sizeof(socktv));
376
377	memset(&pingaddr, 0, sizeof(struct sockaddr_in));
378
379	pingaddr.sin_family = AF_INET;
380
381	if( (ul_hostip=inet_addr(host)) !=INADDR_NONE )
382	{
383		pingaddr.sin_addr.s_addr = ul_hostip;
384	}
385	else if((hostent=gethostbyname(host)) )
386	{
387		memcpy(&pingaddr.sin_addr, hostent->h_addr, sizeof(pingaddr.sin_addr));
388	}
389	struct icmp *pkt;
390	int i;
391	char packet1[package + 8];
392
393	pkt = (struct icmp *) packet1;
394
395	int repeat = 0;
396	ntransmitted=0;
397	nreceived=0;
398	for ( ; repeat<pingcount ; repeat++ ) {
399	    pkt->icmp_type = ICMP_ECHO;
400	    pkt->icmp_code = 0;
401	    pkt->icmp_cksum = 0;
402	    pkt->icmp_seq = ntransmitted++;
403	    pkt->icmp_id = myid;
404	    gettimeofday((struct timeval *)pkt->icmp_data, NULL);
405	    gettimeofday(&tstart, NULL);
406	    pkt->icmp_cksum = in_cksum((unsigned short *) pkt, sizeof(packet1));
407	    struct timeval tmshow;
408	    memcpy(&tmshow, pkt->icmp_data, sizeof(struct timeval));
409	    i = sendto(pingsock, packet1, sizeof(packet1), 0,
410	    		       (struct sockaddr *) &pingaddr, sizeof(struct sockaddr_in));
411	    if ( i<0 || (size_t)i != sizeof(packet1) )
412	    {
413		    printf("	sendping() ** sendto Error !!\n");
414		    return 0;
415	    }
416	}
417	int runtimes = 1;
418	int errotime = 0;
419	while (1) {
420		runtimes++;
421
422		struct sockaddr_in from;
423		socklen_t fromlen = (socklen_t) sizeof(from);
424		int c = 0;
425
426		c = recvfrom(pingsock, packet1, sizeof(packet1), 0,
427						  (struct sockaddr *) &from, &fromlen);
428		if (c < 0) {
429			errotime++;
430
431			if (errno == EINTR) continue;
432
433			if( errotime > 3 ) {
434				nvram_set("qos_ubw_status", "fail");
435				nvram_set("qos_ubw_reason", "DNS server fail");
436				return 0;
437			}
438			if (pingcount > 0 && runtimes>=pingcount)
439			{
440				return 0;
441				break;
442			}
443		        else
444				continue;
445		}
446		else if(c == 0) {
447			return 0;
448			nvram_set("qos_ubw_status", "fail");
449		}
450		if (pingcount > 0)
451		{
452			break;
453		}
454
455	}
456	return 1;
457
458}
459
460extern void deltatime(const char *host, struct timeval *deltaval)
461{
462#ifdef QOS_DEBUG
463	printf("	Start of deltatime()\n");
464#endif
465
466	datalen =ADSLMXLEN;
467	char packet[datalen + MAXIPLEN + MAXICMPLEN];
468	unsigned long int ul_hostip;
469	struct timeval socktv;
470
471	myid = getpid() & 0xFFFF;
472
473	if( (pingsock=socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0 ) {
474#ifdef QOS_DEBUG
475		printf("	deltatime() ** socket() Error!!\n");
476#endif
477		exit(2);
478	}
479int pingsock2=-1;
480if( (pingsock2=socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0 ) {
481#ifdef QOS_DEBUG
482		printf("	deltatime() ** socket() Error!!\n");
483#endif
484		exit(2);
485	}
486
487	socktv.tv_sec = 5;
488	socktv.tv_usec = 0;
489	setsockopt(pingsock2, SOL_SOCKET, SO_RCVTIMEO, &socktv, sizeof(socktv));
490	memset(&pingaddr, 0, sizeof(struct sockaddr_in));
491
492	pingaddr.sin_family = AF_INET;
493
494	if( (ul_hostip=inet_addr(host)) !=INADDR_NONE )
495	{
496		pingaddr.sin_addr.s_addr = ul_hostip;
497	}
498	else if((hostent=gethostbyname(host)) )
499	{
500		memcpy(&pingaddr.sin_addr, hostent->h_addr, sizeof(pingaddr.sin_addr));
501	}
502#ifdef QOS_DEBUG
503	else
504	{
505		printf("	deltatime() ** bad host ip or name!!\n");
506		return ;
507	}
508#endif
509
510#ifdef QOS_DEBUG
511	printf("	deltatime() ** host = %s\n", inet_ntoa(pingaddr.sin_addr));
512#endif
513
514	/* start the ping's going ... */
515	//signal(SIGALRM, sendping);
516	//alarm(1);
517	sendping();
518
519	/* listen for replies */
520	int runtimes = 1;
521	int errotime = 0;
522	while (1) {
523#ifdef 	QOS_DEBUG
524		printf("\n	receive exec times = %d\n", runtimes);
525#endif
526		runtimes++;
527		struct sockaddr_in from;
528		socklen_t fromlen = (socklen_t) sizeof(from);
529		int c = 0;
530
531		c = recvfrom(pingsock2, packet, sizeof(packet), 0,
532						  (struct sockaddr *) &from, &fromlen);
533		if (c < 0 && request_time==1) {
534			errotime++;
535
536			if (errno == EINTR) continue;
537
538			if( errotime > 3 ) {
539				nvram_set("qos_ubw_status", "fail");
540				nvram_set("qos_ubw_reason", "DNS server fail");
541			}
542
543#ifdef QOS_DEBUG
544			printf("	deltatime() ** recvfrom small than sendto !!\n");
545#endif
546
547			if (pingcount > 0 && runtimes>=pingcount)
548				break;
549		        else
550				continue;
551		}
552		else if(c<0 && request_time!=1)
553		{
554			request_time=100;
555			break;
556		}
557
558		else if(c == 0) {
559			nvram_set("qos_ubw_status", "fail");
560		}
561		unpack(packet, c, &from);
562		if (pingcount > 0)
563		{
564			break;
565		}
566		if ( strcmp(nvram_safe_get("qos_ubw_status"), "fail") == 0 )
567		{
568			exit(0);
569		}
570	}
571
572	close(pingsock);
573	close(pingsock2);
574#ifdef QOS_DEBUG
575	printf("	deltatime() ** tv_sec=%ld : tv_usec=%ld\n", tend.tv_sec, tend.tv_usec);
576#endif
577
578}
579
580
581//by icecream
582//function detect wan_ip
583static int detect()
584{
585	FILE *fp=NULL;
586	char cmd[80];
587	char detect_ip[20]="18.52.86.150";
588	char line[254];
589	char get_ip[10][30];
590	int j=0;
591	while(j<=9)
592	{
593		memset(&get_ip[j], 0, sizeof(get_ip[j]));
594		memset(&gateway_ip[j], 0, sizeof(gateway_ip[j]));
595		j++;
596	}
597	snprintf(cmd,sizeof(cmd),"traceroute -m 10 %s >%s",detect_ip,DETECT_FILE);
598	remove(DETECT_FILE);
599	int i=0;
600	int ping=0;
601	system(cmd);
602	if ((fp = fopen(DETECT_FILE, "r")) != NULL)
603		{
604			while(i<10)
605			{
606				if( fgets(line, sizeof(line), fp) != NULL )
607				{
608					char *p=NULL;
609					p=index(line,'(');
610					if(!p)
611					{
612						//printf("has no address!\n\n");
613						ping++;
614						if(ping>=3)
615						{
616							return 0;
617						}
618						continue;
619					}
620					int j=1;
621					while((*p)!=')')
622					{
623						p++;
624						get_ip[i][j-1]=*p;
625						j++;
626					}
627					get_ip[i][j-2]='\0';
628
629				}
630				i++;
631
632			}
633			i=0;
634			while(i<10)
635			{
636				sprintf(gateway_ip[i],"%s",get_ip[i]);
637				i++;
638			}
639		}
640		fclose(fp);
641		return 1;
642}
643
644/**************************************************************************
645 * Function Name: qos_get_wan_rate
646 * Description  : get the ADSL line rate
647 * Parameters   : None
648 * Returns      : Is successful when get the ADSL data rate?
649			0 : Success
650			1 : Link fail
651 **************************************************************************/
652extern int qos_get_wan_rate(void)
653{
654	static struct wan_link_rate wanrate;
655	char us[256], ds[256] ;
656	char * gw_ip=NULL;
657	struct timeval deltaval;
658       	double delta_us = 0;
659	wanrate.us = wanrate.ds = 0;
660	int step=3;
661	char *ip = nvram_safe_get("wan_dns_t");
662	int need_package=80;
663	if( !check_wan_link(0) )
664		return WAN_LINK_FAIL;
665
666	gw_ip = get_gw_ip();
667
668	if((strchr(ip, ' ')) ||(!strcmp(ip, "")))
669	{
670		struct dns_lists *dns_list = get_dns_list(1);
671		int i;
672
673		for(i=0 ; i<dns_list->num_servers ; i++){
674			ip = dns_list->dns_server[i];
675			if(    (!strchr(ip, ' '))
676			    && (strcmp(ip, ""))
677			    && (strcmp(ip, gw_ip))) //WL600g auto assign LAN IP as DNS Server
678				break;
679		}
680		free(dns_list);
681	}
682	if( (strchr(ip, ' ')) || (!strcmp(ip, "")) || (!strcmp(ip, gw_ip)) ) {
683#ifdef QOS_DEBUG
684		printf("	qos_get_wan_rate() ** GET DNS IP Error\n");
685#endif
686		nvram_set("qos_ubw_status", "fail");
687		nvram_set("qos_ubw_reason", "DNS server fail");
688	}
689	else
690	{
691		int choose=1;
692		choose=detect();
693		if(choose==0)
694		{
695			return WAN_LINK_FAIL;
696		}
697		if(strlen(gateway_ip[step])!=0)
698		{
699			while(pre_ping(gateway_ip[step])==0)
700			{
701				if(step==9)
702				{
703					return WAN_LINK_FAIL;
704				}
705				step++;
706				while(strlen(gateway_ip[step])==0)
707				{
708					if(step==9)
709					{
710						return WAN_LINK_FAIL;
711					}
712					step++;
713				}
714
715			}
716			sleep(1);
717		loop:request_time=1;
718			int i=0;
719			while(i<=35)
720			{
721				triptime[i]=0;
722				i++;
723			}
724			//printf("gateway_ip[step]=%s\n",gateway_ip[step]);
725			while(request_time<36)
726			{
727				deltatime(gateway_ip[step], &deltaval);
728				usleep(10);
729				request_time++;
730			}
731			i=0;
732			while(triptime[i]!=0)
733			{
734				i++;
735			}
736			i=i-(i%3);
737			if(i>12)
738			{
739					switch(i)
740					{
741						case 15:
742							triptime[0]=(triptime[3]+triptime[4]+triptime[5])/3;
743							triptime[1]=(triptime[i-1]+triptime[i-2]+triptime[i-3])/3;
744							break;
745						case 18:
746							triptime[0]=(triptime[3]+triptime[4]+triptime[5])/3;
747							triptime[1]=(triptime[i-1]+triptime[i-2]+triptime[i-3])/3;
748							triptime[2]=(triptime[i-4]+triptime[i-5]+triptime[i-6])/3;
749							break;
750						case 21:
751							triptime[0]=(triptime[3]+triptime[4]+triptime[5])/3;
752							triptime[1]=(triptime[i-1]+triptime[i-2]+triptime[i-3])/3;
753							triptime[2]=(triptime[i-4]+triptime[i-5]+triptime[i-6])/3;
754							triptime[3]=(triptime[i-7]+triptime[i-8]+triptime[i-9])/3;
755							break;
756						case 24:
757							triptime[0]=(triptime[3]+triptime[4]+triptime[5])/3;
758							triptime[1]=(triptime[i-1]+triptime[i-2]+triptime[i-3])/3;
759							triptime[2]=(triptime[i-4]+triptime[i-5]+triptime[i-6])/3;
760							triptime[3]=(triptime[i-7]+triptime[i-8]+triptime[i-9])/3;
761							triptime[4]=(triptime[i-10]+triptime[i-11]+triptime[i-12])/3;
762							break;
763						case 27:
764							triptime[0]=(triptime[3]+triptime[4]+triptime[5])/3;
765							triptime[1]=(triptime[i-1]+triptime[i-2]+triptime[i-3])/3;
766							triptime[2]=(triptime[i-4]+triptime[i-5]+triptime[i-6])/3;
767							triptime[3]=(triptime[i-7]+triptime[i-8]+triptime[i-9])/3;
768							triptime[4]=(triptime[i-10]+triptime[i-11]+triptime[i-12])/3;
769							triptime[5]=(triptime[i-13]+triptime[i-14]+triptime[i-15])/3;
770							break;
771						default:
772							triptime[0]=(triptime[3]+triptime[4]+triptime[5])/3;
773							triptime[1]=(triptime[i-1]+triptime[i-2]+triptime[i-3])/3;
774							triptime[2]=(triptime[i-4]+triptime[i-5]+triptime[i-6])/3;
775							triptime[3]=(triptime[i-7]+triptime[i-8]+triptime[i-9])/3;
776							triptime[4]=(triptime[i-10]+triptime[i-11]+triptime[i-12])/3;
777							triptime[5]=(triptime[i-13]+triptime[i-14]+triptime[i-15])/3;
778							triptime[6]=(triptime[i-16]+triptime[i-17]+triptime[i-18])/3;
779							break;
780
781					}
782				 if(i>=33)
783				{
784					int h=0;
785					for(h=0;h<=2;h++)
786					{
787						if(h==0)
788						{
789							need_package=80-15;
790						}
791						else
792						{
793							need_package=80-(h*2)-15;
794						}
795					wanrate.us=wanrate.us+((double)need_package*(datalen+46)*8/(triptime[h+2]-triptime[0])/1024*1000000);
796					int a=0;
797					a=(double)need_package*(datalen+46)*8/(triptime[h+2]-triptime[0])/1024*1000000;
798					printf("this package wanrateus=%d\n",a);
799					printf("finally wanrateus=%d\n",wanrate.us);
800					}
801					wanrate.us=wanrate.us/3;
802					printf("wanrate.us1=%d\n",wanrate.us);
803					if(wanrate.us>10500)
804					{
805						wanrate.us=10080;
806					}
807
808				}
809				else
810				{
811					int y=i;
812					y=(30-y)/3;
813					int h=1;
814					//i=30 need_package=80-15
815					//i=27 need_package=78-15
816					//i=24 need_package=76-15
817					//i=21 need_package=74-15
818					//i=18 need_package=72-15
819					//i=15 need_package=70-15
820					while(need_package>55)
821					{
822						need_package=80-(y*2)-15;
823						y=y+1;
824						h++;
825						wanrate.us=wanrate.us+((double)need_package*(datalen+46)*8/(triptime[h-1]-triptime[0])/1024*1000000);
826						//int a=0;
827						//a=(double)need_package*(datalen+46)*8/(triptime[h-1]-triptime[0])/1024*1000000;
828						//printf("a=%d\n",a);
829						//printf("wanrate.us%d\n",wanrate.us);
830					}
831				wanrate.us=wanrate.us/(h-1);
832				printf("wanrate.us2=%d\n",wanrate.us);
833				if(wanrate.us>10500)
834					{
835						wanrate.us=10080;
836					}
837				}
838
839
840			}
841			else
842			{
843				triptime[0]=(triptime[3]+triptime[4]+triptime[5])/3;
844				triptime[1]=(triptime[9]+triptime[10]+triptime[11])/3;
845				need_package=54-15;
846				wanrate.us = (double)need_package*(datalen+46)*8/(triptime[1]-triptime[0])/1024*1000000 ;
847				if(wanrate.us>10500)
848					{
849						wanrate.us=10080;
850					}
851				if(wanrate.us==0 && i==9)
852				{
853					triptime[0]=(triptime[3]+triptime[4]+triptime[5])/3;
854					triptime[1]=(triptime[6]+triptime[7]+triptime[8])/3;
855					need_package=29-15;
856				wanrate.us = (double)need_package*(datalen+46)*8/(triptime[1]-triptime[0])/1024*1000000*1.1 ;
857				if(wanrate.us>10500)
858					{
859						wanrate.us=10080;
860					}
861				}
862				if(wanrate.us==0 && i==6)
863				{
864					triptime[0]=(triptime[0]+triptime[1]+triptime[2])/3;
865					triptime[1]=(triptime[3]+triptime[4]+triptime[5])/3;
866					need_package=15-9;
867				wanrate.us = (double)need_package*(datalen+46)*8/(triptime[1]-triptime[0])/1024*1000000*1.1 ;
868				if(wanrate.us>10500)
869					{
870						wanrate.us=10080;
871					}
872				}
873				printf("wanrate.us3=%d\n",wanrate.us);
874
875			}
876		}
877		else
878		{
879			step--;
880			while(strlen(gateway_ip[step])==0)
881			{
882				if(step==0)
883				{
884					return WAN_LINK_FAIL;
885				}
886				step--;
887			}
888			while(pre_ping(gateway_ip[step])==0)
889			{
890				if(step==0)
891				{
892					return WAN_LINK_FAIL;
893				}
894				step--;
895			}
896			sleep(1);
897			goto loop;
898		}
899	}
900	free(gw_ip);
901
902	if( strcmp(nvram_safe_get("qos_ubw_status"), "fail") == 0 ) {
903#ifdef WL600g
904		if( !strcmp(nvram_safe_get("qos_ubw_reason"), "DNS server fail") )
905		{
906			//DownStream
907        		if ( glbAdslInfo.ulInterleavedDnStreamRate != 0 )
908         		    wanrate.ds = glbAdslInfo.ulInterleavedDnStreamRate / 1000;
909        		else
910            		    wanrate.ds =  glbAdslInfo.ulFastDnStreamRate / 1000;
911
912			//UpStream
913        		if ( glbAdslInfo.ulInterleavedUpStreamRate != 0 )
914		            wanrate.us = glbAdslInfo.ulInterleavedUpStreamRate / 1000;
915		        else
916            		    wanrate.us = glbAdslInfo.ulFastUpStreamRate / 1000;
917
918			//sprintf(ds, "%u", wanrate.ds);
919			//nvram_set("wan_ds", ds);
920			sprintf(us, "%u", wanrate.us);
921			nvram_set("qos_ubw", us);
922
923			nvram_set("qos_ubw_status", "success");
924
925			return WAN_RATE_SUCCESS;
926		}
927		else
928			return WAN_LINK_FAIL;
929#else
930		return WAN_LINK_FAIL;
931#endif
932	}
933
934#ifdef QOS_DEBUG
935        printf("\n      start time ** tv_sec=%ld: tv_usec=%ld\n",tstart.tv_sec, tstart.tv_usec);
936        printf("        end time   ** tv_sec=%ld : tv_usec=%ld\n", tend.tv_sec, tend.tv_usec);
937        printf("                      delta_sec=%ld : delta_usec=%ld\n", deltaval.tv_sec*1000000, deltaval.tv_usec);
938#endif
939        printf("wanrate.us=%u\n\n",wanrate.us);
940
941
942	if( wanrate.us!=0 )
943		nvram_set("qos_ubw_status", "success");
944
945#ifdef 	QOS_DEBUG
946        printf("\nUpload Bandwidth = %.0u kbps\n", wanrate.us);
947#endif
948
949	wanrate.ds = 0;
950	sprintf(us, "%u", wanrate.us);
951	nvram_set("qos_ubw", us);
952
953
954	return WAN_RATE_SUCCESS;
955
956}
957
958#ifdef WL600g
959//**************************************************************************
960// Function Name: Speedtest_init
961// Description  : init function, called by BcmNtwk_init() in ifcntwkapi.cpp
962// Returns      : 0
963//**************************************************************************
964int Speedtest_init(void) {
965        FILE *fp;
966
967        /* Run it under background */
968        switch (fork()) {
969        case -1:
970                exit(0);
971                break;
972        case 0:
973                // start in a new session
974                (void) setsid();
975                break;
976        default:
977                // parent process should just die
978                return 0;
979        }
980
981        /* write pid */
982        if ((fp=fopen("/var/run/speedtest.pid", "w"))!=NULL)
983        {
984                fprintf(fp, "%d", getpid());
985                fclose(fp);
986        }
987
988	nvram_set("qos_ubw_status", "initialing");
989
990	sleep(60);
991	if( nvram_match("qos_enable", "1") ) {
992
993		qos_get_wan_rate();
994		if(nvram_match("qos_ubw_status", "success") )
995			start_qos();
996	}
997
998	while(1){
999		pause();
1000	}
1001
1002        return 0;
1003}
1004#else
1005//extern void start_qos(void);
1006
1007int Speedtest_Init(void) {
1008	char net_name[32];
1009	FILE *fp=NULL;
1010
1011	printf("*** run Speedtest_Init(). ***\n");
1012
1013// 2009.03 James. Mark these and put them into network.c. {
1014/*	nvram_set("qos_userspec_app", "0");
1015	nvram_set("qos_global_enable", "0");
1016	nvram_set("qos_userdef_enable", "0");
1017	//nvram_set("qos_enable", "0");
1018
1019	if(nvram_invmatch("qos_rulenum_x", "0"))
1020		nvram_set("qos_userspec_app", "1");
1021
1022	//add by Angela 2008.05
1023	if(nvram_match("qos_tos_prio", "1")||nvram_match("qos_pshack_prio", "1")
1024	  || nvram_match("qos_service_enable", "1")|| nvram_match("qos_shortpkt_prio", "1"))
1025		nvram_set("qos_global_enable", "1");
1026
1027	if(nvram_match("qos_userspec_app", "1") || nvram_match("qos_dfragment_enable", "1"))
1028		nvram_set("qos_userdef_enable", "1");//*/
1029// 2009.03 James. }
1030
1031	/* Get interface name */
1032	if (nvram_match("wan0_proto", "pppoe") || nvram_match("wan0_proto", "pptp") || nvram_match("wan0_proto", "l2tp"))
1033		strcpy (net_name, nvram_safe_get("wan0_pppoe_ifname"));
1034	else
1035		strcpy (net_name, nvram_safe_get("wan0_ifname"));
1036
1037	/* Reset all qdisc first */
1038	eval ("tc","qdisc","del", "dev", net_name, "root", "htb");
1039
1040	/* Clean iptables*/
1041	/*eval("iptables", "-F", "-t", "mangle");*/
1042	if ((fp=fopen("/tmp/mangle_rules", "w"))==NULL) return 0;
1043	fprintf(fp, "*mangle\n");
1044	fprintf(fp, "-F\n");
1045	fprintf(fp, "COMMIT\n\n");
1046	fclose(fp);
1047	eval("iptables-restore", "/tmp/mangle_rules");
1048
1049// 2009.03 James. Mark these and put them into network.c. {
1050	/*if(nvram_invmatch("qos_manual_ubw","0") && nvram_invmatch("qos_manual_ubw",""))
1051	{
1052		nvram_set("qos_ubw",nvram_get("qos_manual_ubw"));
1053	}
1054	else if(nvram_invmatch("qos_ubw", "0"))
1055		nvram_set("qos_ubw",nvram_get("qos_ubw_tmp"));
1056
1057#if 0
1058	if(nvram_invmatch("qos_manual_ubw","0") && nvram_invmatch("qos_manual_ubw",""))
1059	{
1060		nvram_set("qos_ubw",nvram_get("qos_manual_ubw"));
1061	}
1062	else if(nvram_match("qos_ubw_tmp", "0"))
1063	{
1064		qos_get_wan_rate();
1065		nvram_set("qos_ubw",nvram_get("qos_ubw_tmp"));
1066	}
1067	else
1068		nvram_set("qos_ubw", nvram_get("qos_ubw_tmp"));
1069#endif//*/
1070// 2009.03 James. Mark these and put them into network.c. }
1071
1072// 2009.03 James. {
1073	/*if(nvram_match("qos_global_enable", "1") || nvram_match("qos_userdef_enable", "1"))
1074	{
1075		nvram_set("qos_enable", "1");
1076		nvram_commit();
1077
1078		if(nvram_invmatch("qos_ubw", "0"))
1079		{
1080			start_qos();
1081		}
1082	}
1083	else{
1084		nvram_set("qos_enable", "0");
1085		nvram_commit();
1086	}//*/
1087	if(nvram_match("qos_enable", "1"))
1088		start_qos();
1089// 2009.03 James. }
1090
1091	return 0;
1092}
1093#endif
1094
1095#ifdef MYGCC
1096int main(int argc, char** argv)
1097{
1098	int i = 0;
1099	char *thisarg;
1100
1101	printf("	%-20s	%-20s\n", "index", "value");
1102
1103	while( i<argc ) {
1104	    printf("	%-20d	%-20s\n", i, argv[i]);
1105	    i++;
1106	}
1107
1108	argc--;
1109	argv++;
1110	while( argc>0 && **argv=='-' ) {
1111	    	thisarg = *argv;
1112		thisarg++;
1113		switch (*thisarg) {
1114		case 'c':
1115			if (--argc <= 0)
1116			        exit(1);
1117			argv++;
1118			pingcount = atoi(*argv);
1119			break;
1120		case 's':
1121			if (--argc <= 0)
1122			        exit(1);
1123			argv++;
1124			datalen = atoi(*argv);
1125			break;
1126		default:
1127			exit(1);
1128		}
1129		argc--;
1130		argv++;
1131	}
1132
1133	if( argc<0 ) 	exit(1);
1134
1135        struct timeval deltaval;
1136
1137        deltatime(*argv, &deltaval);
1138
1139	printf("\n	start time ** tv_sec=%u : tv_usec=%u\n",tstart.tv_sec, tstart.tv_usec);
1140	printf("	end time   ** tv_sec=%u : tv_usec=%u\n", tend.tv_sec, tend.tv_usec);
1141        printf("        	      delta_sec=%u : delta_usec=%u\n", deltaval.tv_sec*1000000, deltaval.tv_usec);
1142
1143	double delta_us = 0;
1144	delta_us = (int)deltaval.tv_sec * 1000000 + deltaval.tv_usec;
1145        printf("        delta interval = %f us\n", delta_us);
1146
1147        double bw = ( (( (datalen+42)*pingcount*8 )/delta_us) )*1000000/1024;
1148        printf("\n	bandwidth = %.0f kbps\n", bw);
1149
1150	return 0;
1151}
1152#endif
1153
1154#endif
1155