Commit 141558b8 authored by Jaroslava Fiedlerova's avatar Jaroslava Fiedlerova

Merge remote-tracking branch 'origin/nr-pdcp-minor-fixes' into integration_2024_w13

parents 08b80710 914e71fd
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
*/ */
#include "common/utils/LOG/log.h" #include "common/utils/LOG/log.h"
#include "nr_pdcp_entity.h"
int decode_t_reordering(int v) int decode_t_reordering(int v)
{ {
...@@ -36,16 +37,16 @@ int decode_t_reordering(int v) ...@@ -36,16 +37,16 @@ int decode_t_reordering(int v)
int decode_sn_size_ul(long s) int decode_sn_size_ul(long s)
{ {
if (s == 0) return 12; if (s == 0) return SHORT_SN_SIZE;
if (s == 1) return 18; if (s == 1) return LONG_SN_SIZE;
LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
exit(1); exit(1);
} }
int decode_sn_size_dl(long s) int decode_sn_size_dl(long s)
{ {
if (s == 0) return 12; if (s == 0) return SHORT_SN_SIZE;
if (s == 1) return 18; if (s == 1) return LONG_SN_SIZE;
LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
exit(1); exit(1);
} }
......
...@@ -32,6 +32,16 @@ ...@@ -32,6 +32,16 @@
#include "LOG/log.h" #include "LOG/log.h"
/**
* @brief returns the maximum PDCP PDU size
* which corresponds to data PDU for DRBs with 18 bits PDCP SN
* and integrity enabled
*/
int nr_max_pdcp_pdu_size(sdu_size_t sdu_size)
{
return (sdu_size + LONG_PDCP_HEADER_SIZE + PDCP_INTEGRITY_SIZE);
}
static void nr_pdcp_entity_recv_pdu(nr_pdcp_entity_t *entity, static void nr_pdcp_entity_recv_pdu(nr_pdcp_entity_t *entity,
char *_buffer, int size) char *_buffer, int size)
{ {
...@@ -46,6 +56,11 @@ static void nr_pdcp_entity_recv_pdu(nr_pdcp_entity_t *entity, ...@@ -46,6 +56,11 @@ static void nr_pdcp_entity_recv_pdu(nr_pdcp_entity_t *entity,
int rx_deliv_sn; int rx_deliv_sn;
uint32_t rx_deliv_hfn; uint32_t rx_deliv_hfn;
if (entity->entity_suspended) {
LOG_W(PDCP, "PDCP entity %d is suspended. Quit RX procedure.\n", entity->rb_id);
return;
}
if (size < 1) { if (size < 1) {
LOG_E(PDCP, "bad PDU received (size = %d)\n", size); LOG_E(PDCP, "bad PDU received (size = %d)\n", size);
return; return;
...@@ -65,21 +80,21 @@ static void nr_pdcp_entity_recv_pdu(nr_pdcp_entity_t *entity, ...@@ -65,21 +80,21 @@ static void nr_pdcp_entity_recv_pdu(nr_pdcp_entity_t *entity,
if (entity->has_sdap_rx) sdap_header_size = 1; // SDAP Header is one byte if (entity->has_sdap_rx) sdap_header_size = 1; // SDAP Header is one byte
if (entity->sn_size == 12) { if (entity->sn_size == SHORT_SN_SIZE) {
rcvd_sn = ((buffer[0] & 0xf) << 8) | rcvd_sn = ((buffer[0] & 0xf) << 8) |
buffer[1]; buffer[1];
header_size = 2; header_size = SHORT_PDCP_HEADER_SIZE;
} else { } else {
rcvd_sn = ((buffer[0] & 0x3) << 16) | rcvd_sn = ((buffer[0] & 0x3) << 16) |
(buffer[1] << 8) | (buffer[1] << 8) |
buffer[2]; buffer[2];
header_size = 3; header_size = LONG_PDCP_HEADER_SIZE;
} }
entity->stats.rxpdu_sn = rcvd_sn; entity->stats.rxpdu_sn = rcvd_sn;
/* SRBs always have MAC-I, even if integrity is not active */ /* SRBs always have MAC-I, even if integrity is not active */
if (entity->has_integrity || entity->type == NR_PDCP_SRB) { if (entity->has_integrity || entity->type == NR_PDCP_SRB) {
integrity_size = 4; integrity_size = PDCP_INTEGRITY_SIZE;
} else { } else {
integrity_size = 0; integrity_size = 0;
} }
...@@ -113,11 +128,11 @@ static void nr_pdcp_entity_recv_pdu(nr_pdcp_entity_t *entity, ...@@ -113,11 +128,11 @@ static void nr_pdcp_entity_recv_pdu(nr_pdcp_entity_t *entity,
entity->rb_id, rcvd_count, entity->is_gnb ? 0 : 1); entity->rb_id, rcvd_count, entity->is_gnb ? 0 : 1);
if (entity->has_integrity) { if (entity->has_integrity) {
unsigned char integrity[4] = {0}; unsigned char integrity[PDCP_INTEGRITY_SIZE] = {0};
entity->integrity(entity->integrity_context, integrity, entity->integrity(entity->integrity_context, integrity,
buffer, size - integrity_size, buffer, size - integrity_size,
entity->rb_id, rcvd_count, entity->is_gnb ? 0 : 1); entity->rb_id, rcvd_count, entity->is_gnb ? 0 : 1);
if (memcmp(integrity, buffer + size - integrity_size, 4) != 0) { if (memcmp(integrity, buffer + size - integrity_size, PDCP_INTEGRITY_SIZE) != 0) {
LOG_E(PDCP, "discard NR PDU, integrity failed\n"); LOG_E(PDCP, "discard NR PDU, integrity failed\n");
entity->stats.rxpdu_dd_pkts++; entity->stats.rxpdu_dd_pkts++;
entity->stats.rxpdu_dd_bytes += size; entity->stats.rxpdu_dd_bytes += size;
...@@ -189,8 +204,14 @@ static int nr_pdcp_entity_process_sdu(nr_pdcp_entity_t *entity, ...@@ -189,8 +204,14 @@ static int nr_pdcp_entity_process_sdu(nr_pdcp_entity_t *entity,
int integrity_size; int integrity_size;
int sdap_header_size = 0; int sdap_header_size = 0;
char *buf = pdu_buffer; char *buf = pdu_buffer;
DevAssert(size + 3 + 4 <= pdu_max_size); DevAssert(nr_max_pdcp_pdu_size(size) <= pdu_max_size);
int dc_bit; int dc_bit;
if (entity->entity_suspended) {
LOG_W(PDCP, "PDCP entity %d is suspended. Quit SDU processing.\n", entity->rb_id);
return -1;
}
entity->stats.rxsdu_pkts++; entity->stats.rxsdu_pkts++;
entity->stats.rxsdu_bytes += size; entity->stats.rxsdu_bytes += size;
...@@ -207,20 +228,20 @@ static int nr_pdcp_entity_process_sdu(nr_pdcp_entity_t *entity, ...@@ -207,20 +228,20 @@ static int nr_pdcp_entity_process_sdu(nr_pdcp_entity_t *entity,
dc_bit = 0; dc_bit = 0;
} }
if (entity->sn_size == 12) { if (entity->sn_size == SHORT_SN_SIZE) {
buf[0] = dc_bit | ((sn >> 8) & 0xf); buf[0] = dc_bit | ((sn >> 8) & 0xf);
buf[1] = sn & 0xff; buf[1] = sn & 0xff;
header_size = 2; header_size = SHORT_PDCP_HEADER_SIZE;
} else { } else {
buf[0] = dc_bit | ((sn >> 16) & 0x3); buf[0] = dc_bit | ((sn >> 16) & 0x3);
buf[1] = (sn >> 8) & 0xff; buf[1] = (sn >> 8) & 0xff;
buf[2] = sn & 0xff; buf[2] = sn & 0xff;
header_size = 3; header_size = LONG_PDCP_HEADER_SIZE;
} }
/* SRBs always have MAC-I, even if integrity is not active */ /* SRBs always have MAC-I, even if integrity is not active */
if (entity->has_integrity || entity->type == NR_PDCP_SRB) { if (entity->has_integrity || entity->type == NR_PDCP_SRB) {
integrity_size = 4; integrity_size = PDCP_INTEGRITY_SIZE;
} else { } else {
integrity_size = 0; integrity_size = 0;
} }
...@@ -228,16 +249,16 @@ static int nr_pdcp_entity_process_sdu(nr_pdcp_entity_t *entity, ...@@ -228,16 +249,16 @@ static int nr_pdcp_entity_process_sdu(nr_pdcp_entity_t *entity,
memcpy(buf + header_size, buffer, size); memcpy(buf + header_size, buffer, size);
if (entity->has_integrity) { if (entity->has_integrity) {
uint8_t integrity[4] = {0}; uint8_t integrity[PDCP_INTEGRITY_SIZE] = {0};
entity->integrity(entity->integrity_context, entity->integrity(entity->integrity_context,
integrity, integrity,
(unsigned char *)buf, header_size + size, (unsigned char *)buf, header_size + size,
entity->rb_id, count, entity->is_gnb ? 1 : 0); entity->rb_id, count, entity->is_gnb ? 1 : 0);
memcpy((unsigned char *)buf + header_size + size, integrity, 4); memcpy((unsigned char *)buf + header_size + size, integrity, PDCP_INTEGRITY_SIZE);
} else if (integrity_size == 4) { } else if (integrity_size == PDCP_INTEGRITY_SIZE) {
// set MAC-I to 0 for SRBs with integrity not active // set MAC-I to 0 for SRBs with integrity not active
memset(buf + header_size + size, 0, 4); memset(buf + header_size + size, 0, PDCP_INTEGRITY_SIZE);
} }
if (entity->has_ciphering && (entity->is_gnb || entity->security_mode_completed)) { if (entity->has_ciphering && (entity->is_gnb || entity->security_mode_completed)) {
...@@ -400,6 +421,7 @@ static void nr_pdcp_entity_suspend(nr_pdcp_entity_t *entity) ...@@ -400,6 +421,7 @@ static void nr_pdcp_entity_suspend(nr_pdcp_entity_t *entity)
} }
entity->rx_next = 0; entity->rx_next = 0;
entity->rx_deliv = 0; entity->rx_deliv = 0;
entity->entity_suspended = true;
} }
static void free_rx_list(nr_pdcp_entity_t *entity) static void free_rx_list(nr_pdcp_entity_t *entity)
...@@ -427,6 +449,9 @@ static void nr_pdcp_entity_reestablish_drb_am(nr_pdcp_entity_t *entity) ...@@ -427,6 +449,9 @@ static void nr_pdcp_entity_reestablish_drb_am(nr_pdcp_entity_t *entity)
/* receiving entity procedures */ /* receiving entity procedures */
/* todo: deal with ciphering/integrity algos and keys */ /* todo: deal with ciphering/integrity algos and keys */
/* Flag PDCP entity as re-established */
entity->entity_suspended = false;
} }
static void nr_pdcp_entity_reestablish_drb_um(nr_pdcp_entity_t *entity) static void nr_pdcp_entity_reestablish_drb_um(nr_pdcp_entity_t *entity)
...@@ -445,6 +470,9 @@ static void nr_pdcp_entity_reestablish_drb_um(nr_pdcp_entity_t *entity) ...@@ -445,6 +470,9 @@ static void nr_pdcp_entity_reestablish_drb_um(nr_pdcp_entity_t *entity)
entity->rx_next = 0; entity->rx_next = 0;
entity->rx_deliv = 0; entity->rx_deliv = 0;
/* todo: deal with ciphering/integrity algos and keys */ /* todo: deal with ciphering/integrity algos and keys */
/* Flag PDCP entity as re-established */
entity->entity_suspended = false;
} }
static void nr_pdcp_entity_reestablish_srb(nr_pdcp_entity_t *entity) static void nr_pdcp_entity_reestablish_srb(nr_pdcp_entity_t *entity)
...@@ -461,6 +489,9 @@ static void nr_pdcp_entity_reestablish_srb(nr_pdcp_entity_t *entity) ...@@ -461,6 +489,9 @@ static void nr_pdcp_entity_reestablish_srb(nr_pdcp_entity_t *entity)
entity->rx_next = 0; entity->rx_next = 0;
entity->rx_deliv = 0; entity->rx_deliv = 0;
/* todo: deal with ciphering/integrity algos and keys */ /* todo: deal with ciphering/integrity algos and keys */
/* Flag PDCP entity as re-established */
entity->entity_suspended = false;
} }
static void nr_pdcp_entity_release(nr_pdcp_entity_t *entity) static void nr_pdcp_entity_release(nr_pdcp_entity_t *entity)
......
...@@ -29,6 +29,18 @@ ...@@ -29,6 +29,18 @@
#include "nr_pdcp_sdu.h" #include "nr_pdcp_sdu.h"
#include "openair2/RRC/NR/rrc_gNB_radio_bearers.h" #include "openair2/RRC/NR/rrc_gNB_radio_bearers.h"
/* PDCP Formats according to clause 6.2 of 3GPP TS 38.323 */
/* SN Size applicable to SRBs, UM DRBs and AM DRBs */
#define SHORT_SN_SIZE 12
/* SN Size applicable to UM DRBs and AM DRBs */
#define LONG_SN_SIZE 18
/* Data PDU for SRBs and DRBs with 12 bits PDCP SN (unit: byte) */
#define SHORT_PDCP_HEADER_SIZE 2
/* Data PDU for DRBs with 18 bits PDCP SN (unit: byte) */
#define LONG_PDCP_HEADER_SIZE 3
/* MAC-I size (unit: byte) */
#define PDCP_INTEGRITY_SIZE 4
typedef enum { typedef enum {
NR_PDCP_DRB_AM, NR_PDCP_DRB_AM,
NR_PDCP_DRB_UM, NR_PDCP_DRB_UM,
...@@ -167,6 +179,9 @@ typedef struct nr_pdcp_entity_t { ...@@ -167,6 +179,9 @@ typedef struct nr_pdcp_entity_t {
// 4- The ITTI task, forwards the message ciphering (e.g., nea2) it. // 4- The ITTI task, forwards the message ciphering (e.g., nea2) it.
// 5- The gNB cannot understand the ciphered Security Mode Complete message. // 5- The gNB cannot understand the ciphered Security Mode Complete message.
bool security_mode_completed; bool security_mode_completed;
/* Keep tracks of whether the PDCP entity was suspended or not */
bool entity_suspended;
} nr_pdcp_entity_t; } nr_pdcp_entity_t;
nr_pdcp_entity_t *new_nr_pdcp_entity( nr_pdcp_entity_t *new_nr_pdcp_entity(
...@@ -190,4 +205,7 @@ nr_pdcp_entity_t *new_nr_pdcp_entity( ...@@ -190,4 +205,7 @@ nr_pdcp_entity_t *new_nr_pdcp_entity(
unsigned char *ciphering_key, unsigned char *ciphering_key,
unsigned char *integrity_key); unsigned char *integrity_key);
/* Get maximum PDCP PDU size */
int nr_max_pdcp_pdu_size(sdu_size_t sdu_size);
#endif /* _NR_PDCP_ENTITY_H_ */ #endif /* _NR_PDCP_ENTITY_H_ */
...@@ -817,10 +817,19 @@ void add_srb(int is_gnb, ...@@ -817,10 +817,19 @@ void add_srb(int is_gnb,
if (nr_pdcp_get_rb(ue, srb_id, true) != NULL) { if (nr_pdcp_get_rb(ue, srb_id, true) != NULL) {
LOG_E(PDCP, "warning SRB %d already exist for UE ID %ld, do nothing\n", srb_id, UEid); LOG_E(PDCP, "warning SRB %d already exist for UE ID %ld, do nothing\n", srb_id, UEid);
} else { } else {
pdcp_srb = new_nr_pdcp_entity(NR_PDCP_SRB, is_gnb, srb_id, pdcp_srb = new_nr_pdcp_entity(NR_PDCP_SRB,
0, false, false, // sdap parameters is_gnb,
deliver_sdu_srb, ue, NULL, ue, srb_id,
12, t_Reordering, -1, 0, // PDU session ID (not relevant)
false, // has SDAP RX (not relevant)
false, // has SDAP TX (not relevant)
deliver_sdu_srb,
ue,
NULL,
ue,
SHORT_SN_SIZE,
t_Reordering,
-1,
ciphering_algorithm, ciphering_algorithm,
integrity_algorithm, integrity_algorithm,
ciphering_key, ciphering_key,
...@@ -1075,9 +1084,13 @@ bool nr_pdcp_data_req_srb(ue_id_t ue_id, ...@@ -1075,9 +1084,13 @@ bool nr_pdcp_data_req_srb(ue_id_t ue_id,
return 0; return 0;
} }
int max_size = sdu_buffer_size + 3 + 4; // 3: max header, 4: max integrity int max_size = nr_max_pdcp_pdu_size(sdu_buffer_size);
char pdu_buf[max_size]; char pdu_buf[max_size];
int pdu_size = rb->process_sdu(rb, (char *)sdu_buffer, sdu_buffer_size, muiP, pdu_buf, max_size); int pdu_size = rb->process_sdu(rb, (char *)sdu_buffer, sdu_buffer_size, muiP, pdu_buf, max_size);
if (pdu_size == -1) {
nr_pdcp_manager_unlock(nr_pdcp_ue_manager);
return 0;
}
AssertFatal(rb->deliver_pdu == NULL, "SRB callback should be NULL, to be provided on every invocation\n"); AssertFatal(rb->deliver_pdu == NULL, "SRB callback should be NULL, to be provided on every invocation\n");
nr_pdcp_manager_unlock(nr_pdcp_ue_manager); nr_pdcp_manager_unlock(nr_pdcp_ue_manager);
...@@ -1098,6 +1111,7 @@ void nr_pdcp_suspend_srb(ue_id_t ue_id, int srb_id) ...@@ -1098,6 +1111,7 @@ void nr_pdcp_suspend_srb(ue_id_t ue_id, int srb_id)
return; return;
} }
srb->suspend_entity(srb); srb->suspend_entity(srb);
LOG_D(PDCP, "SRB %d suspended\n", srb_id);
nr_pdcp_manager_unlock(nr_pdcp_ue_manager); nr_pdcp_manager_unlock(nr_pdcp_ue_manager);
} }
...@@ -1112,6 +1126,7 @@ void nr_pdcp_suspend_drb(ue_id_t ue_id, int drb_id) ...@@ -1112,6 +1126,7 @@ void nr_pdcp_suspend_drb(ue_id_t ue_id, int drb_id)
return; return;
} }
drb->suspend_entity(drb); drb->suspend_entity(drb);
LOG_D(PDCP, "DRB %d suspended\n", drb_id);
nr_pdcp_manager_unlock(nr_pdcp_ue_manager); nr_pdcp_manager_unlock(nr_pdcp_ue_manager);
} }
...@@ -1211,6 +1226,7 @@ void nr_pdcp_reestablishment(ue_id_t ue_id, int rb_id, bool srb_flag) ...@@ -1211,6 +1226,7 @@ void nr_pdcp_reestablishment(ue_id_t ue_id, int rb_id, bool srb_flag)
if (rb != NULL) { if (rb != NULL) {
LOG_D(PDCP, "UE %4.4lx re-establishment of %sRB %d\n", ue_id, srb_flag ? "S" : "D", rb_id); LOG_D(PDCP, "UE %4.4lx re-establishment of %sRB %d\n", ue_id, srb_flag ? "S" : "D", rb_id);
rb->reestablish_entity(rb); rb->reestablish_entity(rb);
LOG_I(PDCP, "%s %d re-established\n", srb_flag ? "SRB" : "DRB" , rb_id);
} else { } else {
LOG_W(PDCP, "UE %4.4lx cannot re-establish %sRB %d, RB not found\n", ue_id, srb_flag ? "S" : "D", rb_id); LOG_W(PDCP, "UE %4.4lx cannot re-establish %sRB %d, RB not found\n", ue_id, srb_flag ? "S" : "D", rb_id);
} }
...@@ -1252,14 +1268,19 @@ bool nr_pdcp_data_req_drb(protocol_ctxt_t *ctxt_pP, ...@@ -1252,14 +1268,19 @@ bool nr_pdcp_data_req_drb(protocol_ctxt_t *ctxt_pP,
rb = nr_pdcp_get_rb(ue, rb_id, false); rb = nr_pdcp_get_rb(ue, rb_id, false);
if (rb == NULL) { if (rb == NULL) {
LOG_E(PDCP, "no DRB found (ue_id %lx, rb_id %ld)\n", ue_id, rb_id); LOG_E(PDCP, "[UE %lx] DRB %ld not found\n", rb_id, ue_id);
nr_pdcp_manager_unlock(nr_pdcp_ue_manager); nr_pdcp_manager_unlock(nr_pdcp_ue_manager);
return 0; return 0;
} }
int max_size = sdu_buffer_size + 3 + 4; // 3: max header, 4: max integrity int max_size = nr_max_pdcp_pdu_size(sdu_buffer_size);
char pdu_buf[max_size]; char pdu_buf[max_size];
int pdu_size = rb->process_sdu(rb, (char *)sdu_buffer, sdu_buffer_size, muiP, pdu_buf, max_size); int pdu_size = rb->process_sdu(rb, (char *)sdu_buffer, sdu_buffer_size, muiP, pdu_buf, max_size);
if (pdu_size == -1) {
nr_pdcp_manager_unlock(nr_pdcp_ue_manager);
return 0;
}
deliver_pdu deliver_pdu_cb = rb->deliver_pdu; deliver_pdu deliver_pdu_cb = rb->deliver_pdu;
nr_pdcp_manager_unlock(nr_pdcp_ue_manager); nr_pdcp_manager_unlock(nr_pdcp_ue_manager);
......
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