aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <holger@moiji-mobile.com>2017-07-09 13:18:17 +0200
committerHarald Welte <laforge@gnumonks.org>2017-07-10 17:19:56 +0000
commit8f7ab69d4ca2cbfa9a669c7cdee62272824be4a3 (patch)
tree0146fefeda9ddc16577a7ce1a9f627ec706484d7
parent61a7e57d8608052a050795c1620f1e918ab80a31 (diff)
sgsn: Fill the cch_pdp with a value coming from the tlv structure
For some GGSNs we need to insert the PDP Charging Characteristics that were returned. We receive these values from GSUP and will fill them into the tlv structure when finding the ggsn context. Change-Id: I1725bfd2403d29ce3550bfcd6fcc1498426ef906
-rw-r--r--openbsc/include/openbsc/gprs_sgsn.h5
-rw-r--r--openbsc/src/gprs/gprs_sgsn.c21
-rw-r--r--openbsc/src/gprs/gprs_subscriber.c14
-rw-r--r--openbsc/src/gprs/sgsn_libgtp.c7
4 files changed, 42 insertions, 5 deletions
diff --git a/openbsc/include/openbsc/gprs_sgsn.h b/openbsc/include/openbsc/gprs_sgsn.h
index fd86174be..4e49c0889 100644
--- a/openbsc/include/openbsc/gprs_sgsn.h
+++ b/openbsc/include/openbsc/gprs_sgsn.h
@@ -393,6 +393,8 @@ struct sgsn_subscriber_pdp_data {
char apn_str[GSM_APN_LENGTH];
uint8_t qos_subscribed[20];
size_t qos_subscribed_len;
+ uint8_t pdp_charg[2];
+ bool has_pdp_charg;
};
struct sgsn_subscriber_data {
@@ -407,6 +409,9 @@ struct sgsn_subscriber_data {
uint8_t hlr[9];
size_t hlr_len;
+
+ uint8_t pdp_charg[2];
+ bool has_pdp_charg;
};
#define SGSN_ERROR_CAUSE_NONE (-1)
diff --git a/openbsc/src/gprs/gprs_sgsn.c b/openbsc/src/gprs/gprs_sgsn.c
index 071dd97c8..fbea5b96b 100644
--- a/openbsc/src/gprs/gprs_sgsn.c
+++ b/openbsc/src/gprs/gprs_sgsn.c
@@ -698,10 +698,21 @@ 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)
+static void insert_extra(struct tlv_parsed *tp,
+ struct sgsn_subscriber_data *data,
+ 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;
+
+ /* Prefer PDP charging characteristics of per subscriber one */
+ if (pdp->has_pdp_charg) {
+ tp->lv[OSMO_IE_GSM_CHARG_CHAR].len = sizeof(pdp->pdp_charg);
+ tp->lv[OSMO_IE_GSM_CHARG_CHAR].val = &pdp->pdp_charg[0];
+ } else if (data->has_pdp_charg) {
+ tp->lv[OSMO_IE_GSM_CHARG_CHAR].len = sizeof(data->pdp_charg);
+ tp->lv[OSMO_IE_GSM_CHARG_CHAR].val = &data->pdp_charg[0];
+ }
}
/**
@@ -750,7 +761,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);
+ insert_extra(tp, mmctx->subscr->sgsn_data, pdp);
continue;
}
if (!llist_empty(&sgsn_apn_ctxts)) {
@@ -759,7 +770,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);
+ insert_extra(tp, mmctx->subscr->sgsn_data, pdp);
selected_apn_str = pdp->apn_str;
break;
}
@@ -767,13 +778,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);
+ insert_extra(tp, mmctx->subscr->sgsn_data, 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);
+ insert_extra(tp, mmctx->subscr->sgsn_data, 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 1bb51418a..c90ba7006 100644
--- a/openbsc/src/gprs/gprs_subscriber.c
+++ b/openbsc/src/gprs/gprs_subscriber.c
@@ -324,6 +324,13 @@ static void gprs_subscr_gsup_insert_data(struct gprs_subscr *subscr,
}
}
+ if (gsup_msg->pdp_charg_enc && gsup_msg->pdp_charg_enc_len >= sizeof(sdata->pdp_charg)) {
+ memcpy(&sdata->pdp_charg, gsup_msg->pdp_charg_enc, sizeof(sdata->pdp_charg));
+ sdata->has_pdp_charg = 1;
+ } else {
+ sdata->has_pdp_charg = 0;
+ }
+
if (gsup_msg->pdp_info_compl) {
rc = gprs_subscr_pdp_data_clear(subscr);
if (rc > 0)
@@ -367,6 +374,13 @@ static void gprs_subscr_gsup_insert_data(struct gprs_subscr *subscr,
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;
+
+ if (pdp_info->pdp_charg_enc && pdp_info->pdp_charg_enc_len >= sizeof(pdp_data->pdp_charg)) {
+ memcpy(&pdp_data->pdp_charg, pdp_info->pdp_charg_enc, sizeof(pdp_data->pdp_charg));
+ pdp_data->has_pdp_charg = 1;
+ } else {
+ pdp_data->has_pdp_charg = 0;
+ }
}
}
diff --git a/openbsc/src/gprs/sgsn_libgtp.c b/openbsc/src/gprs/sgsn_libgtp.c
index 001e61146..90ac48a14 100644
--- a/openbsc/src/gprs/sgsn_libgtp.c
+++ b/openbsc/src/gprs/sgsn_libgtp.c
@@ -234,6 +234,13 @@ struct sgsn_pdp_ctx *sgsn_create_pdp_ctx(struct sgsn_ggsn_ctx *ggsn,
memcpy(pdp->qos_req.v, qos, pdp->qos_req.l);
}
+ /* charging characteristics if present */
+ if (TLVP_LEN(tp, OSMO_IE_GSM_CHARG_CHAR) > 0) {
+ OSMO_ASSERT(TLVP_LEN(tp, OSMO_IE_GSM_CHARG_CHAR) <= sizeof(pdp->cch_pdp));
+ memcpy(&pdp->cch_pdp, TLVP_VAL(tp, OSMO_IE_GSM_CHARG_CHAR),
+ TLVP_LEN(tp, OSMO_IE_GSM_CHARG_CHAR));
+ }
+
/* SGSN address for control plane */
pdp->gsnlc.l = sizeof(sgsn->cfg.gtp_listenaddr.sin_addr);
memcpy(pdp->gsnlc.v, &sgsn->cfg.gtp_listenaddr.sin_addr,