[MME] SGsAP: Implement initial Rx of ALERT-REQUEST

Answer ALERT-REQUEST with either ALERT-ACK or ALERT-REJECT.

This commit leaves unimplemented (to be implemented in the future)
the part regarding setting of internal NEAF flag for UE inside MME
and then triggering SGsAP-UE-ACTIVITY-INDICATION towards VLR.

See 3GPP TS 23.272 and 3GPP TS 29.118 (grep for "Alert" and "Activity")
for further information.
This commit is contained in:
Pau Espin Pedrol
2025-09-09 18:22:22 +02:00
committed by Sukchan Lee
parent a8eec6e9e6
commit 606877bf11
8 changed files with 217 additions and 0 deletions

View File

@@ -91,6 +91,7 @@ ogs_pkbuf_t *sgsap_build_location_update_request(mme_ue_t *mme_ue)
return pkbuf;
}
ogs_pkbuf_t *sgsap_build_tmsi_reallocation_complete(mme_ue_t *mme_ue)
{
mme_csmap_t *csmap = NULL;
@@ -124,6 +125,96 @@ ogs_pkbuf_t *sgsap_build_tmsi_reallocation_complete(mme_ue_t *mme_ue)
return pkbuf;
}
ogs_pkbuf_t *sgsap_build_ue_activity_indication(mme_ue_t *mme_ue)
{
ogs_tlv_t *root = NULL;
ogs_pkbuf_t *pkbuf = NULL;
ogs_assert(mme_ue);
root = ogs_tlv_add(NULL, OGS_TLV_MODE_T1_L1, SGSAP_IE_IMSI_TYPE,
SGSAP_IE_IMSI_LEN, 0, &mme_ue->nas_mobile_identity_imsi);
/* TODO: Maximum UE Availability Time */
pkbuf = ogs_pkbuf_alloc(NULL, OGS_MAX_SDU_LEN);
if (!pkbuf) {
ogs_error("ogs_pkbuf_alloc() failed");
ogs_tlv_free_all(root);
return NULL;
}
ogs_pkbuf_put_u8(pkbuf, SGSAP_UE_ACTIVITY_INDICATION);
ogs_pkbuf_put(pkbuf, OGS_MAX_SDU_LEN-1);
ogs_pkbuf_trim(pkbuf, 1+ogs_tlv_render(root,
pkbuf->data+1, OGS_MAX_SDU_LEN-1));
ogs_tlv_free_all(root);
return pkbuf;
}
ogs_pkbuf_t *sgsap_build_alert_ack(mme_ue_t *mme_ue)
{
ogs_tlv_t *root = NULL;
ogs_pkbuf_t *pkbuf = NULL;
ogs_assert(mme_ue);
root = ogs_tlv_add(NULL, OGS_TLV_MODE_T1_L1, SGSAP_IE_IMSI_TYPE,
SGSAP_IE_IMSI_LEN, 0, &mme_ue->nas_mobile_identity_imsi);
pkbuf = ogs_pkbuf_alloc(NULL, OGS_MAX_SDU_LEN);
if (!pkbuf) {
ogs_error("ogs_pkbuf_alloc() failed");
ogs_tlv_free_all(root);
return NULL;
}
ogs_pkbuf_put_u8(pkbuf, SGSAP_ALERT_ACK);
ogs_pkbuf_put(pkbuf, OGS_MAX_SDU_LEN-1);
ogs_pkbuf_trim(pkbuf, 1+ogs_tlv_render(root,
pkbuf->data+1, OGS_MAX_SDU_LEN-1));
ogs_tlv_free_all(root);
return pkbuf;
}
ogs_pkbuf_t *sgsap_build_alert_reject(
ogs_nas_mobile_identity_imsi_t *nas_mobile_identity_imsi,
int nas_mobile_identity_imsi_len, uint8_t sgs_cause)
{
ogs_tlv_t *root = NULL;
ogs_pkbuf_t *pkbuf = NULL;
ogs_assert(nas_mobile_identity_imsi);
ogs_assert(nas_mobile_identity_imsi_len == SGSAP_IE_IMSI_LEN);
root = ogs_tlv_add(NULL, OGS_TLV_MODE_T1_L1,
SGSAP_IE_IMSI_TYPE, SGSAP_IE_IMSI_LEN, 0, nas_mobile_identity_imsi);
ogs_tlv_add(root, OGS_TLV_MODE_T1_L1,
SGSAP_IE_SGS_CAUSE_TYPE, SGSAP_IE_SGS_CAUSE_LEN, 0, &sgs_cause);
ogs_debug(" CAUSE[%d]", sgs_cause);
pkbuf = ogs_pkbuf_alloc(NULL, OGS_MAX_SDU_LEN);
if (!pkbuf) {
ogs_error("ogs_pkbuf_alloc() failed");
ogs_tlv_free_all(root);
return NULL;
}
ogs_pkbuf_put_u8(pkbuf, SGSAP_ALERT_REJECT);
ogs_pkbuf_put(pkbuf, OGS_MAX_SDU_LEN-1);
ogs_pkbuf_trim(pkbuf, 1+ogs_tlv_render(root,
pkbuf->data+1, OGS_MAX_SDU_LEN-1));
ogs_tlv_free_all(root);
return pkbuf;
}
ogs_pkbuf_t *sgsap_build_detach_indication(mme_ue_t *mme_ue)
{
mme_csmap_t *csmap = NULL;

View File

@@ -30,6 +30,11 @@ extern "C" {
ogs_pkbuf_t *sgsap_build_location_update_request(mme_ue_t *mme_ue);
ogs_pkbuf_t *sgsap_build_tmsi_reallocation_complete(mme_ue_t *mme_ue);
ogs_pkbuf_t *sgsap_build_ue_activity_indication(mme_ue_t *mme_ue);
ogs_pkbuf_t *sgsap_build_alert_ack(mme_ue_t *mme_ue);
ogs_pkbuf_t *sgsap_build_alert_reject(
ogs_nas_mobile_identity_imsi_t *nas_mobile_identity_imsi,
int nas_mobile_identity_imsi_len, uint8_t sgs_cause);
ogs_pkbuf_t *sgsap_build_detach_indication(mme_ue_t *mme_ue);
ogs_pkbuf_t *sgsap_build_mo_csfb_indication(mme_ue_t *mme_ue);
ogs_pkbuf_t *sgsap_build_paging_reject(

View File

@@ -405,6 +405,98 @@ error:
return;
}
void sgsap_handle_alert_request(mme_vlr_t *vlr, ogs_pkbuf_t *pkbuf)
{
ogs_tlv_t *root = NULL, *iter = NULL;
mme_ue_t *mme_ue = NULL;
uint8_t sgs_cause = SGSAP_SGS_CAUSE_IMSI_UNKNOWN;
char imsi_bcd[OGS_MAX_IMSI_BCD_LEN+1] = {0, };
ogs_nas_mobile_identity_imsi_t *nas_mobile_identity_imsi = NULL;
int nas_mobile_identity_imsi_len = 0;
ogs_assert(vlr);
ogs_assert(pkbuf);
ogs_warn("[SGSAP] Rx ALERT-REQUEST");
ogs_pkbuf_pull(pkbuf, 1);
root = ogs_tlv_parse_block(pkbuf->len, pkbuf->data, OGS_TLV_MODE_T1_L1);
if (!root) {
ogs_error("ogs_tlv_parse_block() failed");
sgs_cause = SGSAP_SGS_CAUSE_SEMANTICALLY_INCORRECT_MESSAGE;
goto alert_reject;
}
iter = root;
while (iter) {
switch (iter->type) {
case SGSAP_IE_IMSI_TYPE:
nas_mobile_identity_imsi = iter->value;
nas_mobile_identity_imsi_len = iter->length;
break;
default:
ogs_warn("Invalid Type [%d]", iter->type);
break;
}
iter = iter->next;
}
ogs_tlv_free_all(root);
if (!nas_mobile_identity_imsi) {
ogs_error("No IMSI");
sgs_cause = SGSAP_SGS_CAUSE_MISSING_MANDATORY_IE;
goto alert_reject;
}
if (nas_mobile_identity_imsi_len != SGSAP_IE_IMSI_LEN) {
ogs_error("Invalid IMSI len [%d]", nas_mobile_identity_imsi_len);
sgs_cause = SGSAP_SGS_CAUSE_INVALID_MANDATORY_IE;
goto alert_reject;
}
if (nas_mobile_identity_imsi->type != OGS_NAS_MOBILE_IDENTITY_IMSI) {
ogs_error("nas_mobile_identity_imsi->type == "
"OGS_NAS_MOBILE_IDENTITY_IMSI");
sgs_cause = SGSAP_SGS_CAUSE_INVALID_MANDATORY_IE;
goto alert_reject;
}
ogs_nas_eps_imsi_to_bcd(nas_mobile_identity_imsi,
nas_mobile_identity_imsi_len, imsi_bcd);
mme_ue = mme_ue_find_by_imsi_bcd(imsi_bcd);
if (!mme_ue) {
ogs_error("No UE(mme-ue) context");
sgs_cause = SGSAP_SGS_CAUSE_IMSI_UNKNOWN;
goto alert_reject;
}
/* TODO: Set NEAF flag in UE */
ogs_warn("[SGSAP] Tx ALERT-ACK");
sgsap_send_to_vlr_with_sid(
vlr,
sgsap_build_alert_ack(mme_ue),
0);
return;
alert_reject:
ogs_debug("[SGSAP] Tx ALERT-REJECT");
ogs_debug(" IMSI[%s]", imsi_bcd);
sgsap_send_to_vlr_with_sid(
vlr,
sgsap_build_alert_reject(
nas_mobile_identity_imsi, nas_mobile_identity_imsi_len,
sgs_cause),
0);
return;
}
void sgsap_handle_detach_ack(mme_vlr_t *vlr, ogs_pkbuf_t *pkbuf)
{
ogs_tlv_t *root = NULL, *iter = NULL;

View File

@@ -28,6 +28,7 @@ extern "C" {
void sgsap_handle_location_update_accept(mme_vlr_t *vlr, ogs_pkbuf_t *pkbuf);
void sgsap_handle_location_update_reject(mme_vlr_t *vlr, ogs_pkbuf_t *pkbuf);
void sgsap_handle_alert_request(mme_vlr_t *vlr, ogs_pkbuf_t *pkbuf);
void sgsap_handle_detach_ack(mme_vlr_t *vlr, ogs_pkbuf_t *pkbuf);
void sgsap_handle_paging_request(mme_vlr_t *vlr, ogs_pkbuf_t *pkbuf);
void sgsap_handle_downlink_unitdata(mme_vlr_t *vlr, ogs_pkbuf_t *pkbuf);

View File

@@ -150,6 +150,26 @@ int sgsap_send_tmsi_reallocation_complete(mme_ue_t *mme_ue)
return rv;
}
int sgsap_send_ue_activity_indication(mme_ue_t *mme_ue)
{
int rv;
ogs_pkbuf_t *pkbuf = NULL;
ogs_assert(mme_ue);
ogs_debug("[SGSAP] Tx UE-ACTIVITY-IND");
ogs_debug(" IMSI[%s]", mme_ue->imsi_bcd);
pkbuf = sgsap_build_ue_activity_indication(mme_ue);
if (!pkbuf) {
ogs_error("sgsap_build_tmsi_reallocation_complete() failed");
return OGS_ERROR;
}
rv = sgsap_send_to_vlr(mme_ue, pkbuf);
ogs_expect(rv == OGS_OK);
return rv;
}
int sgsap_send_detach_indication(mme_ue_t *mme_ue)
{
int rv;

View File

@@ -44,6 +44,7 @@ int sgsap_send_to_vlr(mme_ue_t *mme_ue, ogs_pkbuf_t *pkbuf);
int sgsap_send_location_update_request(mme_ue_t *mme_ue);
int sgsap_send_tmsi_reallocation_complete(mme_ue_t *mme_ue);
int sgsap_send_ue_activity_indication(mme_ue_t *mme_ue);
int sgsap_send_detach_indication(mme_ue_t *mme_ue);
int sgsap_send_mo_csfb_indication(mme_ue_t *mme_ue);
int sgsap_send_paging_reject(mme_ue_t *mme_ue, uint8_t sgs_cause);

View File

@@ -153,6 +153,9 @@ void sgsap_state_connected(ogs_fsm_t *s, mme_event_t *e)
case SGSAP_LOCATION_UPDATE_REJECT:
sgsap_handle_location_update_reject(vlr, pkbuf);
break;
case SGSAP_ALERT_REQUEST:
sgsap_handle_alert_request(vlr, pkbuf);
break;
case SGSAP_EPS_DETACH_ACK:
case SGSAP_IMSI_DETACH_ACK:
sgsap_handle_detach_ack(vlr, pkbuf);

View File

@@ -33,6 +33,10 @@ extern "C" {
#define SGSAP_LOCATION_UPDATE_ACCEPT 10
#define SGSAP_LOCATION_UPDATE_REJECT 11
#define SGSAP_TMSI_REALLOCATION_COMPLETE 12
#define SGSAP_ALERT_REQUEST 13
#define SGSAP_ALERT_ACK 14
#define SGSAP_ALERT_REJECT 15
#define SGSAP_UE_ACTIVITY_INDICATION 16
#define SGSAP_EPS_DETACH_INDICATION 17
#define SGSAP_EPS_DETACH_ACK 18
#define SGSAP_IMSI_DETACH_INDICATION 19