Merge remote-tracking branch 'origin/nr-ue-nas-service-reject' into integration_2025_w15 (!3275)
Add 5GMM Service Reject enc/dec library and unit test - introduce the library for the NAS Service Reject enc/dec - add relevant unit test - add handler
This commit is contained in:
@@ -2,6 +2,7 @@ add_library(fgs_5gmm_lib OBJECT
|
||||
fgmm_lib.c
|
||||
fgs_service_request.c
|
||||
fgmm_service_accept.c
|
||||
fgmm_service_reject.c
|
||||
RegistrationRequest.c
|
||||
RegistrationAccept.c
|
||||
FGSIdentityResponse.c
|
||||
|
||||
@@ -143,6 +143,14 @@ int decode_gprs_timer_ie(gprs_timer_t *timer, const byte_array_t *buffer)
|
||||
return decoded;
|
||||
}
|
||||
|
||||
/** @brief Equality check for GPRS Timer */
|
||||
bool eq_gprs_timer(const gprs_timer_t *a, const gprs_timer_t *b)
|
||||
{
|
||||
_NAS_EQ_CHECK_INT(a->value, b->value);
|
||||
_NAS_EQ_CHECK_INT(a->unit, b->unit);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Decode EAP Message (todo) */
|
||||
int decode_eap_msg_ie(const byte_array_t *buffer)
|
||||
{
|
||||
|
||||
@@ -151,6 +151,8 @@ static const text_info_t sa_iei_s[] = {FOREACH_SA_IEI(TO_TEXT)};
|
||||
|
||||
typedef enum { FOREACH_CAUSE(TO_ENUM) } cause_id_t;
|
||||
|
||||
static const text_info_t fgmm_cause_s[] = {FOREACH_CAUSE(TO_TEXT)};
|
||||
|
||||
/* 10.5.7.3 3GPP TS 24.008 */
|
||||
typedef struct {
|
||||
uint8_t value;
|
||||
@@ -161,6 +163,7 @@ int encode_pdu_session_ie(byte_array_t *buffer, nas_service_IEI_t iei, const uin
|
||||
int decode_pdu_session_ie(uint8_t *psi, const byte_array_t *buffer);
|
||||
int encode_gprs_timer_ie(byte_array_t *buffer, nas_service_IEI_t iei, const gprs_timer_t *timer);
|
||||
int decode_gprs_timer_ie(gprs_timer_t *timer, const byte_array_t *buffer);
|
||||
bool eq_gprs_timer(const gprs_timer_t *a, const gprs_timer_t *b);
|
||||
int decode_eap_msg_ie(const byte_array_t *buffer);
|
||||
|
||||
#endif /* FGS_LIB_H */
|
||||
@@ -172,8 +172,8 @@ bool eq_service_accept(const fgs_service_accept_msg_t *a, const fgs_service_acce
|
||||
PRINT_NAS_ERROR("t3448 equality check failed\n");
|
||||
return false;
|
||||
}
|
||||
_NAS_EQ_CHECK_INT(a->t3448->value, b->t3448->value);
|
||||
_NAS_EQ_CHECK_INT(a->t3448->unit, b->t3448->unit);
|
||||
if (!eq_gprs_timer(a->t3448, b->t3448))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#include "fgmm_service_reject.h"
|
||||
#include <string.h>
|
||||
#include <arpa/inet.h> // For htons and ntohs
|
||||
#include <stdlib.h> // For malloc and free
|
||||
#include "common/utils/ds/byte_array.h"
|
||||
#include "common/utils/utils.h"
|
||||
#include "fgmm_lib.h"
|
||||
|
||||
#define SERVICE_REJECT_MIN_LEN 1 // 1 octet
|
||||
|
||||
/** @brief Encode Service Reject (8.2.18 of 3GPP TS 24.501) */
|
||||
int encode_fgs_service_reject(byte_array_t *buffer, const fgs_service_reject_msg_t *msg)
|
||||
{
|
||||
if (buffer->len < SERVICE_REJECT_MIN_LEN) {
|
||||
PRINT_NAS_ERROR("Failed to encode Service Reject: missing Cause IE!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
byte_array_t ba = *buffer; // Local copy of buffer
|
||||
int encoded = 0;
|
||||
|
||||
// 5GMM cause (Mandatory)
|
||||
buffer->buf[encoded++] = msg->cause;
|
||||
UPDATE_BYTE_ARRAY(ba, 1);
|
||||
|
||||
// PDU Session Status (Optional)
|
||||
if (msg->has_psi_status) {
|
||||
ENCODE_NAS_IE(ba, encode_pdu_session_ie(&ba, IEI_PDU_SESSION_STATUS, msg->psi_status), encoded);
|
||||
}
|
||||
|
||||
// T3446 Timer (Optional)
|
||||
if (msg->t3446) {
|
||||
ENCODE_NAS_IE(ba, encode_gprs_timer_ie(&ba, IEI_T3446_VALUE, msg->t3446), encoded);
|
||||
}
|
||||
|
||||
// T3448 Timer (Optional)
|
||||
if (msg->t3448) {
|
||||
ENCODE_NAS_IE(ba, encode_gprs_timer_ie(&ba, IEI_T3448_VALUE, msg->t3448), encoded);
|
||||
}
|
||||
|
||||
return encoded;
|
||||
}
|
||||
|
||||
/** @brief Decode Service Reject (8.2.18 of 3GPP TS 24.501) */
|
||||
int decode_fgs_service_reject(fgs_service_reject_msg_t *msg, const byte_array_t *buffer)
|
||||
{
|
||||
if (buffer->len < SERVICE_REJECT_MIN_LEN) {
|
||||
PRINT_NAS_ERROR("Nothing to decode: missing Cause IE!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
byte_array_t ba = *buffer; // Local copy of buffer to be used in the decoding sub-functions
|
||||
uint32_t decoded = 0;
|
||||
|
||||
// Cause (Mandatory)
|
||||
msg->cause = buffer->buf[decoded++];
|
||||
UPDATE_BYTE_ARRAY(ba, 1);
|
||||
|
||||
// Decode Optional IEs
|
||||
while (decoded < buffer->len) {
|
||||
uint8_t iei = buffer->buf[decoded++];
|
||||
UPDATE_BYTE_ARRAY(ba, 1); // Skip IEI
|
||||
|
||||
switch (iei) {
|
||||
case IEI_PDU_SESSION_STATUS:
|
||||
msg->has_psi_status = true;
|
||||
DECODE_NAS_IE(ba, decode_pdu_session_ie(msg->psi_status, &ba), decoded);
|
||||
break;
|
||||
|
||||
case IEI_T3448_VALUE:
|
||||
msg->t3448 = malloc_or_fail(sizeof(*msg->t3448));
|
||||
DECODE_NAS_IE(ba, decode_gprs_timer_ie(msg->t3448, (const byte_array_t *)&ba), decoded);
|
||||
break;
|
||||
|
||||
case IEI_T3446_VALUE:
|
||||
msg->t3446 = malloc_or_fail(sizeof(*msg->t3446));
|
||||
DECODE_NAS_IE(ba, decode_gprs_timer_ie(msg->t3446, (const byte_array_t *)&ba), decoded);
|
||||
break;
|
||||
|
||||
case IEI_EAPMSG:
|
||||
DECODE_NAS_IE(ba, decode_eap_msg_ie((const byte_array_t *)&ba), decoded);
|
||||
break;
|
||||
|
||||
case IEI_CAG_INFO_LIST: {
|
||||
int cag_list_len = (buffer->buf[decoded] << 8) | buffer->buf[decoded + 1];
|
||||
int cag_len = cag_list_len + 2; // encoded content + 2 octets for the length IE
|
||||
decoded += cag_len;
|
||||
UPDATE_BYTE_ARRAY(ba, cag_len);
|
||||
PRINT_NAS_ERROR("CAG information list IE in NAS Service Reject is not handled\n");
|
||||
} break;
|
||||
|
||||
default:
|
||||
PRINT_NAS_ERROR("Uknown or invalid NAS Service Reject IEI %d\n", iei);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return decoded;
|
||||
}
|
||||
|
||||
/** @brief Equality check for Service Reject (enc/dec) */
|
||||
bool eq_service_reject(const fgs_service_reject_msg_t *a, const fgs_service_reject_msg_t *b)
|
||||
{
|
||||
_NAS_EQ_CHECK_INT(a->cause, b->cause);
|
||||
_NAS_EQ_CHECK_INT(a->has_psi_status, b->has_psi_status);
|
||||
if (a->has_psi_status && b->has_psi_status) {
|
||||
for (int i = 0; i < MAX_NUM_PSI; i++)
|
||||
_NAS_EQ_CHECK_INT(a->psi_status[i], b->psi_status[i]);
|
||||
}
|
||||
if (a->t3448 != NULL || b->t3448 != NULL) {
|
||||
if (a->t3448 == NULL || b->t3448 == NULL) {
|
||||
PRINT_NAS_ERROR("t3448 equality check failed\n");
|
||||
return false;
|
||||
}
|
||||
if (!eq_gprs_timer(a->t3448, b->t3448))
|
||||
return false;
|
||||
}
|
||||
if (a->t3446 != NULL || b->t3446 != NULL) {
|
||||
if (a->t3446 == NULL || b->t3446 == NULL) {
|
||||
PRINT_NAS_ERROR("t3448 equality check failed\n");
|
||||
return false;
|
||||
}
|
||||
if (!eq_gprs_timer(a->t3446, b->t3446))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void free_fgs_service_reject(fgs_service_reject_msg_t *msg)
|
||||
{
|
||||
free(msg->t3446);
|
||||
free(msg->t3448);
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#ifndef FGS_service_reject_H
|
||||
#define FGS_service_reject_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "fgmm_lib.h"
|
||||
|
||||
typedef struct {
|
||||
// 5GMM cause (Mandatory)
|
||||
cause_id_t cause;
|
||||
// T3346 Value (Optional)
|
||||
gprs_timer_t *t3446;
|
||||
// PDU Session Status (Optional)
|
||||
uint8_t psi_status[MAX_NUM_PSI];
|
||||
bool has_psi_status;
|
||||
// T3448 Value (Optional)
|
||||
gprs_timer_t *t3448;
|
||||
} fgs_service_reject_msg_t;
|
||||
|
||||
int decode_fgs_service_reject(fgs_service_reject_msg_t *msg, const byte_array_t *buffer);
|
||||
int encode_fgs_service_reject(byte_array_t *buffer, const fgs_service_reject_msg_t *msg);
|
||||
void free_fgs_service_reject(fgs_service_reject_msg_t *msg);
|
||||
bool eq_service_reject(const fgs_service_reject_msg_t *a, const fgs_service_reject_msg_t *b);
|
||||
|
||||
#endif /* FGS_service_reject_H */
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "common/utils/ds/byte_array.h"
|
||||
#include "fgs_service_request.h"
|
||||
#include "fgmm_service_accept.h"
|
||||
#include "fgmm_service_reject.h"
|
||||
#include "nr_nas_msg.h"
|
||||
|
||||
void exit_function(const char *file, const char *function, const int line, const char *s, const int assert)
|
||||
@@ -127,9 +128,52 @@ static void test_service_accept(void)
|
||||
free_fgs_service_accept(&orig);
|
||||
}
|
||||
|
||||
/** @brief Test NAS Service Reject enc/dec */
|
||||
static void test_service_reject(void)
|
||||
{
|
||||
// Dummy NAS Service Reject message
|
||||
fgs_service_reject_msg_t orig = {
|
||||
.cause = Illegal_UE,
|
||||
.has_psi_status = true,
|
||||
.t3446 = malloc_or_fail(sizeof(*orig.t3446)),
|
||||
.t3448 = malloc_or_fail(sizeof(*orig.t3448)),
|
||||
};
|
||||
orig.psi_status[1] = PDU_SESSION_INACTIVE; // PDU Session 1
|
||||
orig.psi_status[2] = PDU_SESSION_ACTIVE; // PDU Session 2
|
||||
orig.t3446->value = 10;
|
||||
orig.t3446->unit = TWO_SECONDS;
|
||||
orig.t3448->value = 1;
|
||||
orig.t3448->unit = ONE_MINUTE;
|
||||
|
||||
// Expected encoded data
|
||||
uint8_t expected_enc[] = {0x03, 0x50, 0x02, 0x04, 0x00, 0x5F, 0x01, 0x0A, 0x6B, 0x01, 0x21};
|
||||
|
||||
// Buffer
|
||||
uint8_t buf[64] = {0};
|
||||
byte_array_t buffer = {.buf = &buf[0], .len = sizeof(expected_enc)};
|
||||
|
||||
// Encode NAS Service Reject
|
||||
int encoded_length = encode_fgs_service_reject(&buffer, &orig);
|
||||
AssertFatal(encoded_length == sizeofArray(expected_enc), "encode_fgs_service_reject() failed: %d != %ld\n", encoded_length, sizeofArray(expected_enc));
|
||||
|
||||
// Compare the raw encoded buffer with expected encoded data
|
||||
AssertFatal(memcmp(buffer.buf, expected_enc, buffer.len) == 0, "Encoding mismatch!\n");
|
||||
|
||||
// Decode NAS Service Reject
|
||||
fgs_service_reject_msg_t dec = {0};
|
||||
int decoded_length = decode_fgs_service_reject(&dec, &buffer);
|
||||
AssertFatal(decoded_length >= 0, "decode_fgs_service_reject() failed\n");
|
||||
|
||||
// Compare original and decoded messages
|
||||
AssertFatal(eq_service_reject(&orig, &dec), "test_service_reject() failed: original and decoded messages do not match\n");
|
||||
free_fgs_service_reject(&dec);
|
||||
free_fgs_service_reject(&orig);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test_service_request();
|
||||
test_service_accept();
|
||||
test_service_reject();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -66,6 +66,7 @@
|
||||
#include "openair2/SDAP/nr_sdap/nr_sdap.h"
|
||||
#include "fgs_nas_utils.h"
|
||||
#include "fgmm_service_accept.h"
|
||||
#include "fgmm_service_reject.h"
|
||||
|
||||
#define MAX_NAS_UE 4
|
||||
|
||||
@@ -1531,6 +1532,17 @@ static void handle_service_accept(nr_ue_nas_t *nas, const byte_array_t *buffer)
|
||||
print_info(msg.cause->cause, cause_text_info, sizeofArray(cause_text_info)));
|
||||
}
|
||||
|
||||
static void handle_service_reject(nr_ue_nas_t *nas, const byte_array_t *buffer)
|
||||
{
|
||||
fgs_service_reject_msg_t msg = {0};
|
||||
decode_fgs_service_reject(&msg, buffer);
|
||||
// Extract timer t3448 in seconds (optional IE)
|
||||
nas->t3448 = process_gprs_timer(msg.t3448);
|
||||
// Extract timer t3446 in seconds (optional IE)
|
||||
nas->t3446 = process_gprs_timer(msg.t3446);
|
||||
LOG_E(NAS, "Received NAS Service Reject message with cause %s\n", fgmm_cause_s[msg.cause].text);
|
||||
}
|
||||
|
||||
void *nas_nrue(void *args_p)
|
||||
{
|
||||
// Wait for a message or an event
|
||||
@@ -1737,6 +1749,13 @@ void *nas_nrue(void *args_p)
|
||||
handle_service_accept(nas, &buffer);
|
||||
break;
|
||||
}
|
||||
|
||||
case FGS_SERVICE_REJECT: {
|
||||
byte_array_t buffer = {.buf = pdu_buffer, .len = pdu_length};
|
||||
handle_service_reject(nas, &buffer);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
LOG_W(NR_RRC, "unknown message type %d\n", msg_type);
|
||||
break;
|
||||
|
||||
@@ -100,6 +100,8 @@ typedef struct {
|
||||
int t3512;
|
||||
// Timer t3448 in seconds (-1 = disabled)
|
||||
int t3448;
|
||||
// Timer t3446 in seconds (-1 = disabled)
|
||||
int t3446;
|
||||
} nr_ue_nas_t;
|
||||
|
||||
nr_ue_nas_t *get_ue_nas_info(module_id_t module_id);
|
||||
|
||||
Reference in New Issue
Block a user