Commit 35026346 authored by Guido Casati's avatar Guido Casati

Refactor processing of sdap_Config in add_drb (PDCP)

* use get_sdap_Config to process sdap_Config
* move SDAP config logic to the scope where it is relevant
* add SDAP entity direcly in RRC, not from PDCP
* replaced nr_pdcp_add_drbs with single add_drb call: it was no longer
  efficient to keep it in the new logic. The addMod list can be looped directly in RRC.
* add specific function to add bearers from addMod list in E1, NSA, and UE
parent 70d23e43
......@@ -325,7 +325,7 @@ The PDCP implementation is secured by a general mutex, akin to the design of the
Initialization of the PDCP layer follows a structure similar to that of the RLC layer. The function `nr_pdcp_layer_init()` initializes PDCP, while a second initialization function, `pdcp_module_init()`, must also be invoked.
To manage UE connections, `nr_pdcp_add_srbs()` is employed for adding UE SRBs in PDCP, while `nr_pdcp_remove_UE()` is used for their removal. Similarly, `nr_pdcp_add_drbs()` adds UE DRBs in PDCP, with `nr_pdcp_remove_UE()` handling their removal.
To manage UE connections, `nr_pdcp_add_srbs()` is employed for adding UE SRBs in PDCP, while `nr_pdcp_remove_UE()` is used for their removal. Similarly, `add_drb()` adds UE DRB in PDCP, with `nr_pdcp_remove_UE()` handling their removal.
## PDCP Tx flow
......
......@@ -141,6 +141,24 @@ static instance_t get_f1_gtp_instance(void)
return inst->gtpInst;
}
/** @brief Add bearer in PDCP/SDAP for 5GC association (SA) */
static void e1_add_bearers(const int ue_id, const NR_DRB_ToAddModList_t *addMod, const nr_pdcp_entity_security_keys_and_algos_t *sp)
{
for (int i = 0; i < addMod->list.count; i++) {
NR_DRB_ToAddMod_t *drb = addMod->list.array[i];
DevAssert(drb->cnAssociation);
DevAssert(drb->cnAssociation->present != NR_DRB_ToAddMod__cnAssociation_PR_NOTHING);
DevAssert(drb->cnAssociation->present == NR_DRB_ToAddMod__cnAssociation_PR_sdap_Config);
DevAssert(drb->cnAssociation->choice.sdap_Config);
// get SDAP config
sdap_config_t sdap = nr_sdap_get_config(GNB_FLAG_YES, drb->cnAssociation->choice.sdap_Config, drb->drb_Identity);
// add SDAP entity
new_nr_sdap_entity(GNB_FLAG_YES, ue_id, sdap);
// add PDCP entity
add_drb(GNB_FLAG_YES, ue_id, drb->pdcp_Config, &sdap, sp);
}
}
void e1_bearer_context_setup(const e1ap_bearer_setup_req_t *req)
{
bool need_ue_id_mgmt = e1_used();
......@@ -208,11 +226,10 @@ void e1_bearer_context_setup(const e1ap_bearer_setup_req_t *req)
security_parameters.integrity_algorithm = req->secInfo.integrityProtectionAlgorithm;
memcpy(security_parameters.ciphering_key, req->secInfo.encryptionKey, NR_K_KEY_SIZE);
memcpy(security_parameters.integrity_key, req->secInfo.integrityProtectionKey, NR_K_KEY_SIZE);
nr_pdcp_add_drbs(true, // set this to notify PDCP that his not UE
cu_up_ue_id,
&DRB_configList,
&security_parameters);
e1_add_bearers(cu_up_ue_id, &DRB_configList, &security_parameters);
ASN_STRUCT_RESET(asn_DEF_NR_DRB_ToAddModList, &DRB_configList.list);
if (f1inst >= 0) { /* we have F1(-U) */
teid_t dummy_teid = 0xffff; // we will update later with answer from DU
in_addr_t dummy_address = {0}; // IPv4, updated later with answer from DU
......
......@@ -576,74 +576,31 @@ void add_srb(int is_gnb,
}
void add_drb(int is_gnb,
ue_id_t UEid,
struct NR_DRB_ToAddMod *s,
const ue_id_t UEid,
const NR_PDCP_Config_t *pdcp,
sdap_config_t *sdap,
const nr_pdcp_entity_security_keys_and_algos_t *security_parameters)
{
nr_pdcp_entity_t *pdcp_drb;
nr_pdcp_ue_t *ue;
int drb_id = s->drb_Identity;
if (!s->pdcp_Config || !s->pdcp_Config->drb) {
LOG_E(PDCP, "DRB field mandatory present at setup. DRB %d not configured.\n", drb_id);
if (!pdcp->drb) {
LOG_E(PDCP, "Missing PDCP config. DRB %d not configured.\n", sdap->drb_id);
return;
}
struct NR_PDCP_Config__drb *drb = s->pdcp_Config->drb;
struct NR_PDCP_Config__drb *drb = pdcp->drb;
int sn_size_ul = decode_sn_size_ul(*drb->pdcp_SN_SizeUL);
int sn_size_dl = decode_sn_size_dl(*drb->pdcp_SN_SizeDL);
int discard_timer = decode_discard_timer(*drb->discardTimer);
int has_integrity;
int has_ciphering;
/* if pdcp_Config->t_Reordering is not present, it means infinity (-1) */
int t_reordering = -1;
if (s->pdcp_Config->t_Reordering != NULL) {
t_reordering = decode_t_reordering(*s->pdcp_Config->t_Reordering);
}
if (drb->integrityProtection != NULL)
has_integrity = 1;
else
has_integrity = 0;
if (s->pdcp_Config->ext1 != NULL && s->pdcp_Config->ext1->cipheringDisabled != NULL)
has_ciphering = 0;
else
has_ciphering = 1;
if ((!s->cnAssociation) || s->cnAssociation->present == NR_DRB_ToAddMod__cnAssociation_PR_NOTHING) {
LOG_E(PDCP, "fatal, cnAssociation is missing or present is NR_DRB_ToAddMod__cnAssociation_PR_NOTHING\n");
exit(-1);
if (pdcp->t_Reordering != NULL) {
t_reordering = decode_t_reordering(*pdcp->t_Reordering);
}
int pdusession_id;
bool has_sdap_rx = false;
bool has_sdap_tx = false;
bool is_sdap_DefaultDRB = false;
NR_QFI_t *mappedQFIs2Add = NULL;
uint8_t mappedQFIs2AddCount=0;
if (s->cnAssociation->present == NR_DRB_ToAddMod__cnAssociation_PR_eps_BearerIdentity)
pdusession_id = s->cnAssociation->choice.eps_BearerIdentity;
else {
if (!s->cnAssociation->choice.sdap_Config) {
LOG_E(PDCP,"fatal, sdap_Config is null");
exit(-1);
}
pdusession_id = s->cnAssociation->choice.sdap_Config->pdu_Session;
has_sdap_rx = is_sdap_rx(is_gnb, s->cnAssociation->choice.sdap_Config);
has_sdap_tx = is_sdap_tx(is_gnb, s->cnAssociation->choice.sdap_Config);
is_sdap_DefaultDRB = s->cnAssociation->choice.sdap_Config->defaultDRB == true ? 1 : 0;
mappedQFIs2Add = (NR_QFI_t*)s->cnAssociation->choice.sdap_Config->mappedQoS_FlowsToAdd->list.array[0];
mappedQFIs2AddCount = s->cnAssociation->choice.sdap_Config->mappedQoS_FlowsToAdd->list.count;
LOG_D(SDAP, "Captured mappedQoS_FlowsToAdd from RRC: %ld \n", *mappedQFIs2Add);
}
/* TODO(?): accept different UL and DL SN sizes? */
if (sn_size_ul != sn_size_dl) {
LOG_E(PDCP, "fatal, bad SN sizes, must be same. ul=%d, dl=%d\n", sn_size_ul, sn_size_dl);
exit(1);
}
int has_integrity = (drb->integrityProtection != NULL) ? 1 : 0;
int has_ciphering = (pdcp->ext1 != NULL && pdcp->ext1->cipheringDisabled != NULL) ? 0 : 1;
/* get actual ciphering and integrity algorithm based on pdcp_Config */
nr_pdcp_entity_security_keys_and_algos_t actual_security_parameters = *security_parameters;
......@@ -652,29 +609,33 @@ void add_drb(int is_gnb,
nr_pdcp_manager_lock(nr_pdcp_ue_manager);
ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, UEid);
if (nr_pdcp_get_rb(ue, drb_id, false) != NULL) {
LOG_W(PDCP, "warning DRB %d already exist for UE ID %ld, do nothing\n", drb_id, UEid);
if (nr_pdcp_get_rb(ue, sdap->drb_id, false) != NULL) {
LOG_W(PDCP, "warning DRB %d already exist for UE ID %ld, do nothing\n", sdap->drb_id, UEid);
} else {
pdcp_drb = new_nr_pdcp_entity(NR_PDCP_DRB_AM, is_gnb, drb_id, pdusession_id,
has_sdap_rx, has_sdap_tx, deliver_sdu_drb, ue,
is_gnb ?
deliver_pdu_drb_gnb : deliver_pdu_drb_ue,
ue,
sn_size_dl, t_reordering, discard_timer,
&actual_security_parameters);
nr_pdcp_ue_add_drb_pdcp_entity(ue, drb_id, pdcp_drb);
LOG_I(PDCP, "added drb %d to UE ID %ld\n", drb_id, UEid);
/* add new SDAP entity for the PDU session the DRB belongs to */
new_nr_sdap_entity(is_gnb,
has_sdap_rx,
has_sdap_tx,
UEid,
pdusession_id,
is_sdap_DefaultDRB,
drb_id,
mappedQFIs2Add,
mappedQFIs2AddCount);
// code assumption: same SN size for both DL and UL
if (sn_size_ul != sn_size_dl) {
LOG_E(PDCP, "fatal, bad SN sizes, must be same. ul=%d, dl=%d\n", sn_size_ul, sn_size_dl);
exit(1);
}
// add PDCP entity
nr_pdcp_entity_t *pdcp_drb = new_nr_pdcp_entity(NR_PDCP_DRB_AM,
is_gnb,
sdap->drb_id,
sdap->pdusession_id,
sdap->sdap_rx,
sdap->sdap_tx,
deliver_sdu_drb,
ue,
is_gnb ? deliver_pdu_drb_gnb : deliver_pdu_drb_ue,
ue,
sn_size_dl,
t_reordering,
discard_timer,
&actual_security_parameters);
nr_pdcp_ue_add_drb_pdcp_entity(ue, sdap->drb_id, pdcp_drb);
LOG_I(PDCP, "Added DRB %d to UE ID %ld\n", sdap->drb_id, UEid);
}
nr_pdcp_manager_unlock(nr_pdcp_ue_manager);
}
......@@ -692,22 +653,6 @@ void nr_pdcp_add_srbs(eNB_flag_t enb_flag,
LOG_W(PDCP, "nr_pdcp_add_srbs() with void list\n");
}
void nr_pdcp_add_drbs(eNB_flag_t enb_flag,
ue_id_t UEid,
NR_DRB_ToAddModList_t *const drb2add_list,
const nr_pdcp_entity_security_keys_and_algos_t *security_parameters)
{
if (drb2add_list != NULL) {
for (int i = 0; i < drb2add_list->list.count; i++) {
add_drb(enb_flag,
UEid,
drb2add_list->list.array[i],
security_parameters);
}
} else
LOG_W(PDCP, "nr_pdcp_add_drbs() with void list\n");
}
uint64_t get_pdcp_optmask(void)
{
return pdcp_optmask;
......
......@@ -33,6 +33,7 @@
#include "nr_pdcp_ue_manager.h"
struct NR_DRB_ToAddMod;
struct NR_SRB_ToAddMod;
struct sdap_configuration_s;
void nr_pdcp_layer_init(void);
......@@ -42,19 +43,15 @@ bool nr_pdcp_data_ind(const protocol_ctxt_t *const ctxt_pP,
const sdu_size_t sdu_buffer_size,
uint8_t *const sdu_buffer);
void nr_pdcp_add_drbs(eNB_flag_t enb_flag,
ue_id_t UEid,
NR_DRB_ToAddModList_t *const drb2add_list,
const nr_pdcp_entity_security_keys_and_algos_t *security_parameters);
void nr_pdcp_add_srbs(eNB_flag_t enb_flag,
ue_id_t UEid,
NR_SRB_ToAddModList_t *const srb2add_list,
const nr_pdcp_entity_security_keys_and_algos_t *security_parameters);
void add_drb(int is_gnb,
ue_id_t UEid,
struct NR_DRB_ToAddMod *s,
const ue_id_t UEid,
const NR_PDCP_Config_t *pdcp,
struct sdap_configuration_s *sdap,
const nr_pdcp_entity_security_keys_and_algos_t *security_parameters);
void nr_pdcp_remove_UE(ue_id_t ue_id);
......
......@@ -161,6 +161,28 @@ static NR_RadioBearerConfig_t *get_default_rbconfig(int eps_bearer_id,
return rbconfig;
}
static void rrc_nsa_add_drb(const int ue_id,
const NR_DRB_ToAddModList_t *addMod,
const nr_pdcp_entity_security_keys_and_algos_t *sp)
{
for (int i = 0; i < addMod->list.count; i++) {
NR_DRB_ToAddMod_t *drb = addMod->list.array[i];
DevAssert(drb->cnAssociation);
DevAssert(drb->cnAssociation->present != NR_DRB_ToAddMod__cnAssociation_PR_NOTHING);
DevAssert(drb->cnAssociation->present == NR_DRB_ToAddMod__cnAssociation_PR_eps_BearerIdentity);
// get SDAP config
sdap_config_t sdap = {0};
// EPC association
sdap.pdusession_id = drb->cnAssociation->choice.eps_BearerIdentity;
sdap.drb_id = drb->drb_Identity;
sdap.defaultDRB = true;
// add SDAP entity (terminated at gNB, since it's EPC)
new_nr_sdap_entity(GNB_FLAG_YES, ue_id, sdap);
// add PDCP entity
add_drb(GNB_FLAG_YES, ue_id, drb->pdcp_Config, &sdap, sp);
}
}
/* generate prototypes for the tree management functions (RB_INSERT used in rrc_add_nsa_user) */
RB_PROTOTYPE(rrc_nr_ue_tree_s, rrc_gNB_ue_context_s, entries,
rrc_gNB_compare_ue_rnti_id);
......@@ -304,10 +326,7 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc, x2ap_ENDC_sgnb_addition_req_t *m, sctp_
}
DevAssert(UE->rb_config != NULL);
nr_pdcp_add_drbs(GNB_FLAG_YES,
UE->rrc_ue_id,
UE->rb_config->drb_ToAddModList,
&security_parameters);
rrc_nsa_add_drb(UE->rrc_ue_id, UE->rb_config->drb_ToAddModList, &security_parameters);
/* assumption: only a single bearer, see above */
NR_DRB_ToAddModList_t *rb_list = UE->rb_config->drb_ToAddModList;
......
......@@ -599,6 +599,31 @@ static void nr_rrc_process_dedicatedNAS_MessageList(NR_UE_RRC_INST_t *rrc, NR_RR
}
}
/** @brief Add bearer in PDCP/SDAP for 5GC association (SA) */
static void rrc_ue_add_bearer(const int ue_id, const NR_DRB_ToAddMod_t *drb, const nr_pdcp_entity_security_keys_and_algos_t *sp)
{
DevAssert(drb->cnAssociation);
DevAssert(drb->cnAssociation->present != NR_DRB_ToAddMod__cnAssociation_PR_NOTHING);
// get SDAP config
sdap_config_t sdap = {0};
if (drb->cnAssociation->present == NR_DRB_ToAddMod__cnAssociation_PR_eps_BearerIdentity) {
DevAssert(drb->cnAssociation->present == NR_DRB_ToAddMod__cnAssociation_PR_eps_BearerIdentity);
// EPC association
sdap.pdusession_id = drb->cnAssociation->choice.eps_BearerIdentity;
sdap.drb_id = drb->drb_Identity;
sdap.defaultDRB = true;
} else {
DevAssert(drb->cnAssociation->present == NR_DRB_ToAddMod__cnAssociation_PR_sdap_Config);
DevAssert(drb->cnAssociation->choice.sdap_Config);
sdap = nr_sdap_get_config(GNB_FLAG_NO, drb->cnAssociation->choice.sdap_Config, drb->drb_Identity);
}
// add SDAP entity
new_nr_sdap_entity(GNB_FLAG_NO, ue_id, sdap);
// add PDCP entity
add_drb(GNB_FLAG_NO, ue_id, drb->pdcp_Config, &sdap, sp);
}
/**
* @brief add, modify and release SRBs and/or DRBs
* @ref 3GPP TS 38.331
......@@ -706,10 +731,7 @@ static void nr_rrc_ue_process_RadioBearerConfig(NR_UE_RRC_INST_t *ue_rrc, NR_Rad
nr_reconfigure_sdap_entity(sdap_Config, ue_rrc->ue_id, sdap_Config->pdu_Session, DRB_id);
} else {
set_DRB_status(ue_rrc ,DRB_id, RB_ESTABLISHED);
add_drb(false,
ue_rrc->ue_id,
radioBearerConfig->drb_ToAddModList->list.array[cnt],
&security_up_parameters);
rrc_ue_add_bearer(ue_rrc->ue_id, radioBearerConfig->drb_ToAddModList->list.array[cnt], &security_up_parameters);
}
}
} // drb_ToAddModList //
......
......@@ -77,7 +77,7 @@ typedef struct qfi2drb_s {
void nr_pdcp_submit_sdap_ctrl_pdu(ue_id_t ue_id, rb_id_t sdap_ctrl_pdu_drb, nr_sdap_ul_hdr_t ctrl_pdu);
typedef struct {
typedef struct sdap_configuration_s {
int pdusession_id;
int drb_id;
bool sdap_rx;
......
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