9
0
Fork 0

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>
This commit is contained in:
Yann BONNAMY 2010-11-18 10:01:21 +01:00 committed by Harald Welte
parent ad18ccb9df
commit 11a398fbc3
3 changed files with 160 additions and 17 deletions

View File

@ -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)
{

View File

@ -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. */

View File

@ -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;