diff options
-rw-r--r-- | include/openbsc/gprs_sgsn.h | 5 | ||||
-rw-r--r-- | src/gprs/gprs_sgsn.c | 21 | ||||
-rw-r--r-- | src/gprs/gprs_subscriber.c | 14 | ||||
-rw-r--r-- | src/gprs/sgsn_libgtp.c | 7 |
4 files changed, 42 insertions, 5 deletions
diff --git a/include/openbsc/gprs_sgsn.h b/include/openbsc/gprs_sgsn.h index fd86174be..4e49c0889 100644 --- a/include/openbsc/gprs_sgsn.h +++ b/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/src/gprs/gprs_sgsn.c b/src/gprs/gprs_sgsn.c index 18625aefe..11225ddb0 100644 --- a/src/gprs/gprs_sgsn.c +++ b/src/gprs/gprs_sgsn.c @@ -699,10 +699,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]; + } } /** @@ -751,7 +762,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)) { @@ -760,7 +771,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; } @@ -768,13 +779,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/src/gprs/gprs_subscriber.c b/src/gprs/gprs_subscriber.c index 176583b6f..aa03509a5 100644 --- a/src/gprs/gprs_subscriber.c +++ b/src/gprs/gprs_subscriber.c @@ -325,6 +325,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) @@ -368,6 +375,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/src/gprs/sgsn_libgtp.c b/src/gprs/sgsn_libgtp.c index 7595bf83c..0a0de0808 100644 --- a/src/gprs/sgsn_libgtp.c +++ b/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, |