aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYann BONNAMY <yann_bonnamy@yahoo.fr>2010-11-18 10:01:21 +0100
committerHarald Welte <laforge@gnumonks.org>2011-10-07 18:34:56 +0200
commit11a398fbc3ad9b655d8ba947bea7012f7ce81604 (patch)
treeba05f0c6dbc8951846eb0637bda72fa4639a62a3
parentad18ccb9dfea854f6577041e6e8a4725e5512925 (diff)
sgsnemu support for QoS as defined in 3GPP TS 24.008
this patch allows to tweak any bit of the QoS field of the Create PDP context generated by sgsnemu , aligned with 10.5.6.5 of 3GPP TS 24.008 V10.0.0 (2010-09) QoS field can be extended to "lenght 12" with option --qose1, as seen in real life on UMTS networks. extension to lenght 13, 15 and 17 can be done with option --qose2, --qose3, --qose4, never seen IRL but allows to test 3GPP compliance of GGSN. Signed-off-by: Yann BONNAMY <yann_bonnamy@yahoo.fr>
-rw-r--r--sgsnemu/cmdline.c100
-rw-r--r--sgsnemu/cmdline.h12
-rw-r--r--sgsnemu/sgsnemu.c65
3 files changed, 160 insertions, 17 deletions
diff --git a/sgsnemu/cmdline.c b/sgsnemu/cmdline.c
index f40c583..83897cf 100644
--- a/sgsnemu/cmdline.c
+++ b/sgsnemu/cmdline.c
@@ -47,7 +47,11 @@ const char *gengetopt_args_info_help[] = {
" -i, --imsi=STRING IMSI (default=`240010123456789')",
" --nsapi=INT NSAPI (default=`0')",
" -m, --msisdn=STRING Mobile Station ISDN number (default=`46702123456')",
- " -q, --qos=INT Requested quality of service (default=`0x0b921f')",
+ " -q, --qos=INT Requested quality of service (default=`0x000b921f')",
+ " --qose1=INT Requested quality of service Extension 1 (example=`0x9396404074f9ffff')",
+ " --qose2=INT Requested quality of service Extension 2 (example=`0x11')",
+ " --qose3=INT Requested quality of service Extension 3 (example=`0x0101')",
+ " --qose4=INT Requested quality of service Extension 4 (example=`0x4040')",
" --charging=INT Charging characteristics (default=`0x0800')",
" -u, --uid=STRING Login user ID (default=`mig')",
" -p, --pwd=STRING Login password (default=`hemmelig')",
@@ -125,6 +129,10 @@ void clear_given (struct gengetopt_args_info *args_info)
args_info->nsapi_given = 0 ;
args_info->msisdn_given = 0 ;
args_info->qos_given = 0 ;
+ args_info->qose1_given = 0 ;
+ args_info->qose2_given = 0 ;
+ args_info->qose3_given = 0 ;
+ args_info->qose4_given = 0 ;
args_info->charging_given = 0 ;
args_info->uid_given = 0 ;
args_info->pwd_given = 0 ;
@@ -180,8 +188,16 @@ void clear_args (struct gengetopt_args_info *args_info)
args_info->nsapi_orig = NULL;
args_info->msisdn_arg = gengetopt_strdup ("46702123456");
args_info->msisdn_orig = NULL;
- args_info->qos_arg = 0x0b921f;
+ args_info->qos_arg = 0x000b921f;
args_info->qos_orig = NULL;
+ args_info->qose1_arg = 0x9396404074f9ffff;
+ args_info->qose1_orig = NULL;
+ args_info->qose2_arg = 0x11;
+ args_info->qose2_orig = NULL;
+ args_info->qose3_arg = 0x0101;
+ args_info->qose3_orig = NULL;
+ args_info->qose4_arg = 0x4040;
+ args_info->qose4_orig = NULL;
args_info->charging_arg = 0x0800;
args_info->charging_orig = NULL;
args_info->uid_arg = gengetopt_strdup ("mig");
@@ -792,6 +808,10 @@ cmdline_parser_internal (int argc, char * const *argv, struct gengetopt_args_inf
{ "nsapi", 1, NULL, 0 },
{ "msisdn", 1, NULL, 'm' },
{ "qos", 1, NULL, 'q' },
+ { "qose1", 1, NULL, 0 },
+ { "qose2", 1, NULL, 0 },
+ { "qose3", 1, NULL, 0 },
+ { "qose4", 1, NULL, 0 },
{ "charging", 1, NULL, 0 },
{ "uid", 1, NULL, 'u' },
{ "pwd", 1, NULL, 'p' },
@@ -1163,6 +1183,82 @@ cmdline_parser_internal (int argc, char * const *argv, struct gengetopt_args_inf
free (args_info->selmode_orig); /* free previous string */
args_info->selmode_orig = gengetopt_strdup (optarg);
}
+ /* QoS Extension 1. */
+ else if (strcmp (long_options[option_index].name, "qose1") == 0)
+ {
+ if (args_info->qose1_given)
+ {
+ fprintf (stderr, "%s: `--qose1' option given more than once\n", PACKAGE);
+ exit (EXIT_FAILURE);
+ }
+ args_info->qose1_given = 1;
+ args_info->qose1_arg = strtoull (optarg, &stop_char, 0);
+ if (!(stop_char && *stop_char == '\0')) {
+ fprintf(stderr, "%s: invalid numeric value: %s\n", argv[0], optarg);
+ goto failure;
+ }
+ if (args_info->qose1_orig)
+ free (args_info->qose1_orig); /* free previous string */
+ args_info->qose1_orig = gengetopt_strdup (optarg);
+ break;
+ }
+ /* QoS Extension 2. */
+ else if (strcmp (long_options[option_index].name, "qose2") == 0)
+ {
+ if (args_info->qose2_given)
+ {
+ fprintf (stderr, "%s: `--qose2' option given more than once\n", PACKAGE);
+ exit (EXIT_FAILURE);
+ }
+ args_info->qose2_given = 1;
+ args_info->qose2_arg = strtol (optarg, &stop_char, 0);
+ if (!(stop_char && *stop_char == '\0')) {
+ fprintf(stderr, "%s: invalid numeric value: %s\n", argv[0], optarg);
+ goto failure;
+ }
+ if (args_info->qose2_orig)
+ free (args_info->qose2_orig); /* free previous string */
+ args_info->qose2_orig = gengetopt_strdup (optarg);
+ break;
+ }
+ /* QoS Extension 3. */
+ else if (strcmp (long_options[option_index].name, "qose3") == 0)
+ {
+ if (args_info->qose3_given)
+ {
+ fprintf (stderr, "%s: `--qose3' option given more than once\n", PACKAGE);
+ exit (EXIT_FAILURE);
+ }
+ args_info->qose3_given = 1;
+ args_info->qose3_arg = strtol (optarg, &stop_char, 0);
+ if (!(stop_char && *stop_char == '\0')) {
+ fprintf(stderr, "%s: invalid numeric value: %s\n", argv[0], optarg);
+ goto failure;
+ }
+ if (args_info->qose3_orig)
+ free (args_info->qose3_orig); /* free previous string */
+ args_info->qose3_orig = gengetopt_strdup (optarg);
+ break;
+ }
+ /* QoS Extension 4. */
+ else if (strcmp (long_options[option_index].name, "qose4") == 0)
+ {
+ if (args_info->qose4_given)
+ {
+ fprintf (stderr, "%s: `--qose4' option given more than once\n", PACKAGE);
+ exit (EXIT_FAILURE);
+ }
+ args_info->qose4_given = 1;
+ args_info->qose4_arg = strtol (optarg, &stop_char, 0);
+ if (!(stop_char && *stop_char == '\0')) {
+ fprintf(stderr, "%s: invalid numeric value: %s\n", argv[0], optarg);
+ goto failure;
+ }
+ if (args_info->qose4_orig)
+ free (args_info->qose4_orig); /* free previous string */
+ args_info->qose4_orig = gengetopt_strdup (optarg);
+ break;
+ }
/* Radio Access Technology Type. */
else if (strcmp (long_options[option_index].name, "rattype") == 0)
{
diff --git a/sgsnemu/cmdline.h b/sgsnemu/cmdline.h
index 0871f3e..869262f 100644
--- a/sgsnemu/cmdline.h
+++ b/sgsnemu/cmdline.h
@@ -85,6 +85,14 @@ struct gengetopt_args_info
int qos_arg; /* Requested quality of service (default='0x0b921f'). */
char * qos_orig; /* Requested quality of service original value given at command line. */
const char *qos_help; /* Requested quality of service help description. */
+ unsigned long long int qose1_arg; /* Requested quality of service Extension 1 */
+ char * qose1_orig; /* Requested quality of service Extension 1 original value given at command line. */
+ int qose2_arg; /* Requested quality of service Extension 2 */
+ char * qose2_orig; /* Requested quality of service Extension 2 original value given at command line. */
+ int qose3_arg; /* Requested quality of service Extension 3 */
+ char * qose3_orig; /* Requested quality of service Extension 3 original value given at command line. */
+ int qose4_arg; /* Requested quality of service Extension 4 */
+ char * qose4_orig; /* Requested quality of service Extension 4 original value given at command line. */
int charging_arg; /* Charging characteristics (default='0x0800'). */
char * charging_orig; /* Charging characteristics original value given at command line. */
const char *charging_help; /* Charging characteristics help description. */
@@ -144,6 +152,10 @@ struct gengetopt_args_info
int nsapi_given ; /* Whether nsapi was given. */
int msisdn_given ; /* Whether msisdn was given. */
int qos_given ; /* Whether qos was given. */
+ int qose1_given ; /* Whether qos Extension 1 was given. */
+ int qose2_given ; /* Whether qos Extension 2 was given. */
+ int qose3_given ; /* Whether qos Extension 3 was given. */
+ int qose4_given ; /* Whether qos Extension 4 was given. */
int charging_given ; /* Whether charging was given. */
int uid_given ; /* Whether uid was given. */
int pwd_given ; /* Whether pwd was given. */
diff --git a/sgsnemu/sgsnemu.c b/sgsnemu/sgsnemu.c
index 9a15d32..edee09e 100644
--- a/sgsnemu/sgsnemu.c
+++ b/sgsnemu/sgsnemu.c
@@ -246,6 +246,10 @@ int process_options(int argc, char **argv) {
printf("debug: %d\n", args_info.debug_flag);
if (args_info.imsi_arg) printf("imsi: %s\n", args_info.imsi_arg);
printf("qos: %#08x\n", args_info.qos_arg);
+ printf("qose1: %#0.16llx\n", args_info.qose1_arg);
+ printf("qose2: %#04x\n", args_info.qose2_arg);
+ printf("qose3: %#06x\n", args_info.qose3_arg);
+ printf("qose4: %#06x\n", args_info.qose4_arg);
printf("charging: %#04x\n", args_info.charging_arg);
if (args_info.apn_arg) printf("apn: %s\n", args_info.apn_arg);
if (args_info.msisdn_arg) printf("msisdn: %s\n", args_info.msisdn_arg);
@@ -280,6 +284,10 @@ int process_options(int argc, char **argv) {
printf("debug: %d\n", args_info.debug_flag);
if (args_info.imsi_arg) printf("imsi: %s\n", args_info.imsi_arg);
printf("qos: %#08x\n", args_info.qos_arg);
+ printf("qose1: %#0.16llx\n", args_info.qose1_arg);
+ printf("qose2: %#04x\n", args_info.qose2_arg);
+ printf("qose3: %#06x\n", args_info.qose3_arg);
+ printf("qose4: %#06x\n", args_info.qose4_arg);
printf("charging: %#04x\n", args_info.charging_arg);
if (args_info.apn_arg) printf("apn: %s\n", args_info.apn_arg);
if (args_info.msisdn_arg) printf("msisdn: %s\n", args_info.msisdn_arg);
@@ -431,11 +439,38 @@ int process_options(int argc, char **argv) {
/* qos */
- options.qos.l = 3;
- options.qos.v[2] = (args_info.qos_arg) & 0xff;
- options.qos.v[1] = ((args_info.qos_arg) >> 8) & 0xff;
- options.qos.v[0] = ((args_info.qos_arg) >> 16) & 0xff;
-
+ options.qos.l = 4;
+ options.qos.v[3] = (args_info.qos_arg) & 0xff;
+ options.qos.v[2] = ((args_info.qos_arg) >> 8)& 0xff;
+ options.qos.v[1] = ((args_info.qos_arg) >> 16) & 0xff;
+ options.qos.v[0] = ((args_info.qos_arg) >> 24) & 0xff;
+ /* Extensions according to 3GPP TS 24.008 */
+ if (args_info.qose1_given == 1 ) {
+ options.qos.l = 12;
+ options.qos.v[11] = (args_info.qose1_arg) & 0xff;
+ options.qos.v[10] = ((args_info.qose1_arg) >> 8)& 0xff;
+ options.qos.v[9] = ((args_info.qose1_arg) >> 16)& 0xff;
+ options.qos.v[8] = ((args_info.qose1_arg) >> 24)& 0xff;
+ options.qos.v[7] = ((args_info.qose1_arg) >> 32)& 0xff;
+ options.qos.v[6] = ((args_info.qose1_arg) >> 40) & 0xff;
+ options.qos.v[5] = ((args_info.qose1_arg) >> 48) & 0xff;
+ options.qos.v[4] = ((args_info.qose1_arg) >> 56) & 0xff;
+ if (args_info.qose2_given == 1 ) {
+ options.qos.l = 13;
+ options.qos.v[12] = (args_info.qose2_arg) & 0xff;
+ if (args_info.qose3_given == 1 ) {
+ options.qos.l = 15;
+ options.qos.v[14] = (args_info.qose3_arg) & 0xff;
+ options.qos.v[13] = ((args_info.qose3_arg) >> 8)& 0xff;
+ if (args_info.qose4_given == 1 ) {
+ options.qos.l = 17;
+ options.qos.v[16] = (args_info.qose4_arg) & 0xff;
+ options.qos.v[15] = ((args_info.qose4_arg) >> 8)& 0xff;
+ }
+ }
+ }
+ }
+
/* charging */
options.cch = args_info.charging_arg;
@@ -1316,18 +1351,18 @@ int main(int argc, char **argv)
pdp->ipif = tun; /* TODO */
iparr[n].pdp = pdp;
- if (options.qos.l > sizeof(pdp->qos_req0)) {
- sys_err(LOG_ERR, __FILE__, __LINE__, 0, "QoS length too big");
- exit(1);
- }
- else {
- memcpy(pdp->qos_req0, options.qos.v, options.qos.l);
+ if (options.gtpversion == 0) {
+ if (options.qos.l - 1 > sizeof(pdp->qos_req0)) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, 0, "QoS length too big");
+ exit(1);
+ }
+ else {
+ memcpy(pdp->qos_req0, options.qos.v, options.qos.l);
+ }
}
- /* TODO */
- pdp->qos_req.l = 4;
- pdp->qos_req.v[0] = 0x00;
- memcpy(pdp->qos_req.v+1, options.qos.v, options.qos.l);
+ pdp->qos_req.l = options.qos.l ;
+ memcpy(pdp->qos_req.v, options.qos.v, options.qos.l);
pdp->selmode = options.selmode;