Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
pespin committed Dec 11, 2023
1 parent 1fdeb3b commit c697f82
Show file tree
Hide file tree
Showing 8 changed files with 211 additions and 1 deletion.
5 changes: 5 additions & 0 deletions src/mme/mme-context.h
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,11 @@ struct mme_ue_s {
char a_msisdn_bcd[OGS_MAX_MSISDN_BCD_LEN+1];

mme_p_tmsi_t p_tmsi;
struct {
uint32_t sgsn_gn_teid;
ogs_ip_t sgsn_gn_ip;
ogs_ip_t sgsn_gn_ip_alt;
} gn;

struct {
mme_m_tmsi_t *m_tmsi;
Expand Down
71 changes: 70 additions & 1 deletion src/mme/mme-gn-build.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,75 @@

#include "mme-gn-build.h"

/* 3GPP TS 29.060 7.5.4 SGSN Context Response */
ogs_pkbuf_t *mme_gn_build_sgsn_context_response(
mme_ue_t *mme_ue, uint8_t cause)
{
ogs_gtp1_message_t gtp1_message;
ogs_gtp1_sgsn_context_response_t *rsp = NULL;
mme_sess_t *sess = NULL;
ogs_gtp1_gsn_addr_t mme_gnc_gsnaddr;
int gsn_len;
int rv;

ogs_debug("[Gn] build SGSN Context Response");


rsp = &gtp1_message.sgsn_context_response;
memset(&gtp1_message, 0, sizeof(ogs_gtp1_message_t));
gtp1_message.h.type = OGS_GTP1_SGSN_CONTEXT_RESPONSE_TYPE;

/* 3GPP TS 29.060 7.7.1 Cause, Mandatory */
rsp->cause.presence = 1;
rsp->cause.u8 = cause;

/* 3GPP TS 29.060 7.7.2 IMSI, Conditional */
rsp->imsi.presence = !!mme_ue;
if (rsp->imsi.presence) {
rsp->imsi.data = mme_ue->imsi;
rsp->imsi.len = mme_ue->imsi_len;
}

if (cause != OGS_GTP1_CAUSE_REQUEST_ACCEPTED)
goto build_ret;

ogs_assert(mme_ue);

/* FIXME: Reuse S11 TEID as local Gn interface for now */
rsp->tunnel_endpoint_identifier_control_plane.presence = 1;
rsp->tunnel_endpoint_identifier_control_plane.u32 = mme_ue->mme_s11_teid;

ogs_list_for_each(&mme_ue->sess_list, sess) {
if (!MME_HAVE_SGW_S1U_PATH(sess))
continue;
/* TODO: fill some structure with pdp contexts */
}

/* SGSN Address for Control Plane */
if (ogs_gtp_self()->gtpc_addr6 &&
(mme_ue->gn.sgsn_gn_ip.ipv6 || mme_ue->gn.sgsn_gn_ip_alt.ipv6)) {
rv = ogs_gtp1_sockaddr_to_gsn_addr(NULL, ogs_gtp_self()->gtpc_addr6,
&mme_gnc_gsnaddr, &gsn_len);
if (rv != OGS_OK) {
ogs_error("ogs_gtp1_sockaddr_to_gsn_addr() failed");
return NULL;
}
} else {
rv = ogs_gtp1_sockaddr_to_gsn_addr(NULL, ogs_gtp_self()->gtpc_addr,
&mme_gnc_gsnaddr, &gsn_len);
if (rv != OGS_OK) {
ogs_error("ogs_gtp1_sockaddr_to_gsn_addr() failed");
return NULL;
}
}
rsp->sgsn_address_for_control_plane.presence = 1;
rsp->sgsn_address_for_control_plane.data = &mme_gnc_gsnaddr;
rsp->sgsn_address_for_control_plane.len = gsn_len;

build_ret:
return ogs_gtp1_build_msg(&gtp1_message);
}

/* 3GPP TS 29.060 7.5.14.1 RAN Information Relay */
ogs_pkbuf_t *mme_gn_build_ran_information_relay(
uint8_t type, const uint8_t *buf, size_t len,
Expand Down Expand Up @@ -59,4 +128,4 @@ ogs_pkbuf_t *mme_gn_build_ran_information_relay(

gtp1_message.h.type = type;
return ogs_gtp1_build_msg(&gtp1_message);
}
}
3 changes: 3 additions & 0 deletions src/mme/mme-gn-build.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ extern "C" {
}
#endif

ogs_pkbuf_t *mme_gn_build_sgsn_context_response(
mme_ue_t *mme_ue, uint8_t cause);

ogs_pkbuf_t *mme_gn_build_ran_information_relay(
uint8_t type, const uint8_t *buf, size_t len,
const ogs_nas_rai_t *rai, uint16_t cell_id);
Expand Down
94 changes: 94 additions & 0 deletions src/mme/mme-gn-handler.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,100 @@ static int decode_global_enb_id(S1AP_Global_ENB_ID_t *glob_enb_id, const uint8_t
return OGS_OK;
}

/* 3GPP TS 23.003 2.8.2.2 Mapping from RAI and P-TMSI to GUT */
static void rai_ptmsi_to_guti(const ogs_nas_rai_t *rai, mme_m_tmsi_t ptmsi, ogs_nas_eps_guti_t *nas_guti)
{
nas_guti->nas_plmn_id =rai->lai.nas_plmn_id;
nas_guti->mme_gid = rai->lai.lac;
nas_guti->mme_code = 0; /* FIXME: The 8 most significant bits of GERAN/UTRAN <NRI> map to the MME code. */
nas_guti->m_tmsi = (ptmsi & 0x1f000000) | ((rai->rac & 0xff) << 16) | (ptmsi & 0x0000ffff);
}

/* TS 29.060 7.5.3 SGSN Context Request */
void mme_gn_handle_sgsn_context_request(
ogs_gtp_xact_t *xact, ogs_gtp1_sgsn_context_request_t *req)
{
ogs_nas_eps_guti_t nas_guti;
ogs_nas_rai_t *rai;
mme_ue_t *mme_ue;
int rv;

ogs_debug("[Gn] Rx SGSN Context Request");

if (!req->routeing_area_identity.presence) {
ogs_warn("[Gn] Rx SGSN Context Request with no RAI!");
mme_gtp1_send_sgsn_context_response(NULL, OGS_GTP1_CAUSE_MANDATORY_IE_MISSING, xact);
return;
}
if (req->routeing_area_identity.len != sizeof(*rai)) {
ogs_warn("[Gn] Rx SGSN Context Request RAI wrong size %u vs exp %zu!",
req->routeing_area_identity.len, sizeof(*rai));
mme_gtp1_send_sgsn_context_response(NULL, OGS_GTP1_CAUSE_MANDATORY_IE_INCORRECT, xact);
return;
}
if (!req->tunnel_endpoint_identifier_control_plane.presence) {
ogs_warn("[Gn] Rx SGSN Context Request with no Tunnel Endpoint Identifier Control Plane!");
mme_gtp1_send_sgsn_context_response(NULL, OGS_GTP1_CAUSE_MANDATORY_IE_MISSING, xact);
return;
}
if (!req->sgsn_address_for_control_plane.presence) {
ogs_warn("[Gn] Rx SGSN Context Request with no SGSN Address for Control Plane!");
mme_gtp1_send_sgsn_context_response(NULL, OGS_GTP1_CAUSE_MANDATORY_IE_MISSING, xact);
return;
}
if (!req->imsi.presence &&
!req->temporary_logical_link_identifier.presence &&
!req->packet_tmsi.presence) {
ogs_warn("[Gn] Rx SGSN Context Request with no IMSI/TLLI/P-TMSI!");
mme_gtp1_send_sgsn_context_response(NULL, OGS_GTP1_CAUSE_MANDATORY_IE_MISSING, xact);
return;
}

if (req->ms_validated.presence &&
(req->ms_validated.u8 & 0x01) /* 1=> "Yes" */
&& !req->imsi.presence) {
ogs_warn("[Gn] Rx SGSN Context Request with 'MS Validated' but no IMSI!");
mme_gtp1_send_sgsn_context_response(NULL, OGS_GTP1_CAUSE_MANDATORY_IE_MISSING, xact);
return;
}

rai = req->routeing_area_identity.data;

if (req->ms_validated.presence) {
mme_ue = mme_ue_find_by_imsi(req->imsi.data, req->imsi.len);
} else if (req->packet_tmsi.presence) { /* P-TMSI */
rai_ptmsi_to_guti(rai, req->packet_tmsi.u32, &nas_guti);
mme_ue = mme_ue_find_by_guti(&nas_guti);
//mme_ue->p_tmsi = p_tmsi; // Update p-tmsi? not yet used?
} else if (req->temporary_logical_link_identifier.presence) {
/* This should not happen? TLLI not used in 4G case? */
ogs_warn("[Gn] Rx SGSN Context Request with TLLI!");
mme_gtp1_send_sgsn_context_response(NULL, OGS_GTP1_CAUSE_MANDATORY_IE_MISSING, xact);
return;
}

if (!mme_ue) {
mme_gtp1_send_sgsn_context_response(NULL, OGS_GTP1_CAUSE_IMSI_IMEI_NOT_KNOWN, xact);
return;
}

mme_ue->gn.sgsn_gn_teid = req->tunnel_endpoint_identifier_control_plane.u32;

rv = ogs_gtp1_gsn_addr_to_ip(req->sgsn_address_for_control_plane.data,
req->sgsn_address_for_control_plane.len,
&mme_ue->gn.sgsn_gn_ip);
ogs_assert(rv == OGS_OK);

if (req->alternative_sgsn_address_for_control_plane.presence) {
rv = ogs_gtp1_gsn_addr_to_ip(req->alternative_sgsn_address_for_control_plane.data,
req->alternative_sgsn_address_for_control_plane.len,
&mme_ue->gn.sgsn_gn_ip_alt);
ogs_assert(rv == OGS_OK);
}

mme_gtp1_send_sgsn_context_response(mme_ue, OGS_GTP1_CAUSE_REQUEST_ACCEPTED, xact);
}

/* TS 29.060 7.5.14.1 */
void mme_gn_handle_ran_information_relay(
ogs_gtp_xact_t *xact, ogs_gtp1_ran_information_relay_t *req)
Expand Down
3 changes: 3 additions & 0 deletions src/mme/mme-gn-handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ void mme_gn_handle_echo_request(
void mme_gn_handle_echo_response(
ogs_gtp_xact_t *xact, ogs_gtp1_echo_response_t *req);

void mme_gn_handle_sgsn_context_request(
ogs_gtp_xact_t *xact, ogs_gtp1_sgsn_context_request_t *req);

void mme_gn_handle_ran_information_relay(
ogs_gtp_xact_t *xact, ogs_gtp1_ran_information_relay_t *req);

Expand Down
30 changes: 30 additions & 0 deletions src/mme/mme-gtp-path.c
Original file line number Diff line number Diff line change
Expand Up @@ -758,6 +758,36 @@ int mme_gtp_send_bearer_resource_command(
return rv;
}

int mme_gtp1_send_sgsn_context_response(
mme_ue_t *mme_ue, uint8_t cause, ogs_gtp_xact_t *xact)
{
int rv;
ogs_gtp1_header_t h;
ogs_pkbuf_t *pkbuf = NULL;

memset(&h, 0, sizeof(ogs_gtp1_header_t));
h.type = OGS_GTP1_SGSN_CONTEXT_RESPONSE_TYPE;
h.teid = mme_ue ? mme_ue->gn.sgsn_gn_teid : 0;

pkbuf = mme_gn_build_sgsn_context_response(mme_ue, cause);
if (!pkbuf) {
ogs_error("mme_gn_build_sgsn_context_response() failed");
return OGS_ERROR;
}
/* FIXME: Reuse S11 TEID as local Gn interface for now */
xact->local_teid = mme_ue ? mme_ue->mme_s11_teid : 0;

rv = ogs_gtp1_xact_update_tx(xact, &h, pkbuf);
if (rv != OGS_OK) {
ogs_error("ogs_gtp1_xact_update_tx() failed");
return OGS_ERROR;
}

rv = ogs_gtp_xact_commit(xact);
ogs_expect(rv == OGS_OK);

return rv;
}

int mme_gtp1_send_ran_information_relay(
mme_sgsn_t *sgsn, const uint8_t *buf, size_t len,
Expand Down
3 changes: 3 additions & 0 deletions src/mme/mme-gtp-path.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ int mme_gtp_send_delete_indirect_data_forwarding_tunnel_request(
int mme_gtp_send_bearer_resource_command(
mme_bearer_t *bearer, ogs_nas_eps_message_t *nas_message);

int mme_gtp1_send_sgsn_context_response(
mme_ue_t *mme_ue, uint8_t cause, ogs_gtp_xact_t *xact);

int mme_gtp1_send_ran_information_relay(
mme_sgsn_t *sgsn, const uint8_t *buf, size_t len,
const ogs_nas_rai_t *rai, uint16_t cell_id);
Expand Down
3 changes: 3 additions & 0 deletions src/mme/mme-sm.c
Original file line number Diff line number Diff line change
Expand Up @@ -658,6 +658,9 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e)
case OGS_GTP1_ECHO_RESPONSE_TYPE:
mme_gn_handle_echo_response(xact, &gtp1_message.echo_response);
break;
case OGS_GTP1_SGSN_CONTEXT_REQUEST_TYPE:
mme_gn_handle_sgsn_context_request(xact, &gtp1_message.sgsn_context_request);
break;
case OGS_GTP1_RAN_INFORMATION_RELAY_TYPE:
mme_gn_handle_ran_information_relay(xact, &gtp1_message.ran_information_relay);
break;
Expand Down

0 comments on commit c697f82

Please sign in to comment.