Starting to split pdcp_entity into pdcp_entity_lte and pdcp_entity_nr to support NR PDCP

master
Pedro Alvarez 6 years ago committed by Andre Puschmann
parent 069c55f2e5
commit 005d03cb1a

@ -67,16 +67,20 @@ public:
uint32_t lcid; uint32_t lcid;
}; };
class srslte_pdcp_config_lte_t
class srslte_pdcp_config_t
{ {
public: public:
srslte_pdcp_config_t(uint8_t bearer_id_ = 0, bool is_control_ = false, bool is_data_ = false, uint8_t direction_ = SECURITY_DIRECTION_UPLINK) srslte_pdcp_config_lte_t(uint8_t bearer_id_ = 0,
:bearer_id(bearer_id_) bool is_control_ = false,
,direction(direction_) bool is_data_ = false,
,is_control(is_control_) uint8_t direction_ = SECURITY_DIRECTION_UPLINK) :
,is_data(is_data_) bearer_id(bearer_id_),
,sn_len(12) {} direction(direction_),
is_control(is_control_),
is_data(is_data_),
sn_len(12)
{
}
uint32_t bearer_id; uint32_t bearer_id;
uint8_t direction; uint8_t direction;

@ -211,12 +211,12 @@ public:
virtual void add_user(uint16_t rnti) = 0; virtual void add_user(uint16_t rnti) = 0;
virtual void rem_user(uint16_t rnti) = 0; virtual void rem_user(uint16_t rnti) = 0;
virtual void write_sdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t sdu) = 0; virtual void write_sdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t sdu) = 0;
virtual void add_bearer(uint16_t rnti, uint32_t lcid, srslte::srslte_pdcp_config_t cnfg) = 0; virtual void add_bearer(uint16_t rnti, uint32_t lcid, srslte::srslte_pdcp_config_lte_t cnfg) = 0;
virtual void config_security(uint16_t rnti, virtual void config_security(uint16_t rnti,
uint32_t lcid, uint32_t lcid,
uint8_t *k_rrc_enc_, uint8_t* k_rrc_enc_,
uint8_t *k_rrc_int_, uint8_t* k_rrc_int_,
uint8_t *k_up_enc_, uint8_t* k_up_enc_,
srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo_, srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo_,
srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo_) = 0; srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo_) = 0;
virtual void enable_integrity(uint16_t rnti, uint32_t lcid) = 0; virtual void enable_integrity(uint16_t rnti, uint32_t lcid) = 0;

@ -233,23 +233,22 @@ public:
virtual void reestablish(uint32_t lcid) = 0; virtual void reestablish(uint32_t lcid) = 0;
virtual void reset() = 0; virtual void reset() = 0;
virtual void write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu, bool blocking = true) = 0; virtual void write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu, bool blocking = true) = 0;
virtual void add_bearer(uint32_t lcid, srslte::srslte_pdcp_config_t cnfg = srslte::srslte_pdcp_config_t()) = 0; virtual void add_bearer(uint32_t lcid,
srslte::srslte_pdcp_config_lte_t cnfg = srslte::srslte_pdcp_config_lte_t()) = 0;
virtual void change_lcid(uint32_t old_lcid, uint32_t new_lcid) = 0; virtual void change_lcid(uint32_t old_lcid, uint32_t new_lcid) = 0;
virtual void config_security(uint32_t lcid, virtual void config_security(uint32_t lcid,
uint8_t *k_rrc_enc_, uint8_t* k_rrc_enc_,
uint8_t *k_rrc_int_, uint8_t* k_rrc_int_,
uint8_t *k_up_enc_, uint8_t* k_up_enc_,
srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo_, srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo_,
srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo_) = 0; srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo_) = 0;
virtual void config_security_all(uint8_t *k_rrc_enc_, virtual void config_security_all(uint8_t* k_rrc_enc_,
uint8_t *k_rrc_int_, uint8_t* k_rrc_int_,
uint8_t *k_up_enc_, uint8_t* k_up_enc_,
srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo_, srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo_,
srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo_) = 0; srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo_) = 0;
virtual void enable_integrity(uint32_t lcid) = 0; virtual void enable_integrity(uint32_t lcid) = 0;
virtual void enable_encryption(uint32_t lcid) = 0; virtual void enable_encryption(uint32_t lcid) = 0;
virtual uint32_t get_dl_count(uint32_t lcid) = 0;
virtual uint32_t get_ul_count(uint32_t lcid) = 0;
}; };
// PDCP interface for RLC // PDCP interface for RLC

