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. ...@@ -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" `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 Note that: SST=1, no SD is "eMBB"; SST=2, no SD is "URLLC"; SST=3, no SD
is "mMTC" is "mMTC"
- `enable_sdap` (default: true): enable the use of the SDAP layer. If - `enable_sdap` (default: true): set `sdap-HeaderUL` and `sdap-HeaderDL` to
deactivated, a transparent SDAP header is prepended to packets, but no present in the RRC `SDAP-Config` IE for SA PDU sessions. If false, both
further processing is being done. 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. - `cu_sibs` (default: `[]`) list of SIBs to give to the DU for transmission.
Currently supported: Currently supported:
- SIB2: serving-cell reselection parameters (configured in `sib2_config`) - SIB2: serving-cell reselection parameters (configured in `sib2_config`)
......
...@@ -2443,7 +2443,7 @@ gNB_RRC_INST *RCconfig_NRRRC() ...@@ -2443,7 +2443,7 @@ gNB_RRC_INST *RCconfig_NRRRC()
nrrrc_config.num_plmn = set_plmn_config(nrrrc_config.plmn, k); nrrrc_config.num_plmn = set_plmn_config(nrrrc_config.plmn, k);
nrrrc_config.enable_sdap = *GNBParamList.paramarray[i][GNB_ENABLE_SDAP_IDX].iptr; 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); nrrrc_config.um_on_default_drb = *(GNBParamList.paramarray[i][GNB_UMONDEFAULTDRB_IDX].uptr);
}// }//
......
...@@ -102,7 +102,7 @@ typedef enum { ...@@ -102,7 +102,7 @@ typedef enum {
#define GNB_CONFIG_STRING_1ST_ACTIVE_BWP "first_active_bwp" #define GNB_CONFIG_STRING_1ST_ACTIVE_BWP "first_active_bwp"
#define GNB_CONFIG_STRING_LIMIT_RSRP_REPORT "max_num_RSRP_reported" #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_FORCE256QAMOFF "suppress activation of 256 QAM despite UE support"
#define GNB_CONFIG_HLP_MAXMIMOLAYERS "limit on maxMIMO-layers for DL" #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)" #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) ...@@ -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); DevAssert(to_modif->numQosFlowsMod <= E1AP_MAX_NUM_QOS_FLOWS);
modified->numQosFlowSetup = to_modif->numQosFlowsMod; 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++) { 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, LOG_D(NR_RRC,
...@@ -438,11 +444,7 @@ void e1_bearer_context_modif(const e1ap_bearer_mod_req_t *req) ...@@ -438,11 +444,7 @@ void e1_bearer_context_modif(const e1ap_bearer_mod_req_t *req)
req_pdu_mod->sessionId, req_pdu_mod->sessionId,
to_modif->id, to_modif->id,
to_modif->numQosFlowsMod); to_modif->numQosFlowsMod);
nr_sdap_entity_update_qos_flows(req->gNB_cu_up_ue_id, nr_sdap_entity_update_qos_flows(req->gNB_cu_up_ue_id, &sdap);
req_pdu_mod->sessionId,
to_modif->id,
qfi_list,
to_modif->numQosFlowsMod);
} }
if (to_modif->pdcp_config && to_modif->pdcp_config->pDCP_Reestablishment) { 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, ...@@ -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.id = rrc_drb->drb_id;
drb_ngran.sdap_config.defaultDRB = (session->sdap_config.default_drb == drb_ngran.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_UL = !session->sdap_config.header_ul_absent;
drb_ngran.sdap_config.sDAP_Header_DL = session->sdap_config.header_dl_absent ? false : true; 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); 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, ...@@ -162,7 +162,7 @@ bool sdap_data_req(protocol_ctxt_t *ctxt_p,
rqi); 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; nr_sdap_entity_t *sdap_entity;
sdap_entity = nr_sdap_get_entity(ue_id, pdusession_id); 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 ...@@ -172,13 +172,7 @@ void sdap_data_ind(int pdcp_entity, int is_gnb, int pdusession_id, ue_id_t ue_id
return; return;
} }
sdap_entity->rx_entity(sdap_entity, sdap_entity->rx_entity(sdap_entity, drb_id, is_gnb, pdusession_id, ue_id, buf, size);
pdcp_entity,
is_gnb,
pdusession_id,
ue_id,
buf,
size);
} }
static void *sdap_tun_read_thread(void *arg) static void *sdap_tun_read_thread(void *arg)
...@@ -213,14 +207,6 @@ 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); 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}; protocol_ctxt_t ctxt = {.enb_flag = entity->is_gnb, .rntiMaybeUEid = entity->ue_id};
bool dc = entity->is_gnb ? false : SDAP_HDR_UL_DATA_PDU; bool dc = entity->is_gnb ? false : SDAP_HDR_UL_DATA_PDU;
......
...@@ -37,7 +37,7 @@ bool sdap_data_req(protocol_ctxt_t *ctxt_p, ...@@ -37,7 +37,7 @@ bool sdap_data_req(protocol_ctxt_t *ctxt_p,
* Uplink - gNB * Uplink - gNB
* Downlink - nrUE * 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 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); 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 @@ ...@@ -20,7 +20,6 @@
#define SDAP_HDR_UL_CTRL_PDU (0) #define SDAP_HDR_UL_CTRL_PDU (0)
#define SDAP_HDR_LENGTH (1) #define SDAP_HDR_LENGTH (1)
#define SDAP_MAX_QFI (64) #define SDAP_MAX_QFI (64)
#define SDAP_MAP_RULE_EMPTY (0)
#define SDAP_NO_MAPPING_RULE (0) #define SDAP_NO_MAPPING_RULE (0)
#define SDAP_REFLECTIVE_MAPPING (1) #define SDAP_REFLECTIVE_MAPPING (1)
#define SDAP_RQI_HANDLING (1) #define SDAP_RQI_HANDLING (1)
...@@ -78,17 +77,16 @@ typedef struct sdap_configuration_s { ...@@ -78,17 +77,16 @@ typedef struct sdap_configuration_s {
typedef struct nr_sdap_entity_s { typedef struct nr_sdap_entity_s {
ue_id_t ue_id; ue_id_t ue_id;
int default_drb;
/// sdap_tun_read_thread needs to know if we are gNB/UE, so for noS1 mode, /// sdap_tun_read_thread needs to know if we are gNB/UE, so for noS1 mode,
/// store which one we are /// store which one we are
bool is_gnb; bool is_gnb;
bool enable_sdap;
int pdusession_id; int pdusession_id;
int pdusession_sock; int pdusession_sock;
pthread_t pdusession_thread; pthread_t pdusession_thread;
bool stop_thread; bool stop_thread;
int qfi; int qfi;
qfi2drb_t default_drb;
qfi2drb_t qfi2drb_table[SDAP_MAX_QFI]; qfi2drb_t qfi2drb_table[SDAP_MAX_QFI];
void (*qfi2drb_map_update)(struct nr_sdap_entity_s *entity, const sdap_config_t *sdap); 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 { ...@@ -97,7 +95,7 @@ typedef struct nr_sdap_entity_s {
const uint8_t qfi, const uint8_t qfi,
const uint8_t drb_id, const uint8_t drb_id,
const uint8_t role); 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); 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); 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 { ...@@ -116,13 +114,7 @@ typedef struct nr_sdap_entity_s {
const uint8_t qfi, const uint8_t qfi,
const bool rqi); const bool rqi);
void (*rx_entity)(struct nr_sdap_entity_s *entity, 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);
int pdcp_entity,
int is_gnb,
int pdusession_id,
ue_id_t ue_id,
char *buf,
int size);
/* List of entities */ /* List of entities */
struct nr_sdap_entity_s *next_entity; struct nr_sdap_entity_s *next_entity;
...@@ -182,7 +174,7 @@ bool nr_sdap_delete_ue_entities(ue_id_t ue_id); ...@@ -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_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); void set_qfi(uint8_t qfi, uint8_t pduid, ue_id_t ue_id);
#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