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
This commit is contained in:
Holger Hans Peter Freyther 2017-07-09 13:18:17 +02:00 committed by Neels Hofmeyr
parent 38bb344a47
commit 9d6f0625f7
4 changed files with 42 additions and 5 deletions

View File

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

View File

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

View File

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

View File

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