diff options
-rw-r--r-- | README | 43 | ||||
-rw-r--r-- | gtp/gtp.h | 2 | ||||
-rw-r--r-- | sgsnemu/sgsnemu.c | 70 |
3 files changed, 92 insertions, 23 deletions
@@ -96,15 +96,18 @@ the testing of roaming connectivity through a GPRS roaming exchange. Two experiments were performed in order to test the performance of sgsnemu and ggsn. The ggsn used a 550 MHz Athlon with 384 MB of RAM. sgsnemu used a 1 GHz Athlon with 256 MB of RAM. Both machines had -100 Mb/s NICs and were connected through a Netgear FS105 switch. Both -tests were performed by sending ICMP echo packets from the ggsn to -sgsnemu. +100 Mb/s NICs (RTL-8139) and were connected through a crossed patch +cable. Both tests were performed by sending ICMP echo packets from +sgsnemu to the ggsn. -89.4 Mb/s IP downlink throughput when sending 10001 ICMP ping packets -with a payload of 1000 bytes. Transfer time 0.9 sec, no packets lost. +89.5 Mb/s IP throughput when sending 10000 ICMP ping packets with a +payload of 1400 bytes. Transfer time 1.27 sec, no packets lost. -17,1 Mb/s IP downlink throughput when sending 10001 ICMP ping packets with -a payload of 100 bytes. Transfer time 0.6 sec, no packets lost. +71.4 Mb/s IP throughput when sending 10000 ICMP ping packets with a +payload of 1000 bytes. Transfer time 1.15 sec, no packets lost. + +12,1 Mb/s IP throughput when sending 10000 ICMP ping packets with a +payload of 100 bytes. Transfer time 0.84 sec, no packets lost. *** Required software *** @@ -191,6 +194,32 @@ Use ggsn -h for a list of available options. All options available on the command line can also be given in a configuration file. See examples/ggsn.conf for the format of this file. +Start the ggsn as root using the command: + + ggsn -c examples/ggsn.conf --fg -l 10.20.30.40 --net 192.168.0.0 --mask 255.255.0.0 + +First a tun network interface will be created. In the above example +the network interface address is 192.168.0.0 and the mask is +255.255.0.0. You can check that this interface is up by using +ifconfig. + +After tun has been successfully established the ggsn will wait for GTP +create PDP context requests on the local interface +10.20.30.40. Currently all requests are excepted, and no password, +username or APN validation is performed. + +When receiving a create PDP context request a dynamic IP address will +be allocated from the address pool determined by --net and --mask. In +the above example the first allocated address will be 192.168.0.1, +followed by 192.168.0.2 and so on. The request is confirmed by sending +a create PDP context response message to the peer (SGSN). + +Now IP packets will be forwarded between the tun network interface and +the established GTP tunnel. In order to allow users to access the +external network routing needs to be set up. If private addresses are +are used you need to configure network address translation. See the +Linux Networking HOWTO for details. + Remember to enable routing: echo 1 > /proc/sys/net/ipv4/ip_forward *** Running sgsnemu *** @@ -17,7 +17,7 @@ #ifndef _GTP_H #define _GTP_H -#define GTP_DEBUG 1 /* Print debug information */ +#define GTP_DEBUG 0 /* Print debug information */ #define GTP0_PORT 3386 #define GTP1C_PORT 2123 diff --git a/sgsnemu/sgsnemu.c b/sgsnemu/sgsnemu.c index b6741b1..1cdfcac 100644 --- a/sgsnemu/sgsnemu.c +++ b/sgsnemu/sgsnemu.c @@ -120,6 +120,8 @@ int ntransmitted = 0; int tmin = 999999999; int tmax = 0; int tsum = 0; +int pingseq = 0; /* Ping sequence counter */ +struct timeval firstping; int encaps_printf(struct pdp_t *pdp, void *pack, unsigned len) { @@ -168,12 +170,40 @@ char * print_icmptype(int t) { return(ttab[t]); } +/* Calculate time left until we have to send off next ping packet */ +int ping_timeout(struct timeval *tp) { + struct timezone tz; + struct timeval tv; + int diff; + if ((pinghost.s_addr) && (2 == state) && + ((pingseq < pingcount) || (pingcount == 0))) { + gettimeofday(&tv, &tz); + diff = 1000000 / pingrate * pingseq - + 1000000 * (tv.tv_sec - firstping.tv_sec) - + (tv.tv_usec - firstping.tv_usec); /* Microseconds safe up to 500 sec */ + tp->tv_sec = 0; + if (diff > 0) + tp->tv_usec = diff; + else + /* For some reason we get packet loss if set to zero */ + tp->tv_usec = 100000 / pingrate; /* 10 times pingrate */ + } + return 0; +} + /* Print out statistics when at the end of ping sequence */ int ping_finish() { + struct timezone tz; + struct timeval tv; + int elapsed; + gettimeofday(&tv, &tz); + elapsed = 1000000 * (tv.tv_sec - firstping.tv_sec) + + (tv.tv_usec - firstping.tv_usec); /* Microseconds */ printf("\n"); printf("\n----%s PING Statistics----\n", inet_ntoa(pinghost)); - printf("%d packets transmitted, ", ntransmitted ); + printf("%d packets transmitted in %.3f seconds, ", ntransmitted, + elapsed / 1000000.0); printf("%d packets received, ", nreceived ); if (ntransmitted) { if( nreceived > ntransmitted) @@ -190,6 +220,8 @@ int ping_finish() tmin/1000.0, tsum/1000.0/nreceived, tmax/1000.0 ); + printf("%d packets transmitted \n", ntreceived ); + ntransmitted = 0; return 0; } @@ -529,7 +561,10 @@ int main(int argc, char **argv) struct pdp_t *pdp[50]; int n; /* For counter */ int starttime; /* Time program was started */ - int pingseq = 0; /* Ping sequence counter */ + + struct timezone tz; /* Used for calculating ping times */ + struct timeval tv; + int diff; /* function-local options */ struct ul_t imsi, qos, apn, msisdn; @@ -951,16 +986,23 @@ int main(int argc, char **argv) if (gtpfd != -1) gtp_delete_context(gsn, pdp[n], NULL); if ((pinghost.s_addr !=0) && ntransmitted) ping_finish(); } -} + } - /* Ping */ - while ((2 == state) && (pinghost.s_addr !=0) && - ((pingseq < pingcount) || (pingcount == 0)) && - (starttime + pingseq/pingrate) <= time(NULL)) { - create_ping(gsn, pdp[pingseq % contexts], - &pinghost, pingseq, pingsize); - pingseq++; + /* Send off an ICMP ping packet */ + if ((pinghost.s_addr) && (2 == state) && + ((pingseq < pingcount) || (pingcount == 0))) { + if (!pingseq) gettimeofday(&firstping, &tz); /* Set time of first ping */ + gettimeofday(&tv, &tz); + diff = 1000000 / pingrate * pingseq - + 1000000 * (tv.tv_sec - firstping.tv_sec) - + (tv.tv_usec - firstping.tv_usec); /* Microseconds safe up to 500 sec */ + if (diff <=0) { + if (debug) printf("Create_ping %d\n", diff); + create_ping(gsn, pdp[pingseq % contexts], + &pinghost, pingseq, pingsize); + pingseq++; + } } if (ntransmitted && pingcount && nreceived >= pingcount) @@ -973,12 +1015,10 @@ int main(int argc, char **argv) if (gtpfd != -1) FD_SET(gtpfd, &fds); gtp_retranstimeout(gsn, &idleTime); + ping_timeout(&idleTime); - if ((pinghost.s_addr !=0) && - ((idleTime.tv_sec !=0) || (idleTime.tv_usec !=0))) { - idleTime.tv_sec = 0; - idleTime.tv_usec = 1000000 / pingrate; - } + if (debug) printf("idletime.tv_sec %d, idleTime.tv_usec %d\n", + (int) idleTime.tv_sec, (int) idleTime.tv_usec); switch (select(maxfd + 1, &fds, NULL, NULL, &idleTime)) { case -1: |