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]; // 2009.12 James. Directly use gateway_ip.
590	int j=0;
591	while(j<=9)
592	{
593		//memset(&get_ip[j], 0, sizeof(get_ip[j])); // 2009.12 James.
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						gateway_ip[i][j-1]=*p; // 2009.12 James.
626						j++;
627					}
628					//get_ip[i][j-2]='\0';
629					gateway_ip[i][j-2]='\0'; // 2009.12 James.
630				}
631				i++;
632
633			}
634			/*i=0; // 2009.12 James.
635			while(i<10)
636			{
637				sprintf(gateway_ip[i],"%s",get_ip[i]);
638				i++;
639			}//*/
640		}
641		fclose(fp);
642		return 1;
643}
644
645/**************************************************************************
646 * Function Name: qos_get_wan_rate
647 * Description  : get the ADSL line rate
648 * Parameters   : None
649 * Returns      : Is successful when get the ADSL data rate?
650			0 : Success
651			1 : Link fail
652 **************************************************************************/
653extern int qos_get_wan_rate(void)
654{
655	static struct wan_link_rate wanrate;
656	char us[256], ds[256] ;
657	char * gw_ip=NULL;
658	struct timeval deltaval;
659       	double delta_us = 0;
660	wanrate.us = wanrate.ds = 0;
661	int step=3;
662	char *ip = nvram_safe_get("wan_dns_t");
663	int need_package=80;
664	if( !check_wan_link(0) )
665		return WAN_LINK_FAIL;
666
667	gw_ip = get_gw_ip();
668
669	if((strchr(ip, ' ')) ||(!strcmp(ip, "")))
670	{
671		struct dns_lists *dns_list = get_dns_list(1);
672		int i;
673
674		for(i=0 ; i<dns_list->num_servers ; i++){
675			ip = dns_list->dns_server[i];
676			if(    (!strchr(ip, ' '))
677			    && (strcmp(ip, ""))
678			    && (strcmp(ip, gw_ip))) //WL600g auto assign LAN IP as DNS Server
679				break;
680		}
681		free(dns_list);
682	}
683	if( (strchr(ip, ' ')) || (!strcmp(ip, "")) || (!strcmp(ip, gw_ip)) ) {
684#ifdef QOS_DEBUG
685		printf("	qos_get_wan_rate() ** GET DNS IP Error\n");
686#endif
687		nvram_set("qos_ubw_status", "fail");
688		nvram_set("qos_ubw_reason", "DNS server fail");
689	}
690	else
691	{
692		int choose=1;
693		choose=detect();
694		if(choose==0)
695		{
696			return WAN_LINK_FAIL;
697		}
698		if(strlen(gateway_ip[step])!=0)
699		{
700			while(pre_ping(gateway_ip[step])==0)
701			{
702				if(step==9)
703				{
704					return WAN_LINK_FAIL;
705				}
706				step++;
707				while(strlen(gateway_ip[step])==0)
708				{
709					if(step==9)
710					{
711						return WAN_LINK_FAIL;
712					}
713					step++;
714				}
715
716			}
717			sleep(1);
718		loop:request_time=1;
719			int i=0;
720			while(i<=35)
721			{
722				triptime[i]=0;
723				i++;
724			}
725			//printf("gateway_ip[step]=%s\n",gateway_ip[step]);
726			while(request_time<36)
727			{
728				deltatime(gateway_ip[step], &deltaval);
729				usleep(10);
730				request_time++;
731			}
732			i=0;
733			while(triptime[i]!=0)
734			{
735				i++;
736			}
737			i=i-(i%3);
738			if(i>12)
739			{
740					switch(i)
741					{
742						case 15:
743							triptime[0]=(triptime[3]+triptime[4]+triptime[5])/3;
744							triptime[1]=(triptime[i-1]+triptime[i-2]+triptime[i-3])/3;
745							break;
746						case 18:
747							triptime[0]=(triptime[3]+triptime[4]+triptime[5])/3;
748							triptime[1]=(triptime[i-1]+triptime[i-2]+triptime[i-3])/3;
749							triptime[2]=(triptime[i-4]+triptime[i-5]+triptime[i-6])/3;
750							break;
751						case 21:
752							triptime[0]=(triptime[3]+triptime[4]+triptime[5])/3;
753							triptime[1]=(triptime[i-1]+triptime[i-2]+triptime[i-3])/3;
754							triptime[2]=(triptime[i-4]+triptime[i-5]+triptime[i-6])/3;
755							triptime[3]=(triptime[i-7]+triptime[i-8]+triptime[i-9])/3;
756							break;
757						case 24:
758							triptime[0]=(triptime[3]+triptime[4]+triptime[5])/3;
759							triptime[1]=(triptime[i-1]+triptime[i-2]+triptime[i-3])/3;
760							triptime[2]=(triptime[i-4]+triptime[i-5]+triptime[i-6])/3;
761							triptime[3]=(triptime[i-7]+triptime[i-8]+triptime[i-9])/3;
762							triptime[4]=(triptime[i-10]+triptime[i-11]+triptime[i-12])/3;
763							break;
764						case 27:
765							triptime[0]=(triptime[3]+triptime[4]+triptime[5])/3;
766							triptime[1]=(triptime[i-1]+triptime[i-2]+triptime[i-3])/3;
767							triptime[2]=(triptime[i-4]+triptime[i-5]+triptime[i-6])/3;
768							triptime[3]=(triptime[i-7]+triptime[i-8]+triptime[i-9])/3;
769							triptime[4]=(triptime[i-10]+triptime[i-11]+triptime[i-12])/3;
770							triptime[5]=(triptime[i-13]+triptime[i-14]+triptime[i-15])/3;
771							break;
772						default:
773							triptime[0]=(triptime[3]+triptime[4]+triptime[5])/3;
774							triptime[1]=(triptime[i-1]+triptime[i-2]+triptime[i-3])/3;
775							triptime[2]=(triptime[i-4]+triptime[i-5]+triptime[i-6])/3;
776							triptime[3]=(triptime[i-7]+triptime[i-8]+triptime[i-9])/3;
777							triptime[4]=(triptime[i-10]+triptime[i-11]+triptime[i-12])/3;
778							triptime[5]=(triptime[i-13]+triptime[i-14]+triptime[i-15])/3;
779							triptime[6]=(triptime[i-16]+triptime[i-17]+triptime[i-18])/3;
780							break;
781
782					}
783				 if(i>=33)
784				{
785					int h=0;
786					for(h=0;h<=2;h++)
787					{
788						if(h==0)
789						{
790							need_package=80-15;
791						}
792						else
793						{
794							need_package=80-(h*2)-15;
795						}
796					wanrate.us=wanrate.us+((double)need_package*(datalen+46)*8/(triptime[h+2]-triptime[0])/1024*1000000);
797					int a=0;
798					a=(double)need_package*(datalen+46)*8/(triptime[h+2]-triptime[0])/1024*1000000;
799					printf("this package wanrateus=%d\n",a);
800					printf("finally wanrateus=%d\n",wanrate.us);
801					}
802					wanrate.us=wanrate.us/3;
803					printf("wanrate.us1=%d\n",wanrate.us);
804					if(wanrate.us>10500)
805					{
806						wanrate.us=10080;
807					}
808
809				}
810				else
811				{
812					int y=i;
813					y=(30-y)/3;
814					int h=1;
815					//i=30 need_package=80-15
816					//i=27 need_package=78-15
817					//i=24 need_package=76-15
818					//i=21 need_package=74-15
819					//i=18 need_package=72-15
820					//i=15 need_package=70-15
821					while(need_package>55)
822					{
823						need_package=80-(y*2)-15;
824						y=y+1;
825						h++;
826						wanrate.us=wanrate.us+((double)need_package*(datalen+46)*8/(triptime[h-1]-triptime[0])/1024*1000000);
827						//int a=0;
828						//a=(double)need_package*(datalen+46)*8/(triptime[h-1]-triptime[0])/1024*1000000;
829						//printf("a=%d\n",a);
830						//printf("wanrate.us%d\n",wanrate.us);
831					}
832				wanrate.us=wanrate.us/(h-1);
833				printf("wanrate.us2=%d\n",wanrate.us);
834				if(wanrate.us>10500)
835					{
836						wanrate.us=10080;
837					}
838				}
839
840
841			}
842			else
843			{
844				triptime[0]=(triptime[3]+triptime[4]+triptime[5])/3;
845				triptime[1]=(triptime[9]+triptime[10]+triptime[11])/3;
846				need_package=54-15;
847				wanrate.us = (double)need_package*(datalen+46)*8/(triptime[1]-triptime[0])/1024*1000000 ;
848				if(wanrate.us>10500)
849					{
850						wanrate.us=10080;
851					}
852				if(wanrate.us==0 && i==9)
853				{
854					triptime[0]=(triptime[3]+triptime[4]+triptime[5])/3;
855					triptime[1]=(triptime[6]+triptime[7]+triptime[8])/3;
856					need_package=29-15;
857				wanrate.us = (double)need_package*(datalen+46)*8/(triptime[1]-triptime[0])/1024*1000000*1.1 ;
858				if(wanrate.us>10500)
859					{
860						wanrate.us=10080;
861					}
862				}
863				if(wanrate.us==0 && i==6)
864				{
865					triptime[0]=(triptime[0]+triptime[1]+triptime[2])/3;
866					triptime[1]=(triptime[3]+triptime[4]+triptime[5])/3;
867					need_package=15-9;
868				wanrate.us = (double)need_package*(datalen+46)*8/(triptime[1]-triptime[0])/1024*1000000*1.1 ;
869				if(wanrate.us>10500)
870					{
871						wanrate.us=10080;
872					}
873				}
874				printf("wanrate.us3=%d\n",wanrate.us);
875
876			}
877		}
878		else
879		{
880			step--;
881			while(strlen(gateway_ip[step])==0)
882			{
883				if(step==0)
884				{
885					return WAN_LINK_FAIL;
886				}
887				step--;
888			}
889			while(pre_ping(gateway_ip[step])==0)
890			{
891				if(step==0)
892				{
893					return WAN_LINK_FAIL;
894				}
895				step--;
896			}
897			sleep(1);
898			goto loop;
899		}
900	}
901	free(gw_ip);
902
903	if( strcmp(nvram_safe_get("qos_ubw_status"), "fail") == 0 ) {
904#ifdef WL600g
905		if( !strcmp(nvram_safe_get("qos_ubw_reason"), "DNS server fail") )
906		{
907			//DownStream
908        		if ( glbAdslInfo.ulInterleavedDnStreamRate != 0 )
909         		    wanrate.ds = glbAdslInfo.ulInterleavedDnStreamRate / 1000;
910        		else
911            		    wanrate.ds =  glbAdslInfo.ulFastDnStreamRate / 1000;
912
913			//UpStream
914        		if ( glbAdslInfo.ulInterleavedUpStreamRate != 0 )
915		            wanrate.us = glbAdslInfo.ulInterleavedUpStreamRate / 1000;
916		        else
917            		    wanrate.us = glbAdslInfo.ulFastUpStreamRate / 1000;
918
919			//sprintf(ds, "%u", wanrate.ds);
920			//nvram_set("wan_ds", ds);
921			sprintf(us, "%u", wanrate.us);
922			nvram_set("qos_ubw", us);
923
924			nvram_set("qos_ubw_status", "success");
925
926			return WAN_RATE_SUCCESS;
927		}
928		else
929			return WAN_LINK_FAIL;
930#else
931		return WAN_LINK_FAIL;
932#endif
933	}
934
935#ifdef QOS_DEBUG
936        printf("\n      start time ** tv_sec=%ld: tv_usec=%ld\n",tstart.tv_sec, tstart.tv_usec);
937        printf("        end time   ** tv_sec=%ld : tv_usec=%ld\n", tend.tv_sec, tend.tv_usec);
938        printf("                      delta_sec=%ld : delta_usec=%ld\n", deltaval.tv_sec*1000000, deltaval.tv_usec);
939#endif
940        printf("wanrate.us=%u\n\n",wanrate.us);
941
942
943	if( wanrate.us!=0 )
944		nvram_set("qos_ubw_status", "success");
945
946#ifdef 	QOS_DEBUG
947        printf("\nUpload Bandwidth = %.0u kbps\n", wanrate.us);
948#endif
949
950	wanrate.ds = 0;
951	sprintf(us, "%u", wanrate.us);
952	nvram_set("qos_ubw", us);
953
954
955	return WAN_RATE_SUCCESS;
956
957}
958
959#ifdef WL600g
960//**************************************************************************
961// Function Name: Speedtest_init
962// Description  : init function, called by BcmNtwk_init() in ifcntwkapi.cpp
963// Returns      : 0
964//**************************************************************************
965int Speedtest_init(void) {
966        FILE *fp;
967
968        /* Run it under background */
969        switch (fork()) {
970        case -1:
971                exit(0);
972                break;
973        case 0:
974                // start in a new session
975                (void) setsid();
976                break;
977        default:
978                // parent process should just die
979                return 0;
980        }
981
982        /* write pid */
983        if ((fp=fopen("/var/run/speedtest.pid", "w"))!=NULL)
984        {
985                fprintf(fp, "%d", getpid());
986                fclose(fp);
987        }
988
989	nvram_set("qos_ubw_status", "initialing");
990
991	sleep(60);
992	if( nvram_match("qos_enable", "1") ) {
993
994		qos_get_wan_rate();
995		if(nvram_match("qos_ubw_status", "success") )
996			start_qos();
997	}
998
999	while(1){
1000		pause();
1001	}
1002
1003        return 0;
1004}
1005#else
1006//extern void start_qos(void);
1007
1008int Speedtest_Init(void) {
1009	char net_name[32];
1010	FILE *fp=NULL;
1011
1012	printf("*** run Speedtest_Init(). ***\n");
1013
1014// 2009.03 James. Mark these and put them into network.c. {
1015/*	nvram_set("qos_userspec_app", "0");
1016	nvram_set("qos_global_enable", "0");
1017	nvram_set("qos_userdef_enable", "0");
1018	//nvram_set("qos_enable", "0");
1019
1020	if(nvram_invmatch("qos_rulenum_x", "0"))
1021		nvram_set("qos_userspec_app", "1");
1022
1023	//add by Angela 2008.05
1024	if(nvram_match("qos_tos_prio", "1")||nvram_match("qos_pshack_prio", "1")
1025	  || nvram_match("qos_service_enable", "1")|| nvram_match("qos_shortpkt_prio", "1"))
1026		nvram_set("qos_global_enable", "1");
1027
1028	if(nvram_match("qos_userspec_app", "1") || nvram_match("qos_dfragment_enable", "1"))
1029		nvram_set("qos_userdef_enable", "1");//*/
1030// 2009.03 James. }
1031
1032	/* Get interface name */
1033	if (nvram_match("wan0_proto", "pppoe") || nvram_match("wan0_proto", "pptp") || nvram_match("wan0_proto", "l2tp"))
1034		strcpy (net_name, nvram_safe_get("wan0_pppoe_ifname"));
1035	else
1036		strcpy (net_name, nvram_safe_get("wan0_ifname"));
1037
1038	/* Reset all qdisc first */
1039	eval ("tc","qdisc","del", "dev", net_name, "root", "htb");
1040
1041	/* Clean iptables*/
1042	/*eval("iptables", "-F", "-t", "mangle");*/
1043	if ((fp=fopen("/tmp/mangle_rules", "w"))==NULL) return 0;
1044	fprintf(fp, "*mangle\n");
1045	fprintf(fp, "-F\n");
1046	fprintf(fp, "COMMIT\n\n");
1047	fclose(fp);
1048	eval("iptables-restore", "/tmp/mangle_rules");
1049
1050// 2009.03 James. Mark these and put them into network.c. {
1051	/*if(nvram_invmatch("qos_manual_ubw","0") && nvram_invmatch("qos_manual_ubw",""))
1052	{
1053		nvram_set("qos_ubw",nvram_get("qos_manual_ubw"));
1054	}
1055	else if(nvram_invmatch("qos_ubw", "0"))
1056		nvram_set("qos_ubw",nvram_get("qos_ubw_tmp"));
1057
1058#if 0
1059	if(nvram_invmatch("qos_manual_ubw","0") && nvram_invmatch("qos_manual_ubw",""))
1060	{
1061		nvram_set("qos_ubw",nvram_get("qos_manual_ubw"));
1062	}
1063	else if(nvram_match("qos_ubw_tmp", "0"))
1064	{
1065		qos_get_wan_rate();
1066		nvram_set("qos_ubw",nvram_get("qos_ubw_tmp"));
1067	}
1068	else
1069		nvram_set("qos_ubw", nvram_get("qos_ubw_tmp"));
1070#endif//*/
1071// 2009.03 James. Mark these and put them into network.c. }
1072
1073// 2009.03 James. {
1074	/*if(nvram_match("qos_global_enable", "1") || nvram_match("qos_userdef_enable", "1"))
1075	{
1076		nvram_set("qos_enable", "1");
1077		nvram_commit();
1078
1079		if(nvram_invmatch("qos_ubw", "0"))
1080		{
1081			start_qos();
1082		}
1083	}
1084	else{
1085		nvram_set("qos_enable", "0");
1086		nvram_commit();
1087	}//*/
1088	if(nvram_match("qos_enable", "1"))
1089		start_qos();
1090// 2009.03 James. }
1091
1092	return 0;
1093}
1094#endif
1095
1096#ifdef MYGCC
1097int main(int argc, char** argv)
1098{
1099	int i = 0;
1100	char *thisarg;
1101
1102	printf("	%-20s	%-20s\n", "index", "value");
1103
1104	while( i<argc ) {
1105	    printf("	%-20d	%-20s\n", i, argv[i]);
1106	    i++;
1107	}
1108
1109	argc--;
1110	argv++;
1111	while( argc>0 && **argv=='-' ) {
1112	    	thisarg = *argv;
1113		thisarg++;
1114		switch (*thisarg) {
1115		case 'c':
1116			if (--argc <= 0)
1117			        exit(1);
1118			argv++;
1119			pingcount = atoi(*argv);
1120			break;
1121		case 's':
1122			if (--argc <= 0)
1123			        exit(1);
1124			argv++;
1125			datalen = atoi(*argv);
1126			break;
1127		default:
1128			exit(1);
1129		}
1130		argc--;
1131		argv++;
1132	}
1133
1134	if( argc<0 ) 	exit(1);
1135
1136        struct timeval deltaval;
1137
1138        deltatime(*argv, &deltaval);
1139
1140	printf("\n	start time ** tv_sec=%u : tv_usec=%u\n",tstart.tv_sec, tstart.tv_usec);
1141	printf("	end time   ** tv_sec=%u : tv_usec=%u\n", tend.tv_sec, tend.tv_usec);
1142        printf("        	      delta_sec=%u : delta_usec=%u\n", deltaval.tv_sec*1000000, deltaval.tv_usec);
1143
1144	double delta_us = 0;
1145	delta_us = (int)deltaval.tv_sec * 1000000 + deltaval.tv_usec;
1146        printf("        delta interval = %f us\n", delta_us);
1147
1148        double bw = ( (( (datalen+42)*pingcount*8 )/delta_us) )*1000000/1024;
1149        printf("\n	bandwidth = %.0f kbps\n", bw);
1150
1151	return 0;
1152}
1153#endif
1154
1155#endif
1156