Commit aff84037 authored by Robert Schmidt's avatar Robert Schmidt

Merge remote-tracking branch 'GuidoCasati/sdap-header-fix' into integration_2026_w28

SDAP header handling fixes (#249)

OAI SDAP treated SDAP header presence as a single PDU-session flag
(enable_sdap), so a valid asymmetric RRC config (UL header present, DL
header absent) caused the UE to parse downlink payload as an SDAP QFI
and drop traffic (e.g. IPv4 0x45 -> bogus QFI 5).

SDAP now follows RRC SDAP-Config per DRB and per direction from (TS
38.331 / TS 37.324). Header presence, QFI-to-DRB mapping, and
default-DRB fallback all derive from what RRC configured for each DRB.

In the new implementation, RRC (SDAP-Config IE) fills sdap_config_t per
DRB (role, defaultDRB, mapped QFIs), SDAP entity stores it in
qfi2drb_table + default_drb row to be used in the TX/RX data path.

Also, simplify mapping logic, improves E1 QoS-flow remap, and completes
UE reflective QoS mapping with the correct entity_role on new QFI rows.
Reviewed-by: default avatarRobert Schmidt <robert.schmidt@openairinterface.org>
Reviewed-by: default avatarBartosz Podrygajlo <bartosz.podrygajlo@openairinterface.org>
parents fef21545 14b5bcb6
......@@ -90,9 +90,9 @@ the [MAC configuration](../MAC/mac-usage.md) as well for SIB configuration.
`0xffffff` is a reserved value and means "no SD"
Note that: SST=1, no SD is "eMBB"; SST=2, no SD is "URLLC"; SST=3, no SD
is "mMTC"
- `enable_sdap` (default: true): enable the use of the SDAP layer. If
deactivated, a transparent SDAP header is prepended to packets, but no
further processing is being done.
- `enable_sdap` (default: true): set `sdap-HeaderUL` and `sdap-HeaderDL` to
present in the RRC `SDAP-Config` IE for SA PDU sessions. If false, both
headers are absent (per DRB). SDAP entities are still created, SDAP layer always enabled.
- `cu_sibs` (default: `[]`) list of SIBs to give to the DU for transmission.
Currently supported:
- SIB2: serving-cell reselection parameters (configured in `sib2_config`)
......
......@@ -2443,7 +2443,7 @@ gNB_RRC_INST *RCconfig_NRRRC()
nrrrc_config.num_plmn = set_plmn_config(nrrrc_config.plmn, k);
nrrrc_config.enable_sdap = *GNBParamList.paramarray[i][GNB_ENABLE_SDAP_IDX].iptr;
LOG_I(GNB_APP, "SDAP layer is %s\n", nrrrc_config.enable_sdap ? "enabled" : "disabled");
LOG_I(GNB_APP, "SDAP UL/DL headers in RRC are %s\n", nrrrc_config.enable_sdap ? "present" : "absent");
nrrrc_config.um_on_default_drb = *(GNBParamList.paramarray[i][GNB_UMONDEFAULTDRB_IDX].uptr);
}//
......
......@@ -102,7 +102,7 @@ typedef enum {
#define GNB_CONFIG_STRING_1ST_ACTIVE_BWP "first_active_bwp"
#define GNB_CONFIG_STRING_LIMIT_RSRP_REPORT "max_num_RSRP_reported"
#define GNB_CONFIG_HLP_STRING_ENABLE_SDAP "enable the SDAP layer\n"
#define GNB_CONFIG_HLP_STRING_ENABLE_SDAP "set sdap-HeaderUL/DL present in RRC SDAP-Config (false = both absent)\n"
#define GNB_CONFIG_HLP_FORCE256QAMOFF "suppress activation of 256 QAM despite UE support"
#define GNB_CONFIG_HLP_MAXMIMOLAYERS "limit on maxMIMO-layers for DL"
#define GNB_CONFIG_HLP_DISABLE_HARQ "disable feedback for all HARQ processes (REL17 feature)"
......
......@@ -427,9 +427,15 @@ void e1_bearer_context_modif(const e1ap_bearer_mod_req_t *req)
DevAssert(to_modif->numQosFlowsMod <= E1AP_MAX_NUM_QOS_FLOWS);
modified->numQosFlowSetup = to_modif->numQosFlowsMod;
uint8_t qfi_list[E1AP_MAX_NUM_QOS_FLOWS];
sdap_config_t sdap = {
.pdusession_id = req_pdu_mod->sessionId,
.drb_id = to_modif->id,
.mappedQFIs2AddCount = to_modif->numQosFlowsMod,
};
for (int q = 0; q < to_modif->numQosFlowsMod; q++) {
modified->qosFlows[q].qfi = qfi_list[q] = to_modif->qosFlows[q].qfi;
sdap.mappedQFIs2Add[q] = to_modif->qosFlows[q].qfi;
modified->qosFlows[q].qfi = to_modif->qosFlows[q].qfi;
}
LOG_D(NR_RRC,
......@@ -438,11 +444,7 @@ void e1_bearer_context_modif(const e1ap_bearer_mod_req_t *req)
req_pdu_mod->sessionId,
to_modif->id,
to_modif->numQosFlowsMod);
nr_sdap_entity_update_qos_flows(req->gNB_cu_up_ue_id,
req_pdu_mod->sessionId,
to_modif->id,
qfi_list,
to_modif->numQosFlowsMod);
nr_sdap_entity_update_qos_flows(req->gNB_cu_up_ue_id, &sdap);
}
if (to_modif->pdcp_config && to_modif->pdcp_config->pDCP_Reestablishment) {
......
......@@ -345,8 +345,8 @@ static DRB_nGRAN_to_setup_t fill_e1_drb_to_setup(const drb_t *rrc_drb,
drb_ngran.id = rrc_drb->drb_id;
drb_ngran.sdap_config.defaultDRB = (session->sdap_config.default_drb == drb_ngran.id);
drb_ngran.sdap_config.sDAP_Header_UL = session->sdap_config.header_ul_absent ? false : true;
drb_ngran.sdap_config.sDAP_Header_DL = session->sdap_config.header_dl_absent ? false : true;
drb_ngran.sdap_config.sDAP_Header_UL = !session->sdap_config.header_ul_absent;
drb_ngran.sdap_config.sDAP_Header_DL = !session->sdap_config.header_dl_absent;
drb_ngran.pdcp_config = set_bearer_context_pdcp_config(rrc_drb->pdcp_config, um_on_default_drb, redcap_cap);
......
......@@ -162,7 +162,7 @@ bool sdap_data_req(protocol_ctxt_t *ctxt_p,
rqi);
}
void sdap_data_ind(int pdcp_entity, int is_gnb, int pdusession_id, ue_id_t ue_id, char *buf, int size)
void sdap_data_ind(int drb_id, int is_gnb, int pdusession_id, ue_id_t ue_id, char *buf, int size)
{
nr_sdap_entity_t *sdap_entity;
sdap_entity = nr_sdap_get_entity(ue_id, pdusession_id);
......@@ -172,13 +172,7 @@ void sdap_data_ind(int pdcp_entity, int is_gnb, int pdusession_id, ue_id_t ue_id
return;
}
sdap_entity->rx_entity(sdap_entity,
pdcp_entity,
is_gnb,
pdusession_id,
ue_id,
buf,
size);
sdap_entity->rx_entity(sdap_entity, drb_id, is_gnb, pdusession_id, ue_id, buf, size);
}
static void *sdap_tun_read_thread(void *arg)
......@@ -213,14 +207,6 @@ static void *sdap_tun_read_thread(void *arg)
LOG_D(SDAP, "read data of size %d\n", len);
if (!entity->is_gnb && entity->enable_sdap && (entity->qfi < 0 || entity->qfi >= SDAP_MAX_QFI)) {
LOG_W(SDAP,
"Dropping UL SDU for UE %ld PDU session %d: no QoS rule QFI available for SDAP header\n",
entity->ue_id,
entity->pdusession_id);
continue;
}
protocol_ctxt_t ctxt = {.enb_flag = entity->is_gnb, .rntiMaybeUEid = entity->ue_id};
bool dc = entity->is_gnb ? false : SDAP_HDR_UL_DATA_PDU;
......
......@@ -37,7 +37,7 @@ bool sdap_data_req(protocol_ctxt_t *ctxt_p,
* Uplink - gNB
* Downlink - nrUE
*/
void sdap_data_ind(int pdcp_entity, int is_gnb, int pdusession_id, ue_id_t ue_id, char *buf, int size);
void sdap_data_ind(int drb_id, int is_gnb, int pdusession_id, ue_id_t ue_id, char *buf, int size);
void start_sdap_tun_gnb_first_ue_default_pdu_session(ue_id_t ue_id, int pdu_session_id);
void create_ue_ip_if(const char *ipv4, const char *ipv6, int ue_id, int pdu_session_id, bool is_default);
......
This diff is collapsed.
......@@ -20,7 +20,6 @@
#define SDAP_HDR_UL_CTRL_PDU (0)
#define SDAP_HDR_LENGTH (1)
#define SDAP_MAX_QFI (64)
#define SDAP_MAP_RULE_EMPTY (0)
#define SDAP_NO_MAPPING_RULE (0)
#define SDAP_REFLECTIVE_MAPPING (1)
#define SDAP_RQI_HANDLING (1)
......@@ -78,17 +77,16 @@ typedef struct sdap_configuration_s {
typedef struct nr_sdap_entity_s {
ue_id_t ue_id;
int default_drb;
/// sdap_tun_read_thread needs to know if we are gNB/UE, so for noS1 mode,
/// store which one we are
bool is_gnb;
bool enable_sdap;
int pdusession_id;
int pdusession_sock;
pthread_t pdusession_thread;
bool stop_thread;
int qfi;
qfi2drb_t default_drb;
qfi2drb_t qfi2drb_table[SDAP_MAX_QFI];
void (*qfi2drb_map_update)(struct nr_sdap_entity_s *entity, const sdap_config_t *sdap);
......@@ -97,7 +95,7 @@ typedef struct nr_sdap_entity_s {
const uint8_t qfi,
const uint8_t drb_id,
const uint8_t role);
int (*qfi2drb_map)(struct nr_sdap_entity_s *entity, uint8_t qfi);
const qfi2drb_t *(*qfi2drb_map)(const struct nr_sdap_entity_s *entity, uint8_t qfi);
nr_sdap_ul_hdr_t (*sdap_construct_ctrl_pdu)(uint8_t qfi);
int (*sdap_map_ctrl_pdu)(struct nr_sdap_entity_s *entity, int map_type, uint8_t dl_qfi);
......@@ -116,13 +114,7 @@ typedef struct nr_sdap_entity_s {
const uint8_t qfi,
const bool rqi);
void (*rx_entity)(struct nr_sdap_entity_s *entity,
int pdcp_entity,
int is_gnb,
int pdusession_id,
ue_id_t ue_id,
char *buf,
int size);
void (*rx_entity)(struct nr_sdap_entity_s *entity, int drb_id, int is_gnb, int pdusession_id, ue_id_t ue_id, char *buf, int size);
/* List of entities */
struct nr_sdap_entity_s *next_entity;
......@@ -182,7 +174,7 @@ bool nr_sdap_delete_ue_entities(ue_id_t ue_id);
*/
void nr_reconfigure_sdap_entity(NR_SDAP_Config_t *sdap_config, ue_id_t ue_id, int pdusession_id, int drb_id);
void nr_sdap_entity_update_qos_flows(ue_id_t ue_id, int pdusession_id, int drb_id, const uint8_t *qfis, int n_qfis);
void nr_sdap_entity_update_qos_flows(ue_id_t ue_id, sdap_config_t *sdap);
void set_qfi(uint8_t qfi, uint8_t pduid, ue_id_t ue_id);
#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