@ -25,7 +25,7 @@
#include "srslte/common/log.h" #include "srslte/common/log.h"
#include "srslte/common/common.h" #include "srslte/common/common.h"
#include "srslte/interfaces/ue_interfaces.h" #include "srslte/interfaces/ue_interfaces.h"
#include "srslte/upper/pdcp_entity.h" #include "srslte/upper/pdcp_entity_lte.h"
namespace srslte { namespace srslte {
@ -49,25 +49,23 @@ public:
void reset(); void reset();
void write_sdu(uint32_t lcid, unique_byte_buffer_t sdu, bool blocking = true); void write_sdu(uint32_t lcid, unique_byte_buffer_t sdu, bool blocking = true);
void write_sdu_mch(uint32_t lcid, unique_byte_buffer_t sdu); void write_sdu_mch(uint32_t lcid, unique_byte_buffer_t sdu);
void add_bearer(uint32_t lcid, srslte_pdcp_config_t cnfg = srslte_pdcp_config_t()); void add_bearer(uint32_t lcid, srslte_pdcp_config_lte_t cnfg = srslte_pdcp_config_lte_t());
void add_bearer_mrb(uint32_t lcid, srslte_pdcp_config_t cnfg = srslte_pdcp_config_t()); void add_bearer_mrb(uint32_t lcid, srslte_pdcp_config_lte_t cnfg = srslte_pdcp_config_lte_t());
void del_bearer(uint32_t lcid); void del_bearer(uint32_t lcid);
void change_lcid(uint32_t old_lcid, uint32_t new_lcid); void change_lcid(uint32_t old_lcid, uint32_t new_lcid);
void config_security(uint32_t lcid, void config_security(uint32_t lcid,
uint8_t *k_rrc_enc, uint8_t* k_rrc_enc,
uint8_t *k_rrc_int, uint8_t* k_rrc_int,
uint8_t *k_up_enc, uint8_t* k_up_enc,
CIPHERING_ALGORITHM_ID_ENUM cipher_algo, CIPHERING_ALGORITHM_ID_ENUM cipher_algo,
INTEGRITY_ALGORITHM_ID_ENUM integ_algo); INTEGRITY_ALGORITHM_ID_ENUM integ_algo);
void config_security_all(uint8_t *k_rrc_enc, void config_security_all(uint8_t* k_rrc_enc,
uint8_t *k_rrc_int, uint8_t* k_rrc_int,
uint8_t *k_up_enc, uint8_t* k_up_enc,
CIPHERING_ALGORITHM_ID_ENUM cipher_algo, CIPHERING_ALGORITHM_ID_ENUM cipher_algo,
INTEGRITY_ALGORITHM_ID_ENUM integ_algo); INTEGRITY_ALGORITHM_ID_ENUM integ_algo);
void enable_integrity(uint32_t lcid); void enable_integrity(uint32_t lcid);
void enable_encryption(uint32_t lcid); void enable_encryption(uint32_t lcid);
uint32_t get_dl_count(uint32_t lcid);
uint32_t get_ul_count(uint32_t lcid);
// RLC interface // RLC interface
void write_pdu(uint32_t lcid, unique_byte_buffer_t sdu); void write_pdu(uint32_t lcid, unique_byte_buffer_t sdu);
@ -81,8 +79,8 @@ private:
srsue::rrc_interface_pdcp* rrc = nullptr; srsue::rrc_interface_pdcp* rrc = nullptr;
srsue::gw_interface_pdcp* gw = nullptr; srsue::gw_interface_pdcp* gw = nullptr;
typedef std::map<uint16_t, pdcp_entity_interface*> pdcp_map_t; typedef std::map<uint16_t, pdcp_entity_lte*> pdcp_map_t;
typedef std::pair<uint16_t, pdcp_entity_interface*> pdcp_map_pair_t; typedef std::pair<uint16_t, pdcp_entity_lte*> pdcp_map_pair_t;
log* pdcp_log = nullptr; log* pdcp_log = nullptr;
pdcp_map_t pdcp_array, pdcp_array_mrb; pdcp_map_t pdcp_array, pdcp_array_mrb;

@ -0,0 +1,114 @@
/*
* Copyright 2013-2019 Software Radio Systems Limited
*
* This file is part of srsLTE.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#ifndef SRSLTE_PDCP_ENTITY_BASE_H
#define SRSLTE_PDCP_ENTITY_BASE_H
#include "srslte/common/buffer_pool.h"
#include "srslte/common/common.h"
#include "srslte/common/log.h"
#include "srslte/common/security.h"
#include "srslte/common/threads.h"
#include "srslte/interfaces/ue_interfaces.h"
#include <mutex>
namespace srslte {
/****************************************************************************
* Structs and Defines common to both LTE and NR
* Ref: 3GPP TS 36.323 v10.1.0 and TS 38.323 v15.2.0
***************************************************************************/
#define PDCP_PDU_TYPE_PDCP_STATUS_REPORT 0x0
#define PDCP_PDU_TYPE_INTERSPERSED_ROHC_FEEDBACK_PACKET 0x1
typedef enum {
PDCP_D_C_CONTROL_PDU = 0,
PDCP_D_C_DATA_PDU,
PDCP_D_C_N_ITEMS,
} pdcp_d_c_t;
static const char pdcp_d_c_text[PDCP_D_C_N_ITEMS][20] = {"Control PDU", "Data PDU"};
/****************************************************************************
* PDCP Entity interface
* Common interface for LTE and NR PDCP entities
***************************************************************************/
class pdcp_entity_base
{
public:
pdcp_entity_base();
virtual ~pdcp_entity_base();
virtual void reset() = 0;
virtual void reestablish() = 0;
bool is_active() { return active; }
bool is_control() { return rb_is_control; }
bool is_data() { return !rb_is_control; }
// RRC interface
void enable_integrity() { do_integrity = true; }
void enable_encryption() { do_encryption = true; }
void config_security(uint8_t* k_rrc_enc_,
uint8_t* k_rrc_int_,
uint8_t* k_up_enc_,
uint8_t* k_up_int_, // NR Only, pass nullptr in LTE
CIPHERING_ALGORITHM_ID_ENUM cipher_algo_,
INTEGRITY_ALGORITHM_ID_ENUM integ_algo_);
// GW/SDAP/RRC interface
void write_sdu(unique_byte_buffer_t sdu, bool blocking);
// RLC interface
void write_pdu(unique_byte_buffer_t pdu);
protected:
byte_buffer_pool* pool = byte_buffer_pool::get_instance();
srslte::log* log = nullptr;
bool active = false;
uint32_t lcid = 0;
bool rb_is_control = false;
bool do_integrity = false;
bool do_encryption = false;
private:
uint8_t k_rrc_enc[32] = {};
uint8_t k_rrc_int[32] = {};
uint8_t k_up_enc[32] = {};
uint8_t k_up_int[32] = {};
CIPHERING_ALGORITHM_ID_ENUM cipher_algo = CIPHERING_ALGORITHM_ID_EEA0;
INTEGRITY_ALGORITHM_ID_ENUM integ_algo = INTEGRITY_ALGORITHM_ID_EIA0;
std::mutex mutex;
void integrity_generate(
uint8_t* msg, uint32_t msg_len, uint32_t count, uint32_t bearer_id, uint32_t direction, uint8_t* mac);
bool integrity_verify(
uint8_t* msg, uint32_t msg_len, uint32_t count, uint32_t bearer_id, uint32_t direction, uint8_t* mac);
void
cipher_encrypt(uint8_t* msg, uint32_t msg_len, uint32_t count, uint32_t bearer_id, uint32_t direction, uint8_t* ct);
void
cipher_decrypt(uint8_t* ct, uint32_t ct_len, uint32_t count, uint32_t bearer_id, uint32_t direction, uint8_t* msg);
};
} // namespace srslte
#endif // SRSLTE_PDCP_ENTITY_BASE_H

@ -19,8 +19,8 @@
* *
*/ */
#ifndef SRSLTE_PDCP_ENTITY_H #ifndef SRSLTE_PDCP_ENTITY_LTE_H
#define SRSLTE_PDCP_ENTITY_H #define SRSLTE_PDCP_ENTITY_LTE_H
#include "srslte/common/buffer_pool.h" #include "srslte/common/buffer_pool.h"
#include "srslte/common/log.h" #include "srslte/common/log.h"
@ -28,7 +28,7 @@
#include "srslte/interfaces/ue_interfaces.h" #include "srslte/interfaces/ue_interfaces.h"
#include "srslte/common/security.h" #include "srslte/common/security.h"
#include "srslte/common/threads.h" #include "srslte/common/threads.h"
#include "pdcp_interface.h" #include "pdcp_entity_base.h"
namespace srslte { namespace srslte {
@ -40,46 +40,29 @@ namespace srslte {
#define PDCP_CONTROL_MAC_I 0x00000000 #define PDCP_CONTROL_MAC_I 0x00000000
#define PDCP_PDU_TYPE_PDCP_STATUS_REPORT 0x0
#define PDCP_PDU_TYPE_INTERSPERSED_ROHC_FEEDBACK_PACKET 0x1
typedef enum{
PDCP_D_C_CONTROL_PDU = 0,
PDCP_D_C_DATA_PDU,
PDCP_D_C_N_ITEMS,
}pdcp_d_c_t;
static const char pdcp_d_c_text[PDCP_D_C_N_ITEMS][20] = {"Control PDU",
"Data PDU"};
/**************************************************************************** /****************************************************************************
* PDCP Entity interface * LTE PDCP Entity
* Common interface for all PDCP entities * Class for LTE PDCP entities
***************************************************************************/ ***************************************************************************/
class pdcp_entity : public pdcp_entity_interface class pdcp_entity_lte final: public pdcp_entity_base
{ {
public: public:
pdcp_entity(); pdcp_entity_lte();
~pdcp_entity(); ~pdcp_entity_lte();
void init(srsue::rlc_interface_pdcp *rlc_, void init(srsue::rlc_interface_pdcp* rlc_,
srsue::rrc_interface_pdcp *rrc_, srsue::rrc_interface_pdcp* rrc_,
srsue::gw_interface_pdcp *gw_, srsue::gw_interface_pdcp* gw_,
srslte::log *log_, srslte::log* log_,
uint32_t lcid_, uint32_t lcid_,
srslte_pdcp_config_t cfg_); srslte_pdcp_config_lte_t cfg_);
void reset(); void reset();
void reestablish(); void reestablish();
bool is_active(); bool is_active();
// RRC interface // GW/RRC interface
void write_sdu(unique_byte_buffer_t sdu, bool blocking); void write_sdu(unique_byte_buffer_t sdu, bool blocking);
void config_security(uint8_t *k_rrc_enc_,
uint8_t *k_rrc_int_,
uint8_t *k_up_enc_,
CIPHERING_ALGORITHM_ID_ENUM cipher_algo_,
INTEGRITY_ALGORITHM_ID_ENUM integ_algo_);
void enable_integrity();
void enable_encryption();
uint32_t get_dl_count(); uint32_t get_dl_count();
uint32_t get_ul_count(); uint32_t get_ul_count();
@ -87,25 +70,15 @@ public:
void write_pdu(unique_byte_buffer_t pdu); void write_pdu(unique_byte_buffer_t pdu);
private: private:
byte_buffer_pool* pool = byte_buffer_pool::get_instance();
srslte::log* log = nullptr;
srsue::rlc_interface_pdcp* rlc = nullptr; srsue::rlc_interface_pdcp* rlc = nullptr;
srsue::rrc_interface_pdcp* rrc = nullptr; srsue::rrc_interface_pdcp* rrc = nullptr;
srsue::gw_interface_pdcp* gw = nullptr; srsue::gw_interface_pdcp* gw = nullptr;
bool active = false; srslte_pdcp_config_lte_t cfg = {};
uint32_t lcid = 0;
srslte_pdcp_config_t cfg = {};
uint8_t sn_len_bytes = 0; uint8_t sn_len_bytes = 0;
bool do_integrity = false;
bool do_encryption = false;
uint32_t rx_count = 0; uint32_t rx_count = 0;
uint32_t tx_count = 0; uint32_t tx_count = 0;
uint8_t k_rrc_enc[32] = {};
uint8_t k_rrc_int[32] = {};
uint8_t k_up_enc[32] = {};
uint32_t rx_hfn = 0; uint32_t rx_hfn = 0;
uint32_t next_pdcp_rx_sn = 0; uint32_t next_pdcp_rx_sn = 0;
@ -113,18 +86,8 @@ private:
uint32_t last_submitted_pdcp_rx_sn = 0; uint32_t last_submitted_pdcp_rx_sn = 0;
uint32_t maximum_pdcp_sn = 0; uint32_t maximum_pdcp_sn = 0;
CIPHERING_ALGORITHM_ID_ENUM cipher_algo = CIPHERING_ALGORITHM_ID_EEA0;
INTEGRITY_ALGORITHM_ID_ENUM integ_algo = INTEGRITY_ALGORITHM_ID_EIA0;
pthread_mutex_t mutex;
void handle_um_drb_pdu(const srslte::unique_byte_buffer_t& pdu); void handle_um_drb_pdu(const srslte::unique_byte_buffer_t& pdu);
void handle_am_drb_pdu(const srslte::unique_byte_buffer_t& pdu); void handle_am_drb_pdu(const srslte::unique_byte_buffer_t& pdu);
void integrity_generate(uint8_t* msg, uint32_t msg_len, uint8_t* mac);
bool integrity_verify(uint8_t* msg, uint32_t count, uint32_t msg_len, uint8_t* mac);
void cipher_encrypt(uint8_t* msg, uint32_t msg_len, uint8_t* ct);
void cipher_decrypt(uint8_t* ct, uint32_t count, uint32_t ct_len, uint8_t* msg);
}; };
/**************************************************************************** /****************************************************************************
@ -141,4 +104,4 @@ void pdcp_pack_data_pdu_long_sn(uint32_t sn, byte_buffer_t *sdu);
void pdcp_unpack_data_pdu_long_sn(byte_buffer_t *sdu, uint32_t *sn); void pdcp_unpack_data_pdu_long_sn(byte_buffer_t *sdu, uint32_t *sn);
} // namespace srslte } // namespace srslte
#endif // SRSLTE_PDCP_ENTITY_H #endif // SRSLTE_PDCP_ENTITY_LTE_H

@ -0,0 +1,103 @@
/*
* Copyright 2013-2019 Software Radio Systems Limited
*
* This file is part of srsLTE.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#ifndef SRSLTE_PDCP_ENTITY_NR_H
#define SRSLTE_PDCP_ENTITY_NR_H
#include "srslte/common/buffer_pool.h"
#include "srslte/common/log.h"
#include "srslte/common/common.h"
#include "srslte/common/interfaces_common.h"
#include "srslte/common/security.h"
#include "srslte/common/threads.h"
#include "pdcp_entity_base.h"
namespace srslte {
/****************************************************************************
* PDCP Entity interface
* Common interface for all PDCP entities
***************************************************************************/
class pdcp_entity_nr : public pdcp_entity_base
{
public:
pdcp_entity_nr();
~pdcp_entity_nr();
void init(srsue::rlc_interface_pdcp* rlc_,
srsue::rrc_interface_pdcp* rrc_,
srsue::gw_interface_pdcp* gw_,
srslte::log* log_,
uint32_t lcid_,
srslte_pdcp_config_nr_t cfg_);
void reset();
void reestablish();
// RRC interface
void write_sdu(unique_byte_buffer_t sdu, bool blocking);
void config_security(uint8_t* k_rrc_enc_,
uint8_t* k_rrc_int_,
uint8_t* k_up_enc_,
uint8_t* k_up_int_,
CIPHERING_ALGORITHM_ID_ENUM cipher_algo_,
INTEGRITY_ALGORITHM_ID_ENUM integ_algo_);
void enable_integrity();
void enable_encryption();
uint32_t get_dl_count();
uint32_t get_ul_count();
// RLC interface
void write_pdu(unique_byte_buffer_t pdu);
private:
srsue::rlc_interface_pdcp* rlc = nullptr;
srsue::rrc_interface_pdcp* rrc = nullptr;
srsue::gw_interface_pdcp* gw = nullptr;
uint32_t rx_count = 0;
uint32_t tx_count = 0;
uint32_t rx_hfn = 0;
uint32_t next_pdcp_rx_sn = 0;
uint32_t reordering_window = 0;
uint32_t last_submitted_pdcp_rx_sn = 0;
uint32_t maximum_pdcp_sn = 0;
void handle_um_drb_pdu(const srslte::unique_byte_buffer_t& pdu);
void handle_am_drb_pdu(const srslte::unique_byte_buffer_t& pdu);
};
/****************************************************************************
* Pack/Unpack helper functions
* Ref: 3GPP TS 36.323 v10.1.0
***************************************************************************/
void pdcp_pack_control_pdu(uint32_t sn, byte_buffer_t *sdu);
void pdcp_unpack_control_pdu(byte_buffer_t *sdu, uint32_t *sn);
void pdcp_pack_data_pdu_short_sn(uint32_t sn, byte_buffer_t *sdu);
void pdcp_unpack_data_pdu_short_sn(byte_buffer_t *sdu, uint32_t *sn);
void pdcp_pack_data_pdu_long_sn(uint32_t sn, byte_buffer_t *sdu);
void pdcp_unpack_data_pdu_long_sn(byte_buffer_t *sdu, uint32_t *sn);
} // namespace srslte
#endif // SRSLTE_PDCP_ENTITY_NR_H

@ -1,71 +0,0 @@
/*
* Copyright 2013-2019 Software Radio Systems Limited
*
* This file is part of srsLTE.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#ifndef SRSLTE_PDCP_INTERFACE_H
#define SRSLTE_PDCP_INTERFACE_H
#include "srslte/common/buffer_pool.h"
#include "srslte/common/log.h"
#include "srslte/common/common.h"
#include "srslte/interfaces/ue_interfaces.h"
#include "srslte/common/security.h"
#include "srslte/common/threads.h"
namespace srslte {
/****************************************************************************
* Virtual PDCP interface common for all PDCP entities
***************************************************************************/
class pdcp_entity_interface
{
public:
virtual ~pdcp_entity_interface() {};
virtual void init(srsue::rlc_interface_pdcp *rlc_,
srsue::rrc_interface_pdcp *rrc_,
srsue::gw_interface_pdcp *gw_,
srslte::log *log_,
uint32_t lcid_,
srslte_pdcp_config_t cfg_) = 0;
virtual void reset() = 0;
virtual void reestablish() = 0;
virtual bool is_active() = 0;
// RRC interface
virtual void write_sdu(unique_byte_buffer_t sdu, bool blocking) = 0;
virtual void config_security(uint8_t *k_rrc_enc_,
uint8_t *k_rrc_int_,
uint8_t *k_up_enc_,
CIPHERING_ALGORITHM_ID_ENUM cipher_algo_,
INTEGRITY_ALGORITHM_ID_ENUM integ_algo_) = 0;
virtual void enable_integrity() = 0;
virtual void enable_encryption() = 0;
virtual uint32_t get_dl_count() = 0;
virtual uint32_t get_ul_count() = 0;
// RLC interface
virtual void write_pdu(unique_byte_buffer_t pdu) = 0;
};
} // namespace srslte
#endif // SRSLTE_PDCP_INTERFACE_H

@ -120,11 +120,11 @@ void pdcp::write_sdu_mch(uint32_t lcid, unique_byte_buffer_t sdu)
pthread_rwlock_unlock(&rwlock); pthread_rwlock_unlock(&rwlock);
} }
void pdcp::add_bearer(uint32_t lcid, srslte_pdcp_config_t cfg) void pdcp::add_bearer(uint32_t lcid, srslte_pdcp_config_lte_t cfg)
{ {
pthread_rwlock_wrlock(&rwlock); pthread_rwlock_wrlock(&rwlock);
if (not valid_lcid(lcid)) { if (not valid_lcid(lcid)) {
if (not pdcp_array.insert(pdcp_map_pair_t(lcid, new pdcp_entity())).second) { if (not pdcp_array.insert(pdcp_map_pair_t(lcid, new pdcp_entity_lte())).second) {
pdcp_log->error("Error inserting PDCP entity in to array\n."); pdcp_log->error("Error inserting PDCP entity in to array\n.");
goto unlock_and_exit; goto unlock_and_exit;
} }
@ -141,11 +141,11 @@ unlock_and_exit:
pthread_rwlock_unlock(&rwlock); pthread_rwlock_unlock(&rwlock);
} }
void pdcp::add_bearer_mrb(uint32_t lcid, srslte_pdcp_config_t cfg) void pdcp::add_bearer_mrb(uint32_t lcid, srslte_pdcp_config_lte_t cfg)
{ {
pthread_rwlock_wrlock(&rwlock); pthread_rwlock_wrlock(&rwlock);
if (not valid_mch_lcid(lcid)) { if (not valid_mch_lcid(lcid)) {
if (not pdcp_array_mrb.insert(pdcp_map_pair_t(lcid, new pdcp_entity())).second) { if (not pdcp_array_mrb.insert(pdcp_map_pair_t(lcid, new pdcp_entity_lte())).second) {
pdcp_log->error("Error inserting PDCP entity in to array\n."); pdcp_log->error("Error inserting PDCP entity in to array\n.");
goto unlock_and_exit; goto unlock_and_exit;
} }
@ -184,7 +184,7 @@ void pdcp::change_lcid(uint32_t old_lcid, uint32_t new_lcid)
if (valid_lcid(old_lcid) && not valid_lcid(new_lcid)) { if (valid_lcid(old_lcid) && not valid_lcid(new_lcid)) {
// insert old PDCP entity into new LCID // insert old PDCP entity into new LCID
pdcp_map_t::iterator it = pdcp_array.find(old_lcid); pdcp_map_t::iterator it = pdcp_array.find(old_lcid);
pdcp_entity_interface *pdcp_entity = it->second; pdcp_entity_lte *pdcp_entity = it->second;
if (not pdcp_array.insert(pdcp_map_pair_t(new_lcid, pdcp_entity)).second) { if (not pdcp_array.insert(pdcp_map_pair_t(new_lcid, pdcp_entity)).second) {
pdcp_log->error("Error inserting PDCP entity into array\n."); pdcp_log->error("Error inserting PDCP entity into array\n.");
goto exit; goto exit;
@ -208,7 +208,7 @@ void pdcp::config_security(uint32_t lcid,
{ {
pthread_rwlock_rdlock(&rwlock); pthread_rwlock_rdlock(&rwlock);
if (valid_lcid(lcid)) { if (valid_lcid(lcid)) {
pdcp_array.at(lcid)->config_security(k_rrc_enc, k_rrc_int, k_up_enc, cipher_algo, integ_algo); pdcp_array.at(lcid)->config_security(k_rrc_enc, k_rrc_int, k_up_enc, nullptr, cipher_algo, integ_algo);
} }
pthread_rwlock_unlock(&rwlock); pthread_rwlock_unlock(&rwlock);
} }
@ -218,7 +218,7 @@ void pdcp::config_security_all(uint8_t* k_rrc_enc, uint8_t* k_rrc_int, uint8_t*
{ {
pthread_rwlock_rdlock(&rwlock); pthread_rwlock_rdlock(&rwlock);
for (pdcp_map_t::iterator it = pdcp_array.begin(); it != pdcp_array.end(); ++it) { for (pdcp_map_t::iterator it = pdcp_array.begin(); it != pdcp_array.end(); ++it) {
it->second->config_security(k_rrc_enc, k_rrc_int, k_up_enc, cipher_algo, integ_algo); it->second->config_security(k_rrc_enc, k_rrc_int, k_up_enc, nullptr, cipher_algo, integ_algo);
} }
pthread_rwlock_unlock(&rwlock); pthread_rwlock_unlock(&rwlock);
} }
@ -241,29 +241,6 @@ void pdcp::enable_encryption(uint32_t lcid)
pthread_rwlock_unlock(&rwlock); pthread_rwlock_unlock(&rwlock);
} }
uint32_t pdcp::get_dl_count(uint32_t lcid)
{
int ret = 0;
pthread_rwlock_rdlock(&rwlock);
if (valid_lcid(lcid)) {
ret = pdcp_array.at(lcid)->get_dl_count();
}
pthread_rwlock_unlock(&rwlock);
return ret;
}
uint32_t pdcp::get_ul_count(uint32_t lcid)
{
int ret = 0;
pthread_rwlock_rdlock(&rwlock);
if (valid_lcid(lcid)) {
ret = pdcp_array.at(lcid)->get_ul_count();
}
pthread_rwlock_unlock(&rwlock);
return ret;
}
/******************************************************************************* /*******************************************************************************
RLC interface RLC interface
*******************************************************************************/ *******************************************************************************/

@ -0,0 +1,245 @@
/*
* Copyright 2013-2019 Software Radio Systems Limited
*
* This file is part of srsLTE.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include "srslte/upper/pdcp_entity_base.h"
#include "srslte/common/security.h"
namespace srslte {
pdcp_entity_base::pdcp_entity_base() {}
pdcp_entity_base::~pdcp_entity_base() {}
void pdcp_entity_base::config_security(uint8_t* k_rrc_enc_,
uint8_t* k_rrc_int_,
uint8_t* k_up_enc_,
uint8_t* k_up_int_,
CIPHERING_ALGORITHM_ID_ENUM cipher_algo_,
INTEGRITY_ALGORITHM_ID_ENUM integ_algo_)
{
// TODO add mutex
for (int i = 0; i < 32; i++) {
k_rrc_enc[i] = k_rrc_enc_[i];
k_rrc_int[i] = k_rrc_int_[i];
k_up_enc[i] = k_up_enc_[i];
if (k_up_int != nullptr) {
k_up_int[i] = k_up_int_[i];
}
}
cipher_algo = cipher_algo_;
integ_algo = integ_algo_;
}
/****************************************************************************
* Security functions
***************************************************************************/
void pdcp_entity_base::integrity_generate(
uint8_t* msg, uint32_t msg_len, uint32_t count, uint32_t bearer_id, uint32_t direction, uint8_t* mac)
{
uint8_t *k_int;
// If control plane use RRC integrity key. If data use user plane key
if (is_control()) {
k_int = k_rrc_int;
} else {
k_int = k_up_int;
}
switch(integ_algo)
{
case INTEGRITY_ALGORITHM_ID_EIA0:
break;
case INTEGRITY_ALGORITHM_ID_128_EIA1:
security_128_eia1(&k_int[16],
count,
bearer_id - 1,
direction,
msg,
msg_len,
mac);
break;
case INTEGRITY_ALGORITHM_ID_128_EIA2:
security_128_eia2(&k_int[16],
count,
bearer_id - 1,
direction,
msg,
msg_len,
mac);
break;
default:
break;
}
log->debug("Integrity gen input: COUNT %d, Bearer ID %d, Direction %s\n",
count,
bearer_id,
(direction == SECURITY_DIRECTION_DOWNLINK ? "Downlink" : "Uplink"));
log->debug_hex(mac, 4, "MAC (generated)");
log->debug_hex(msg, msg_len, " Message");
}
bool pdcp_entity_base::integrity_verify(
uint8_t* msg, uint32_t msg_len, uint32_t count, uint32_t bearer_id, uint32_t direction, uint8_t* mac)
{
uint8_t mac_exp[4] = {};
bool is_valid = true;
uint8_t *k_int;
// If control plane use RRC integrity key. If data use user plane key
if (is_control()) {
k_int = k_rrc_int;
} else {
k_int = k_up_int;
}
switch (integ_algo) {
case INTEGRITY_ALGORITHM_ID_EIA0:
break;
case INTEGRITY_ALGORITHM_ID_128_EIA1:
security_128_eia1(&k_int[16],
count,
bearer_id - 1,
(direction == SECURITY_DIRECTION_DOWNLINK) ? (SECURITY_DIRECTION_UPLINK)
: (SECURITY_DIRECTION_DOWNLINK),
msg,
msg_len,
mac_exp);
break;
case INTEGRITY_ALGORITHM_ID_128_EIA2:
security_128_eia2(&k_int[16],
count,
bearer_id - 1,
(direction == SECURITY_DIRECTION_DOWNLINK) ? (SECURITY_DIRECTION_UPLINK)
: (SECURITY_DIRECTION_DOWNLINK),
msg,
msg_len,
mac_exp);
break;
default:
break;
}
log->debug("Integrity check input: COUNT %d, Bearer ID %d, Direction %s\n",
count,
bearer_id,
(direction == SECURITY_DIRECTION_DOWNLINK ? "Downlink" : "Uplink"));
log->debug_hex(msg, msg_len, " Message");
if (integ_algo != INTEGRITY_ALGORITHM_ID_EIA0) {
for (uint8_t i = 0; i < 4; i++) {
if (mac[i] != mac_exp[i]) {
log->error_hex(mac_exp, 4, "MAC mismatch (expected)");
log->error_hex(mac, 4, "MAC mismatch (found)");
is_valid = false;
break;
}
}
if (is_valid) {
log->info_hex(mac_exp, 4, "MAC match");
}
}
return is_valid;
}
void pdcp_entity_base::cipher_encrypt(
uint8_t* msg, uint32_t msg_len, uint32_t count, uint32_t bearer_id, uint32_t direction, uint8_t* ct)
{
byte_buffer_t ct_tmp;
uint8_t *k_enc;
// If control plane use RRC encrytion key. If data use user plane key
if (is_control()) {
k_enc = k_rrc_enc;
} else {
k_enc = k_up_enc;
}
log->debug("Cipher encrypt input: COUNT: %d, Bearer ID: %d, Direction %s\n",
count,
bearer_id,
(direction == SECURITY_DIRECTION_DOWNLINK) ? "Downlink" : "Uplink");
switch (cipher_algo) {
case CIPHERING_ALGORITHM_ID_EEA0:
break;
case CIPHERING_ALGORITHM_ID_128_EEA1:
security_128_eea1(&(k_enc[16]), count, bearer_id - 1, direction, msg, msg_len, ct_tmp.msg);
memcpy(ct, ct_tmp.msg, msg_len);
break;
case CIPHERING_ALGORITHM_ID_128_EEA2:
security_128_eea2(&(k_enc[16]), count, bearer_id - 1, direction, msg, msg_len, ct_tmp.msg);
memcpy(ct, ct_tmp.msg, msg_len);
break;
default:
break;
}
}
void pdcp_entity_base::cipher_decrypt(
uint8_t* ct, uint32_t ct_len, uint32_t count, uint32_t bearer_id, uint32_t direction, uint8_t* msg)
{
byte_buffer_t msg_tmp;
uint8_t *k_enc;
// If control plane use RRC encrytion key. If data use user plane key
if (is_control()) {
k_enc = k_rrc_enc;
} else {
k_enc = k_up_enc;
}
log->debug("Cipher decript input: COUNT: %d, Bearer ID: %d, Direction %s\n",
count,
bearer_id,
(direction == SECURITY_DIRECTION_DOWNLINK) ? "Downlink" : "Uplink");
switch(cipher_algo)
{
case CIPHERING_ALGORITHM_ID_EEA0:
break;
case CIPHERING_ALGORITHM_ID_128_EEA1:
security_128_eea1(&(k_enc[16]),
count,
bearer_id - 1,
(direction == SECURITY_DIRECTION_DOWNLINK) ? (SECURITY_DIRECTION_UPLINK) : (SECURITY_DIRECTION_DOWNLINK),
ct,
ct_len,
msg_tmp.msg);
memcpy(msg, msg_tmp.msg, ct_len);
break;
case CIPHERING_ALGORITHM_ID_128_EEA2:
security_128_eea2(&(k_enc[16]),
count,
bearer_id - 1,
(direction == SECURITY_DIRECTION_DOWNLINK) ? (SECURITY_DIRECTION_UPLINK) : (SECURITY_DIRECTION_DOWNLINK),
ct,
ct_len,
msg_tmp.msg);
memcpy(msg, msg_tmp.msg, ct_len);
break;
default:
break;
}
}
}

@ -0,0 +1,374 @@
/*
* Copyright 2013-2019 Software Radio Systems Limited
*
* This file is part of srsLTE.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include "srslte/upper/pdcp_entity_lte.h"
#include "srslte/common/security.h"
namespace srslte {
pdcp_entity_lte::pdcp_entity_lte() {}
pdcp_entity_lte::~pdcp_entity_lte() {}
void pdcp_entity_lte::init(srsue::rlc_interface_pdcp* rlc_,
srsue::rrc_interface_pdcp* rrc_,
srsue::gw_interface_pdcp* gw_,
srslte::log* log_,
uint32_t lcid_,
srslte_pdcp_config_lte_t cfg_)
{
rlc = rlc_;
rrc = rrc_;
gw = gw_;
log = log_;
lcid = lcid_;
cfg = cfg_;
active = true;
tx_count = 0;
rx_count = 0;
do_integrity = false;
do_encryption = false;
cfg = cfg_;
// set length of SN field in bytes
sn_len_bytes = (cfg.sn_len == 5) ? 1 : 2;
if (cfg.is_control) {
reordering_window = 0;
} else if (cfg.is_data) {
reordering_window = 2048;
}
rx_hfn = 0;
next_pdcp_rx_sn = 0;
maximum_pdcp_sn = (1 << cfg.sn_len) - 1;
last_submitted_pdcp_rx_sn = maximum_pdcp_sn;
log->info("Init %s with bearer ID: %d\n", rrc->get_rb_name(lcid).c_str(), cfg.bearer_id);
log->info("SN len bits: %d, SN len bytes: %d, reordering window: %d, Maximum SN %d\n",
cfg.sn_len,
sn_len_bytes,
reordering_window,
maximum_pdcp_sn);
}
// Reestablishment procedure: 36.323 5.2
void pdcp_entity_lte::reestablish()
{
log->info("Re-establish %s with bearer ID: %d\n", rrc->get_rb_name(lcid).c_str(), cfg.bearer_id);
// For SRBs
if (cfg.is_control) {
tx_count = 0;
rx_count = 0;
rx_hfn = 0;
next_pdcp_rx_sn = 0;
} else {
// Only reset counter in RLC-UM
if (rlc->rb_is_um(lcid)) {
tx_count = 0;
rx_count = 0;
rx_hfn = 0;
next_pdcp_rx_sn = 0;
} else {
tx_count = 0;
rx_count = 0;
rx_hfn = 0;
next_pdcp_rx_sn = 0;
last_submitted_pdcp_rx_sn = maximum_pdcp_sn;
}
}
}
// Used to stop/pause the entity (called on RRC conn release)
void pdcp_entity_lte::reset()
{
active = false;
if (log) {
log->debug("Reset %s\n", rrc->get_rb_name(lcid).c_str());
}
}
// GW/RRC interface
void pdcp_entity_lte::write_sdu(unique_byte_buffer_t sdu, bool blocking)
{
log->info_hex(sdu->msg, sdu->N_bytes,
"TX %s SDU, SN: %d, do_integrity = %s, do_encryption = %s",
rrc->get_rb_name(lcid).c_str(), tx_count,
(do_integrity) ? "true" : "false", (do_encryption) ? "true" : "false");
pthread_mutex_lock(&mutex);
if (cfg.is_control) {
pdcp_pack_control_pdu(tx_count, sdu.get());
if(do_integrity) {
integrity_generate(sdu->msg,
sdu->N_bytes-4,
&sdu->msg[sdu->N_bytes-4]);
}
}
if (cfg.is_data) {
if(12 == cfg.sn_len) {
pdcp_pack_data_pdu_long_sn(tx_count, sdu.get());
} else {
pdcp_pack_data_pdu_short_sn(tx_count, sdu.get());
}
}
if(do_encryption) {
cipher_encrypt(&sdu->msg[sn_len_bytes],
sdu->N_bytes-sn_len_bytes,
&sdu->msg[sn_len_bytes]);
log->info_hex(sdu->msg, sdu->N_bytes, "TX %s SDU (encrypted)", rrc->get_rb_name(lcid).c_str());
}
tx_count++;
pthread_mutex_unlock(&mutex);
rlc->write_sdu(lcid, std::move(sdu), blocking);
}
// RLC interface
void pdcp_entity_lte::write_pdu(unique_byte_buffer_t pdu)
{
log->info_hex(pdu->msg,
pdu->N_bytes,
"RX %s PDU (%d B), do_integrity = %s, do_encryption = %s",
rrc->get_rb_name(lcid).c_str(),
pdu->N_bytes,
(do_integrity) ? "true" : "false",
(do_encryption) ? "true" : "false");
// Sanity check
if (pdu->N_bytes <= sn_len_bytes) {
return;
}
pthread_mutex_lock(&mutex);
if (cfg.is_data) {
// Handle DRB messages
if (rlc->rb_is_um(lcid)) {
handle_um_drb_pdu(pdu);
} else {
handle_am_drb_pdu(pdu);
}
gw->write_pdu(lcid, std::move(pdu));
} else {
// Handle SRB messages
if (cfg.is_control) {
uint32_t sn = *pdu->msg & 0x1F;
if (do_encryption) {
cipher_decrypt(&pdu->msg[sn_len_bytes], sn, pdu->N_bytes - sn_len_bytes, &(pdu->msg[sn_len_bytes]));
log->info_hex(pdu->msg, pdu->N_bytes, "RX %s PDU (decrypted)", rrc->get_rb_name(lcid).c_str());
}
if (do_integrity) {
if (not integrity_verify(pdu->msg, sn, pdu->N_bytes - 4, &(pdu->msg[pdu->N_bytes - 4]))) {
log->error_hex(pdu->msg, pdu->N_bytes, "%s Dropping PDU", rrc->get_rb_name(lcid).c_str());
goto exit;
}
}
pdcp_unpack_control_pdu(pdu.get(), &sn);
log->info_hex(pdu->msg, pdu->N_bytes, "RX %s PDU SN: %d", rrc->get_rb_name(lcid).c_str(), sn);
}
// pass to RRC
rrc->write_pdu(lcid, std::move(pdu));
}
exit:
rx_count++;
pthread_mutex_unlock(&mutex);
}
/****************************************************************************
* Rx data/control handler functions
* Ref: 3GPP TS 36.323 v10.1.0 Section 5.1.2
***************************************************************************/
// DRBs mapped on RLC UM (5.1.2.1.3)
void pdcp_entity_lte::handle_um_drb_pdu(const srslte::unique_byte_buffer_t &pdu)
{
uint32_t sn;
if (12 == cfg.sn_len) {
pdcp_unpack_data_pdu_long_sn(pdu.get(), &sn);
} else {
pdcp_unpack_data_pdu_short_sn(pdu.get(), &sn);
}
if (sn < next_pdcp_rx_sn) {
rx_hfn++;
}
uint32_t count = (rx_hfn << cfg.sn_len) | sn;
if (do_encryption) {
cipher_decrypt(pdu->msg, count, pdu->N_bytes, pdu->msg);
log->debug_hex(pdu->msg, pdu->N_bytes, "RX %s PDU (decrypted)", rrc->get_rb_name(lcid).c_str());
}
next_pdcp_rx_sn = sn + 1;
if (next_pdcp_rx_sn > maximum_pdcp_sn) {
next_pdcp_rx_sn = 0;
rx_hfn++;
}
log->info_hex(pdu->msg, pdu->N_bytes, "RX %s PDU SN: %d", rrc->get_rb_name(lcid).c_str(), sn);
return;
}
// DRBs mapped on RLC AM, without re-ordering (5.1.2.1.2)
void pdcp_entity_lte::handle_am_drb_pdu(const srslte::unique_byte_buffer_t &pdu)
{
uint32_t sn, count;
pdcp_unpack_data_pdu_long_sn(pdu.get(), &sn);
int32_t last_submit_diff_sn = last_submitted_pdcp_rx_sn - sn;
int32_t sn_diff_last_submit = sn - last_submitted_pdcp_rx_sn;
int32_t sn_diff_next_pdcp_rx_sn = sn - next_pdcp_rx_sn;
log->debug("RX HFN: %d, SN: %d, Last_Submitted_PDCP_RX_SN: %d, Next_PDCP_RX_SN %d\n",
rx_hfn,
sn,
last_submitted_pdcp_rx_sn,
next_pdcp_rx_sn);
bool discard = false;
if ((0 <= sn_diff_last_submit && sn_diff_last_submit > (int32_t)reordering_window) ||
(0 <= last_submit_diff_sn && last_submit_diff_sn < (int32_t)reordering_window)) {
log->debug("|SN - last_submitted_sn| is larger than re-ordering window.\n");
if (sn > next_pdcp_rx_sn) {
count = (rx_hfn - 1) << cfg.sn_len | sn;
} else {
count = rx_hfn << cfg.sn_len | sn;
}
discard = true;
} else if ((int32_t)(next_pdcp_rx_sn - sn) > (int32_t)reordering_window) {
log->debug("(Next_PDCP_RX_SN - SN) is larger than re-ordering window.\n");
rx_hfn++;
count = (rx_hfn << cfg.sn_len) | sn;
next_pdcp_rx_sn = sn + 1;
} else if (sn_diff_next_pdcp_rx_sn >= (int32_t)reordering_window) {
log->debug("(SN - Next_PDCP_RX_SN) is larger or equal than re-ordering window.\n");
count = ((rx_hfn - 1) << cfg.sn_len) | sn;
} else if (sn >= next_pdcp_rx_sn) {
log->debug("SN is larger or equal than Next_PDCP_RX_SN.\n");
count = (rx_hfn << cfg.sn_len) | sn;
next_pdcp_rx_sn = sn + 1;
if (next_pdcp_rx_sn > maximum_pdcp_sn) {
next_pdcp_rx_sn = 0;
rx_hfn++;
}
} else if (sn < next_pdcp_rx_sn) {
log->debug("SN is smaller than Next_PDCP_RX_SN.\n");
count = (rx_hfn << cfg.sn_len) | sn;
}
// FIXME Check if PDU is not due to re-establishment of lower layers?
cipher_decrypt(pdu->msg, count, pdu->N_bytes, pdu->msg);
log->debug_hex(pdu->msg, pdu->N_bytes, "RX %s PDU (decrypted)", rrc->get_rb_name(lcid).c_str());
if (!discard) {
last_submitted_pdcp_rx_sn = sn;
}
return;
}
/****************************************************************************
* Security functions
***************************************************************************/
uint32_t pdcp_entity_lte::get_dl_count()
{
return rx_count;
}
uint32_t pdcp_entity_lte::get_ul_count()
{
return tx_count;
}
/****************************************************************************
* Pack/Unpack helper functions
* Ref: 3GPP TS 36.323 v10.1.0
***************************************************************************/
void pdcp_pack_control_pdu(uint32_t sn, byte_buffer_t *sdu)
{
// Make room and add header
sdu->msg--;
sdu->N_bytes++;
*sdu->msg = sn & 0x1F;
// Add MAC
sdu->msg[sdu->N_bytes++] = (PDCP_CONTROL_MAC_I >> 24) & 0xFF;
sdu->msg[sdu->N_bytes++] = (PDCP_CONTROL_MAC_I >> 16) & 0xFF;
sdu->msg[sdu->N_bytes++] = (PDCP_CONTROL_MAC_I >> 8) & 0xFF;
sdu->msg[sdu->N_bytes++] = PDCP_CONTROL_MAC_I & 0xFF;
}
void pdcp_unpack_control_pdu(byte_buffer_t *pdu, uint32_t *sn)
{
// Strip header
*sn = *pdu->msg & 0x1F;
pdu->msg++;
pdu->N_bytes--;
// Strip MAC
pdu->N_bytes -= 4;
// TODO: integrity check MAC
}
void pdcp_pack_data_pdu_short_sn(uint32_t sn, byte_buffer_t *sdu)
{
// Make room and add header
sdu->msg--;
sdu->N_bytes++;
sdu->msg[0] = (PDCP_D_C_DATA_PDU << 7) | (sn & 0x7F);
}
void pdcp_unpack_data_pdu_short_sn(byte_buffer_t *sdu, uint32_t *sn)
{
// Strip header
*sn = sdu->msg[0] & 0x7F;
sdu->msg++;
sdu->N_bytes--;
}
void pdcp_pack_data_pdu_long_sn(uint32_t sn, byte_buffer_t *sdu)
{
// Make room and add header
sdu->msg -= 2;
sdu->N_bytes += 2;
sdu->msg[0] = (PDCP_D_C_DATA_PDU << 7) | ((sn >> 8) & 0x0F);
sdu->msg[1] = sn & 0xFF;
}
void pdcp_unpack_data_pdu_long_sn(byte_buffer_t *sdu, uint32_t *sn)
{
// Strip header
*sn = (sdu->msg[0] & 0x0F) << 8;
*sn |= sdu->msg[1];
sdu->msg += 2;
sdu->N_bytes -= 2;
}
}

@ -19,37 +19,29 @@
* *
*/ */
#include "srslte/upper/pdcp_entity.h" #include "srslte/upper/pdcp_entity_nr.h"
#include "srslte/common/security.h" #include "srslte/common/security.h"
namespace srslte { namespace srslte {
pdcp_entity::pdcp_entity() pdcp_entity::pdcp_entity() {}
{
pthread_mutex_init(&mutex, nullptr);
}
pdcp_entity::~pdcp_entity() pdcp_entity::~pdcp_entity() {}
{
pthread_mutex_destroy(&mutex);
}
void pdcp_entity::init(srsue::rlc_interface_pdcp* rlc_, void pdcp_entity_nr::init(srsue::rlc_interface_pdcp* rlc_,
srsue::rrc_interface_pdcp* rrc_, srsue::rrc_interface_pdcp* rrc_,
srsue::gw_interface_pdcp* gw_, srsue::sdap_interface_pdcp* sdap_,
srslte::log* log_, srslte::log* log_,
uint32_t lcid_, uint32_t lcid_,
srslte_pdcp_config_t cfg_) srslte_pdcp_nr_config_t cfg_)
{ {
rlc = rlc_; rlc = rlc_;
rrc = rrc_; rrc = rrc_;
gw = gw_; sdap = sdap_;
log = log_; log = log_;
lcid = lcid_; lcid = lcid_;
cfg = cfg_; cfg = cfg_;
active = true; active = true;
tx_count = 0;
rx_count = 0;
do_integrity = false; do_integrity = false;
do_encryption = false; do_encryption = false;
@ -117,7 +109,7 @@ bool pdcp_entity::is_active()
return active; return active;
} }
// GW/RRC interface // SDAP/RRC interface
void pdcp_entity::write_sdu(unique_byte_buffer_t sdu, bool blocking) void pdcp_entity::write_sdu(unique_byte_buffer_t sdu, bool blocking)
{ {
log->info_hex(sdu->msg, sdu->N_bytes, log->info_hex(sdu->msg, sdu->N_bytes,
@ -552,7 +544,7 @@ uint32_t pdcp_entity::get_ul_count()
/**************************************************************************** /****************************************************************************
* Pack/Unpack helper functions * Pack/Unpack helper functions
* Ref: 3GPP TS 36.323 v10.1.0 * Ref: 3GPP TS 38.323 v15.2.0
***************************************************************************/ ***************************************************************************/
void pdcp_pack_control_pdu(uint32_t sn, byte_buffer_t *sdu) void pdcp_pack_control_pdu(uint32_t sn, byte_buffer_t *sdu)
@ -562,7 +554,7 @@ void pdcp_pack_control_pdu(uint32_t sn, byte_buffer_t *sdu)
sdu->N_bytes++; sdu->N_bytes++;
*sdu->msg = sn & 0x1F; *sdu->msg = sn & 0x1F;
// Add MAC // Pack FMC
sdu->msg[sdu->N_bytes++] = (PDCP_CONTROL_MAC_I >> 24) & 0xFF; sdu->msg[sdu->N_bytes++] = (PDCP_CONTROL_MAC_I >> 24) & 0xFF;
sdu->msg[sdu->N_bytes++] = (PDCP_CONTROL_MAC_I >> 16) & 0xFF; sdu->msg[sdu->N_bytes++] = (PDCP_CONTROL_MAC_I >> 16) & 0xFF;
sdu->msg[sdu->N_bytes++] = (PDCP_CONTROL_MAC_I >> 8) & 0xFF; sdu->msg[sdu->N_bytes++] = (PDCP_CONTROL_MAC_I >> 8) & 0xFF;

@ -48,16 +48,17 @@ public:
void add_user(uint16_t rnti); void add_user(uint16_t rnti);
void rem_user(uint16_t rnti); void rem_user(uint16_t rnti);
void write_sdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t sdu); void write_sdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t sdu);
void add_bearer(uint16_t rnti, uint32_t lcid, srslte::srslte_pdcp_config_t cnfg); void add_bearer(uint16_t rnti, uint32_t lcid, srslte::srslte_pdcp_config_lte_t cnfg);
void config_security(uint16_t rnti, void config_security(uint16_t rnti,
uint32_t lcid, uint32_t lcid,
uint8_t *k_rrc_enc_, uint8_t* k_rrc_enc_,
uint8_t *k_rrc_int_, uint8_t* k_rrc_int_,
uint8_t *k_up_enc_, uint8_t* k_up_enc_,
srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo_, srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo_,
srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo_); srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo_);
void enable_integrity(uint16_t rnti, uint32_t lcid); void enable_integrity(uint16_t rnti, uint32_t lcid);
void enable_encryption(uint16_t rnti, uint32_t lcid); void enable_encryption(uint16_t rnti, uint32_t lcid);
private: private:
class user_interface_rlc : public srsue::rlc_interface_pdcp class user_interface_rlc : public srsue::rlc_interface_pdcp

@ -193,7 +193,7 @@ void rrc::add_user(uint16_t rnti)
} }
if (rnti == SRSLTE_MRNTI) { if (rnti == SRSLTE_MRNTI) {
srslte::srslte_pdcp_config_t cfg; srslte::srslte_pdcp_config_lte_t cfg;
cfg.is_control = false; cfg.is_control = false;
cfg.is_data = true; cfg.is_data = true;
cfg.sn_len = 12; cfg.sn_len = 12;
@ -1529,7 +1529,7 @@ void rrc::ue::send_connection_setup(bool is_setup)
parent->rlc->add_bearer(rnti, 1, srslte::rlc_config_t::srb_config(1)); parent->rlc->add_bearer(rnti, 1, srslte::rlc_config_t::srb_config(1));
// Configure SRB1 in PDCP // Configure SRB1 in PDCP
srslte::srslte_pdcp_config_t pdcp_cnfg; srslte::srslte_pdcp_config_lte_t pdcp_cnfg;
pdcp_cnfg.bearer_id = 1; pdcp_cnfg.bearer_id = 1;
pdcp_cnfg.is_control = true; pdcp_cnfg.is_control = true;
pdcp_cnfg.is_data = false; pdcp_cnfg.is_data = false;
@ -1739,7 +1739,7 @@ void rrc::ue::send_connection_reconf(srslte::unique_byte_buffer_t pdu)
parent->rlc->add_bearer(rnti, 2, srslte::rlc_config_t::srb_config(2)); parent->rlc->add_bearer(rnti, 2, srslte::rlc_config_t::srb_config(2));
// Configure SRB2 in PDCP // Configure SRB2 in PDCP
srslte::srslte_pdcp_config_t pdcp_cnfg; srslte::srslte_pdcp_config_lte_t pdcp_cnfg;
pdcp_cnfg.bearer_id = 2; pdcp_cnfg.bearer_id = 2;
pdcp_cnfg.direction = SECURITY_DIRECTION_DOWNLINK; pdcp_cnfg.direction = SECURITY_DIRECTION_DOWNLINK;
pdcp_cnfg.is_control = true; pdcp_cnfg.is_control = true;
@ -1821,7 +1821,7 @@ void rrc::ue::send_connection_reconf_new_bearer(LIBLTE_S1AP_E_RABTOBESETUPLISTBE
parent->rlc->add_bearer(rnti, lcid, srslte::make_rlc_config_t(drb_item.rlc_cfg)); parent->rlc->add_bearer(rnti, lcid, srslte::make_rlc_config_t(drb_item.rlc_cfg));
// Configure DRB in PDCP // Configure DRB in PDCP
srslte::srslte_pdcp_config_t pdcp_config; srslte::srslte_pdcp_config_lte_t pdcp_config;
pdcp_config.bearer_id = drb_item.drb_id - 1; // TODO: Review all ID mapping LCID DRB ERAB EPSBID Mapping pdcp_config.bearer_id = drb_item.drb_id - 1; // TODO: Review all ID mapping LCID DRB ERAB EPSBID Mapping
pdcp_config.is_control = false; pdcp_config.is_control = false;
pdcp_config.is_data = true; pdcp_config.is_data = true;

@ -82,7 +82,7 @@ void pdcp::rem_user(uint16_t rnti)
pthread_rwlock_unlock(&rwlock); pthread_rwlock_unlock(&rwlock);
} }
void pdcp::add_bearer(uint16_t rnti, uint32_t lcid, srslte::srslte_pdcp_config_t cfg) void pdcp::add_bearer(uint16_t rnti, uint32_t lcid, srslte::srslte_pdcp_config_lte_t cfg)
{ {
pthread_rwlock_rdlock(&rwlock); pthread_rwlock_rdlock(&rwlock);
if (users.count(rnti)) { if (users.count(rnti)) {

@ -3145,7 +3145,7 @@ void rrc::handle_con_reest(rrc_conn_reest_s* setup)
void rrc::add_srb(srb_to_add_mod_s* srb_cnfg) void rrc::add_srb(srb_to_add_mod_s* srb_cnfg)
{ {
// Setup PDCP // Setup PDCP
srslte_pdcp_config_t pdcp_cfg; srslte_pdcp_config_lte_t pdcp_cfg;
pdcp_cfg.is_control = true; pdcp_cfg.is_control = true;
pdcp_cfg.is_data = false; pdcp_cfg.is_data = false;
pdcp_cfg.sn_len = 5; pdcp_cfg.sn_len = 5;
@ -3222,7 +3222,7 @@ void rrc::add_drb(drb_to_add_mod_s* drb_cnfg)
} }
// Setup PDCP // Setup PDCP
srslte_pdcp_config_t pdcp_cfg = {}; srslte_pdcp_config_lte_t pdcp_cfg = {};
pdcp_cfg.is_data = true; pdcp_cfg.is_data = true;
pdcp_cfg.bearer_id = drb_cnfg->drb_id; pdcp_cfg.bearer_id = drb_cnfg->drb_id;
if (drb_cnfg->pdcp_cfg.rlc_um_present) { if (drb_cnfg->pdcp_cfg.rlc_um_present) {

Loading…
Cancel
Save