Merge remote-tracking branch 'origin/nr-pdcp-minor-fixes' into integration_2024_w13
This commit is contained in:
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user