Define for PDCP Formats
- short and long SN sizes - PDCP PDU header sizes - PDCP integrity size - getter for maximim PDCP PDU size
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)
|
||||
{
|
||||
@@ -65,21 +75,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 +123,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,7 +199,7 @@ 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;
|
||||
entity->stats.rxsdu_pkts++;
|
||||
entity->stats.rxsdu_bytes += size;
|
||||
@@ -207,20 +217,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 +238,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)) {
|
||||
|
||||
@@ -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,
|
||||
@@ -190,4 +202,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,7 +1084,7 @@ 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);
|
||||
AssertFatal(rb->deliver_pdu == NULL, "SRB callback should be NULL, to be provided on every invocation\n");
|
||||
@@ -1257,7 +1266,7 @@ bool nr_pdcp_data_req_drb(protocol_ctxt_t *ctxt_pP,
|
||||
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);
|
||||
deliver_pdu deliver_pdu_cb = rb->deliver_pdu;
|
||||
|
||||
Reference in New Issue
Block a user