Commit 8b022848 authored by Sakthivel Velumani's avatar Sakthivel Velumani

Enable AT command interface and link to NAS layer

1. Add AT command handlers to set and activate PDP context.
2. Changes to NAS for sending multiple PDU session request.
3. Provide command line option to enable AT command interface.
parent e33c7d26
...@@ -217,6 +217,9 @@ int create_tasks_nrue(uint32_t ue_nb) { ...@@ -217,6 +217,9 @@ int create_tasks_nrue(uint32_t ue_nb) {
if (itti_create_task(TASK_NAS_NRUE, nas_nrue_task, &parmsNAS) < 0) { if (itti_create_task(TASK_NAS_NRUE, nas_nrue_task, &parmsNAS) < 0) {
LOG_E(NR_RRC, "Create task for NAS UE failed\n"); LOG_E(NR_RRC, "Create task for NAS UE failed\n");
return -1; return -1;
} else {
if (get_nrUE_params()->enable_AT)
nas_nrue_user((void *)&parmsNAS);
} }
} }
......
...@@ -12,6 +12,12 @@ ...@@ -12,6 +12,12 @@
#define CONFIG_HLP_DLSCH_PARA "number of threads for dlsch processing 0 for no parallelization\n" #define CONFIG_HLP_DLSCH_PARA "number of threads for dlsch processing 0 for no parallelization\n"
#define CONFIG_HLP_OFFSET_DIV "Divisor for computing OFDM symbol offset in Rx chain (num samples in CP/<the value>). Default value is 8. To set the sample offset to 0, set this value ~ 10e6\n" #define CONFIG_HLP_OFFSET_DIV "Divisor for computing OFDM symbol offset in Rx chain (num samples in CP/<the value>). Default value is 8. To set the sample offset to 0, set this value ~ 10e6\n"
#define CONFIG_HLP_MAX_LDPC_ITERATIONS "Maximum LDPC decoder iterations\n" #define CONFIG_HLP_MAX_LDPC_ITERATIONS "Maximum LDPC decoder iterations\n"
#define CONFIG_HLP_AT_IF \
"Name of the virtual serial interface to be used by UE process (used along with --AT). Use 'socat' utility to connect two " \
"virtual serial ports and " \
"access the AT command interface. One interface (given here) will be used by the UE process and other interface can be " \
"accessed via minicom or screen.\n"
#define CONFIG_HLP_AT "Enable AT-command interface\n"
/***************************************************************************************************************************************/ /***************************************************************************************************************************************/
/* command line options definitions, CMDLINE_XXXX_DESC macros are used to initialize paramdef_t arrays which are then used as argument /* command line options definitions, CMDLINE_XXXX_DESC macros are used to initialize paramdef_t arrays which are then used as argument
when calling config_get or config_getlist functions */ when calling config_get or config_getlist functions */
...@@ -61,6 +67,8 @@ ...@@ -61,6 +67,8 @@
{"chest-time", CONFIG_HLP_CHESTTIME, 0, .iptr=&(nrUE_params.chest_time), .defintval=0, TYPE_INT, 0}, \ {"chest-time", CONFIG_HLP_CHESTTIME, 0, .iptr=&(nrUE_params.chest_time), .defintval=0, TYPE_INT, 0}, \
{"ue-timing-correction-disable", CONFIG_HLP_DISABLETIMECORR, PARAMFLAG_BOOL, .iptr=&(nrUE_params.no_timing_correction), .defintval=0, TYPE_INT, 0}, \ {"ue-timing-correction-disable", CONFIG_HLP_DISABLETIMECORR, PARAMFLAG_BOOL, .iptr=&(nrUE_params.no_timing_correction), .defintval=0, TYPE_INT, 0}, \
{"SLC", CONFIG_HLP_SLF, 0, .u64ptr=&(sidelink_frequency[0][0]), .defuintval=2600000000,TYPE_UINT64,0}, \ {"SLC", CONFIG_HLP_SLF, 0, .u64ptr=&(sidelink_frequency[0][0]), .defuintval=2600000000,TYPE_UINT64,0}, \
{"AT", CONFIG_HLP_AT, PARAMFLAG_BOOL, .iptr=&(nrUE_params.enable_AT), .defintval=0, TYPE_INT, 0}, \
{"AT-interface", CONFIG_HLP_AT_IF, 0, .strptr=&(nrUE_params.at_interface_name), .defstrval="/dev/pts/7", TYPE_STRING, 0}, \
} }
// clang-format on // clang-format on
...@@ -80,6 +88,8 @@ typedef struct { ...@@ -80,6 +88,8 @@ typedef struct {
int nb_antennas_tx; int nb_antennas_tx;
int N_RB_DL; int N_RB_DL;
int ssb_start_subcarrier; int ssb_start_subcarrier;
int enable_AT;
char *at_interface_name;
} nrUE_params_t; } nrUE_params_t;
extern uint64_t get_nrUE_optmask(void); extern uint64_t get_nrUE_optmask(void);
extern uint64_t set_nrUE_optmask(uint64_t bitmask); extern uint64_t set_nrUE_optmask(uint64_t bitmask);
......
...@@ -464,13 +464,6 @@ typedef ul_info_transfer_cnf_t dl_info_transfer_cnf_t; ...@@ -464,13 +464,6 @@ typedef ul_info_transfer_cnf_t dl_info_transfer_cnf_t;
*/ */
typedef ul_info_transfer_ind_t dl_info_transfer_ind_t; typedef ul_info_transfer_ind_t dl_info_transfer_ind_t;
typedef struct nas_pdu_session_req_s {
int pdusession_id;
int pdusession_type;
int sst;
int sd;
} nas_pdu_session_req_t;
typedef struct nas_nos1_msg_s { typedef struct nas_nos1_msg_s {
rnti_t rnti; rnti_t rnti;
} nas_nos1_msg_t; } nas_nos1_msg_t;
...@@ -552,6 +545,18 @@ typedef struct rab_release_ind_s { ...@@ -552,6 +545,18 @@ typedef struct rab_release_ind_s {
as_rab_id_t rabID; /* Radio access bearer identity */ as_rab_id_t rabID; /* Radio access bearer identity */
} rab_release_ind_t; } rab_release_ind_t;
/* PDP context stored in UE */
typedef struct nr_nas_pdp_context_s {
int pdu_session_id;
int pdu_session_type;
char dnn[64];
char nssaiStr[64];
int nssai_sst;
int nssai_sd;
bool is_active;
bool is_defined;
} nr_nas_pdp_context_t;
/* /*
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Structure of the AS messages handled by the network sublayer * Structure of the AS messages handled by the network sublayer
......
...@@ -84,6 +84,6 @@ MESSAGE_DEF(NRRRC_FRAME_PROCESS, MESSAGE_PRIORITY_MED, NRRrcFramePr ...@@ -84,6 +84,6 @@ MESSAGE_DEF(NRRRC_FRAME_PROCESS, MESSAGE_PRIORITY_MED, NRRrcFramePr
// eNB: RLC -> RRC messages // eNB: RLC -> RRC messages
MESSAGE_DEF(RLC_SDU_INDICATION, MESSAGE_PRIORITY_MED, RlcSduIndication, rlc_sdu_indication) MESSAGE_DEF(RLC_SDU_INDICATION, MESSAGE_PRIORITY_MED, RlcSduIndication, rlc_sdu_indication)
MESSAGE_DEF(NAS_PDU_SESSION_REQ, MESSAGE_PRIORITY_MED, nas_pdu_session_req_t, nas_pdu_session_req) MESSAGE_DEF(NAS_PDU_SESSION_REQ, MESSAGE_PRIORITY_MED, nr_nas_pdp_context_t, nas_pdu_session_req)
MESSAGE_DEF(NAS_INIT_NOS1_IF, MESSAGE_PRIORITY_MED, nas_nos1_msg_t, nas_init_nos1_if) MESSAGE_DEF(NAS_INIT_NOS1_IF, MESSAGE_PRIORITY_MED, nas_nos1_msg_t, nas_init_nos1_if)
MESSAGE_DEF(NAS_PDU_SESSION_REL, MESSAGE_PRIORITY_MED, nas_pdu_session_req_t, nas_pdu_session_rel) MESSAGE_DEF(NAS_PDU_SESSION_REL, MESSAGE_PRIORITY_MED, nr_nas_pdp_context_t, nas_pdu_session_rel)
...@@ -27,19 +27,19 @@ ...@@ -27,19 +27,19 @@
extern char *baseNetAddress; extern char *baseNetAddress;
static uint16_t getShort(uint8_t *input) static uint16_t getShort(const uint8_t *input)
{ {
uint16_t tmp16; uint16_t tmp16;
memcpy(&tmp16, input, sizeof(tmp16)); memcpy(&tmp16, input, sizeof(tmp16));
return htons(tmp16); return htons(tmp16);
} }
void capture_pdu_session_establishment_accept_msg(uint8_t *buffer, uint32_t msg_length) void capture_pdu_session_establishment_accept_msg(const uint8_t *buffer, uint32_t msg_length, int *pdu_id)
{ {
security_protected_nas_5gs_msg_t sec_nas_hdr; security_protected_nas_5gs_msg_t sec_nas_hdr;
security_protected_plain_nas_5gs_msg_t sec_nas_msg; security_protected_plain_nas_5gs_msg_t sec_nas_msg;
pdu_session_establishment_accept_msg_t psea_msg; pdu_session_establishment_accept_msg_t psea_msg;
uint8_t *curPtr = buffer; const uint8_t *curPtr = buffer;
sec_nas_hdr.epd = *curPtr++; sec_nas_hdr.epd = *curPtr++;
sec_nas_hdr.sht = *curPtr++; sec_nas_hdr.sht = *curPtr++;
uint32_t tmp; uint32_t tmp;
...@@ -56,6 +56,7 @@ void capture_pdu_session_establishment_accept_msg(uint8_t *buffer, uint32_t msg_ ...@@ -56,6 +56,7 @@ void capture_pdu_session_establishment_accept_msg(uint8_t *buffer, uint32_t msg_
/* Mandatory Presence IEs */ /* Mandatory Presence IEs */
psea_msg.epd = *curPtr++; psea_msg.epd = *curPtr++;
psea_msg.pdu_id = *curPtr++; psea_msg.pdu_id = *curPtr++;
*pdu_id = psea_msg.pdu_id;
psea_msg.pti = *curPtr++; psea_msg.pti = *curPtr++;
psea_msg.msg_type = *curPtr++; psea_msg.msg_type = *curPtr++;
psea_msg.pdu_type = *curPtr & 0x0f; psea_msg.pdu_type = *curPtr & 0x0f;
......
...@@ -166,6 +166,6 @@ typedef struct security_protected_nas_5gs_msg_s { ...@@ -166,6 +166,6 @@ typedef struct security_protected_nas_5gs_msg_s {
uint8_t sqn; /* Sequence Number */ uint8_t sqn; /* Sequence Number */
} security_protected_nas_5gs_msg_t; /* 24.501 Figure 9.1.1.2 */ } security_protected_nas_5gs_msg_t; /* 24.501 Figure 9.1.1.2 */
void capture_pdu_session_establishment_accept_msg(uint8_t *buffer, uint32_t msg_length); void capture_pdu_session_establishment_accept_msg(const uint8_t *buffer, uint32_t msg_length, int *pdu_id);
#endif #endif
...@@ -53,12 +53,16 @@ ...@@ -53,12 +53,16 @@
#include "openair3/SECU/nas_stream_eia2.h" #include "openair3/SECU/nas_stream_eia2.h"
#include "openair3/UTILS/conversions.h" #include "openair3/UTILS/conversions.h"
#include "openair3/NAS/UE/nas_user.h"
#include "openair3/NAS/UE/API/USER/user_api.h"
#include "openair3/NAS/UE/user_defs.h"
#include "executables/nr-uesoftmodem.h"
uint8_t *registration_request_buf; uint8_t *registration_request_buf;
uint32_t registration_request_len; uint32_t registration_request_len;
extern char *baseNetAddress; extern char *baseNetAddress;
extern uint16_t NB_UE_INST; extern uint16_t NB_UE_INST;
static nr_ue_nas_t nr_ue_nas = {0}; static nr_ue_nas_t nr_ue_nas = {0};
static nr_nas_msg_snssai_t nas_allowed_nssai[8];
static nr_nas_thread_info_t softmodem_nas_info; static nr_nas_thread_info_t softmodem_nas_info;
static int nas_protected_security_header_encode( static int nas_protected_security_header_encode(
...@@ -801,7 +805,7 @@ static void generateDeregistrationRequest(nr_ue_nas_t *nas, as_nas_info_t *initi ...@@ -801,7 +805,7 @@ static void generateDeregistrationRequest(nr_ue_nas_t *nas, as_nas_info_t *initi
initialNasMsg->data[2 + i] = mac[i]; initialNasMsg->data[2 + i] = mac[i];
} }
static void generatePduSessionEstablishRequest(nr_ue_nas_t *nas, as_nas_info_t *initialNasMsg, nas_pdu_session_req_t *pdu_req) static void generatePduSessionEstablishRequest(nr_ue_nas_t *nas, as_nas_info_t *initialNasMsg, nr_nas_pdp_context_t *pdu_req)
{ {
int size = 0; int size = 0;
fgs_nas_message_t nas_msg={0}; fgs_nas_message_t nas_msg={0};
...@@ -811,11 +815,11 @@ static void generatePduSessionEstablishRequest(nr_ue_nas_t *nas, as_nas_info_t * ...@@ -811,11 +815,11 @@ static void generatePduSessionEstablishRequest(nr_ue_nas_t *nas, as_nas_info_t *
uint8_t *req_buffer = malloc(req_length); uint8_t *req_buffer = malloc(req_length);
pdu_session_establishment_request_msg pdu_session_establish; pdu_session_establishment_request_msg pdu_session_establish;
pdu_session_establish.protocoldiscriminator = FGS_SESSION_MANAGEMENT_MESSAGE; pdu_session_establish.protocoldiscriminator = FGS_SESSION_MANAGEMENT_MESSAGE;
pdu_session_establish.pdusessionid = pdu_req->pdusession_id; pdu_session_establish.pdusessionid = pdu_req->pdu_session_id;
pdu_session_establish.pti = 1; pdu_session_establish.pti = 1;
pdu_session_establish.pdusessionestblishmsgtype = FGS_PDU_SESSION_ESTABLISHMENT_REQ; pdu_session_establish.pdusessionestblishmsgtype = FGS_PDU_SESSION_ESTABLISHMENT_REQ;
pdu_session_establish.maxdatarate = 0xffff; pdu_session_establish.maxdatarate = 0xffff;
pdu_session_establish.pdusessiontype = pdu_req->pdusession_type; pdu_session_establish.pdusessiontype = pdu_req->pdu_session_type;
encode_pdu_session_establishment_request(&pdu_session_establish, req_buffer); encode_pdu_session_establishment_request(&pdu_session_establish, req_buffer);
...@@ -850,25 +854,25 @@ static void generatePduSessionEstablishRequest(nr_ue_nas_t *nas, as_nas_info_t * ...@@ -850,25 +854,25 @@ static void generatePduSessionEstablishRequest(nr_ue_nas_t *nas, as_nas_info_t *
mm_msg->uplink_nas_transport.fgspayloadcontainer.payloadcontainercontents.length = req_length; mm_msg->uplink_nas_transport.fgspayloadcontainer.payloadcontainercontents.length = req_length;
mm_msg->uplink_nas_transport.fgspayloadcontainer.payloadcontainercontents.value = req_buffer; mm_msg->uplink_nas_transport.fgspayloadcontainer.payloadcontainercontents.value = req_buffer;
size += (2+req_length); size += (2+req_length);
mm_msg->uplink_nas_transport.pdusessionid = pdu_req->pdusession_id; mm_msg->uplink_nas_transport.pdusessionid = pdu_req->pdu_session_id;
mm_msg->uplink_nas_transport.requesttype = 1; mm_msg->uplink_nas_transport.requesttype = 1;
size += 3; size += 3;
const bool has_nssai_sd = pdu_req->sd != 0xffffff; // 0xffffff means "no SD", TS 23.003 const bool has_nssai_sd = pdu_req->nssai_sd != 0xffffff; // 0xffffff means "no SD", TS 23.003
const size_t nssai_len = has_nssai_sd ? 4 : 1; const size_t nssai_len = has_nssai_sd ? 4 : 1;
mm_msg->uplink_nas_transport.snssai.length = nssai_len; mm_msg->uplink_nas_transport.snssai.length = nssai_len;
//Fixme: it seems there are a lot of memory errors in this: this value was on the stack, //Fixme: it seems there are a lot of memory errors in this: this value was on the stack,
// but pushed in a itti message to another thread // but pushed in a itti message to another thread
// this kind of error seems in many places in 5G NAS // this kind of error seems in many places in 5G NAS
mm_msg->uplink_nas_transport.snssai.value = calloc(1, nssai_len); mm_msg->uplink_nas_transport.snssai.value = calloc(1, nssai_len);
mm_msg->uplink_nas_transport.snssai.value[0] = pdu_req->sst; mm_msg->uplink_nas_transport.snssai.value[0] = pdu_req->nssai_sst;
if (has_nssai_sd) if (has_nssai_sd)
INT24_TO_BUFFER(pdu_req->sd, &mm_msg->uplink_nas_transport.snssai.value[1]); INT24_TO_BUFFER(pdu_req->nssai_sd, &mm_msg->uplink_nas_transport.snssai.value[1]);
size += 1 + 1 + nssai_len; size += 1 + 1 + nssai_len;
int dnnSize=strlen(nas->uicc->dnnStr); int dnnSize = strlen(pdu_req->dnn);
mm_msg->uplink_nas_transport.dnn.value=calloc(1,dnnSize+1); mm_msg->uplink_nas_transport.dnn.value=calloc(1,dnnSize+1);
mm_msg->uplink_nas_transport.dnn.length = dnnSize + 1; mm_msg->uplink_nas_transport.dnn.length = dnnSize + 1;
mm_msg->uplink_nas_transport.dnn.value[0] = dnnSize; mm_msg->uplink_nas_transport.dnn.value[0] = dnnSize;
memcpy(mm_msg->uplink_nas_transport.dnn.value + 1, nas->uicc->dnnStr, dnnSize); memcpy(mm_msg->uplink_nas_transport.dnn.value + 1, pdu_req->dnn, dnnSize);
size += (1+1+dnnSize+1); size += (1+1+dnnSize+1);
// encode the message // encode the message
...@@ -1033,24 +1037,155 @@ static void get_allowed_nssai(nr_nas_msg_snssai_t nssai[8], const uint8_t *pdu_b ...@@ -1033,24 +1037,155 @@ static void get_allowed_nssai(nr_nas_msg_snssai_t nssai[8], const uint8_t *pdu_b
} }
} }
static void request_default_pdusession(int instance, int nssai_idx) static void request_pdusession(const nr_nas_pdp_context_t *pdp_cxt, int instance)
{ {
MessageDef *message_p = itti_alloc_new_message(TASK_NAS_NRUE, 0, NAS_PDU_SESSION_REQ); MessageDef *message_p = itti_alloc_new_message(TASK_NAS_NRUE, 0, NAS_PDU_SESSION_REQ);
NAS_PDU_SESSION_REQ(message_p).pdusession_id = softmodem_nas_info.default_pdu_session_id; NAS_PDU_SESSION_REQ(message_p) = *pdp_cxt;
NAS_PDU_SESSION_REQ(message_p).pdusession_type = 0x91;
NAS_PDU_SESSION_REQ(message_p).sst = nas_allowed_nssai[nssai_idx].sst;
NAS_PDU_SESSION_REQ(message_p).sd = nas_allowed_nssai[nssai_idx].sd;
itti_send_msg_to_task(TASK_NAS_NRUE, instance, message_p); itti_send_msg_to_task(TASK_NAS_NRUE, instance, message_p);
} }
static int get_user_nssai_idx(const nr_nas_msg_snssai_t allowed_nssai[8], const nr_ue_nas_t *nas) int nas_request_pdu_release(nas_user_t *user, int cid)
{
LOG_E(NAS, "PDU release not implemented yet\n");
return RETURNerror;
}
int nas_request_pdusession(nas_user_t *nas_user, int cid)
{
int ret = RETURNerror;
if ((cid < MAX_PDP_CONTEXTS) && (cid > 0)) {
nr_nas_pdp_context_t *pdp_cxt = &nas_user->pdp_context[cid];
request_pdusession(pdp_cxt, 0 /*instance*/);
ret = RETURNok;
} else {
LOG_E(NAS, "Invalid PDP context id: %d\n", cid);
}
return ret;
}
/* @brief Set active flag for PDP context */
static void set_pdp_active_flag(nr_ue_nas_t *nas, int pdu_session_id, bool flag)
{
for (int i = 0; i < MAX_PDP_CONTEXTS; i++) {
nr_nas_pdp_context_t *p = &nas->nas_user->pdp_context[i];
if (p->pdu_session_id == pdu_session_id) {
AssertFatal(p->is_defined, "Trying to de/activate a PDP context (%d) thats not defined by user. Something went wrong!\n", i);
p->is_active = true;
break;
}
}
}
/* @brief Check if user entered NSSAI fields match with
the list received from the network */
static bool valid_user_nssai(const nr_nas_msg_snssai_t allowed_nssai[8], const nr_nas_pdp_context_t *pdp_cxt)
{ {
for (int i = 0; i < 8; i++) { for (int i = 0; i < 8; i++) {
const nr_nas_msg_snssai_t *nssai = allowed_nssai + i; const nr_nas_msg_snssai_t *nssai = allowed_nssai + i;
if ((nas->uicc->nssai_sst == nssai->sst) && (nas->uicc->nssai_sd == nssai->sd)) if ((pdp_cxt->nssai_sst == nssai->sst) && (pdp_cxt->nssai_sd == nssai->sd))
return i; return true;
}
return false;
}
static void parse_nssai_string(const char *nssaiStr, int *sst, int *sd)
{
if (nssaiStr[0] == '\0')
return;
const char *del = ".";
char *tmp = (char *)nssaiStr;
char *token = strtok(tmp, del);
*sst = atoi(token);
token = strtok(NULL, del);
*sd = atoi(token);
token = strtok(NULL, del);
DevAssert(token == NULL);
}
int nas_reset_pdp_context(nas_user_t *user, int index)
{
if ((user == NULL) || (index >= MAX_PDP_CONTEXTS)) {
LOG_E(NAS, "Can't reset PDP context\n");
return RETURNerror;
}
memset(&user->pdp_context[index], 0, sizeof(user->pdp_context[index]));
return RETURNok;
}
/* @brief Sets additional PDP context from user */
int nas_set_pdp_context(nas_user_t *user,
int index,
int pdu_session_type,
const char *dnn,
int ipv4_addr,
int emergency,
int p_cscf,
int im_cn_signal,
const char *nssai)
{
if (!((index > 0) && (index < MAX_PDP_CONTEXTS))) {
LOG_E(NAS, "Invalid index.\n"); // index 0 for default PDP
return RETURNerror;
} }
return -1; if (!dnn || !nssai) {
LOG_E(NAS, "No DNN or NSSAI config.\n");
return RETURNerror;
}
nr_nas_pdp_context_t *pdp_cxt = &user->pdp_context[index];
pdp_cxt->pdu_session_id = user->pdp_context[0].pdu_session_id + index;
pdp_cxt->pdu_session_type = 0x90 | (pdu_session_type & 0xf);
strcpy(pdp_cxt->nssaiStr, nssai);
parse_nssai_string(nssai, &pdp_cxt->nssai_sst, &pdp_cxt->nssai_sd);
pdp_cxt->is_defined = true;
memcpy(&pdp_cxt->dnn, dnn, strlen(dnn));
return RETURNok;
}
/* @brief Sets the first and default PDP context in NAS.
This is requested after registration. */
static void set_default_pdp_context(nr_ue_nas_t *nas)
{
nr_nas_pdp_context_t *pdp_cxt = &nas->nas_user->pdp_context[0];
pdp_cxt->pdu_session_id = get_softmodem_params()->default_pdu_session_id;
pdp_cxt->pdu_session_type = 0x91; // IPv4 (first octet: 0x01)
pdp_cxt->nssai_sd = nas->uicc->nssai_sd;
pdp_cxt->nssai_sst = nas->uicc->nssai_sst;
sprintf(pdp_cxt->nssaiStr, "%02d.%06d", pdp_cxt->nssai_sst, pdp_cxt->nssai_sd); /* used by AT get command */
pdp_cxt->is_defined = true;
memcpy(&pdp_cxt->dnn, nas->uicc->dnnStr, strlen(nas->uicc->dnnStr));
}
int nas_get_pdp_status(nas_user_t *user, int *index, int *status, int n_pdn_max)
{
int n_pdn = 0;
for (int i = 0; ((i < MAX_PDP_CONTEXTS) && (n_pdn < n_pdn_max)); i++) {
if (!user->pdp_context[i].is_defined)
continue;
*(index++) = i;
*(status++) = user->pdp_context[i].is_active;
n_pdn++;
}
return n_pdn;
}
int nas_get_pdp_contexts(nas_user_t *user, int *index, int *types, const char **apns, const char **nssai, int n_pdn_max)
{
int n_pdn = 0;
for (int i = 0; ((i < MAX_PDP_CONTEXTS) && (n_pdn < n_pdn_max)); i++) {
if (!user->pdp_context[i].is_defined)
continue;
*(index++) = i;
*(types++) = user->pdp_context[i].pdu_session_type;
*(apns++) = user->pdp_context[i].dnn;
*(nssai++) = user->pdp_context[i].nssaiStr;
n_pdn++;
}
return n_pdn;
}
int nas_get_pdp_range(nas_user_t *user)
{
return MAX_PDP_CONTEXTS;
} }
void *nas_nrue_task(void *args_p) void *nas_nrue_task(void *args_p)
...@@ -1059,6 +1194,9 @@ void *nas_nrue_task(void *args_p) ...@@ -1059,6 +1194,9 @@ void *nas_nrue_task(void *args_p)
softmodem_nas_info = *nas_info; softmodem_nas_info = *nas_info;
free(nas_info); free(nas_info);
nr_ue_nas.uicc = checkUicc(0); nr_ue_nas.uicc = checkUicc(0);
nas_user_t nas_user = {0};
nr_ue_nas.nas_user = &nas_user;
set_default_pdp_context(&nr_ue_nas);
while (1) { while (1) {
nas_nrue(NULL); nas_nrue(NULL);
} }
...@@ -1071,7 +1209,7 @@ static void handle_registration_accept(instance_t instance, ...@@ -1071,7 +1209,7 @@ static void handle_registration_accept(instance_t instance,
{ {
LOG_I(NAS, "[UE] Received REGISTRATION ACCEPT message\n"); LOG_I(NAS, "[UE] Received REGISTRATION ACCEPT message\n");
decodeRegistrationAccept(pdu_buffer, msg_length, nas); decodeRegistrationAccept(pdu_buffer, msg_length, nas);
get_allowed_nssai(nas_allowed_nssai, pdu_buffer, msg_length); get_allowed_nssai(nas->nas_allowed_nssai, pdu_buffer, msg_length);
as_nas_info_t initialNasMsg = {0}; as_nas_info_t initialNasMsg = {0};
generateRegistrationComplete(nas, &initialNasMsg, NULL); generateRegistrationComplete(nas, &initialNasMsg, NULL);
...@@ -1079,11 +1217,11 @@ static void handle_registration_accept(instance_t instance, ...@@ -1079,11 +1217,11 @@ static void handle_registration_accept(instance_t instance,
send_nas_uplink_data_req(instance, &initialNasMsg); send_nas_uplink_data_req(instance, &initialNasMsg);
LOG_I(NAS, "Send NAS_UPLINK_DATA_REQ message(RegistrationComplete)\n"); LOG_I(NAS, "Send NAS_UPLINK_DATA_REQ message(RegistrationComplete)\n");
} }
const int nssai_idx = get_user_nssai_idx(nas_allowed_nssai, nas); if (!valid_user_nssai(nas->nas_allowed_nssai, &nas->nas_user->pdp_context[0])) {
if (nssai_idx < 0) {
LOG_E(NAS, "NSSAI parameters not match with allowed NSSAI. Couldn't request PDU session.\n"); LOG_E(NAS, "NSSAI parameters not match with allowed NSSAI. Couldn't request PDU session.\n");
} else { } else {
request_default_pdusession(instance, nssai_idx); /* Default PDU session */
request_pdusession(&nas->nas_user->pdp_context[0], instance);
} }
} }
...@@ -1144,7 +1282,7 @@ void *nas_nrue(void *args_p) ...@@ -1144,7 +1282,7 @@ void *nas_nrue(void *args_p)
case NAS_PDU_SESSION_REQ: { case NAS_PDU_SESSION_REQ: {
as_nas_info_t pduEstablishMsg = {0}; as_nas_info_t pduEstablishMsg = {0};
nas_pdu_session_req_t *pduReq = &NAS_PDU_SESSION_REQ(msg_p); nr_nas_pdp_context_t *pduReq = &NAS_PDU_SESSION_REQ(msg_p);
nr_ue_nas_t *nas = get_ue_nas_info(0); nr_ue_nas_t *nas = get_ue_nas_info(0);
generatePduSessionEstablishRequest(nas, &pduEstablishMsg, pduReq); generatePduSessionEstablishRequest(nas, &pduEstablishMsg, pduReq);
if (pduEstablishMsg.length > 0) { if (pduEstablishMsg.length > 0) {
...@@ -1165,11 +1303,13 @@ void *nas_nrue(void *args_p) ...@@ -1165,11 +1303,13 @@ void *nas_nrue(void *args_p)
uint8_t *pdu_buffer = NAS_CONN_ESTABLI_CNF(msg_p).nasMsg.data; uint8_t *pdu_buffer = NAS_CONN_ESTABLI_CNF(msg_p).nasMsg.data;
int msg_type = get_msg_type(pdu_buffer, NAS_CONN_ESTABLI_CNF(msg_p).nasMsg.length); int msg_type = get_msg_type(pdu_buffer, NAS_CONN_ESTABLI_CNF(msg_p).nasMsg.length);
nr_ue_nas_t *nas = get_ue_nas_info(0);
if (msg_type == REGISTRATION_ACCEPT) { if (msg_type == REGISTRATION_ACCEPT) {
nr_ue_nas_t *nas = get_ue_nas_info(0);
handle_registration_accept(instance, nas, pdu_buffer, NAS_CONN_ESTABLI_CNF(msg_p).nasMsg.length); handle_registration_accept(instance, nas, pdu_buffer, NAS_CONN_ESTABLI_CNF(msg_p).nasMsg.length);
} else if (msg_type == FGS_PDU_SESSION_ESTABLISHMENT_ACC) { } else if (msg_type == FGS_PDU_SESSION_ESTABLISHMENT_ACC) {
capture_pdu_session_establishment_accept_msg(pdu_buffer, NAS_CONN_ESTABLI_CNF(msg_p).nasMsg.length); int pdu_session_id = -1;
capture_pdu_session_establishment_accept_msg(pdu_buffer, NAS_CONN_ESTABLI_CNF(msg_p).nasMsg.length, &pdu_session_id);
set_pdp_active_flag(nas, pdu_session_id, true);
} }
break; break;
...@@ -1312,8 +1452,8 @@ void *nas_nrue(void *args_p) ...@@ -1312,8 +1452,8 @@ void *nas_nrue(void *args_p)
case NAS_PDU_SESSION_REL: { case NAS_PDU_SESSION_REL: {
// TODO: Initiate PDU session release request & send NAS signal to network // TODO: Initiate PDU session release request & send NAS signal to network
nas_pdu_session_req_t *pdu_rel = &NAS_PDU_SESSION_REL(msg_p); nr_nas_pdp_context_t *pdu_rel = &NAS_PDU_SESSION_REL(msg_p);
nr_sdap_delete_entity(instance, pdu_rel->pdusession_id, true); nr_sdap_delete_entity(instance, pdu_rel->pdu_session_id, true);
break; break;
} }
...@@ -1327,3 +1467,52 @@ void *nas_nrue(void *args_p) ...@@ -1327,3 +1467,52 @@ void *nas_nrue(void *args_p)
} }
return NULL; return NULL;
} }
static void *nas_user_mngr(void *args)
{
user_api_id_t user_api = {0};
at_response_t atr = {0};
user_at_commands_t atc = {0};
if (user_api_initialize(&user_api, NULL, NULL, get_nrUE_params()->at_interface_name, "9600") != RETURNok) {
LOG_E(NAS, "Unable to initialize NAS user interface\n");
}
nas_user_t *nas_user = nr_ue_nas.nas_user;
nas_user->nas_ue_type = UE_NR;
nas_user->nas_reset_pdn = nas_reset_pdp_context;
nas_user->nas_get_pdn = nas_get_pdp_contexts;
nas_user->nas_set_pdn = nas_set_pdp_context;
nas_user->nas_get_pdn_range = nas_get_pdp_range;
nas_user->nas_deactivate_pdn = nas_request_pdu_release;
nas_user->nas_activate_pdn = nas_request_pdusession;
nas_user->nas_get_pdn_status = nas_get_pdp_status;
nas_user->user_api_id = &user_api;
nas_user->at_response = &atr;
nas_user->user_at_commands = &atc;
nas_user_context_t user_ctxt = {0};
const char *version = "v1.0";
nas_user_context_initialize(&user_ctxt, version);
user_ctxt.sim_status = NAS_USER_READY; /* set SIM ready by default */
nas_user->nas_user_context = &user_ctxt;
bool exit_loop = false;
int fd = user_api_get_fd(&user_api);
LOG_I(NAS, "User interface manager started with fd %d\n", fd);
while (!exit_loop) {
exit_loop = nas_user_receive_and_process(nr_ue_nas.nas_user, NULL);
}
user_api_close(nr_ue_nas.nas_user->user_api_id);
LOG_I(NAS, "User interface manager ended\n");
return NULL;
}
void nas_nrue_user(void *args_p)
{
pthread_t user_mngr;
threadCreate(&user_mngr, nas_user_mngr, NULL, "UE-nas", -1, OAI_PRIORITY_RT_LOW);
}
\ No newline at end of file
...@@ -42,6 +42,9 @@ ...@@ -42,6 +42,9 @@
#include "FGSUplinkNasTransport.h" #include "FGSUplinkNasTransport.h"
#include <openair3/UICC/usim_interface.h> #include <openair3/UICC/usim_interface.h>
#include "secu_defs.h" #include "secu_defs.h"
#include <openair3/NAS/UE/API/USER/user_api_defs.h>
#include "openair3/NAS/UE/API/USER/at_response.h"
#include "openair3/NAS/UE/user_defs.h"
#define PLAIN_5GS_MSG 0b0000 #define PLAIN_5GS_MSG 0b0000
#define INTEGRITY_PROTECTED 0b0001 #define INTEGRITY_PROTECTED 0b0001
...@@ -108,6 +111,8 @@ typedef struct { ...@@ -108,6 +111,8 @@ typedef struct {
stream_security_container_t *security_container; stream_security_container_t *security_container;
Guti5GSMobileIdentity_t *guti; Guti5GSMobileIdentity_t *guti;
bool termination_procedure; bool termination_procedure;
nr_nas_msg_snssai_t nas_allowed_nssai[8];
nas_user_t *nas_user;
} nr_ue_nas_t; } nr_ue_nas_t;
typedef enum fgs_protocol_discriminator_e { typedef enum fgs_protocol_discriminator_e {
...@@ -194,6 +199,7 @@ void generateRegistrationRequest(as_nas_info_t *initialNasMsg, nr_ue_nas_t *nas) ...@@ -194,6 +199,7 @@ void generateRegistrationRequest(as_nas_info_t *initialNasMsg, nr_ue_nas_t *nas)
void *nas_nrue_task(void *args_p); void *nas_nrue_task(void *args_p);
void *nas_nrue(void *args_p); void *nas_nrue(void *args_p);
void nr_ue_create_ip_if(const char *ifname, int ue_id, int pdu_session_id, bool ipv6, const uint8_t addr[IPV4V6_ADDR_LEN]); void nr_ue_create_ip_if(const char *ifname, int ue_id, int pdu_session_id, bool ipv6, const uint8_t addr[IPV4V6_ADDR_LEN]);
void nas_nrue_user(void *args_p);
#endif /* __NR_NAS_MSG_SIM_H__*/ #endif /* __NR_NAS_MSG_SIM_H__*/
......
...@@ -55,8 +55,8 @@ Description Defines the ATtention (AT) command set supported by the NAS ...@@ -55,8 +55,8 @@ Description Defines the ATtention (AT) command set supported by the NAS
/****************************************************************************/ /****************************************************************************/
// FIXME Put this in .h // FIXME Put this in .h
extern int at_response_format_v1; extern bool at_response_format_v1;
extern int at_error_code_suppression_q1; extern bool at_error_code_suppression_q1;
extern at_error_format_t at_error_format; extern at_error_format_t at_error_format;
/****************************************************************************/ /****************************************************************************/
...@@ -1512,7 +1512,11 @@ static int parse_cereg_test(const char* string, int position, at_command_t* at_c ...@@ -1512,7 +1512,11 @@ static int parse_cereg_test(const char* string, int position, at_command_t* at_c
static int parse_cgdcont_set(const char* string, int position, at_command_t* at_command) static int parse_cgdcont_set(const char* string, int position, at_command_t* at_command)
{ {
/* CGDCONT parameter command - Parameters [<cid>[,<PDP_type>[,<APN>[,<PDP_addr>[,<d_comp>[,<h_comp>[,<IPv4AddrAlloc>[,<emergency indication>[,<P-CSCF_discovery>[,<IM_CN_Signalling_Flag_Ind>]]]]]]]]]] */ /* CGDCONT parameter command - Parameters [<cid>[,<PDP_type>[,<APN>[,<PDP_addr>[,<d_comp>[,<h_comp>
[,<IPv4AddrAlloc>[,<request_type>[,<P-CSCF_discovery>[,<IM_CN_Signalling_Flag_Ind>[,<NSLPI>[,<securePCO>
[,<IPv4_MTU_discovery>[,<Local_Addr_Ind>[,<Non-IP_MTU_discovery>[,<Reliable_Data_Service>[,<SSC_mode>
[,<S-NSSAI>[,<Pref_access_type>]]]]]]]]]]]]]]]]]]]
*/
at_command->id = AT_CGDCONT; at_command->id = AT_CGDCONT;
unsigned char* parameter_start_index = (unsigned char*) string + position; unsigned char* parameter_start_index = (unsigned char*) string + position;
...@@ -1752,6 +1756,80 @@ static int parse_cgdcont_set(const char* string, int position, at_command_t* at_ ...@@ -1752,6 +1756,80 @@ static int parse_cgdcont_set(const char* string, int position, at_command_t* at_
AT_CGDCONT_EMERGECY_INDICATION_MASK | AT_CGDCONT_P_CSCF_DISCOVERY_MASK | AT_CGDCONT_IM_CN_SIGNALLING_FLAG_IND_MASK; AT_CGDCONT_EMERGECY_INDICATION_MASK | AT_CGDCONT_P_CSCF_DISCOVERY_MASK | AT_CGDCONT_IM_CN_SIGNALLING_FLAG_IND_MASK;
break; break;
case 19: /* <cid>,<PDP_type>,<APN>,<PDP_addr>,<d_comp>,<h_comp>
,<IPv4AddrAlloc>,<request_type>,<P-CSCF_discovery>,<IM_CN_Signalling_Flag_Ind>,<NSLPI>,<securePCO>
,<IPv4_MTU_discovery>,<Local_Addr_Ind>,<Non-IP_MTU_discovery>,<Reliable_Data_Service>,<SSC_mode>
,<S-NSSAI>,<Pref_access_type> are present */
if (ParseCommand(parameter_start_index,
"@i,@r,@r,@r,@I,@I,@I,@I,@I,@I,@I,@I,@I,@I,@I,@I,@I,@r,@I",
&at_command->command.cgdcont.cid,
&at_command->command.cgdcont.PDP_type,
AT_CGDCONT_PDP_SIZE,
&at_command->command.cgdcont.APN,
AT_CGDCONT_APN_SIZE,
&at_command->command.cgdcont.PDP_addr,
AT_CGDCONT_ADDR_SIZE,
&at_command->command.cgdcont.d_comp,
&at_command->command.cgdcont.h_comp,
&at_command->command.cgdcont.IPv4AddrAlloc,
&at_command->command.cgdcont.emergency_indication,
&at_command->command.cgdcont.P_CSCF_discovery,
&at_command->command.cgdcont.IM_CN_Signalling_Flag_Ind,
&at_command->command.cgdcont.nspli,
&at_command->command.cgdcont.secure_PCO,
&at_command->command.cgdcont.IPv4_MTU_discovery,
&at_command->command.cgdcont.Local_Addr_Ind,
&at_command->command.cgdcont.Non_IP_MTU_discovery,
&at_command->command.cgdcont.Reliable_Data_Service,
&at_command->command.cgdcont.SSC_mode,
&at_command->command.cgdcont.nssaiStr,
AT_CGDCONT_NSSAI_SIZE,
&at_command->command.cgdcont.Pref_access_type)
!= RETURNok) {
LOG_TRACE(ERROR,
"USR-API - Parsing of "
"AT+CGDCONT=<cid>,<PDP_type>,<APN>,<PDP_addr>,<d_comp>,<h_comp>,<IPv4AddrAlloc>,<request_type>,<P-CSCF_discovery>,<"
"IM_CN_Signalling_Flag_Ind>,<NSLPI>,<securePCO>,<IPv4_MTU_discovery>,<Local_Addr_Ind>,<Non-IP_MTU_discovery>,<"
"Reliable_Data_Service>,<SSC_mode>,<S-NSSAI>,<Pref_access_type> failed\n");
return RETURNerror;
}
LOG_TRACE(INFO,
"USR-API - Parsing of "
"AT+CGDCONT=<cid>,<PDP_type>,<APN>,<PDP_addr>,<d_comp>,<h_comp>,<IPv4AddrAlloc>,<request_type>,<P-CSCF_discovery>,<"
"IM_CN_Signalling_Flag_Ind>,<NSLPI>,<securePCO>,<IPv4_MTU_discovery>,<Local_Addr_Ind>,<Non-IP_MTU_discovery>,<"
"Reliable_Data_Service>,<SSC_mode>,<S-NSSAI>,<Pref_access_type> succeeded (cid:%d, PDP_type:%s ,APN:%s, PDP_addr:%s, "
"d_comp:%d, h_comp:%d, IPv4AddrAlloc:%d, request_type:%d, P-CSCF_discovery:%d, IM_CN_Signalling_Flag_Ind:%d, "
"NSLPI:%d, securePCO:%d, IPv4_MTU_discovery:%d, Local_Addr_Ind:%d, Non-IP_MTU_discovery:%d, "
"Reliable_Data_Service:%d, SSC_mode:%d, S-NSSAI:%s, Pref_access_type:%d)",
at_command->command.cgdcont.cid,
at_command->command.cgdcont.PDP_type,
at_command->command.cgdcont.APN,
at_command->command.cgdcont.PDP_addr,
at_command->command.cgdcont.d_comp,
at_command->command.cgdcont.h_comp,
at_command->command.cgdcont.IPv4AddrAlloc,
at_command->command.cgdcont.emergency_indication,
at_command->command.cgdcont.P_CSCF_discovery,
at_command->command.cgdcont.IM_CN_Signalling_Flag_Ind,
at_command->command.cgdcont.nspli,
at_command->command.cgdcont.secure_PCO,
at_command->command.cgdcont.IPv4_MTU_discovery,
at_command->command.cgdcont.Local_Addr_Ind,
at_command->command.cgdcont.Non_IP_MTU_discovery,
at_command->command.cgdcont.Reliable_Data_Service,
at_command->command.cgdcont.SSC_mode,
at_command->command.cgdcont.nssaiStr,
at_command->command.cgdcont.Pref_access_type);
at_command->mask = AT_CGDCONT_CID_MASK | AT_CGDCONT_PDP_TYPE_MASK | AT_CGDCONT_APN_MASK | AT_CGDCONT_PDP_ADDR_MASK
| AT_CGDCONT_D_COMP_MASK | AT_CGDCONT_H_COMP_MASK | AT_CGDCONT_IPV4ADDRALLOC_MASK
| AT_CGDCONT_EMERGECY_INDICATION_MASK | AT_CGDCONT_P_CSCF_DISCOVERY_MASK
| AT_CGDCONT_IM_CN_SIGNALLING_FLAG_IND_MASK | AT_CGDCONT_NSPLI | AT_CGDCONT_SECURE_PCO
| AT_CGDCONT_IPV4_MTU_DIS | AT_CGDCONT_LOCAL_ADDR_IND | AT_CGDCONT_NON_IP_MTU_DIS
| AT_CGDCONT_REL_DATA_SERVICE | AT_CGDCONT_SSC_MODE | AT_CGDCONT_NSSAI | AT_CGDCONT_PREF_ACCESS_TYPE;
break;
default: default:
LOG_TRACE(ERROR, "USR-API - Invalid number of parameters (%d)", number_of_parameters); LOG_TRACE(ERROR, "USR-API - Invalid number of parameters (%d)", number_of_parameters);
return RETURNerror; return RETURNerror;
......
...@@ -65,6 +65,9 @@ Description Defines the ATtention (AT) command set supported by the NAS ...@@ -65,6 +65,9 @@ Description Defines the ATtention (AT) command set supported by the NAS
#define AT_COMMAND_PARAM14 0x2000 /* 14th parameter is present */ #define AT_COMMAND_PARAM14 0x2000 /* 14th parameter is present */
#define AT_COMMAND_PARAM15 0x4000 /* 15th parameter is present */ #define AT_COMMAND_PARAM15 0x4000 /* 15th parameter is present */
#define AT_COMMAND_PARAM16 0x8000 /* 16th parameter is present */ #define AT_COMMAND_PARAM16 0x8000 /* 16th parameter is present */
#define AT_COMMAND_PARAM17 0x10000 /* 17th parameter is present */
#define AT_COMMAND_PARAM18 0x20000 /* 18th parameter is present */
#define AT_COMMAND_PARAM19 0x40000 /* 19th parameter is present */
/* Value of the mask parameter for AT commands without any parameters */ /* Value of the mask parameter for AT commands without any parameters */
#define AT_COMMAND_NO_PARAM AT_COMMAND_PARAM0 #define AT_COMMAND_NO_PARAM AT_COMMAND_PARAM0
...@@ -737,6 +740,15 @@ typedef struct { ...@@ -737,6 +740,15 @@ typedef struct {
#define AT_CGDCONT_EMERGECY_INDICATION_MASK AT_COMMAND_PARAM8 #define AT_CGDCONT_EMERGECY_INDICATION_MASK AT_COMMAND_PARAM8
#define AT_CGDCONT_P_CSCF_DISCOVERY_MASK AT_COMMAND_PARAM9 #define AT_CGDCONT_P_CSCF_DISCOVERY_MASK AT_COMMAND_PARAM9
#define AT_CGDCONT_IM_CN_SIGNALLING_FLAG_IND_MASK AT_COMMAND_PARAM10 #define AT_CGDCONT_IM_CN_SIGNALLING_FLAG_IND_MASK AT_COMMAND_PARAM10
#define AT_CGDCONT_NSPLI AT_COMMAND_PARAM11
#define AT_CGDCONT_SECURE_PCO AT_COMMAND_PARAM12
#define AT_CGDCONT_IPV4_MTU_DIS AT_COMMAND_PARAM13
#define AT_CGDCONT_LOCAL_ADDR_IND AT_COMMAND_PARAM14
#define AT_CGDCONT_NON_IP_MTU_DIS AT_COMMAND_PARAM15
#define AT_CGDCONT_REL_DATA_SERVICE AT_COMMAND_PARAM16
#define AT_CGDCONT_SSC_MODE AT_COMMAND_PARAM17
#define AT_CGDCONT_NSSAI AT_COMMAND_PARAM18
#define AT_CGDCONT_PREF_ACCESS_TYPE AT_COMMAND_PARAM19
/* CGDCONT AT command type */ /* CGDCONT AT command type */
typedef struct { typedef struct {
...@@ -754,6 +766,16 @@ typedef struct { ...@@ -754,6 +766,16 @@ typedef struct {
int emergency_indication; int emergency_indication;
int P_CSCF_discovery; int P_CSCF_discovery;
int IM_CN_Signalling_Flag_Ind; int IM_CN_Signalling_Flag_Ind;
int nspli;
int secure_PCO;
int IPv4_MTU_discovery;
int Local_Addr_Ind;
int Non_IP_MTU_discovery;
int Reliable_Data_Service;
int SSC_mode;
#define AT_CGDCONT_NSSAI_SIZE 16
char nssaiStr[AT_CGDCONT_NSSAI_SIZE];
int Pref_access_type;
} at_cgdcont_t; } at_cgdcont_t;
/* CGACT: PDP context activate or deactivate /* CGACT: PDP context activate or deactivate
......
...@@ -50,7 +50,7 @@ Description Defines error codes returned when execution of AT command ...@@ -50,7 +50,7 @@ Description Defines error codes returned when execution of AT command
/****************************************************************************/ /****************************************************************************/
// FIXME put this in .h // FIXME put this in .h
extern int at_response_format_v1; extern bool at_response_format_v1;
/* /*
* Result code suppression indicator (set by ATQ0 and ATQ1) * Result code suppression indicator (set by ATQ0 and ATQ1)
......
...@@ -951,8 +951,13 @@ static int _at_response_encode_cgdcont(char* buffer, const at_response_t* data) ...@@ -951,8 +951,13 @@ static int _at_response_encode_cgdcont(char* buffer, const at_response_t* data)
offset += sprintf(buffer+offset, ",%s", cgdcont->APN[i]); offset += sprintf(buffer+offset, ",%s", cgdcont->APN[i]);
/* No data/header compression */ /* No data/header compression */
offset += sprintf(buffer+offset, ",%u,%u\r\n", offset +=
(unsigned int)(AT_CGDCONT_D_COMP_OFF), (unsigned int)(AT_CGDCONT_H_COMP_OFF)); sprintf(buffer + offset, ",%u,%u", (unsigned int)(AT_CGDCONT_D_COMP_OFF), (unsigned int)(AT_CGDCONT_H_COMP_OFF));
offset += sprintf(buffer + offset, ",,,,,,,,,,,"); /* Currently unused parameters */
/* NSSAI */
offset += sprintf(buffer + offset, ",%s", cgdcont->nssaiStr[i]);
/* Preferred access type */
offset += sprintf(buffer + offset, ",\r\n");
} }
} else if (data->type == AT_COMMAND_TST) { } else if (data->type == AT_COMMAND_TST) {
const at_cgdcont_tst_t * cgdcont = &(data->response.cgdcont.tst); const at_cgdcont_tst_t * cgdcont = &(data->response.cgdcont.tst);
......
...@@ -641,6 +641,19 @@ typedef struct { ...@@ -641,6 +641,19 @@ typedef struct {
const char* APN[AT_CGDCONT_RESP_SIZE]; const char* APN[AT_CGDCONT_RESP_SIZE];
int d_comp[AT_CGDCONT_RESP_SIZE]; int d_comp[AT_CGDCONT_RESP_SIZE];
int h_comp[AT_CGDCONT_RESP_SIZE]; int h_comp[AT_CGDCONT_RESP_SIZE];
int IPv4AddrAlloc[AT_CGDCONT_RESP_SIZE];
int emergency_indication[AT_CGDCONT_RESP_SIZE];
int P_CSCF_discovery[AT_CGDCONT_RESP_SIZE];
int IM_CN_Signalling_Flag_Ind[AT_CGDCONT_RESP_SIZE];
int nspli[AT_CGDCONT_RESP_SIZE];
int secure_PCO[AT_CGDCONT_RESP_SIZE];
int IPv4_MTU_discovery[AT_CGDCONT_RESP_SIZE];
int Local_Addr_Ind[AT_CGDCONT_RESP_SIZE];
int Non_IP_MTU_discovery[AT_CGDCONT_RESP_SIZE];
int Reliable_Data_Service[AT_CGDCONT_RESP_SIZE];
int SSC_mode[AT_CGDCONT_RESP_SIZE];
const char* nssaiStr[AT_CGDCONT_RESP_SIZE];
int Pref_access_type[AT_CGDCONT_RESP_SIZE];
} at_cgdcont_get_t; } at_cgdcont_get_t;
/* Structure of CGDCONT AT read parameter command */ /* Structure of CGDCONT AT read parameter command */
......
...@@ -106,6 +106,15 @@ void nas_proc_initialize(nas_user_t *user, emm_indication_callback_t emm_cb, ...@@ -106,6 +106,15 @@ void nas_proc_initialize(nas_user_t *user, emm_indication_callback_t emm_cb,
/* Initialize the ESM procedure manager */ /* Initialize the ESM procedure manager */
esm_main_initialize(user, esm_cb); esm_main_initialize(user, esm_cb);
AssertFatal(user->nas_ue_type != UE_NR, "Wrong UE type\n");
user->nas_reset_pdn = nas_proc_reset_pdn;
user->nas_set_pdn = nas_proc_set_pdn;
user->nas_get_pdn = nas_proc_get_pdn_param;
user->nas_get_pdn_range = nas_proc_get_pdn_range;
user->nas_deactivate_pdn = nas_proc_deactivate_pdn;
user->nas_activate_pdn = nas_proc_activate_pdn;
user->nas_get_pdn_status = nas_proc_get_pdn_status;
LOG_FUNC_OUT; LOG_FUNC_OUT;
} }
...@@ -652,11 +661,11 @@ bool nas_proc_get_attach_status(nas_user_t *user) ...@@ -652,11 +661,11 @@ bool nas_proc_get_attach_status(nas_user_t *user)
** Others: None ** ** Others: None **
** ** ** **
***************************************************************************/ ***************************************************************************/
int nas_proc_get_pdn_range(esm_data_t *esm_data) int nas_proc_get_pdn_range(nas_user_t *user)
{ {
LOG_FUNC_IN; LOG_FUNC_IN;
int max_pdn_id = esm_main_get_nb_pdns_max(esm_data); int max_pdn_id = esm_main_get_nb_pdns_max(user->esm_data);
LOG_FUNC_RETURN (max_pdn_id); LOG_FUNC_RETURN (max_pdn_id);
} }
...@@ -721,13 +730,13 @@ int nas_proc_get_pdn_status(nas_user_t *user, int *cids, int *states, int n_pdn_ ...@@ -721,13 +730,13 @@ int nas_proc_get_pdn_status(nas_user_t *user, int *cids, int *states, int n_pdn_
** Others: None ** ** Others: None **
** ** ** **
***************************************************************************/ ***************************************************************************/
int nas_proc_get_pdn_param(esm_data_t *esm_data, int *cids, int *types, const char **apns, int nas_proc_get_pdn_param(nas_user_t *user, int *cids, int *types, const char **apns, const char **nssai, int n_pdn_max)
int n_pdn_max)
{ {
LOG_FUNC_IN; LOG_FUNC_IN;
int cid; int cid;
int n_defined_pdn = 0; int n_defined_pdn = 0;
esm_data_t *esm_data = user->esm_data;
/* Get the maximum number of supported PDN contexts */ /* Get the maximum number of supported PDN contexts */
int n_pdn = esm_main_get_nb_pdns_max(esm_data); int n_pdn = esm_main_get_nb_pdns_max(esm_data);
...@@ -836,9 +845,20 @@ int nas_proc_get_pdn_addr(nas_user_t *user, int cid, int *cids, const char **add ...@@ -836,9 +845,20 @@ int nas_proc_get_pdn_addr(nas_user_t *user, int cid, int *cids, const char **add
** Others: None ** ** Others: None **
** ** ** **
***************************************************************************/ ***************************************************************************/
int nas_proc_set_pdn(nas_user_t *user, int cid, int type, const char *apn, int ipv4_addr, int nas_proc_set_pdn(nas_user_t *user,
int emergency, int p_cscf, int im_cn_signal) int cid,
int type,
const char *apn,
int ipv4_addr,
int emergency,
int p_cscf,
int im_cn_signal,
const char *nssai)
{ {
if (user->nas_ue_type != UE_LTE || nssai != NULL) {
LOG_TRACE(ERROR, "NSSAI is an unvalid parameter for LTE\n");
return RETURNerror;
}
LOG_FUNC_IN; LOG_FUNC_IN;
int rc; int rc;
......
...@@ -95,12 +95,18 @@ int nas_proc_attach(nas_user_t *user); ...@@ -95,12 +95,18 @@ int nas_proc_attach(nas_user_t *user);
bool nas_proc_get_attach_status(nas_user_t *user); bool nas_proc_get_attach_status(nas_user_t *user);
int nas_proc_reset_pdn(nas_user_t *user, int cid); int nas_proc_reset_pdn(nas_user_t *user, int cid);
int nas_proc_set_pdn(nas_user_t *user, int cid, int type, const char *apn, int ipv4_addr, int nas_proc_set_pdn(nas_user_t *user,
int emergency, int p_cscf, int im_cn_signal); int cid,
int nas_proc_get_pdn_range(esm_data_t *esm_data); int type,
const char *apn,
int ipv4_addr,
int emergency,
int p_cscf,
int im_cn_signal,
const char *nssai);
int nas_proc_get_pdn_range(nas_user_t *user);
int nas_proc_get_pdn_status(nas_user_t *user, int *cids, int *states, int n_pdn_max); int nas_proc_get_pdn_status(nas_user_t *user, int *cids, int *states, int n_pdn_max);
int nas_proc_get_pdn_param(esm_data_t *esm_data, int *cids, int *types, const char **apns, int nas_proc_get_pdn_param(nas_user_t *user, int *cids, int *types, const char **apns, const char **nssai, int n_pdn_max);
int n_pdn_max);
int nas_proc_get_pdn_addr(nas_user_t *user, int cid, int *cids, const char **addr1, int nas_proc_get_pdn_addr(nas_user_t *user, int cid, int *cids, const char **addr1,
const char **addr2, int n_addr_max); const char **addr2, int n_addr_max);
int nas_proc_deactivate_pdn(nas_user_t *user, int cid); int nas_proc_deactivate_pdn(nas_user_t *user, int cid);
......
...@@ -134,6 +134,7 @@ void *nas_ue_task(void *args_p) ...@@ -134,6 +134,7 @@ void *nas_ue_task(void *args_p)
user->at_response = calloc_or_fail(1, sizeof(at_response_t)); user->at_response = calloc_or_fail(1, sizeof(at_response_t));
user->lowerlayer_data = calloc_or_fail(1, sizeof(lowerlayer_data_t)); user->lowerlayer_data = calloc_or_fail(1, sizeof(lowerlayer_data_t));
/* Initialize NAS user */ /* Initialize NAS user */
user->nas_ue_type = UE_LTE;
nas_user_initialize(user, &user_api_emm_callback, &user_api_esm_callback, FIRMWARE_VERSION); nas_user_initialize(user, &user_api_emm_callback, &user_api_esm_callback, FIRMWARE_VERSION);
} }
} }
...@@ -174,6 +175,7 @@ void *nas_ue_task(void *args_p) ...@@ -174,6 +175,7 @@ void *nas_ue_task(void *args_p)
user->at_response = calloc_or_fail(1, sizeof(at_response_t)); user->at_response = calloc_or_fail(1, sizeof(at_response_t));
user->lowerlayer_data = calloc_or_fail(1, sizeof(lowerlayer_data_t)); user->lowerlayer_data = calloc_or_fail(1, sizeof(lowerlayer_data_t));
/* Initialize NAS user */ /* Initialize NAS user */
user->nas_ue_type = UE_LTE;
nas_user_initialize(user, &user_api_emm_callback, &user_api_esm_callback, FIRMWARE_VERSION); nas_user_initialize(user, &user_api_emm_callback, &user_api_esm_callback, FIRMWARE_VERSION);
user->ueid = 0; user->ueid = 0;
} }
......
...@@ -53,6 +53,8 @@ Description NAS procedure functions triggered by the user ...@@ -53,6 +53,8 @@ Description NAS procedure functions triggered by the user
#include <string.h> // memset, strncpy, strncmp #include <string.h> // memset, strncpy, strncmp
#include <stdlib.h> // free #include <stdlib.h> // free
#include "openair3/NAS/NR_UE/nr_nas_msg_sim.h"
/****************************************************************************/ /****************************************************************************/
/**************** E X T E R N A L D E F I N I T I O N S ****************/ /**************** E X T E R N A L D E F I N I T I O N S ****************/
/****************************************************************************/ /****************************************************************************/
...@@ -128,7 +130,8 @@ static const char *const _nas_user_sim_status_str[] = {"READY", "SIM PIN", "SIM ...@@ -128,7 +130,8 @@ static const char *const _nas_user_sim_status_str[] = {"READY", "SIM PIN", "SIM
/****************** E X P O R T E D F U N C T I O N S ******************/ /****************** E X P O R T E D F U N C T I O N S ******************/
/****************************************************************************/ /****************************************************************************/
void _nas_user_context_initialize(nas_user_context_t *nas_user_context, const char *version) { void nas_user_context_initialize(nas_user_context_t *nas_user_context, const char *version)
{
nas_user_context->version = version; nas_user_context->version = version;
nas_user_context->sim_status = NAS_USER_SIM_PIN; nas_user_context->sim_status = NAS_USER_SIM_PIN;
nas_user_context->fun = AT_CFUN_FUN_DEFAULT; nas_user_context->fun = AT_CFUN_FUN_DEFAULT;
...@@ -164,7 +167,7 @@ void nas_user_initialize(nas_user_t *user, emm_indication_callback_t emm_cb, ...@@ -164,7 +167,7 @@ void nas_user_initialize(nas_user_t *user, emm_indication_callback_t emm_cb,
} }
user->nas_user_context = calloc_or_fail(1, sizeof(nas_user_context_t)); user->nas_user_context = calloc_or_fail(1, sizeof(nas_user_context_t));
_nas_user_context_initialize(user->nas_user_context, version); nas_user_context_initialize(user->nas_user_context, version);
/* Initialize the internal NAS processing data */ /* Initialize the internal NAS processing data */
nas_proc_initialize(user, emm_cb, esm_cb, user->nas_user_nvdata->IMEI); nas_proc_initialize(user, emm_cb, esm_cb, user->nas_user_nvdata->IMEI);
...@@ -201,6 +204,7 @@ bool nas_user_receive_and_process(nas_user_t *user, char *message) ...@@ -201,6 +204,7 @@ bool nas_user_receive_and_process(nas_user_t *user, char *message)
} else { } else {
/* Read the user data message */ /* Read the user data message */
bytes = user_api_read_data (user_api_id); bytes = user_api_read_data (user_api_id);
LOG_TRACE(INFO, "%d bytes read\n", bytes);
if (bytes == RETURNerror) { if (bytes == RETURNerror) {
/* Failed to read data from the user application layer; /* Failed to read data from the user application layer;
...@@ -1816,6 +1820,7 @@ static int _nas_user_proc_cgdcont(nas_user_t *user, const at_command_t *data) ...@@ -1816,6 +1820,7 @@ static int _nas_user_proc_cgdcont(nas_user_t *user, const at_command_t *data)
int emergency = AT_CGDCONT_EBS_DEFAULT; int emergency = AT_CGDCONT_EBS_DEFAULT;
int p_cscf = AT_CGDCONT_PCSCF_DEFAULT; int p_cscf = AT_CGDCONT_PCSCF_DEFAULT;
int im_cn_signalling = AT_CGDCONT_IM_CM_DEFAULT; int im_cn_signalling = AT_CGDCONT_IM_CM_DEFAULT;
const char *nssai = NULL;
bool reset_pdn = true; bool reset_pdn = true;
at_response->id = data->id; at_response->id = data->id;
...@@ -1967,18 +1972,20 @@ static int _nas_user_proc_cgdcont(nas_user_t *user, const at_command_t *data) ...@@ -1967,18 +1972,20 @@ static int _nas_user_proc_cgdcont(nas_user_t *user, const at_command_t *data)
im_cn_signalling = data->command.cgdcont.IM_CN_Signalling_Flag_Ind; im_cn_signalling = data->command.cgdcont.IM_CN_Signalling_Flag_Ind;
} }
if (data->mask & AT_CGDCONT_NSSAI) {
nssai = data->command.cgdcont.nssaiStr;
}
/* /*
* Setup PDN context * Setup PDN context
*/ */
if (reset_pdn) { if (reset_pdn) {
/* A special form of the set command, +CGDCONT=<cid> causes /* A special form of the set command, +CGDCONT=<cid> causes
* the values for context number <cid> to become undefined */ * the values for context number <cid> to become undefined */
ret_code = nas_proc_reset_pdn(user, cid); ret_code = user->nas_reset_pdn(user, cid);
} else { } else {
/* Define a new PDN connection */ /* Define a new PDN connection */
ret_code = nas_proc_set_pdn(user, cid, pdn_type, apn, ret_code = user->nas_set_pdn(user, cid, pdn_type, apn, ipv4_addr_allocation, emergency, p_cscf, im_cn_signalling, nssai);
ipv4_addr_allocation, emergency,
p_cscf, im_cn_signalling);
} }
if (ret_code != RETURNok) { if (ret_code != RETURNok) {
...@@ -1994,10 +2001,8 @@ static int _nas_user_proc_cgdcont(nas_user_t *user, const at_command_t *data) ...@@ -1994,10 +2001,8 @@ static int _nas_user_proc_cgdcont(nas_user_t *user, const at_command_t *data)
* Read command returns the current settings for each * Read command returns the current settings for each
* defined PDN connection/default EPS bearer context * defined PDN connection/default EPS bearer context
*/ */
cgdcont->n_pdns = nas_proc_get_pdn_param(user->esm_data, cgdcont->cid, cgdcont->n_pdns =
cgdcont->PDP_type, user->nas_get_pdn(user, cgdcont->cid, cgdcont->PDP_type, cgdcont->APN, cgdcont->nssaiStr, AT_CGDCONT_RESP_SIZE);
cgdcont->APN,
AT_CGDCONT_RESP_SIZE);
if (cgdcont->n_pdns == 0) { if (cgdcont->n_pdns == 0) {
LOG_TRACE(ERROR, "USR-MAIN - No any PDN context is defined"); LOG_TRACE(ERROR, "USR-MAIN - No any PDN context is defined");
...@@ -2012,7 +2017,7 @@ static int _nas_user_proc_cgdcont(nas_user_t *user, const at_command_t *data) ...@@ -2012,7 +2017,7 @@ static int _nas_user_proc_cgdcont(nas_user_t *user, const at_command_t *data)
*/ */
{ {
/* Get the maximum value of a PDN context identifier */ /* Get the maximum value of a PDN context identifier */
int cid_max = nas_proc_get_pdn_range(user->esm_data); int cid_max = user->nas_get_pdn_range(user);
if (cid_max > AT_CGDCONT_RESP_SIZE) { if (cid_max > AT_CGDCONT_RESP_SIZE) {
/* The range is defined by the user interface */ /* The range is defined by the user interface */
...@@ -2115,9 +2120,9 @@ static int _nas_user_proc_cgact(nas_user_t *user, const at_command_t *data) ...@@ -2115,9 +2120,9 @@ static int _nas_user_proc_cgact(nas_user_t *user, const at_command_t *data)
ret_code = RETURNerror; ret_code = RETURNerror;
if (state == AT_CGACT_DEACTIVATED) { if (state == AT_CGACT_DEACTIVATED) {
ret_code = nas_proc_deactivate_pdn(user, cid); ret_code = user->nas_deactivate_pdn(user, cid);
} else if (state == AT_CGACT_ACTIVATED) { } else if (state == AT_CGACT_ACTIVATED) {
ret_code = nas_proc_activate_pdn(user, cid); ret_code = user->nas_activate_pdn(user, cid);
} }
if (ret_code != RETURNok) { if (ret_code != RETURNok) {
...@@ -2135,8 +2140,7 @@ static int _nas_user_proc_cgact(nas_user_t *user, const at_command_t *data) ...@@ -2135,8 +2140,7 @@ static int _nas_user_proc_cgact(nas_user_t *user, const at_command_t *data)
* The read command returns the current activation states for * The read command returns the current activation states for
* all the defined PDN/EPS bearer contexts * all the defined PDN/EPS bearer contexts
*/ */
cgact->n_pdns = nas_proc_get_pdn_status(user, cgact->cid, cgact->state, cgact->n_pdns = user->nas_get_pdn_status(user, cgact->cid, cgact->state, AT_CGACT_RESP_SIZE);
AT_CGACT_RESP_SIZE);
if (cgact->n_pdns == 0) { if (cgact->n_pdns == 0) {
LOG_TRACE(ERROR, "USR-MAIN - No any PDN context is defined"); LOG_TRACE(ERROR, "USR-MAIN - No any PDN context is defined");
......
...@@ -43,6 +43,7 @@ Description NAS procedure functions triggered by the user ...@@ -43,6 +43,7 @@ Description NAS procedure functions triggered by the user
#include "emm_main.h" #include "emm_main.h"
#include "esm_ebr.h" #include "esm_ebr.h"
#include "user_defs.h" #include "user_defs.h"
#include "openair3/NAS/NR_UE/nr_nas_msg_sim.h"
/****************************************************************************/ /****************************************************************************/
/********************* G L O B A L C O N S T A N T S *******************/ /********************* G L O B A L C O N S T A N T S *******************/
...@@ -69,4 +70,6 @@ int nas_user_process_data(nas_user_t *user, const void *data); ...@@ -69,4 +70,6 @@ int nas_user_process_data(nas_user_t *user, const void *data);
const void *nas_user_get_data(nas_user_t *nas_user); const void *nas_user_get_data(nas_user_t *nas_user);
void nas_user_context_initialize(nas_user_context_t *nas_user_context, const char *version);
#endif /* __NAS_USER_H__*/ #endif /* __NAS_USER_H__*/
...@@ -51,8 +51,18 @@ Description NAS type definition to manage a user equipment ...@@ -51,8 +51,18 @@ Description NAS type definition to manage a user equipment
#include "SecurityModeControl.h" #include "SecurityModeControl.h"
#include "userDef.h" #include "userDef.h"
#include "at_response.h" #include "at_response.h"
#include "as_message.h"
typedef struct { enum ue_type {
UE_LTE,
UE_NR,
};
#define MAX_PDP_CONTEXTS 8
struct nas_user_s;
typedef struct nas_user_s {
int ueid; /* UE lower layer identifier */ int ueid; /* UE lower layer identifier */
proc_data_t proc; proc_data_t proc;
// Eps Session Management // Eps Session Management
...@@ -79,6 +89,23 @@ typedef struct { ...@@ -79,6 +89,23 @@ typedef struct {
user_at_commands_t *user_at_commands; //decoded data received from the user application layer user_at_commands_t *user_at_commands; //decoded data received from the user application layer
user_api_id_t *user_api_id; user_api_id_t *user_api_id;
lowerlayer_data_t *lowerlayer_data; lowerlayer_data_t *lowerlayer_data;
enum ue_type nas_ue_type;
nr_nas_pdp_context_t pdp_context[MAX_PDP_CONTEXTS];
int (*nas_reset_pdn)(struct nas_user_s *user, int cid);
int (*nas_set_pdn)(struct nas_user_s *user,
int cid,
int type,
const char *apn,
int ipv4_addr,
int emergency,
int p_cscf,
int im_cn_signal,
const char *nssai);
int (*nas_get_pdn)(struct nas_user_s *user, int *cids, int *types, const char **apns, const char **nssai, int n_pdn_max);
int (*nas_get_pdn_range)(struct nas_user_s *user);
int (*nas_deactivate_pdn)(struct nas_user_s *user, int cid);
int (*nas_activate_pdn)(struct nas_user_s *user, int cid);
int (*nas_get_pdn_status)(struct nas_user_s *user, int *cid, int *status, int n_pdn_max);
} nas_user_t; } nas_user_t;
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment