From e448554568fb4244a1b95e2e8666714f9498d69a Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Wed, 22 Apr 2015 22:10:44 -0400 Subject: gsup: Document passing MSISDN as part of the response When asking the GGSN to create/open a PDP context one needs to send a MSISDN. The MSISDN can only be provided through the GSUP interface. --- openbsc/doc/sgsn-remote-protocol.txt | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/openbsc/doc/sgsn-remote-protocol.txt b/openbsc/doc/sgsn-remote-protocol.txt index 3369d19b1..27b9abf4b 100644 --- a/openbsc/doc/sgsn-remote-protocol.txt +++ b/openbsc/doc/sgsn-remote-protocol.txt @@ -119,6 +119,7 @@ Network peer -> SGSN IEI Info Element Type Pres. Format Length Message type 4.2.1 M V 1 01 IMSI 4.2.9 M TLV 2-10 + 08 MSISDN 4.2.10 O TLV 0-9 04 PDP info complete 4.2.8 O TLV 2 05 PDP info 4.2.3 1-10 TLV @@ -354,6 +355,7 @@ IEI that shall be used for the encoding. | 0x05 PDP info 4.2.3 | | 0x06 Cancel type 4.2.6 | | 0x07 Freeze P-TMSI 4.2.8 | + | 0x08 MSISDN ISDN-AddressString/octet, 4.2.10 | | 0x10 PDP context id big endian int | | 0x11 PDP type 4.2.4 | | 0x12 APN 04.08, 10.5.6.1 | @@ -397,3 +399,24 @@ The IMSI is encoded like in octet 4-N of the Called Party BCD Number defined in Note 1) Either '1 1 1 1 | Number digit N' (N odd) or 'Number digit N | Number digit N-1' (N even), where N is the number of digits. + +4.2.10. ISDN-AddressString / MSISDN / Called Party BCD Number + +The MSISDN is encoded as an ISDN-AddressString in GSM 09.02 and Called Party +BCD Number in GSM 04.08. It will be stored by the SGSN and then passed as is +to the GGSN during the activation of the primary PDP Context. + + 8 7 6 5 4 3 2 1 + +-----------------------------------------------------+ + | | IEI | octet 1 + +-----------------------------------------------------+ + | Length of IE contents | octet 2 + +-----------------------------------------------------+ + | ext | Type of num | Numbering plan | octet 2 + +-----------------------------------------------------+ + | Number digit 2 | Number digit 1 | octet 3 + +-----------------------------------------------------+ + | Number digit 4 | Number digit 3 | octet 4 + +-----------------------------------------------------+ + : : : + +-----------------------------------------------------+ -- cgit v1.2.3 From 02d8c472bdff0a085cbedd9d902f7ced29e5d712 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Wed, 22 Apr 2015 22:42:23 -0400 Subject: gsup: Specify the QoS service for the PDP info QoS is a mess. In MAP there is qos-Subscribed which is then extended using ext-QoS-Subscribed, ext2-QoS-Subscribed, ext3-QoS-Subscribed and maybe even ext4-QoS-Subscribed by now. The MAP ASN1 files defined how these need to be "linearized". Instead of copying this I have decided to include the two semantics with/without the Allocation/Retention policy using the size of the data. --- openbsc/doc/sgsn-remote-protocol.txt | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/openbsc/doc/sgsn-remote-protocol.txt b/openbsc/doc/sgsn-remote-protocol.txt index 27b9abf4b..acb24a5ef 100644 --- a/openbsc/doc/sgsn-remote-protocol.txt +++ b/openbsc/doc/sgsn-remote-protocol.txt @@ -280,6 +280,7 @@ This is a container for information elements describing a single PDP. 10 PDP context id big endian int, 1-N C TLV 3 11 PDP type 4.2.4 C TLV 4 12 Access point name 04.08, 10.5.6.1 C TLV 3-102 + 13 Quality of Service 4.2.11 O TLV 1-20 The conditional IE are mandantory unless mentioned otherwise. @@ -359,6 +360,7 @@ IEI that shall be used for the encoding. | 0x10 PDP context id big endian int | | 0x11 PDP type 4.2.4 | | 0x12 APN 04.08, 10.5.6.1 | + | 0x13 QoS 4.2.11 | | 0x20 RAND octet string | | 0x21 SRES octet string | | 0x22 Kc octet string | @@ -420,3 +422,23 @@ to the GGSN during the activation of the primary PDP Context. +-----------------------------------------------------+ : : : +-----------------------------------------------------+ + + +4.2.11 Quality of Service Subscribed Service + +This encodes the subscribed QoS of a subscriber. It will be used by the +SGSN during the PDP Context activation. If the length of the QoS data +is 3 (three) octets it is assumed that these are octets 3-5 of the TS +3GPP TS 24.008 Quality of Service Octets. If it is more than three then +then it is assumed that the first octet is the Allocation/Retention +Priority and the reset are encoded as octets 3-N of 24.008. + + + 8 7 6 5 4 3 2 1 + +-----------------------------------------------------+ + | | IEI | octet 1 + +-----------------------------------------------------+ + | Length of IE contents | octet 2 + +-----------------------------------------------------+ + : : : + +-----------------------------------------------------+ -- cgit v1.2.3 From b927f1c3199b48becb03c0d56926c3b98d6ff5ce Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Wed, 22 Apr 2015 23:09:41 -0400 Subject: gsup: Extract the new MSISDN string Extract the new MSISDN IE from the GSUP message and verify that it is read/written to the message. --- openbsc/include/openbsc/gprs_gsup_messages.h | 4 ++++ openbsc/src/gprs/gprs_gsup_messages.c | 11 +++++++++++ openbsc/tests/gprs/gprs_test.c | 2 ++ 3 files changed, 17 insertions(+) diff --git a/openbsc/include/openbsc/gprs_gsup_messages.h b/openbsc/include/openbsc/gprs_gsup_messages.h index 9857b979d..a2d3cc798 100644 --- a/openbsc/include/openbsc/gprs_gsup_messages.h +++ b/openbsc/include/openbsc/gprs_gsup_messages.h @@ -29,6 +29,7 @@ #define GPRS_GSUP_MAX_NUM_PDP_INFO 10 /* GSM 09.02 limits this to 50 */ #define GPRS_GSUP_MAX_NUM_AUTH_INFO 5 +#define GPRS_GSUP_MAX_MSISDN_LEN 9 #define GPRS_GSUP_PDP_TYPE_SIZE 2 @@ -40,6 +41,7 @@ enum gprs_gsup_iei { GPRS_GSUP_PDP_INFO_IE = 0x05, GPRS_GSUP_CANCEL_TYPE_IE = 0x06, GPRS_GSUP_FREEZE_PTMSI_IE = 0x07, + GPRS_GSUP_MSISDN_IE = 0x08, GPRS_GSUP_PDP_CONTEXT_ID_IE = 0x10, GPRS_GSUP_PDP_TYPE_IE = 0x11, GPRS_GSUP_ACCESS_POINT_NAME_IE = 0x12, @@ -102,6 +104,8 @@ struct gprs_gsup_message { size_t num_auth_tuples; struct gprs_gsup_pdp_info pdp_infos[GPRS_GSUP_MAX_NUM_PDP_INFO]; size_t num_pdp_infos; + const uint8_t *msisdn_enc; + size_t msisdn_enc_len; }; int gprs_gsup_decode(const uint8_t *data, size_t data_len, diff --git a/openbsc/src/gprs/gprs_gsup_messages.c b/openbsc/src/gprs/gprs_gsup_messages.c index 9d9b6be20..56f78fd12 100644 --- a/openbsc/src/gprs/gprs_gsup_messages.c +++ b/openbsc/src/gprs/gprs_gsup_messages.c @@ -2,6 +2,7 @@ /* * (C) 2014 by Sysmocom s.f.m.c. GmbH + * (C) 2015 by Holger Hans Peter Freyther * All Rights Reserved * * Author: Jacob Erlbeck @@ -291,6 +292,12 @@ int gprs_gsup_decode(const uint8_t *const_data, size_t data_len, gsup_msg->auth_tuples[gsup_msg->num_auth_tuples++] = auth_info; break; + + case GPRS_GSUP_MSISDN_IE: + gsup_msg->msisdn_enc = value; + gsup_msg->msisdn_enc_len = value_len; + break; + default: LOGP(DGPRS, LOGL_NOTICE, "GSUP IE type %d unknown\n", iei); @@ -374,6 +381,10 @@ void gprs_gsup_encode(struct msgb *msg, const struct gprs_gsup_message *gsup_msg msgb_tlv_put(msg, GPRS_GSUP_IMSI_IE, bcd_len - 1, &bcd_buf[1]); /* specific parts */ + if (gsup_msg->msisdn_enc) + msgb_tlv_put(msg, GPRS_GSUP_MSISDN_IE, + gsup_msg->msisdn_enc_len, gsup_msg->msisdn_enc); + if ((u8 = gsup_msg->cause)) msgb_tlv_put(msg, GPRS_GSUP_CAUSE_IE, sizeof(u8), &u8); diff --git a/openbsc/tests/gprs/gprs_test.c b/openbsc/tests/gprs/gprs_test.c index 0ae06e780..a7c240183 100644 --- a/openbsc/tests/gprs/gprs_test.c +++ b/openbsc/tests/gprs/gprs_test.c @@ -443,6 +443,8 @@ static void test_gsup_messages_dec_enc(void) static const uint8_t update_location_res[] = { 0x06, TEST_IMSI_IE, + 0x08, 0x07, /* MSISDN of the subscriber */ + 0x91, 0x94, 0x61, 0x46, 0x32, 0x24, 0x43, 0x04, 0x00, /* PDP info complete */ 0x05, 0x12, 0x10, 0x01, 0x01, -- cgit v1.2.3 From 49c1a7156c7e0ced1709aee4a3d3438db60bae41 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Thu, 23 Apr 2015 09:13:01 -0400 Subject: gsup: Extract the QoS field Add roundtrip test for the new QoS IE. It will be consumed in later commits. --- openbsc/include/openbsc/gprs_gsup_messages.h | 3 +++ openbsc/src/gprs/gprs_gsup_messages.c | 10 ++++++++++ openbsc/tests/gprs/gprs_test.c | 3 ++- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/openbsc/include/openbsc/gprs_gsup_messages.h b/openbsc/include/openbsc/gprs_gsup_messages.h index a2d3cc798..123e1fc05 100644 --- a/openbsc/include/openbsc/gprs_gsup_messages.h +++ b/openbsc/include/openbsc/gprs_gsup_messages.h @@ -45,6 +45,7 @@ enum gprs_gsup_iei { GPRS_GSUP_PDP_CONTEXT_ID_IE = 0x10, GPRS_GSUP_PDP_TYPE_IE = 0x11, GPRS_GSUP_ACCESS_POINT_NAME_IE = 0x12, + GPRS_GSUP_PDP_QOS_IE = 0x13, GPRS_GSUP_RAND_IE = 0x20, GPRS_GSUP_SRES_IE = 0x21, GPRS_GSUP_KC_IE = 0x22 @@ -91,6 +92,8 @@ struct gprs_gsup_pdp_info { uint16_t pdp_type; const uint8_t *apn_enc; size_t apn_enc_len; + const uint8_t *qos_enc; + size_t qos_enc_len; }; struct gprs_gsup_message { diff --git a/openbsc/src/gprs/gprs_gsup_messages.c b/openbsc/src/gprs/gprs_gsup_messages.c index 56f78fd12..cb14fa114 100644 --- a/openbsc/src/gprs/gprs_gsup_messages.c +++ b/openbsc/src/gprs/gprs_gsup_messages.c @@ -94,6 +94,11 @@ static int decode_pdp_info(uint8_t *data, size_t data_len, pdp_info->apn_enc_len = value_len; break; + case GPRS_GSUP_PDP_QOS_IE: + pdp_info->qos_enc = value; + pdp_info->qos_enc_len = value_len; + break; + default: LOGP(DGPRS, LOGL_ERROR, "GSUP IE type %d not expected in PDP info\n", iei); @@ -333,6 +338,11 @@ static void encode_pdp_info(struct msgb *msg, enum gprs_gsup_iei iei, pdp_info->apn_enc_len, pdp_info->apn_enc); } + if (pdp_info->qos_enc) { + msgb_tlv_put(msg, GPRS_GSUP_PDP_QOS_IE, + pdp_info->qos_enc_len, pdp_info->qos_enc); + } + /* Update length field */ *len_field = msgb_length(msg) - old_len; } diff --git a/openbsc/tests/gprs/gprs_test.c b/openbsc/tests/gprs/gprs_test.c index a7c240183..bbd1d8ab3 100644 --- a/openbsc/tests/gprs/gprs_test.c +++ b/openbsc/tests/gprs/gprs_test.c @@ -446,10 +446,11 @@ static void test_gsup_messages_dec_enc(void) 0x08, 0x07, /* MSISDN of the subscriber */ 0x91, 0x94, 0x61, 0x46, 0x32, 0x24, 0x43, 0x04, 0x00, /* PDP info complete */ - 0x05, 0x12, + 0x05, 0x15, 0x10, 0x01, 0x01, 0x11, 0x02, 0xf1, 0x21, /* IPv4 */ 0x12, 0x09, 0x04, 't', 'e', 's', 't', 0x03, 'a', 'p', 'n', + 0x13, 0x01, 0x02, 0x05, 0x11, 0x10, 0x01, 0x02, 0x11, 0x02, 0xf1, 0x21, /* IPv4 */ -- cgit v1.2.3 From 9ba273d365ac731a9c3ff285821062c346724390 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Thu, 23 Apr 2015 09:53:53 -0400 Subject: sgsn: Copy the msisdn to the sgsn_data and use it in PDP activation The MSISDN should be present for "security" reasons in the first activation of a PDP context. Take the encoded MSISDN, store it for future use and then put it into the PDP activation request. The MM Context contains a field for a decoded MSISDN already. As we need to forward the data to the GGSN I want to avoid having to store TON and NPI in another place. Simply store the data in the encoded form. --- openbsc/include/openbsc/gprs_sgsn.h | 3 +++ openbsc/src/gprs/gprs_subscriber.c | 14 ++++++++++++++ openbsc/src/gprs/sgsn_libgtp.c | 12 ++++++++++-- openbsc/tests/sgsn/sgsn_test.c | 9 +++++++++ 4 files changed, 36 insertions(+), 2 deletions(-) diff --git a/openbsc/include/openbsc/gprs_sgsn.h b/openbsc/include/openbsc/gprs_sgsn.h index 2572ead52..baa2d781b 100644 --- a/openbsc/include/openbsc/gprs_sgsn.h +++ b/openbsc/include/openbsc/gprs_sgsn.h @@ -302,6 +302,9 @@ struct sgsn_subscriber_data { int auth_triplets_updated; struct llist_head pdp_list; int error_cause; + + uint8_t msisdn[9]; + size_t msisdn_len; }; #define SGSN_ERROR_CAUSE_NONE (-1) diff --git a/openbsc/src/gprs/gprs_subscriber.c b/openbsc/src/gprs/gprs_subscriber.c index 60f223a0b..52e7ba78d 100644 --- a/openbsc/src/gprs/gprs_subscriber.c +++ b/openbsc/src/gprs/gprs_subscriber.c @@ -1,6 +1,7 @@ /* MS subscriber data handling */ /* (C) 2014 by sysmocom s.f.m.c. GmbH + * (C) 2015 by Holger Hans Peter Freyther * * All Rights Reserved * @@ -259,9 +260,22 @@ static struct sgsn_subscriber_pdp_data *gprs_subscr_pdp_data_get_by_id( static void gprs_subscr_gsup_insert_data(struct gsm_subscriber *subscr, struct gprs_gsup_message *gsup_msg) { + struct sgsn_subscriber_data *sdata = subscr->sgsn_data; unsigned idx; int rc; + if (gsup_msg->msisdn_enc) { + if (gsup_msg->msisdn_enc_len > sizeof(sdata->msisdn)) { + LOGP(DGPRS, LOGL_ERROR, "MSISDN too long (%zu)\n", + gsup_msg->msisdn_enc_len); + sdata->msisdn_len = 0; + } else { + memcpy(sdata->msisdn, gsup_msg->msisdn_enc, + gsup_msg->msisdn_enc_len); + sdata->msisdn_len = gsup_msg->msisdn_enc_len; + } + } + if (gsup_msg->pdp_info_compl) { rc = gprs_subscr_pdp_data_clear(subscr); if (rc > 0) diff --git a/openbsc/src/gprs/sgsn_libgtp.c b/openbsc/src/gprs/sgsn_libgtp.c index 455e8af39..25b30d0fd 100644 --- a/openbsc/src/gprs/sgsn_libgtp.c +++ b/openbsc/src/gprs/sgsn_libgtp.c @@ -3,6 +3,7 @@ /* (C) 2010 by Harald Welte * (C) 2010 by On-Waves + * (C) 2015 by Holger Hans Peter Freyther * All Rights Reserved * * This program is free software; you can redistribute it and/or modify @@ -45,6 +46,7 @@ #include #include #include +#include #include #include @@ -153,8 +155,14 @@ struct sgsn_pdp_ctx *sgsn_create_pdp_ctx(struct sgsn_ggsn_ctx *ggsn, /* IMSI, TEID/TEIC, FLLU/FLLC, TID, NSAPI set in pdp_newpdp */ - /* FIXME: MSISDN in BCD format from mmctx */ - //pdp->msisdn.l/.v + /* Put the MSISDN in case we have it */ + if (mmctx->subscr) { + pdp->msisdn.l = mmctx->subscr->sgsn_data->msisdn_len; + if (pdp->msisdn.l > sizeof(pdp->msisdn.v)) + pdp->msisdn.l = sizeof(pdp->msisdn.l); + memcpy(pdp->msisdn.v, mmctx->subscr->sgsn_data->msisdn, + pdp->msisdn.l); + } /* End User Address from GMM requested PDP address */ pdp->eua.l = TLVP_LEN(tp, OSMO_IE_GSM_REQ_PDP_ADDR); diff --git a/openbsc/tests/sgsn/sgsn_test.c b/openbsc/tests/sgsn/sgsn_test.c index 197be9da4..d9b162dc2 100644 --- a/openbsc/tests/sgsn/sgsn_test.c +++ b/openbsc/tests/sgsn/sgsn_test.c @@ -414,9 +414,14 @@ static void test_subscriber_gsup(void) 0x02, 0x01, 0x07 /* GPRS not allowed */ }; +#define MSISDN 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09 + + static const uint8_t s1_msisdn[] = { MSISDN }; + static const uint8_t update_location_res[] = { 0x06, TEST_GSUP_IMSI1_IE, + 0x08, 0x09, MSISDN, 0x04, 0x00, /* PDP info complete */ 0x05, 0x12, 0x10, 0x01, 0x01, @@ -428,6 +433,8 @@ static void test_subscriber_gsup(void) 0x12, 0x08, 0x03, 'f', 'o', 'o', 0x03, 'a', 'p', 'n', }; +#undef MSISDN + static const uint8_t update_location_err[] = { 0x05, TEST_GSUP_IMSI1_IE, @@ -534,6 +541,8 @@ static void test_subscriber_gsup(void) OSMO_ASSERT(last_updated_subscr == s1); OSMO_ASSERT(s1->flags & GPRS_SUBSCRIBER_ENABLE_PURGE); OSMO_ASSERT(s1->sgsn_data->error_cause == SGSN_ERROR_CAUSE_NONE); + OSMO_ASSERT(s1->sgsn_data->msisdn_len == sizeof(s1_msisdn)); + OSMO_ASSERT(memcmp(s1->sgsn_data->msisdn, s1_msisdn, sizeof(s1_msisdn)) == 0); OSMO_ASSERT(!llist_empty(&s1->sgsn_data->pdp_list)); pdpd = llist_entry(s1->sgsn_data->pdp_list.next, struct sgsn_subscriber_pdp_data, list); -- cgit v1.2.3 From 8cedded88c9a0c4c486f987b818ccba57e96421e Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Thu, 23 Apr 2015 11:33:35 -0400 Subject: sgsn: Store subscribed QoS and attempt to use it sgsn_create_pdp_ctx should use the subscribed QoS. When selecting the PDP context we inject the QoS to be used into the TLV structure and use it during the request. Assume a "qos-Subscribed" structure only with three bytes and prepend the Allocation/Retention policy to the request. --- openbsc/include/openbsc/gprs_sgsn.h | 2 ++ openbsc/include/openbsc/gsm_04_08_gprs.h | 1 + openbsc/src/gprs/gprs_sgsn.c | 15 +++++++++++++++ openbsc/src/gprs/gprs_subscriber.c | 9 +++++++++ openbsc/src/gprs/sgsn_libgtp.c | 18 ++++++++++++++---- 5 files changed, 41 insertions(+), 4 deletions(-) diff --git a/openbsc/include/openbsc/gprs_sgsn.h b/openbsc/include/openbsc/gprs_sgsn.h index baa2d781b..7a429cdab 100644 --- a/openbsc/include/openbsc/gprs_sgsn.h +++ b/openbsc/include/openbsc/gprs_sgsn.h @@ -294,6 +294,8 @@ struct sgsn_subscriber_pdp_data { unsigned int context_id; uint16_t pdp_type; char apn_str[GSM_APN_LENGTH]; + uint8_t qos_subscribed[20]; + size_t qos_subscribed_len; }; struct sgsn_subscriber_data { diff --git a/openbsc/include/openbsc/gsm_04_08_gprs.h b/openbsc/include/openbsc/gsm_04_08_gprs.h index 3eec98365..f35d11b60 100644 --- a/openbsc/include/openbsc/gsm_04_08_gprs.h +++ b/openbsc/include/openbsc/gsm_04_08_gprs.h @@ -100,6 +100,7 @@ enum gsm48_gprs_ie_sm { * but which we use to simplify internal APIs */ OSMO_IE_GSM_REQ_QOS = 0xfd, OSMO_IE_GSM_REQ_PDP_ADDR = 0xfe, + OSMO_IE_GSM_SUB_QOS = 0xff, }; /* Chapter 9.4.15 / Table 9.4.15 */ diff --git a/openbsc/src/gprs/gprs_sgsn.c b/openbsc/src/gprs/gprs_sgsn.c index 94c2b6fbe..711540e03 100644 --- a/openbsc/src/gprs/gprs_sgsn.c +++ b/openbsc/src/gprs/gprs_sgsn.c @@ -582,6 +582,17 @@ void sgsn_update_subscriber_data(struct sgsn_mm_ctx *mmctx) sgsn_auth_update(mmctx); } +static void insert_qos(struct tlv_parsed *tp, struct sgsn_subscriber_pdp_data *pdp) +{ + tp->lv[OSMO_IE_GSM_SUB_QOS].len = pdp->qos_subscribed_len; + tp->lv[OSMO_IE_GSM_SUB_QOS].val = pdp->qos_subscribed; +} + +/** + * The tlv_parsed tp parameter will be modified to insert a + * OSMO_IE_GSM_SUB_QOS in case the data is available in the + * PDP context handling. + */ struct sgsn_ggsn_ctx *sgsn_mm_ctx_find_ggsn_ctx(struct sgsn_mm_ctx *mmctx, struct tlv_parsed *tp, enum gsm48_gsm_cause *gsm_cause) @@ -621,6 +632,7 @@ struct sgsn_ggsn_ctx *sgsn_mm_ctx_find_ggsn_ctx(struct sgsn_mm_ctx *mmctx, { allow_any_apn = 1; selected_apn_str = ""; + insert_qos(tp, pdp); continue; } if (!llist_empty(&sgsn_apn_ctxts)) { @@ -629,6 +641,7 @@ struct sgsn_ggsn_ctx *sgsn_mm_ctx_find_ggsn_ctx(struct sgsn_mm_ctx *mmctx, if (apn_ctx == NULL) continue; } + insert_qos(tp, pdp); selected_apn_str = pdp->apn_str; break; } @@ -636,11 +649,13 @@ struct sgsn_ggsn_ctx *sgsn_mm_ctx_find_ggsn_ctx(struct sgsn_mm_ctx *mmctx, /* Check whether the given APN is granted */ llist_for_each_entry(pdp, &mmctx->subscr->sgsn_data->pdp_list, list) { if (strcmp(pdp->apn_str, "*") == 0) { + insert_qos(tp, pdp); selected_apn_str = req_apn_str; allow_any_apn = 1; continue; } if (strcasecmp(pdp->apn_str, req_apn_str) == 0) { + insert_qos(tp, pdp); selected_apn_str = req_apn_str; break; } diff --git a/openbsc/src/gprs/gprs_subscriber.c b/openbsc/src/gprs/gprs_subscriber.c index 52e7ba78d..c2a3ae184 100644 --- a/openbsc/src/gprs/gprs_subscriber.c +++ b/openbsc/src/gprs/gprs_subscriber.c @@ -295,6 +295,13 @@ static void gprs_subscr_gsup_insert_data(struct gsm_subscriber *subscr, continue; } + if (pdp_info->qos_enc_len > sizeof(pdp_data->qos_subscribed)) { + LOGGSUBSCRP(LOGL_ERROR, subscr, + "QoS info too long (%zu)\n", + pdp_info->qos_enc_len); + continue; + } + LOGGSUBSCRP(LOGL_INFO, subscr, "Will set PDP info, context id = %zu, APN = %s\n", ctx_id, osmo_hexdump(pdp_info->apn_enc, pdp_info->apn_enc_len)); @@ -310,6 +317,8 @@ static void gprs_subscr_gsup_insert_data(struct gsm_subscriber *subscr, pdp_data->pdp_type = pdp_info->pdp_type; gprs_apn_to_str(pdp_data->apn_str, pdp_info->apn_enc, pdp_info->apn_enc_len); + memcpy(pdp_data->qos_subscribed, pdp_info->qos_enc, pdp_info->qos_enc_len); + pdp_data->qos_subscribed_len = pdp_info->qos_enc_len; } } diff --git a/openbsc/src/gprs/sgsn_libgtp.c b/openbsc/src/gprs/sgsn_libgtp.c index 25b30d0fd..dd02457ff 100644 --- a/openbsc/src/gprs/sgsn_libgtp.c +++ b/openbsc/src/gprs/sgsn_libgtp.c @@ -123,6 +123,8 @@ struct sgsn_pdp_ctx *sgsn_create_pdp_ctx(struct sgsn_ggsn_ctx *ggsn, struct sgsn_pdp_ctx *pctx; struct pdp_t *pdp; uint64_t imsi_ui64; + size_t qos_len; + const uint8_t *qos; int rc; LOGP(DGPRS, LOGL_ERROR, "Create PDP Context\n"); @@ -188,12 +190,20 @@ struct sgsn_pdp_ctx *sgsn_create_pdp_ctx(struct sgsn_ggsn_ctx *ggsn, memcpy(pdp->pco_req.v, TLVP_VAL(tp, GSM48_IE_GSM_PROTO_CONF_OPT), pdp->pco_req.l); - /* QoS options from GMM */ - pdp->qos_req.l = TLVP_LEN(tp, OSMO_IE_GSM_REQ_QOS); + /* QoS options from GMM or remote */ + if (TLVP_LEN(tp, OSMO_IE_GSM_SUB_QOS) > 0) { + qos_len = TLVP_LEN(tp, OSMO_IE_GSM_SUB_QOS); + qos = TLVP_VAL(tp, OSMO_IE_GSM_SUB_QOS); + } else { + qos_len = TLVP_LEN(tp, OSMO_IE_GSM_REQ_QOS); + qos = TLVP_VAL(tp, OSMO_IE_GSM_REQ_QOS); + } + + pdp->qos_req.l = qos_len + 1; if (pdp->qos_req.l > sizeof(pdp->qos_req.v)) pdp->qos_req.l = sizeof(pdp->qos_req.v); - memcpy(pdp->qos_req.v, TLVP_VAL(tp, OSMO_IE_GSM_REQ_QOS), - pdp->qos_req.l); + pdp->qos_req.v[0] = 0; /* Allocation/Retention policy */ + memcpy(&pdp->qos_req.v[1], qos, pdp->qos_req.l - 1); /* SGSN address for control plane */ pdp->gsnlc.l = sizeof(sgsn->cfg.gtp_listenaddr.sin_addr); -- cgit v1.2.3 From 4bd931f96d75d3e71b73a06e67f84ffdcab9caf6 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Thu, 23 Apr 2015 11:50:41 -0400 Subject: sgsn: Handle different levels of QoS If QoS is only three bytes it does not include the allocation/ retention policy. Otherwise it does. Copy it depending on that. We should have a macro for the clamping to reduce code duplication. The insanity does come from the MAP data and this seems to be the easiest in terms of complexity. It is an array of bytes that is transported from MAPProxy to the SGSN and then simply forwarded. The case of more than three bytes is neither unit nor manually tested so far. --- openbsc/src/gprs/sgsn_libgtp.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/openbsc/src/gprs/sgsn_libgtp.c b/openbsc/src/gprs/sgsn_libgtp.c index dd02457ff..eee3ef21c 100644 --- a/openbsc/src/gprs/sgsn_libgtp.c +++ b/openbsc/src/gprs/sgsn_libgtp.c @@ -199,11 +199,18 @@ struct sgsn_pdp_ctx *sgsn_create_pdp_ctx(struct sgsn_ggsn_ctx *ggsn, qos = TLVP_VAL(tp, OSMO_IE_GSM_REQ_QOS); } - pdp->qos_req.l = qos_len + 1; - if (pdp->qos_req.l > sizeof(pdp->qos_req.v)) - pdp->qos_req.l = sizeof(pdp->qos_req.v); - pdp->qos_req.v[0] = 0; /* Allocation/Retention policy */ - memcpy(&pdp->qos_req.v[1], qos, pdp->qos_req.l - 1); + if (qos_len <= 3) { + pdp->qos_req.l = qos_len + 1; + if (pdp->qos_req.l > sizeof(pdp->qos_req.v)) + pdp->qos_req.l = sizeof(pdp->qos_req.v); + pdp->qos_req.v[0] = 0; /* Allocation/Retention policy */ + memcpy(&pdp->qos_req.v[1], qos, pdp->qos_req.l - 1); + } else { + pdp->qos_req.l = qos_len; + if (pdp->qos_req.l > sizeof(pdp->qos_req.v)) + pdp->qos_req.l = sizeof(pdp->qos_req.v); + memcpy(pdp->qos_req.v, qos, pdp->qos_req.l); + } /* SGSN address for control plane */ pdp->gsnlc.l = sizeof(sgsn->cfg.gtp_listenaddr.sin_addr); -- cgit v1.2.3 From f7b3826f03772d57d1d1a1153c5684f7d4799b60 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Thu, 23 Apr 2015 16:58:33 -0400 Subject: sgsn: Dump the E164 (encoded) assigned to the subscriber --- openbsc/src/gprs/sgsn_vty.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/openbsc/src/gprs/sgsn_vty.c b/openbsc/src/gprs/sgsn_vty.c index 684204a1f..7ea8890b3 100644 --- a/openbsc/src/gprs/sgsn_vty.c +++ b/openbsc/src/gprs/sgsn_vty.c @@ -471,6 +471,11 @@ static void subscr_dump_full_vty(struct vty *vty, struct gsm_subscriber *subscr, if (subscr->tmsi != GSM_RESERVED_TMSI) vty_out(vty, " TMSI: %08X%s", subscr->tmsi, VTY_NEWLINE); + if (subscr->sgsn_data->msisdn_len > 0) + vty_out(vty, " MSISDN (BCD): %s%s", + osmo_hexdump(subscr->sgsn_data->msisdn, + subscr->sgsn_data->msisdn_len), + VTY_NEWLINE); if (strlen(subscr->equipment.imei) > 0) vty_out(vty, " IMEI: %s%s", subscr->equipment.imei, VTY_NEWLINE); -- cgit v1.2.3 From d05e06989def81f886c673956da476e626a27af5 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Thu, 23 Apr 2015 16:59:04 -0400 Subject: sgsn: Show the QoS that has been assigned --- openbsc/src/gprs/sgsn_vty.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openbsc/src/gprs/sgsn_vty.c b/openbsc/src/gprs/sgsn_vty.c index 7ea8890b3..be575d337 100644 --- a/openbsc/src/gprs/sgsn_vty.c +++ b/openbsc/src/gprs/sgsn_vty.c @@ -500,8 +500,9 @@ static void subscr_dump_full_vty(struct vty *vty, struct gsm_subscriber *subscr, } llist_for_each_entry(pdp, &subscr->sgsn_data->pdp_list, list) { - vty_out(vty, " PDP info: Id: %d, Type: 0x%04x, APN: '%s'%s", + vty_out(vty, " PDP info: Id: %d, Type: 0x%04x, APN: '%s' QoS: %s%s", pdp->context_id, pdp->pdp_type, pdp->apn_str, + osmo_hexdump(pdp->qos_subscribed, pdp->qos_subscribed_len), VTY_NEWLINE); } -- cgit v1.2.3