forked from acouzens/open5gs
[MME] Support for Insert Subscriber Data (#1794)
* [MME] Support for Insert Subscriber Data * Supported AVPs in IDR will overwrite existing subscription information * Provide error on partial APN updates * IDR and ULA use same function to process AVPs * Move subdatamask values into s6a, so both HSS and MME can use them * Updates are not actioned at this time. A Re-attach is required for most changes to take effect * Memory issue on IDR exceptions * Remove of handling MSIDSN change until DSR is used
This commit is contained in:
parent
35ae3317b7
commit
1f2a8678ed
|
@ -77,6 +77,19 @@ extern "C" {
|
|||
#define OGS_DIAM_S6A_CT_UPDATE_PROCEDURE_IWF (3)
|
||||
#define OGS_DIAM_S6A_CT_INITIAL_ATTACH_PROCEDURE (4)
|
||||
|
||||
#define OGS_DIAM_S6A_SUBDATA_NO_UPDATE (0)
|
||||
#define OGS_DIAM_S6A_SUBDATA_SUB_STATUS (1)
|
||||
#define OGS_DIAM_S6A_SUBDATA_MSISDN (1 << 1)
|
||||
#define OGS_DIAM_S6A_SUBDATA_A_MSISDN (1 << 2)
|
||||
#define OGS_DIAM_S6A_SUBDATA_NAM (1 << 3)
|
||||
#define OGS_DIAM_S6A_SUBDATA_ODB (1 << 4)
|
||||
#define OGS_DIAM_S6A_SUBDATA_ARD (1 << 5)
|
||||
#define OGS_DIAM_S6A_SUBDATA_CC (1 << 6)
|
||||
#define OGS_DIAM_S6A_SUBDATA_UEAMBR (1 << 7)
|
||||
#define OGS_DIAM_S6A_SUBDATA_APN_CONFIG (1 << 8)
|
||||
#define OGS_DIAM_S6A_SUBDATA_RAU_TAU_TIMER (1 << 9)
|
||||
#define OGS_DIAM_S6A_SUBDATA_ALL 0xFFFFFFFF
|
||||
|
||||
extern struct dict_object *ogs_diam_s6a_application;
|
||||
|
||||
extern struct dict_object *ogs_diam_s6a_cmd_air;
|
||||
|
@ -179,6 +192,7 @@ typedef struct ogs_diam_s6a_idr_message_s {
|
|||
#define OGS_DIAM_S6A_IDR_FLAGS_RAT_TYPE (1 << 7)
|
||||
#define OGS_DIAM_S6A_IDR_FLAGS_PCSCF_Restoration (1 << 8)
|
||||
uint32_t idr_flags;
|
||||
uint32_t subdatamask;
|
||||
ogs_subscription_data_t subscription_data;
|
||||
} ogs_diam_s6a_idr_message_t;
|
||||
|
||||
|
|
|
@ -651,6 +651,7 @@ typedef struct ogs_slice_data_s {
|
|||
bool default_indicator;
|
||||
|
||||
uint32_t context_identifier; /* EPC for checking default APN */
|
||||
uint32_t all_apn_config_inc;
|
||||
|
||||
int num_of_session;
|
||||
ogs_session_t session[OGS_MAX_NUM_OF_SESS];
|
||||
|
|
|
@ -1238,50 +1238,36 @@ int hss_handle_change_event(const bson_t *document)
|
|||
"request_cancel_location") &&
|
||||
BSON_ITER_HOLDS_BOOL(&child2_iter)) {
|
||||
send_clr_flag = (char *)bson_iter_bool(&child2_iter);
|
||||
} else if (!strncmp(child2_key, "msisdn",
|
||||
strlen("msisdn"))) {
|
||||
int msisdn_count = 0;
|
||||
bson_iter_recurse(&child2_iter, &child3_iter);
|
||||
while (bson_iter_next(&child3_iter)) {
|
||||
if (BSON_ITER_HOLDS_UTF8(&child3_iter)) {
|
||||
msisdn_count++;
|
||||
}
|
||||
}
|
||||
if (msisdn_count) {
|
||||
send_idr_flag = true;
|
||||
subdatamask = (subdatamask |
|
||||
OGS_HSS_SUBDATA_MSISDN);
|
||||
} else {
|
||||
send_clr_flag = true;
|
||||
}
|
||||
} else if (!strncmp(child2_key,
|
||||
"access_restriction_data",
|
||||
strlen("access_restriction_data"))) {
|
||||
send_idr_flag = true;
|
||||
subdatamask = (subdatamask | OGS_HSS_SUBDATA_ARD);
|
||||
subdatamask = (subdatamask | OGS_DIAM_S6A_SUBDATA_ARD);
|
||||
} else if (!strncmp(child2_key,
|
||||
"subscriber_status",
|
||||
strlen("subscriber_status"))) {
|
||||
send_idr_flag = true;
|
||||
subdatamask = (subdatamask |
|
||||
OGS_HSS_SUBDATA_SUB_STATUS);
|
||||
OGS_DIAM_S6A_SUBDATA_SUB_STATUS);
|
||||
} else if (!strncmp(child2_key,
|
||||
"network_access_mode",
|
||||
strlen("network_access_mode"))) {
|
||||
send_idr_flag = true;
|
||||
subdatamask = (subdatamask | OGS_HSS_SUBDATA_NAM);
|
||||
subdatamask = (subdatamask | OGS_DIAM_S6A_SUBDATA_NAM);
|
||||
} else if (!strncmp(child2_key, "ambr", strlen("ambr"))) {
|
||||
send_idr_flag = true;
|
||||
subdatamask = (subdatamask | OGS_HSS_SUBDATA_UEAMBR);
|
||||
subdatamask = (subdatamask |
|
||||
OGS_DIAM_S6A_SUBDATA_UEAMBR);
|
||||
} else if (!strncmp(child2_key,
|
||||
"subscribed_rau_tau_timer",
|
||||
strlen("subscribed_rau_tau_timer"))) {
|
||||
send_idr_flag = true;
|
||||
subdatamask = (subdatamask |
|
||||
OGS_HSS_SUBDATA_RAU_TAU_TIMER);
|
||||
OGS_DIAM_S6A_SUBDATA_RAU_TAU_TIMER);
|
||||
} else if (!strncmp(child2_key, "slice", strlen("slice"))) {
|
||||
send_idr_flag = true;
|
||||
subdatamask = (subdatamask | OGS_HSS_SUBDATA_SLICE);
|
||||
subdatamask = (subdatamask |
|
||||
OGS_DIAM_S6A_SUBDATA_APN_CONFIG);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -314,7 +314,7 @@ static int hss_s6a_avp_add_subscription_data(
|
|||
|
||||
int i;
|
||||
|
||||
if (subdatamask & OGS_HSS_SUBDATA_MSISDN) {
|
||||
if (subdatamask & OGS_DIAM_S6A_SUBDATA_MSISDN) {
|
||||
/*
|
||||
* TS29.328
|
||||
* 6.3.2 MSISDN AVP
|
||||
|
@ -350,7 +350,7 @@ static int hss_s6a_avp_add_subscription_data(
|
|||
}
|
||||
}
|
||||
|
||||
if (subdatamask & OGS_HSS_SUBDATA_ARD) {
|
||||
if (subdatamask & OGS_DIAM_S6A_SUBDATA_ARD) {
|
||||
if (subscription_data->access_restriction_data) {
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_access_restriction_data, 0,
|
||||
&avp_access_restriction_data);
|
||||
|
@ -364,7 +364,7 @@ static int hss_s6a_avp_add_subscription_data(
|
|||
}
|
||||
}
|
||||
|
||||
if (subdatamask & OGS_HSS_SUBDATA_SUB_STATUS) {
|
||||
if (subdatamask & OGS_DIAM_S6A_SUBDATA_SUB_STATUS) {
|
||||
ret = fd_msg_avp_new(
|
||||
ogs_diam_s6a_subscriber_status, 0, &avp_subscriber_status);
|
||||
ogs_assert(ret == 0);
|
||||
|
@ -375,7 +375,7 @@ static int hss_s6a_avp_add_subscription_data(
|
|||
ogs_assert(ret == 0);
|
||||
}
|
||||
|
||||
if (subdatamask & OGS_HSS_SUBDATA_NAM) {
|
||||
if (subdatamask & OGS_DIAM_S6A_SUBDATA_NAM) {
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_network_access_mode, 0,
|
||||
&avp_network_access_mode);
|
||||
ogs_assert(ret == 0);
|
||||
|
@ -386,7 +386,7 @@ static int hss_s6a_avp_add_subscription_data(
|
|||
ogs_assert(ret == 0);
|
||||
}
|
||||
|
||||
if (subdatamask & OGS_HSS_SUBDATA_UEAMBR) {
|
||||
if (subdatamask & OGS_DIAM_S6A_SUBDATA_UEAMBR) {
|
||||
/* Set the AMBR */
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_ambr, 0, &avp_ambr);
|
||||
ogs_assert(ret == 0);
|
||||
|
@ -412,7 +412,7 @@ static int hss_s6a_avp_add_subscription_data(
|
|||
ogs_assert(ret == 0);
|
||||
}
|
||||
|
||||
if (subdatamask & OGS_HSS_SUBDATA_RAU_TAU_TIMER) {
|
||||
if (subdatamask & OGS_DIAM_S6A_SUBDATA_RAU_TAU_TIMER) {
|
||||
/* Set the Subscribed RAU TAU Timer */
|
||||
ret = fd_msg_avp_new(
|
||||
ogs_diam_s6a_subscribed_rau_tau_timer, 0, &avp_rau_tau_timer);
|
||||
|
@ -425,7 +425,7 @@ static int hss_s6a_avp_add_subscription_data(
|
|||
ogs_assert(ret == 0);
|
||||
}
|
||||
|
||||
if (subdatamask & OGS_HSS_SUBDATA_SLICE) {
|
||||
if (subdatamask & OGS_DIAM_S6A_SUBDATA_APN_CONFIG) {
|
||||
/* For EPC, we'll use first Slice in Subscription */
|
||||
if (subscription_data->num_of_slice)
|
||||
slice_data = &subscription_data->slice[0];
|
||||
|
@ -910,7 +910,7 @@ static int hss_ogs_diam_s6a_ulr_cb( struct msg **msg, struct avp *avp,
|
|||
ret = fd_msg_avp_new(ogs_diam_s6a_subscription_data, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
rv = hss_s6a_avp_add_subscription_data(&subscription_data,
|
||||
avp, OGS_HSS_SUBDATA_ALL);
|
||||
avp, OGS_DIAM_S6A_SUBDATA_ALL);
|
||||
if (rv != OGS_OK) {
|
||||
result_code = OGS_DIAM_S6A_ERROR_UNKNOWN_EPS_SUBSCRIPTION;
|
||||
goto out;
|
||||
|
|
|
@ -26,16 +26,6 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define OGS_HSS_SUBDATA_NO_UPDATE (0)
|
||||
#define OGS_HSS_SUBDATA_MSISDN (1)
|
||||
#define OGS_HSS_SUBDATA_ARD (1 << 1)
|
||||
#define OGS_HSS_SUBDATA_SUB_STATUS (1 << 2)
|
||||
#define OGS_HSS_SUBDATA_NAM (1 << 3)
|
||||
#define OGS_HSS_SUBDATA_UEAMBR (1 << 4)
|
||||
#define OGS_HSS_SUBDATA_RAU_TAU_TIMER (1 << 5)
|
||||
#define OGS_HSS_SUBDATA_SLICE (1 << 6)
|
||||
#define OGS_HSS_SUBDATA_ALL 0xFFFFFFFF
|
||||
|
||||
/* HSS Sends Cancel Location Request to MME */
|
||||
void hss_s6a_send_clr(char *imsi_bcd, char *mme_host, char *mme_realm,
|
||||
uint32_t cancellation_type);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -33,6 +33,9 @@
|
|||
static uint8_t emm_cause_from_diameter(
|
||||
const uint32_t *dia_err, const uint32_t *dia_exp_err);
|
||||
|
||||
static uint8_t mme_ue_session_from_slice_data(mme_ue_t *mme_ue,
|
||||
ogs_slice_data_t *slice_data);
|
||||
|
||||
uint8_t mme_s6a_handle_aia(
|
||||
mme_ue_t *mme_ue, ogs_diam_s6a_message_t *s6a_message)
|
||||
{
|
||||
|
@ -74,7 +77,7 @@ uint8_t mme_s6a_handle_ula(
|
|||
ogs_diam_s6a_ula_message_t *ula_message = NULL;
|
||||
ogs_subscription_data_t *subscription_data = NULL;
|
||||
ogs_slice_data_t *slice_data = NULL;
|
||||
int i, rv;
|
||||
int rv;
|
||||
|
||||
ogs_assert(mme_ue);
|
||||
ogs_assert(s6a_message);
|
||||
|
@ -95,58 +98,13 @@ uint8_t mme_s6a_handle_ula(
|
|||
|
||||
mme_session_remove_all(mme_ue);
|
||||
|
||||
for (i = 0; i < slice_data->num_of_session; i++) {
|
||||
if (i >= OGS_MAX_NUM_OF_SESS) {
|
||||
ogs_warn("Ignore max session count overflow [%d>=%d]",
|
||||
slice_data->num_of_session, OGS_MAX_NUM_OF_SESS);
|
||||
break;
|
||||
}
|
||||
|
||||
if (slice_data->session[i].name) {
|
||||
mme_ue->session[i].name = ogs_strdup(slice_data->session[i].name);
|
||||
ogs_assert(mme_ue->session[i].name);
|
||||
}
|
||||
|
||||
mme_ue->session[i].context_identifier =
|
||||
slice_data->session[i].context_identifier;
|
||||
|
||||
if (slice_data->session[i].session_type == OGS_PDU_SESSION_TYPE_IPV4 ||
|
||||
slice_data->session[i].session_type == OGS_PDU_SESSION_TYPE_IPV6 ||
|
||||
slice_data->session[i].session_type ==
|
||||
OGS_PDU_SESSION_TYPE_IPV4V6) {
|
||||
mme_ue->session[i].session_type =
|
||||
slice_data->session[i].session_type;
|
||||
} else {
|
||||
ogs_error("Invalid PDN_TYPE[%d]",
|
||||
slice_data->session[i].session_type);
|
||||
if (mme_ue->session[i].name)
|
||||
ogs_free(mme_ue->session[i].name);
|
||||
break;
|
||||
}
|
||||
memcpy(&mme_ue->session[i].paa, &slice_data->session[i].paa,
|
||||
sizeof(mme_ue->session[i].paa));
|
||||
|
||||
memcpy(&mme_ue->session[i].qos, &slice_data->session[i].qos,
|
||||
sizeof(mme_ue->session[i].qos));
|
||||
memcpy(&mme_ue->session[i].ambr, &slice_data->session[i].ambr,
|
||||
sizeof(mme_ue->session[i].ambr));
|
||||
|
||||
memcpy(&mme_ue->session[i].smf_ip, &slice_data->session[i].smf_ip,
|
||||
sizeof(mme_ue->session[i].smf_ip));
|
||||
|
||||
memcpy(&mme_ue->session[i].charging_characteristics,
|
||||
&slice_data->session[i].charging_characteristics,
|
||||
sizeof(mme_ue->session[i].charging_characteristics));
|
||||
mme_ue->session[i].charging_characteristics_presence =
|
||||
slice_data->session[i].charging_characteristics_presence;
|
||||
}
|
||||
|
||||
if (i == 0) {
|
||||
rv = mme_ue_session_from_slice_data(mme_ue, slice_data);
|
||||
if (rv == 0) {
|
||||
ogs_error("No Session");
|
||||
return OGS_NAS_EMM_CAUSE_SEVERE_NETWORK_FAILURE;
|
||||
}
|
||||
mme_ue->num_of_session = rv;
|
||||
|
||||
mme_ue->num_of_session = i;
|
||||
mme_ue->context_identifier = slice_data->context_identifier;
|
||||
|
||||
if (mme_ue->nas_eps.type == MME_EPS_TYPE_ATTACH_REQUEST) {
|
||||
|
@ -168,6 +126,48 @@ uint8_t mme_s6a_handle_ula(
|
|||
return OGS_NAS_EMM_CAUSE_REQUEST_ACCEPTED;
|
||||
}
|
||||
|
||||
uint8_t mme_s6a_handle_idr(
|
||||
mme_ue_t *mme_ue, ogs_diam_s6a_message_t *s6a_message)
|
||||
{
|
||||
ogs_diam_s6a_idr_message_t *idr_message = NULL;
|
||||
ogs_subscription_data_t *subscription_data = NULL;
|
||||
ogs_slice_data_t *slice_data = NULL;
|
||||
int rv;
|
||||
|
||||
ogs_assert(mme_ue);
|
||||
ogs_assert(s6a_message);
|
||||
idr_message = &s6a_message->idr_message;
|
||||
ogs_assert(idr_message);
|
||||
subscription_data = &idr_message->subscription_data;
|
||||
ogs_assert(subscription_data);
|
||||
|
||||
if (idr_message->subdatamask & OGS_DIAM_S6A_SUBDATA_UEAMBR) {
|
||||
memcpy(&mme_ue->ambr, &subscription_data->ambr, sizeof(ogs_bitrate_t));
|
||||
}
|
||||
|
||||
if (idr_message->subdatamask & OGS_DIAM_S6A_SUBDATA_APN_CONFIG) {
|
||||
ogs_assert(subscription_data->num_of_slice == 1);
|
||||
slice_data = &subscription_data->slice[0];
|
||||
|
||||
if (!slice_data->all_apn_config_inc) {
|
||||
mme_session_remove_all(mme_ue);
|
||||
rv = mme_ue_session_from_slice_data(mme_ue, slice_data);
|
||||
if (rv == 0) {
|
||||
ogs_error("No Session");
|
||||
return OGS_ERROR;
|
||||
}
|
||||
mme_ue->num_of_session = rv;
|
||||
} else {
|
||||
ogs_error ("Partial APN-Configuration Not Supported in IDR.");
|
||||
return OGS_ERROR;
|
||||
}
|
||||
|
||||
mme_ue->context_identifier = slice_data->context_identifier;
|
||||
}
|
||||
|
||||
return OGS_OK;
|
||||
}
|
||||
|
||||
void mme_s6a_handle_clr(
|
||||
mme_ue_t *mme_ue, ogs_diam_s6a_clr_message_t *clr_message)
|
||||
{
|
||||
|
@ -215,7 +215,60 @@ void mme_s6a_handle_clr(
|
|||
}
|
||||
}
|
||||
|
||||
/* 3GPP TS 29.272 Annex A; Table !.a:
|
||||
static uint8_t mme_ue_session_from_slice_data(mme_ue_t *mme_ue,
|
||||
ogs_slice_data_t *slice_data)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < slice_data->num_of_session; i++) {
|
||||
if (i >= OGS_MAX_NUM_OF_SESS) {
|
||||
ogs_warn("Ignore max session count overflow [%d>=%d]",
|
||||
slice_data->num_of_session, OGS_MAX_NUM_OF_SESS);
|
||||
break;
|
||||
}
|
||||
|
||||
if (slice_data->session[i].name) {
|
||||
mme_ue->session[i].name = ogs_strdup(slice_data->session[i].name);
|
||||
ogs_assert(mme_ue->session[i].name);
|
||||
}
|
||||
|
||||
mme_ue->session[i].context_identifier =
|
||||
slice_data->session[i].context_identifier;
|
||||
|
||||
if (slice_data->session[i].session_type == OGS_PDU_SESSION_TYPE_IPV4 ||
|
||||
slice_data->session[i].session_type == OGS_PDU_SESSION_TYPE_IPV6 ||
|
||||
slice_data->session[i].session_type ==
|
||||
OGS_PDU_SESSION_TYPE_IPV4V6) {
|
||||
mme_ue->session[i].session_type =
|
||||
slice_data->session[i].session_type;
|
||||
} else {
|
||||
ogs_error("Invalid PDN_TYPE[%d]",
|
||||
slice_data->session[i].session_type);
|
||||
if (mme_ue->session[i].name)
|
||||
ogs_free(mme_ue->session[i].name);
|
||||
break;
|
||||
}
|
||||
memcpy(&mme_ue->session[i].paa, &slice_data->session[i].paa,
|
||||
sizeof(mme_ue->session[i].paa));
|
||||
|
||||
memcpy(&mme_ue->session[i].qos, &slice_data->session[i].qos,
|
||||
sizeof(mme_ue->session[i].qos));
|
||||
memcpy(&mme_ue->session[i].ambr, &slice_data->session[i].ambr,
|
||||
sizeof(mme_ue->session[i].ambr));
|
||||
|
||||
memcpy(&mme_ue->session[i].smf_ip, &slice_data->session[i].smf_ip,
|
||||
sizeof(mme_ue->session[i].smf_ip));
|
||||
|
||||
memcpy(&mme_ue->session[i].charging_characteristics,
|
||||
&slice_data->session[i].charging_characteristics,
|
||||
sizeof(mme_ue->session[i].charging_characteristics));
|
||||
mme_ue->session[i].charging_characteristics_presence =
|
||||
slice_data->session[i].charging_characteristics_presence;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/* 3GPP TS 29.272 Annex A; Table A.1:
|
||||
* Mapping from S6a error codes to NAS Cause Codes */
|
||||
static uint8_t emm_cause_from_diameter(
|
||||
const uint32_t *dia_err, const uint32_t *dia_exp_err)
|
||||
|
|
|
@ -30,6 +30,8 @@ uint8_t mme_s6a_handle_aia(
|
|||
mme_ue_t *mme_ue, ogs_diam_s6a_message_t *s6a_message);
|
||||
uint8_t mme_s6a_handle_ula(
|
||||
mme_ue_t *mme_ue, ogs_diam_s6a_message_t *s6a_message);
|
||||
uint8_t mme_s6a_handle_idr(
|
||||
mme_ue_t *mme_ue, ogs_diam_s6a_message_t *s6a_message);
|
||||
void mme_s6a_handle_clr(
|
||||
mme_ue_t *mme_ue, ogs_diam_s6a_clr_message_t *clr_message);
|
||||
|
||||
|
|
|
@ -435,11 +435,13 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e)
|
|||
mme_s6a_handle_clr(mme_ue, &s6a_message->clr_message);
|
||||
break;
|
||||
case OGS_DIAM_S6A_CMD_CODE_INSERT_SUBSCRIBER_DATA:
|
||||
mme_s6a_handle_idr(mme_ue, s6a_message);
|
||||
break;
|
||||
default:
|
||||
ogs_error("Invalid Type[%d]", s6a_message->cmd_code);
|
||||
break;
|
||||
}
|
||||
ogs_subscription_data_free(&s6a_message->idr_message.subscription_data);
|
||||
ogs_subscription_data_free(&s6a_message->ula_message.subscription_data);
|
||||
ogs_free(s6a_message);
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue