Commit 286c092c authored by nikaeinn's avatar nikaeinn

* add reordering window management to PDCP

* update PDCP security and count calculation



git-svn-id: http://svn.eurecom.fr/openair4G/trunk@5307 818b1a75-f10b-46b9-bf7c-635c3b92a50f
parent c8d0d4b7
......@@ -594,7 +594,7 @@ uint32_t dlsch_decoding(PHY_VARS_UE *phy_vars_ue,
#ifdef USER_MODE // need to be adapted for the emulation in the kernel space
if (uniformrandom() < bler) {
LOG_I(OCM,"abstraction_decoding failed (mcs=%d, sinr_eff=%f, bler=%f)\n",mcs,sinr_eff,bler);
LOG_N(OCM,"abstraction_decoding failed (mcs=%d, sinr_eff=%f, bler=%f)\n",mcs,sinr_eff,bler);
return(0);
}
else {
......@@ -671,7 +671,11 @@ uint32_t dlsch_decoding_emul(PHY_VARS_UE *phy_vars_ue,
LOG_T(PHY,"\n current harq pid is %d ue id %d \n", harq_pid, ue_id);
#endif
if (dlsch_abstraction_MIESM(phy_vars_ue->sinr_dB, phy_vars_ue->transmission_mode[eNB_id], dlsch_eNB->rb_alloc, dlsch_eNB->harq_processes[harq_pid]->mcs,PHY_vars_eNB_g[eNB_id]->mu_mimo_mode[ue_id].dl_pow_off) == 1) {
if (dlsch_abstraction_MIESM(phy_vars_ue->sinr_dB,
phy_vars_ue->transmission_mode[eNB_id],
dlsch_eNB->rb_alloc,
dlsch_eNB->harq_processes[harq_pid]->mcs,
PHY_vars_eNB_g[eNB_id]->mu_mimo_mode[ue_id].dl_pow_off) == 1) {
// reset HARQ
dlsch_ue->harq_processes[harq_pid]->status = SCH_IDLE;
dlsch_ue->harq_processes[harq_pid]->round = 0;
......
......@@ -96,6 +96,7 @@ typedef signed int rlc_op_status_t;
//-----------------------------------------------------------------------------
typedef uint16_t pdcp_sn_t;
typedef uint32_t pdcp_hfn_t;
typedef int16_t pdcp_hfn_offset_t;
typedef enum pdcp_transmission_mode_e {
PDCP_TRANSMISSION_MODE_UNKNOWN = 0,
......
......@@ -4472,30 +4472,6 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
//if (subframeP%5 == 0)
#ifdef EXMIMO
pdcp_run(frameP, 1, 0, module_idP);
/*
ret = pthread_mutex_trylock (&pdcp_mutex);
if (ret != 0) {
if (ret==EBUSY)
LOG_E(PDCP,"Mutex busy\n");
else
LOG_E(PDCP,"Cannot lock mutex\n");
//return(-1);
}
else {
pdcp_instance_cnt++;
pthread_mutex_unlock(&pdcp_mutex);
if (pdcp_instance_cnt == 0) {
if (pthread_cond_signal(&pdcp_cond) != 0) {
LOG_E(PDCP,"pthread_cond_signal unsuccessfull\n");
//return(-1);
}
}
else {
LOG_W(PDCP,"PDCP thread busy!!! inst_cnt=%d\n",pdcp_instance_cnt);
}
}
*/
#endif
#ifdef CELLULAR
rrc_rx_tx(module_idP, frameP, 0, 0);
......
......@@ -283,11 +283,12 @@ boolean_t pdcp_data_req(
start_meas(&UE_pdcp_stats[ue_mod_idP].apply_security);
pdcp_apply_security(pdcp_p,
rb_idP % maxDRB,
pdcp_header_len,
current_sn,
pdcp_pdu_p->data,
sdu_buffer_sizeP);
srb_flagP,
rb_idP % maxDRB,
pdcp_header_len,
current_sn,
pdcp_pdu_p->data,
sdu_buffer_sizeP);
if (enb_flagP == ENB_FLAG_NO)
stop_meas(&eNB_pdcp_stats[enb_mod_idP].apply_security);
......@@ -510,14 +511,22 @@ boolean_t pdcp_data_ind(
* Parse the PDU placed at the beginning of SDU to check
* if incoming SN is in line with RX window
*/
if (pdcp_header_len == PDCP_USER_PLANE_DATA_PDU_LONG_SN_HEADER_SIZE) { // DRB
sequence_number = pdcp_get_sequence_number_of_pdu_with_long_sn((unsigned char*)sdu_buffer_pP->data);
// uint8_t dc = pdcp_get_dc_filed((unsigned char*)sdu_buffer->data);
} else { //SRB1/2
sequence_number = pdcp_get_sequence_number_of_pdu_with_SRB_sn((unsigned char*)sdu_buffer_pP->data);
if (MBMS_flagP == 0 ) {
if (srb_flagP) { //SRB1/2
sequence_number = pdcp_get_sequence_number_of_pdu_with_SRB_sn((unsigned char*)sdu_buffer_pP->data);
} else { // DRB
if (pdcp_p->seq_num_size == PDCP_SN_7BIT){
sequence_number = pdcp_get_sequence_number_of_pdu_with_short_sn((unsigned char*)sdu_buffer_pP->data);
}else if (pdcp_p->seq_num_size == PDCP_SN_12BIT){
sequence_number = pdcp_get_sequence_number_of_pdu_with_long_sn((unsigned char*)sdu_buffer_pP->data);
} else {
//sequence_number = 4095;
LOG_E(PDCP,"wrong sequence number (%d) for this pdcp entity \n", pdcp_p->seq_num_size);
}
//uint8_t dc = pdcp_get_dc_filed((unsigned char*)sdu_buffer_pP->data);
}
}
if (pdcp_is_rx_seq_number_valid(sequence_number, pdcp_p) == TRUE) {
if (pdcp_is_rx_seq_number_valid(sequence_number, pdcp_p, srb_flagP) == TRUE) {
LOG_D(PDCP, "Incoming PDU has a sequence number (%d) in accordance with RX window\n", sequence_number);
/* if (dc == PDCP_DATA_PDU )
LOG_D(PDCP, "Passing piggybacked SDU to NAS driver...\n");
......@@ -546,19 +555,19 @@ boolean_t pdcp_data_ind(
else
start_meas(&UE_pdcp_stats[ue_mod_idP].validate_security);
pdcp_validate_security(pdcp_p,
rb_idP,
pdcp_header_len,
sequence_number,
sdu_buffer_pP->data,
sdu_buffer_sizeP - pdcp_tailer_len);
if (enb_flagP == ENB_FLAG_NO)
stop_meas(&eNB_pdcp_stats[enb_mod_idP].validate_security);
else
stop_meas(&UE_pdcp_stats[ue_mod_idP].validate_security);
}
pdcp_validate_security(pdcp_p,
srb_flagP,
rb_idP,
pdcp_header_len,
sequence_number,
sdu_buffer_pP->data,
sdu_buffer_sizeP - pdcp_tailer_len);
if (enb_flagP == ENB_FLAG_NO)
stop_meas(&eNB_pdcp_stats[enb_mod_idP].validate_security);
else
stop_meas(&UE_pdcp_stats[ue_mod_idP].validate_security);
}
#endif
//rrc_lite_data_ind(module_id, //Modified MW - L2 Interface
pdcp_rrc_data_ind(enb_mod_idP,
......@@ -591,7 +600,11 @@ boolean_t pdcp_data_ind(
if (oai_emulation.info.otg_enabled == 1) {
module_id_t src_id, dst_id;
int ctime;
if (pdcp_p->rlc_mode == RLC_MODE_AM ) {
pdcp_p->last_submitted_pdcp_rx_sn = sequence_number;
}
rlc_util_print_hex_octets(PDCP,
(unsigned char*)&sdu_buffer_pP->data[payload_offset],
sdu_buffer_sizeP - payload_offset);
......@@ -626,6 +639,9 @@ boolean_t pdcp_data_ind(
new_sdu_p = get_free_mem_block(sdu_buffer_sizeP - payload_offset + sizeof (pdcp_data_ind_header_t));
if (new_sdu_p) {
if (pdcp_p->rlc_mode == RLC_MODE_AM ) {
pdcp_p->last_submitted_pdcp_rx_sn = sequence_number;
}
/*
* Prepend PDCP indication header which is going to be removed at pdcp_fifo_flush_sdus()
*/
......@@ -854,7 +870,7 @@ boolean_t rrc_pdcp_config_asn1_req (
rlc_mode_t rlc_type = RLC_MODE_NONE;
DRB_Identity_t drb_id = 0;
DRB_Identity_t *pdrb_id_p = NULL;
uint8_t drb_sn = 0;
uint8_t drb_sn = 12;
uint8_t srb_sn = 5; // fixed sn for SRBs
uint8_t drb_report = 0;
long int cnt = 0;
......@@ -968,7 +984,8 @@ boolean_t rrc_pdcp_config_asn1_req (
}
if (drb_toaddmod_p->pdcp_Config->rlc_AM) {
drb_report = drb_toaddmod_p->pdcp_Config->rlc_AM->statusReportRequired;
rlc_type =RLC_MODE_AM;
drb_sn = PDCP_Config__rlc_UM__pdcp_SN_Size_len12bits; // default SN size
rlc_type = RLC_MODE_AM;
}
if (drb_toaddmod_p->pdcp_Config->rlc_UM){
drb_sn = drb_toaddmod_p->pdcp_Config->rlc_UM->pdcp_SN_Size;
......@@ -1149,32 +1166,35 @@ boolean_t pdcp_config_req_asn1 (pdcp_t *pdcp_pP,
pdcp_pP->header_compression_profile = header_compression_profileP;
pdcp_pP->status_report = rb_reportP;
if (rb_snP == PDCP_Config__rlc_UM__pdcp_SN_Size_len7bits) {
pdcp_pP->seq_num_size = 7;
} else if (rb_snP == PDCP_Config__rlc_UM__pdcp_SN_Size_len12bits) {
pdcp_pP->seq_num_size = 12;
if (rb_snP == PDCP_Config__rlc_UM__pdcp_SN_Size_len12bits) {
pdcp_pP->seq_num_size = PDCP_SN_12BIT;
} else if (rb_snP == PDCP_Config__rlc_UM__pdcp_SN_Size_len7bits) {
pdcp_pP->seq_num_size = PDCP_SN_7BIT;
} else {
pdcp_pP->seq_num_size = 5;
pdcp_pP->seq_num_size = PDCP_SN_5BIT;
}
pdcp_pP->rlc_mode = rlc_modeP;
pdcp_pP->next_pdcp_tx_sn = 0;
pdcp_pP->next_pdcp_rx_sn = 0;
pdcp_pP->tx_hfn = 0;
pdcp_pP->rx_hfn = 0;
pdcp_pP->last_submitted_pdcp_rx_sn = 4095;
pdcp_pP->first_missing_pdu = -1;
pdcp_pP->rlc_mode = rlc_modeP;
pdcp_pP->next_pdcp_tx_sn = 0;
pdcp_pP->next_pdcp_rx_sn = 0;
pdcp_pP->next_pdcp_rx_sn_before_integrity = 0;
pdcp_pP->tx_hfn = 0;
pdcp_pP->rx_hfn = 0;
pdcp_pP->last_submitted_pdcp_rx_sn = 4095;
pdcp_pP->first_missing_pdu = -1;
pdcp_pP->rx_hfn_offset = 0;
if (enb_flagP == ENB_FLAG_NO) {
LOG_I(PDCP, "[UE %d] Config request : Action ADD for eNB %d: Frame %d LCID %d (rb id %d) "
"configured with SN size %d bits and RLC %s\n",
ue_mod_idP, enb_mod_idP, frameP, lc_idP, rb_idP, pdcp_pP->seq_num_size,
(rlc_modeP == 1) ? "AM" : (rlc_modeP == 2) ? "TM" : "UM");
(rlc_modeP == RLC_MODE_AM ) ? "AM" : (rlc_modeP == RLC_MODE_TM) ? "TM" : "UM");
} else {
LOG_I(PDCP, "[eNB %d] Config request : Action ADD for UE %d: Frame %d LCID %d (rb id %d) "
"configured with SN size %d bits and RLC %s\n",
enb_mod_idP, ue_mod_idP, frameP, lc_idP, rb_idP, pdcp_pP->seq_num_size,
(rlc_modeP == 1) ? "AM" : (rlc_modeP == 2) ? "TM" : "UM");
(rlc_modeP == RLC_MODE_AM) ? "AM" : (rlc_modeP == RLC_MODE_TM) ? "TM" : "UM");
}
/* Setup security */
......@@ -1208,12 +1228,12 @@ boolean_t pdcp_config_req_asn1 (pdcp_t *pdcp_pP,
LOG_I(PDCP,"[UE %d] Config request : Action MODIFY for eNB %d: Frame %d LCID %d "
"RB id %d configured with SN size %d and RLC %s \n",
ue_mod_idP, enb_mod_idP, frameP, lc_idP, rb_idP, rb_snP,
(rlc_modeP == 1) ? "AM" : (rlc_modeP == 2) ? "TM" : "UM");
(rlc_modeP == RLC_MODE_AM) ? "AM" : (rlc_modeP == RLC_MODE_TM) ? "TM" : "UM");
} else {
LOG_I(PDCP,"[eNB %d] Config request : Action MODIFY for UE %d: Frame %d LCID %d "
"RB id %d configured with SN size %d and RLC %s \n",
enb_mod_idP, ue_mod_idP, frameP, lc_idP, rb_idP, rb_snP,
(rlc_modeP == 1) ? "AM" : (rlc_modeP == 2) ? "TM" : "UM");
(rlc_modeP == RLC_MODE_AM) ? "AM" : (rlc_modeP == RLC_MODE_TM) ? "TM" : "UM");
}
break;
case CONFIG_ACTION_REMOVE:
......
......@@ -151,11 +151,14 @@ typedef struct pdcp_t {
*/
pdcp_sn_t next_pdcp_tx_sn;
pdcp_sn_t next_pdcp_rx_sn;
pdcp_sn_t next_pdcp_rx_sn_before_integrity;
/*
* TX and RX Hyper Frame Numbers
*/
pdcp_hfn_t tx_hfn;
pdcp_hfn_t rx_hfn;
pdcp_hfn_offset_t rx_hfn_offset; // related to sn mismatch
/*
* SN of the last PDCP SDU delivered to upper layers
*/
......@@ -172,6 +175,11 @@ typedef struct pdcp_t {
* which is not also a valid sequence number
*/
short int first_missing_pdu;
/*
* decipher using a different rx_hfn
*/
} pdcp_t;
#if defined(Rel10)
......@@ -439,6 +447,21 @@ typedef struct pdcp_missing_pdu_info_t {
#define PDCP_MAX_SN_7BIT 127 // 2^7-1
#define PDCP_MAX_SN_12BIT 4095 // 2^12-1
/*
* Reordering_Window: half of the PDCP SN space
*/
#define REORDERING_WINDOW_SN_5BIT 16
#define REORDERING_WINDOW_SN_7BIT 64
#define REORDERING_WINDOW_SN_12BIT 2048
/*
* SN size
*/
#define PDCP_SN_5BIT 5
#define PDCP_SN_7BIT 7
#define PDCP_SN_12BIT 12
protected_pdcp(signed int pdcp_2_nas_irq;)
public_pdcp(pdcp_stats_t UE_pdcp_stats[NUMBER_OF_UE_MAX];)
public_pdcp(pdcp_stats_t eNB_pdcp_stats[NUMBER_OF_eNB_MAX];)
......
......@@ -113,8 +113,8 @@ int pdcp_netlink_init(void) {
pdcp_netlink_queue_ue = calloc(nb_inst_ue, sizeof(struct lfds611_queue_state*));
pdcp_netlink_nb_element_ue = malloc(nb_inst_ue * sizeof(uint32_t));
LOG_I(PDCP, "Creating %d queues for eNB Netlink -> PDCP communication\n", nb_inst_enb);
LOG_I(PDCP, "Creating %d queues for UE Netlink -> PDCP communication\n", nb_inst_ue);
LOG_I(PDCP, "[NETLINK] Creating %d queues for eNB Netlink -> PDCP communication\n", nb_inst_enb);
LOG_I(PDCP, "[NETLINK] Creating %d queues for UE Netlink -> PDCP communication\n", nb_inst_ue);
for (i = 0; i < nb_inst_enb; i++) {
pdcp_netlink_nb_element_enb[i] = 0;
......@@ -132,7 +132,7 @@ int pdcp_netlink_init(void) {
}
if (pthread_attr_init(&attr) != 0) {
LOG_E(PDCP, "Failed to initialize pthread attribute for Netlink -> PDCP communication (%d:%s)\n",
LOG_E(PDCP, "[NETLINK]Failed to initialize pthread attribute for Netlink -> PDCP communication (%d:%s)\n",
errno, strerror(errno));
exit(EXIT_FAILURE);
}
......@@ -147,7 +147,7 @@ int pdcp_netlink_init(void) {
* should be avoided if we want a reliable link.
*/
if (pthread_create(&pdcp_netlink_thread, &attr, pdcp_netlink_thread_fct, NULL) != 0) {
LOG_E(PDCP, "Failed to create new thread for Netlink/PDCP communcation (%d:%s)\n",
LOG_E(PDCP, "[NETLINK]Failed to create new thread for Netlink/PDCP communcation (%d:%s)\n",
errno, strerror(errno));
exit(EXIT_FAILURE);
}
......@@ -166,12 +166,12 @@ int pdcp_netlink_dequeue_element(
if (eNB_flagP) {
ret = lfds611_queue_dequeue(pdcp_netlink_queue_enb[enb_mod_idP], (void **)data_ppP);
if (ret != 0) {
LOG_D(PDCP, "De-queueing packet for eNB instance %d\n", enb_mod_idP);
LOG_D(PDCP,"[NETLINK]De-queueing packet for eNB instance %d\n", enb_mod_idP);
}
} else {
ret = lfds611_queue_dequeue(pdcp_netlink_queue_ue[ue_mod_idP], (void **)data_ppP);
if (ret != 0) {
LOG_D(PDCP, "De-queueing packet for UE instance %d\n", ue_mod_idP);
LOG_D(PDCP, "[NETLINK]De-queueing packet for UE instance %d\n", ue_mod_idP);
}
}
......@@ -187,6 +187,7 @@ void *pdcp_netlink_thread_fct(void *arg) {
pdcp_thread_read_state = 0;
memset(nl_rx_buf, 0, NL_MAX_PAYLOAD);
LOG_I(PDCP, "[NETLINK_THREAD] binding to fd %d\n",nas_sock_fd);
while (1) {
......
......@@ -153,11 +153,15 @@ void pdcp_config_set_security(pdcp_t *pdcp_pP, module_id_t enb_mod_idP, module_i
uint16_t lc_idP, uint8_t security_modeP, uint8_t *kRRCenc_pP, uint8_t *kRRCint_pP, uint8_t *kUPenc_pP);
#if defined(ENABLE_SECURITY)
int pdcp_apply_security(pdcp_t *pdcp_entity, rb_id_t rb_id,
int pdcp_apply_security(pdcp_t *pdcp_entity,
srb_flag_t srb_flagP,
rb_id_t rb_id,
uint8_t pdcp_header_len, uint16_t current_sn, uint8_t *pdcp_pdu_buffer,
uint16_t sdu_buffer_size);
int pdcp_validate_security(pdcp_t *pdcp_entity, rb_id_t rb_id,
int pdcp_validate_security(pdcp_t *pdcp_entity,
srb_flag_t srb_flagP,
rb_id_t rb_id,
uint8_t pdcp_header_len, uint16_t current_sn, uint8_t *pdcp_pdu_buffer,
uint16_t sdu_buffer_size);
#endif /* defined(ENABLE_SECURITY) */
......
......@@ -27,9 +27,10 @@
*******************************************************************************/
/*! \file pdcp_security.c
* \brief PDCP Security Methods
* \author ROUX Sebastien
* \date 2013
* \brief PDCP Security Methods
* \author ROUX Sebastie and Navid Nikaein
* \email openair_tech@eurecom.fr, navid.nikaein@eurecom.fr
* \date 2014
*/
#include <stdint.h>
......@@ -48,47 +49,62 @@
#if defined(ENABLE_SECURITY)
static
uint32_t pdcp_get_next_count_tx(pdcp_t *pdcp_entity, uint8_t pdcp_header_len, uint16_t pdcp_sn);
uint32_t pdcp_get_next_count_tx(pdcp_t *pdcp_entity, srb_flag_t srb_flagP, uint16_t pdcp_sn);
static
uint32_t pdcp_get_next_count_rx(pdcp_t *pdcp_entity, uint8_t pdcp_header_len, uint16_t pdcp_sn);
uint32_t pdcp_get_next_count_rx(pdcp_t *pdcp_entity, srb_flag_t srb_flagP, uint16_t pdcp_sn);
static
uint32_t pdcp_get_next_count_tx(pdcp_t *pdcp_entity, uint8_t pdcp_header_len, uint16_t pdcp_sn)
uint32_t pdcp_get_next_count_tx(pdcp_t *pdcp_entity, srb_flag_t srb_flagP, uint16_t pdcp_sn)
{
uint32_t count;
/* For TX COUNT = TX_HFN << length of SN | pdcp SN */
if (pdcp_header_len == PDCP_CONTROL_PLANE_DATA_PDU_SN_SIZE) {
/* 5 bits length SN */
count = (pdcp_entity->tx_hfn << 5) | (pdcp_sn & 0x001F);
} else {
/* 12 bits length SN */
count = (pdcp_entity->tx_hfn << 12) | (pdcp_sn & 0x0FFF);
uint32_t count;
/* For TX COUNT = TX_HFN << length of SN | pdcp SN */
if (srb_flagP) {
/* 5 bits length SN */
count = ((pdcp_entity->tx_hfn << 5) | (pdcp_sn & 0x001F));
} else {
if (pdcp_entity->seq_num_size == PDCP_Config__rlc_UM__pdcp_SN_Size_len7bits) {
count = ((pdcp_entity->tx_hfn << 7) | (pdcp_sn & 0x07F));
} else { /*Default is the 12 bits length SN */
count = ((pdcp_entity->tx_hfn << 12) | (pdcp_sn & 0x0FFF));
}
// LOG_D(PDCP, "[OSA] TX COUNT = 0x%08x\n", count);
return count;
}
LOG_D(PDCP, "[OSA] TX COUNT = 0x%08x\n", count);
return count;
}
static
uint32_t pdcp_get_next_count_rx(pdcp_t *pdcp_entity, uint8_t pdcp_header_len, uint16_t pdcp_sn)
uint32_t pdcp_get_next_count_rx(pdcp_t *pdcp_entity, srb_flag_t srb_flagP, uint16_t pdcp_sn)
{
uint32_t count;
/* For RX COUNT = RX_HFN << length of SN | pdcp SN of received PDU */
if (pdcp_header_len == PDCP_CONTROL_PLANE_DATA_PDU_SN_SIZE) {
/* 5 bits length SN */
count = (pdcp_entity->rx_hfn << 5) | (pdcp_sn & 0x001F);
} else {
/* 12 bits length SN */
count = (pdcp_entity->rx_hfn << 12) | (pdcp_sn & 0x0FFF);
uint32_t count;
/* For RX COUNT = RX_HFN << length of SN | pdcp SN of received PDU */
if (srb_flagP) {
/* 5 bits length SN */
count = (((pdcp_entity->rx_hfn + pdcp_entity->rx_hfn_offset) << 5) | (pdcp_sn & 0x001F));
} else {
if (pdcp_entity->seq_num_size == PDCP_Config__rlc_UM__pdcp_SN_Size_len7bits) {
/* 7 bits length SN */
count = (((pdcp_entity->rx_hfn + pdcp_entity->rx_hfn_offset) << 7) | (pdcp_sn & 0x007F));
} else { // default
/* 12 bits length SN */
count = (((pdcp_entity->rx_hfn + pdcp_entity->rx_hfn_offset) << 12) | (pdcp_sn & 0x0FFF));
}
// LOG_D(PDCP, "[OSA] RX COUNT = 0x%08x\n", count);
return count;
}
// reset the hfn offset
pdcp_entity->rx_hfn_offset =0;
LOG_D(PDCP, "[OSA] RX COUNT = 0x%08x\n", count);
return count;
}
int pdcp_apply_security(pdcp_t *pdcp_entity, rb_id_t rb_id,
uint8_t pdcp_header_len, uint16_t current_sn, uint8_t *pdcp_pdu_buffer,
uint16_t sdu_buffer_size)
int pdcp_apply_security(pdcp_t *pdcp_entity,
srb_flag_t srb_flagP,
rb_id_t rb_id,
uint8_t pdcp_header_len,
uint16_t current_sn,
uint8_t *pdcp_pdu_buffer,
uint16_t sdu_buffer_size)
{
uint8_t *buffer_encrypted = NULL;
stream_cipher_t encrypt_params;
......@@ -99,12 +115,12 @@ int pdcp_apply_security(pdcp_t *pdcp_entity, rb_id_t rb_id,
vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_APPLY_SECURITY, VCD_FUNCTION_IN);
encrypt_params.direction = (pdcp_entity->is_ue == 1) ? SECU_DIRECTION_UPLINK : SECU_DIRECTION_DOWNLINK;
encrypt_params.direction = (pdcp_entity->is_ue == 1) ? SECU_DIRECTION_UPLINK : SECU_DIRECTION_DOWNLINK;
encrypt_params.bearer = rb_id - 1;
encrypt_params.count = pdcp_get_next_count_tx(pdcp_entity, pdcp_header_len, current_sn);
encrypt_params.count = pdcp_get_next_count_tx(pdcp_entity, srb_flagP, current_sn);
encrypt_params.key_length = 16;
if (rb_id < DTCH) {
if (srb_flagP) {
/* SRBs */
uint8_t *mac_i;
......@@ -119,7 +135,8 @@ int pdcp_apply_security(pdcp_t *pdcp_entity, rb_id_t rb_id,
/* Both header and data parts are integrity protected for
* control-plane PDUs */
stream_compute_integrity(pdcp_entity->integrityProtAlgorithm, &encrypt_params,
stream_compute_integrity(pdcp_entity->integrityProtAlgorithm,
&encrypt_params,
mac_i);
encrypt_params.key = pdcp_entity->kRRCenc; // + 128 // bit key
......@@ -136,7 +153,8 @@ int pdcp_apply_security(pdcp_t *pdcp_entity, rb_id_t rb_id,
buffer_encrypted = &pdcp_pdu_buffer[pdcp_header_len];
/* Apply ciphering if any requested */
stream_encrypt(pdcp_entity->cipheringAlgorithm, &encrypt_params,
stream_encrypt(pdcp_entity->cipheringAlgorithm,
&encrypt_params,
&buffer_encrypted);
vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_APPLY_SECURITY, VCD_FUNCTION_OUT);
......@@ -144,9 +162,13 @@ int pdcp_apply_security(pdcp_t *pdcp_entity, rb_id_t rb_id,
return 0;
}
int pdcp_validate_security(pdcp_t *pdcp_entity, rb_id_t rb_id,
uint8_t pdcp_header_len, uint16_t current_sn, uint8_t *pdcp_pdu_buffer,
uint16_t sdu_buffer_size)
int pdcp_validate_security(pdcp_t *pdcp_entity,
srb_flag_t srb_flagP,
rb_id_t rb_id,
uint8_t pdcp_header_len,
uint16_t current_sn,
uint8_t *pdcp_pdu_buffer,
uint16_t sdu_buffer_size)
{
uint8_t *buffer_decrypted = NULL;
stream_cipher_t decrypt_params;
......@@ -162,12 +184,12 @@ int pdcp_validate_security(pdcp_t *pdcp_entity, rb_id_t rb_id,
decrypt_params.direction = (pdcp_entity->is_ue == 1) ? SECU_DIRECTION_DOWNLINK : SECU_DIRECTION_UPLINK ;
decrypt_params.bearer = rb_id - 1;
decrypt_params.count = pdcp_get_next_count_rx(pdcp_entity, pdcp_header_len, current_sn);
decrypt_params.count = pdcp_get_next_count_rx(pdcp_entity, srb_flagP, current_sn);
decrypt_params.message = &pdcp_pdu_buffer[pdcp_header_len];
decrypt_params.blength = (sdu_buffer_size - pdcp_header_len) << 3;
decrypt_params.key_length = 16;
if (rb_id < DTCH) {
if (srb_flagP) {
LOG_D(PDCP, "[OSA][RB %d] %s Validating control-plane security\n",
rb_id, (pdcp_entity->is_ue != 0) ? "eNB -> UE" : "UE -> eNB");
decrypt_params.key = pdcp_entity->kRRCenc;// + 128;
......@@ -178,25 +200,28 @@ int pdcp_validate_security(pdcp_t *pdcp_entity, rb_id_t rb_id,
}
/* Uncipher the block */
stream_decrypt(pdcp_entity->cipheringAlgorithm, &decrypt_params, &buffer_decrypted);
if (rb_id < DTCH) {
/* Now check the integrity of the complete PDU */
decrypt_params.message = pdcp_pdu_buffer;
decrypt_params.blength = sdu_buffer_size << 3;
decrypt_params.key = pdcp_entity->kRRCint + 16;// 128;
if (stream_check_integrity(pdcp_entity->integrityProtAlgorithm,
&decrypt_params, &pdcp_pdu_buffer[sdu_buffer_size]) != 0)
{
LOG_E(PDCP, "[OSA] failed to validate MAC-I of incoming PDU\n");
vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_VALIDATE_SECURITY, VCD_FUNCTION_OUT);
return -1;
}
stream_decrypt(pdcp_entity->cipheringAlgorithm,
&decrypt_params,
&buffer_decrypted);
if (srb_flagP) {
/* Now check the integrity of the complete PDU */
decrypt_params.message = pdcp_pdu_buffer;
decrypt_params.blength = sdu_buffer_size << 3;
decrypt_params.key = pdcp_entity->kRRCint + 16;// 128;
if (stream_check_integrity(pdcp_entity->integrityProtAlgorithm,
&decrypt_params,
&pdcp_pdu_buffer[sdu_buffer_size]) != 0)
{
LOG_E(PDCP, "[OSA] failed to validate MAC-I of incoming PDU\n");
vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_VALIDATE_SECURITY, VCD_FUNCTION_OUT);
return -1;
}
}
vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_VALIDATE_SECURITY, VCD_FUNCTION_OUT);
return 0;
}
......
......@@ -29,8 +29,9 @@
/*! \file pdcp_sequence_manager.c
* \brief PDCP Sequence Numbering Methods
* \author Baris Demiray
* \date 2011
* \author Baris Demiray and Navid Nikaein
* \email navid.nikaein@eurecom.fr
* \date 2014
*/
#include "pdcp_sequence_manager.h"
......@@ -146,9 +147,11 @@ boolean_t pdcp_advance_rx_window(pdcp_t* pdcp_entity)
* @return 1 if SN is okay, 0 otherwise
* XXX Reordering window should also be handled here
*/
boolean_t pdcp_is_rx_seq_number_valid(uint16_t seq_num, pdcp_t* pdcp_entity)
{
LOG_D(PDCP, "Incoming RX Seq # is %04d\n", seq_num);
boolean_t pdcp_is_rx_seq_number_valid(uint16_t seq_num, pdcp_t* pdcp_entity,srb_flag_t srb_flagP) {
uint16_t reordering_window = 0;
LOG_D(PDCP, "Incoming RX Sequence number is %04d\n", seq_num);
if (pdcp_is_seq_num_size_valid(pdcp_entity) == FALSE || pdcp_is_seq_num_valid(seq_num, pdcp_entity->seq_num_size) == FALSE)
return FALSE;
......@@ -164,27 +167,117 @@ boolean_t pdcp_is_rx_seq_number_valid(uint16_t seq_num, pdcp_t* pdcp_entity)
}
/*
* XXX Since we do not implement reordering window yet we expect to receive
* exactly the next SN from lower layer. When reordering window is implemented
* the operator utilized here should be >= as stated in 5.1.2.1.2
* RX Procedures for SRB and DRBs as described in sec 5.1.2 of 36.323
*/
if (srb_flagP) { // SRB
if (seq_num < pdcp_entity->next_pdcp_rx_sn) {
// decipher and verify the integrity of the PDU (if applicable) using COUNT based on RX_HFN + 1 and the received PDCP SN
pdcp_entity->rx_hfn++;
pdcp_entity->rx_hfn_offset = 0;
} else{
// decipher and verify the integrity of the PDU (if applicable) using COUNT based using COUNT based on RX_HFN and the received PDCP SN
pdcp_entity->rx_hfn_offset = 0;
}
// Assume that integrity verification is applicable and the integrity verification is passed successfully;
// or assume that integrity verification is not applicable:
// same the old next_pdcp_rx_sn to revert otherwise
pdcp_entity->next_pdcp_rx_sn_before_integrity = pdcp_entity->next_pdcp_rx_sn;
if (seq_num != pdcp_entity->next_pdcp_rx_sn)
LOG_D(PDCP,"Re-adjusting the sequence number to %d\n", seq_num);
//set Next_PDCP_RX_SN to the received PDCP SN +1 ;
pdcp_entity->next_pdcp_rx_sn = seq_num;
pdcp_advance_rx_window(pdcp_entity); // + 1, and check if it is larger than Maximum_PDCP_SN:
} else { // DRB
if (pdcp_entity->seq_num_size == PDCP_SN_7BIT)
reordering_window = REORDERING_WINDOW_SN_7BIT;
else
reordering_window = REORDERING_WINDOW_SN_12BIT;
switch (pdcp_entity->rlc_mode) {
case RLC_MODE_AM:
if ((seq_num - pdcp_entity->last_submitted_pdcp_rx_sn > reordering_window) ||
((0 <= pdcp_entity->last_submitted_pdcp_rx_sn - seq_num) &&
(pdcp_entity->last_submitted_pdcp_rx_sn - seq_num < reordering_window) )) {
if (seq_num > pdcp_entity->next_pdcp_rx_sn) {
/*
* decipher the PDCP PDU as specified in the subclause 5.6, using COUNT based on RX_HFN - 1 and the received PDCP SN;
*/
pdcp_entity->rx_hfn_offset = -1;
} else {
/*
* decipher the PDCP PDU as specified in the subclause 5.6, using COUNT based on RX_HFN and the received PDCP SN;
*/
pdcp_entity->rx_hfn_offset = 0;
}
// discard this PDCP SDU;
LOG_W(PDCP, "Out of the reordering window (Incoming SN:%d, Expected SN:%d): discard this PDCP SDU\n",
seq_num, pdcp_entity->next_pdcp_rx_sn);
return FALSE;
} else if (pdcp_entity->next_pdcp_rx_sn - seq_num > reordering_window) {
pdcp_entity->rx_hfn++;
// use COUNT based on RX_HFN and the received PDCP SN for deciphering the PDCP PDU;
pdcp_entity->rx_hfn_offset = 0;
pdcp_entity->next_pdcp_rx_sn++;
}
else if (seq_num - pdcp_entity->next_pdcp_rx_sn >= reordering_window ){
// use COUNT based on RX_HFN – 1 and the received PDCP SN for deciphering the PDCP PDU;
pdcp_entity->rx_hfn_offset = -1;
}
else if (seq_num >= pdcp_entity->next_pdcp_rx_sn ) {
// use COUNT based on RX_HFN and the received PDCP SN for deciphering the PDCP PDU;
pdcp_entity->rx_hfn_offset = 0;
//set Next_PDCP_RX_SN to the received PDCP SN +1 ;
pdcp_entity->next_pdcp_rx_sn = seq_num;
pdcp_advance_rx_window(pdcp_entity); // + 1, anc check if it is larger than Maximum_PDCP_SN:
LOG_D(PDCP,"Re-adjusting the sequence number to %d\n", seq_num);
} else if (seq_num < pdcp_entity->next_pdcp_rx_sn){
// use COUNT based on RX_HFN and the received PDCP SN for deciphering the PDCP PDU;
pdcp_entity->rx_hfn_offset = 0;
}
break;
case RLC_MODE_UM :
if (seq_num < pdcp_entity->next_pdcp_rx_sn)
pdcp_entity->rx_hfn++;
// decipher the PDCP Data PDU using COUNT based on RX_HFN and the received PDCP SN as specified in the subclause 5.6;
//set Next_PDCP_RX_SN to the received PDCP SN +1 ;
pdcp_entity->next_pdcp_rx_sn = seq_num;
pdcp_advance_rx_window(pdcp_entity); // + 1, and check if it is larger than Maximum_PDCP_SN:
break;
case RLC_MODE_TM :
default:
LOG_W(PDCP,"RLC mode %d not supported\n",pdcp_entity->rlc_mode);
return FALSE;