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 @@
*/
#include "common/utils/LOG/log.h"
#include "nr_pdcp_entity.h"
int decode_t_reordering(int v)
{
......@@ -36,16 +37,16 @@ int decode_t_reordering(int v)
int decode_sn_size_ul(long s)
{
if (s == 0) return 12;
if (s == 1) return 18;
if (s == 0) return SHORT_SN_SIZE;
if (s == 1) return LONG_SN_SIZE;
LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
exit(1);
}
int decode_sn_size_dl(long s)
{
if (s == 0) return 12;
if (s == 1) return 18;
if (s == 0) return SHORT_SN_SIZE;
if (s == 1) return LONG_SN_SIZE;
LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
exit(1);
}
......
......@@ -32,6 +32,16 @@
#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,
char *_buffer, int size)
{
......@@ -46,6 +56,11 @@ static void nr_pdcp_entity_recv_pdu(nr_pdcp_entity_t *entity,
int rx_deliv_sn;
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) {
LOG_E(PDCP, "bad PDU received (size = %d)\n", size);
return;
......@@ -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->sn_size == 12) {
if (entity->sn_size == SHORT_SN_SIZE) {
rcvd_sn = ((buffer[0] & 0xf) << 8) |
buffer[1];
header_size = 2;
header_size = SHORT_PDCP_HEADER_SIZE;
} else {
rcvd_sn = ((buffer[0] & 0x3) << 16) |
(buffer[1] << 8) |
buffer[2];
header_size = 3;
header_size = LONG_PDCP_HEADER_SIZE;
}
entity->stats.rxpdu_sn = rcvd_sn;
/* SRBs always have MAC-I, even if integrity is not active */
if (entity->has_integrity || entity->type == NR_PDCP_SRB) {
integrity_size = 4;
integrity_size = PDCP_INTEGRITY_SIZE;
} else {
integrity_size = 0;
}
......@@ -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);
if (entity->has_integrity) {
unsigned char integrity[4] = {0};
unsigned char integrity[PDCP_INTEGRITY_SIZE] = {0};
entity->integrity(entity->integrity_context, integrity,
buffer, size - integrity_size,
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");
entity->stats.rxpdu_dd_pkts++;
entity->stats.rxpdu_dd_bytes += size;
......@@ -189,8 +204,14 @@ static int nr_pdcp_entity_process_sdu(nr_pdcp_entity_t *entity,
int integrity_size;
int sdap_header_size = 0;
char *buf = pdu_buffer;
DevAssert(size + 3 + 4 <= pdu_max_size);
DevAssert(nr_max_pdcp_pdu_size(size) <= pdu_max_size);
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_bytes += size;
......@@ -207,20 +228,20 @@ static int nr_pdcp_entity_process_sdu(nr_pdcp_entity_t *entity,
dc_bit = 0;
}
if (entity->sn_size == 12) {
if (entity->sn_size == SHORT_SN_SIZE) {
buf[0] = dc_bit | ((sn >> 8) & 0xf);
buf[1] = sn & 0xff;
header_size = 2;
header_size = SHORT_PDCP_HEADER_SIZE;
} else {
buf[0] = dc_bit | ((sn >> 16) & 0x3);
buf[1] = (sn >> 8) & 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 */
if (entity->has_integrity || entity->type == NR_PDCP_SRB) {
integrity_size = 4;
integrity_size = PDCP_INTEGRITY_SIZE;
} else {
integrity_size = 0;
}
......@@ -228,16 +249,16 @@ static int nr_pdcp_entity_process_sdu(nr_pdcp_entity_t *entity,
memcpy(buf + header_size, buffer, size);
if (entity->has_integrity) {
uint8_t integrity[4] = {0};
uint8_t integrity[PDCP_INTEGRITY_SIZE] = {0};
entity->integrity(entity->integrity_context,
integrity,
(unsigned char *)buf, header_size + size,
entity->rb_id, count, entity->is_gnb ? 1 : 0);
memcpy((unsigned char *)buf + header_size + size, integrity, 4);
} else if (integrity_size == 4) {
memcpy((unsigned char *)buf + header_size + size, integrity, PDCP_INTEGRITY_SIZE);
} else if (integrity_size == PDCP_INTEGRITY_SIZE) {
// 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)) {
......@@ -400,6 +421,7 @@ static void nr_pdcp_entity_suspend(nr_pdcp_entity_t *entity)
}
entity->rx_next = 0;
entity->rx_deliv = 0;
entity->entity_suspended = true;
}
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)
/* receiving entity procedures */
/* 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)
......@@ -445,6 +470,9 @@ static void nr_pdcp_entity_reestablish_drb_um(nr_pdcp_entity_t *entity)
entity->rx_next = 0;
entity->rx_deliv = 0;
/* 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)
......@@ -461,6 +489,9 @@ static void nr_pdcp_entity_reestablish_srb(nr_pdcp_entity_t *entity)
entity->rx_next = 0;
entity->rx_deliv = 0;
/* 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)
......
......@@ -29,6 +29,18 @@
#include "nr_pdcp_sdu.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 {
NR_PDCP_DRB_AM,
NR_PDCP_DRB_UM,
......@@ -167,6 +179,9 @@ typedef struct nr_pdcp_entity_t {
// 4- The ITTI task, forwards the message ciphering (e.g., nea2) it.
// 5- The gNB cannot understand the ciphered Security Mode Complete message.
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 *new_nr_pdcp_entity(
......@@ -190,4 +205,7 @@ nr_pdcp_entity_t *new_nr_pdcp_entity(
unsigned char *ciphering_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_ */
......@@ -817,10 +817,19 @@ void add_srb(int is_gnb,
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);
} else {
pdcp_srb = new_nr_pdcp_entity(NR_PDCP_SRB, is_gnb, srb_id,
0, false, false, // sdap parameters
deliver_sdu_srb, ue, NULL, ue,
12, t_Reordering, -1,
pdcp_srb = new_nr_pdcp_entity(NR_PDCP_SRB,
is_gnb,
srb_id,
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,
integrity_algorithm,
ciphering_key,
......@@ -1075,9 +1084,13 @@ bool nr_pdcp_data_req_srb(ue_id_t ue_id,
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];
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");
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)
return;
}
srb->suspend_entity(srb);
LOG_D(PDCP, "SRB %d suspended\n", srb_id);
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)
return;
}
drb->suspend_entity(drb);
LOG_D(PDCP, "DRB %d suspended\n", drb_id);
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)
if (rb != NULL) {
LOG_D(PDCP, "UE %4.4lx re-establishment of %sRB %d\n", ue_id, srb_flag ? "S" : "D", rb_id);
rb->reestablish_entity(rb);
LOG_I(PDCP, "%s %d re-established\n", srb_flag ? "SRB" : "DRB" , rb_id);
} else {
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,
rb = nr_pdcp_get_rb(ue, rb_id, false);
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);
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];
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;
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