diff --git a/openair2/LAYER2/nr_pdcp/asn1_utils.c b/openair2/LAYER2/nr_pdcp/asn1_utils.c index 473c5f2331..6b45a73acf 100644 --- a/openair2/LAYER2/nr_pdcp/asn1_utils.c +++ b/openair2/LAYER2/nr_pdcp/asn1_utils.c @@ -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); } diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c index cea73170dc..546e154604 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c @@ -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)) { diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h index 8d342a8206..212f4026d4 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h @@ -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_ */ diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c index ef2da07d57..49f9ac7982 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c @@ -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;