aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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,