aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README43
-rw-r--r--gtp/gtp.h2
-rw-r--r--sgsnemu/sgsnemu.c70
3 files changed, 92 insertions, 23 deletions
diff --git a/README b/README
index acf94f7..a16ed6d 100644
--- a/README
+++ b/README
@@ -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 ***
diff --git a/gtp/gtp.h b/gtp/gtp.h
index 191eef1..5c6706d 100644
--- a/gtp/gtp.h
+++ b/gtp/gtp.h
@@ -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: