Merge branch 'next' into agpl_next

master
Codebot 3 years ago committed by Your Name
commit 958542dc2b

File diff suppressed because it is too large Load Diff

@ -1822,11 +1822,11 @@ public:
nas_5gs_hdr hdr;
SRSASN_CODE pack(unique_byte_buffer_t& buf);
SRSASN_CODE pack(std::vector<uint8_t> buf);
SRSASN_CODE pack(std::vector<uint8_t>& buf);
SRSASN_CODE unpack(const unique_byte_buffer_t& buf);
SRSASN_CODE unpack(const std::vector<uint8_t> buf);
SRSASN_CODE unpack(const std::vector<uint8_t>& buf);
SRSASN_CODE unpack_outer_hdr(const unique_byte_buffer_t& buf);
SRSASN_CODE unpack_outer_hdr(const std::vector<uint8_t> buf);
SRSASN_CODE unpack_outer_hdr(const std::vector<uint8_t>& buf);
void set(msg_types::options e = msg_types::nulltype) { hdr.message_type = e; };
// Getters

@ -22,6 +22,7 @@
#ifndef SRSRAN_BEARER_MANAGER_H
#define SRSRAN_BEARER_MANAGER_H
#include "srsenb/hdr/common/common_enb.h"
#include "srsran/common/common.h"
#include "srsran/common/rwlock_guard.h"
#include "srsran/srslog/srslog.h"
@ -30,10 +31,53 @@
namespace srsran {
namespace detail {
/**
* @brief Implementation of UE bearer manager internal functionality that is common to both srsue and
* srsenb applications
*/
class ue_bearer_manager_impl
{
public:
struct radio_bearer_t {
srsran::srsran_rat_t rat;
uint32_t lcid;
uint32_t eps_bearer_id;
bool is_valid() const { return rat != srsran_rat_t::nulltype; }
};
static const radio_bearer_t invalid_rb;
/// Registers EPS bearer with PDCP RAT type and LCID
bool add_eps_bearer(uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid);
/// Single EPS bearer is removed from map when the associated DRB is deleted
bool remove_eps_bearer(uint8_t eps_bearer_id);
void reset();
bool has_active_radio_bearer(uint32_t eps_bearer_id);
radio_bearer_t get_radio_bearer(uint32_t eps_bearer_id);
radio_bearer_t get_lcid_bearer(uint32_t lcid);
private:
using eps_rb_map_t = std::map<uint32_t, radio_bearer_t>;
eps_rb_map_t bearers;
std::map<uint32_t, uint32_t> lcid_to_eps_bearer_id;
};
} // namespace detail
} // namespace srsran
namespace srsue {
/**
* @brief Helper class to manage the mapping between EPS bearer and radio bearer
*
* The class maps EPS bearers that are known to NAS and GW (UE) or GTPU (eNB)
* The class maps EPS bearers that are known to NAS and GW (UE)
* to radio bearer (RB) that are only known to RRC.
* Since the lifetime of a EPS bearer is usually longer than the lifetime of a RB,
* the GW/GTPU needs to query the Stack to check whether a
@ -49,20 +93,15 @@ namespace srsran {
* used by the eNB.
*
*/
class bearer_manager
class ue_bearer_manager
{
public:
bearer_manager();
~bearer_manager();
using radio_bearer_t = srsran::detail::ue_bearer_manager_impl::radio_bearer_t;
struct radio_bearer_t {
srsran::srsran_rat_t rat;
uint32_t lcid;
uint32_t eps_bearer_id;
bool is_valid() const { return rat != srsran_rat_t::nulltype; }
};
/// Single user interface (for UE)
ue_bearer_manager();
ue_bearer_manager(const ue_bearer_manager&) = delete;
ue_bearer_manager& operator=(const ue_bearer_manager&) = delete;
~ue_bearer_manager();
// RRC interface
/// Registers EPS bearer with PDCP RAT type and LCID
@ -74,36 +113,43 @@ public:
/// All registered bearer are removed (e.g. after connection release)
void reset();
// GW interface
bool has_active_radio_bearer(uint32_t eps_bearer_id);
bool has_active_radio_bearer(uint32_t eps_bearer_id) { return impl.has_active_radio_bearer(eps_bearer_id); }
// Stack interface to retrieve active RB
radio_bearer_t get_radio_bearer(uint32_t eps_bearer_id);
radio_bearer_t get_radio_bearer(uint32_t eps_bearer_id) { return impl.get_radio_bearer(eps_bearer_id); }
radio_bearer_t get_lcid_bearer(uint16_t rnti, uint32_t lcid);
radio_bearer_t get_lcid_bearer(uint32_t lcid) { return impl.get_lcid_bearer(lcid); }
private:
pthread_rwlock_t rwlock = {}; /// RW lock to protect access from RRC/GW threads
srslog::basic_logger& logger;
srsran::detail::ue_bearer_manager_impl impl;
};
} // namespace srsue
namespace srsenb {
class enb_bearer_manager
{
public:
using radio_bearer_t = srsran::detail::ue_bearer_manager_impl::radio_bearer_t;
enb_bearer_manager();
/// Multi-user interface (see comments above)
void add_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid);
void remove_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id);
void reset(uint16_t rnti);
void rem_user(uint16_t rnti);
bool has_active_radio_bearer(uint16_t rnti, uint32_t eps_bearer_id);
radio_bearer_t get_radio_bearer(uint16_t rnti, uint32_t eps_bearer_id);
radio_bearer_t get_lcid_bearer(uint16_t rnti, uint32_t lcid);
private:
pthread_rwlock_t rwlock = {}; /// RW lock to protect access from RRC/GW threads
srslog::basic_logger& logger;
typedef std::map<uint32_t, radio_bearer_t> eps_rb_map_t;
struct user_bearers {
eps_rb_map_t bearers;
std::map<uint32_t, uint32_t> lcid_to_eps_bearer_id;
};
std::map<uint16_t, user_bearers> users_map;
const uint16_t default_key = 0xffff; // dummy RNTI used for public interface without explicit RNTI
radio_bearer_t invalid_rb = {srsran::srsran_rat_t::nulltype, 0, 0};
srsenb::rnti_map_t<srsran::detail::ue_bearer_manager_impl> users_map;
};
} // namespace srsran
} // namespace srsenb
#endif // SRSRAN_BEARER_MANAGER_H

@ -40,7 +40,8 @@ public:
/// Logs into the underlying log channel any RRC event.
virtual void log_rrc_event(uint32_t enb_cc_idx,
const std::string& asn1,
const std::string& asn1_oct_str,
const std::string& asn1_txt_str,
unsigned type,
unsigned additional_info,
uint16_t rnti) = 0;
@ -52,16 +53,35 @@ public:
virtual void log_s1_ctx_delete(uint32_t enb_cc_idx, uint32_t mme_id, uint32_t enb_id, uint16_t rnti) = 0;
/// Logs into the underlying log channel when a sector has been started.
virtual void log_sector_start(uint32_t cc_idx, uint32_t pci, uint32_t cell_id) = 0;
virtual void log_sector_start(uint32_t cc_idx, uint32_t pci, uint32_t cell_id, const std::string &hnb_name) = 0;
/// Logs into the underlying log channel when a sector has been stopped.
virtual void log_sector_stop(uint32_t cc_idx, uint32_t pci, uint32_t cell_id) = 0;
/// Logs into the underlying log channel a measurement report event..
virtual void log_measurement_report(uint32_t enb_cc_idx, const std::string& asn1, uint16_t rnti) = 0;
/// Logs into the underlying log channel a RLF event.
virtual void log_rlf(uint32_t enb_cc_idx, const std::string& asn1, uint16_t rnti) = 0;
virtual void log_sector_stop(uint32_t cc_idx, uint32_t pci, uint32_t cell_id, const std::string &hnb_name) = 0;
/// Logs into the underlying log channel a measurement report event.
virtual void log_measurement_report(uint32_t enb_cc_idx,
const std::string& asn1_oct_str,
const std::string& asn1_txt_str,
uint16_t rnti) = 0;
/// Logs into the underlying log channel a RLF report.
virtual void log_rlf_report(uint32_t enb_cc_idx,
const std::string& asn1_oct_str,
const std::string& asn1_txt_str,
uint16_t rnti) = 0;
/// Logs into the underlying log channel a RLF detection event.
virtual void log_rlf_detected(uint32_t enb_cc_idx, const std::string& type, uint16_t rnti) = 0;
/// Logs into the underlying log channel a handover command event.
virtual void log_handover_command(uint32_t enb_cc_idx,
uint32_t target_pci,
uint32_t target_earfcn,
uint16_t new_ue_rnti,
uint16_t rnti) = 0;
/// Logs into the underlying log channel a connection resume event.
virtual void log_connection_resume(uint32_t enb_cc_idx, uint16_t resume_rnti, uint16_t rnti) = 0;
};
/// Singleton class to provide global access to the event_logger_interface interface.
@ -70,12 +90,15 @@ class event_logger
event_logger() = default;
public:
/// ASN1 output printing format.
enum class asn1_output_format { text, octets };
/// Returns the instance of the event logger.
static event_logger_interface& get();
/// Uses the specified log channel for event logging.
/// NOTE: This method is not thread safe.
static void configure(srslog::log_channel& c);
static void configure(srslog::log_channel& c, asn1_output_format asn1_format);
private:
static std::unique_ptr<event_logger_interface> pimpl;

@ -147,6 +147,13 @@ LIBLTE_ERROR_ENUM liblte_security_generate_k_up(uint8*
uint8* k_up_int);
LIBLTE_ERROR_ENUM liblte_security_generate_sk_gnb(uint8_t* k_enb, uint8_t* sk_gnb, uint16_t scg_counter);
LIBLTE_ERROR_ENUM liblte_security_generate_res_star(uint8_t* ck,
uint8_t* ik,
const char* serving_network_name,
uint8_t* rand,
uint8_t* res,
size_t res_len,
uint8_t* res_star);
/*********************************************************************
Name: liblte_security_128_eia2

@ -27,7 +27,21 @@
*****************************************************************************/
#include "srsran/common/common.h"
#include "srsran/srslog/srslog.h"
#include <vector>
#define AKA_RAND_LEN 16
#define AKA_AUTN_LEN 16
#define AKA_AUTS_LEN 14
#define RES_MAX_LEN 16
#define MAC_LEN 8
#define IK_LEN 16
#define CK_LEN 16
#define AK_LEN 6
#define SQN_LEN 6
#define KEY_LEN 32
namespace srsran {
typedef enum {
@ -82,55 +96,120 @@ struct as_security_config_t {
CIPHERING_ALGORITHM_ID_ENUM cipher_algo;
};
template <typename... Args>
void log_error(const char* format, Args&&... args)
{
srslog::fetch_basic_logger("SEC").error(format, std::forward<Args>(args)...);
}
template <typename... Args>
void log_warning(const char* format, Args&&... args)
{
srslog::fetch_basic_logger("SEC").warning(format, std::forward<Args>(args)...);
}
template <typename... Args>
void log_info(const char* format, Args&&... args)
{
srslog::fetch_basic_logger("SEC").info(format, std::forward<Args>(args)...);
}
template <typename... Args>
void log_debug(const char* format, Args&&... args)
{
srslog::fetch_basic_logger("SEC").debug(format, std::forward<Args>(args)...);
}
/******************************************************************************
* Key Generation
*****************************************************************************/
uint8_t security_generate_k_asme(uint8_t* ck,
uint8_t* ik,
uint8_t* ak,
uint8_t* sqn,
uint16_t mcc,
uint16_t mnc,
uint8_t* k_asme);
uint8_t security_generate_k_enb(uint8_t* k_asme, uint32_t nas_count, uint8_t* k_enb);
uint8_t security_generate_k_enb_star(uint8_t* k_enb, uint32_t pci, uint32_t earfcn, uint8_t* k_enb_star);
uint8_t security_generate_nh(uint8_t* k_asme, uint8_t* sync, uint8_t* nh);
uint8_t security_generate_k_nas(uint8_t* k_asme,
CIPHERING_ALGORITHM_ID_ENUM enc_alg_id,
INTEGRITY_ALGORITHM_ID_ENUM int_alg_id,
uint8_t* k_nas_enc,
uint8_t* k_nas_int);
uint8_t security_generate_k_rrc(uint8_t* k_enb,
CIPHERING_ALGORITHM_ID_ENUM enc_alg_id,
INTEGRITY_ALGORITHM_ID_ENUM int_alg_id,
uint8_t* k_rrc_enc,
uint8_t* k_rrc_int);
uint8_t security_generate_k_up(uint8_t* k_enb,
CIPHERING_ALGORITHM_ID_ENUM enc_alg_id,
INTEGRITY_ALGORITHM_ID_ENUM int_alg_id,
uint8_t* k_up_enc,
uint8_t* k_up_int);
uint8_t security_generate_k_nr_rrc(uint8_t* k_gnb,
CIPHERING_ALGORITHM_ID_ENUM enc_alg_id,
INTEGRITY_ALGORITHM_ID_ENUM int_alg_id,
uint8_t* k_rrc_enc,
uint8_t* k_rrc_int);
uint8_t security_generate_k_nr_up(uint8_t* k_gnb,
CIPHERING_ALGORITHM_ID_ENUM enc_alg_id,
INTEGRITY_ALGORITHM_ID_ENUM int_alg_id,
uint8_t* k_up_enc,
uint8_t* k_up_int);
uint8_t security_generate_sk_gnb(uint8_t* k_enb, uint8_t* sk_gnb, uint16_t scg_count);
int kdf_common(const uint8_t fc, const std::array<uint8_t, 32>& key, const std::vector<uint8_t>& P, uint8_t* output);
int kdf_common(const uint8_t fc,
const std::array<uint8_t, 32>& key,
const std::vector<uint8_t>& P0,
const std::vector<uint8_t>& P1,
uint8_t* output);
int kdf_common(const uint8_t fc,
const std::array<uint8_t, 32>& key,
const std::vector<uint8_t>& P0,
const std::vector<uint8_t>& P1,
const std::vector<uint8_t>& P3,
uint8_t* output);
uint8_t security_generate_k_asme(const uint8_t* ck,
const uint8_t* ik,
const uint8_t* ak_xor_sqn,
const uint16_t mcc,
const uint16_t mnc,
uint8_t* k_asme);
uint8_t security_generate_k_ausf(const uint8_t* ck,
const uint8_t* ik,
const uint8_t* ak_xor_sqn,
const char* serving_network_name,
uint8_t* k_ausf);
uint8_t security_generate_k_amf(const uint8_t* k_seaf,
const char* supi_,
const uint8_t* abba_,
const uint32_t abba_len,
uint8_t* k_amf);
uint8_t security_generate_k_seaf(const uint8_t* k_ausf, const char* serving_network_name, uint8_t* k_seaf);
uint8_t security_generate_k_enb(const uint8_t* k_asme, const uint32_t nas_count, uint8_t* k_enb);
uint8_t
security_generate_k_enb_star(const uint8_t* k_enb, const uint32_t pci, const uint32_t earfcn, uint8_t* k_enb_star);
uint8_t security_generate_nh(const uint8_t* k_asme, const uint8_t* sync, uint8_t* nh);
uint8_t security_generate_k_nas(const uint8_t* k_asme,
const CIPHERING_ALGORITHM_ID_ENUM enc_alg_id,
const INTEGRITY_ALGORITHM_ID_ENUM int_alg_id,
uint8_t* k_nas_enc,
uint8_t* k_nas_int);
uint8_t security_generate_k_nas_5g(const uint8_t* k_amf,
const CIPHERING_ALGORITHM_ID_ENUM enc_alg_id,
const INTEGRITY_ALGORITHM_ID_ENUM int_alg_id,
uint8_t* k_nas_enc,
uint8_t* k_nas_int);
uint8_t security_generate_k_rrc(const uint8_t* k_enb,
const CIPHERING_ALGORITHM_ID_ENUM enc_alg_id,
const INTEGRITY_ALGORITHM_ID_ENUM int_alg_id,
uint8_t* k_rrc_enc,
uint8_t* k_rrc_int);
uint8_t security_generate_k_up(const uint8_t* k_enb,
const CIPHERING_ALGORITHM_ID_ENUM enc_alg_id,
const INTEGRITY_ALGORITHM_ID_ENUM int_alg_id,
uint8_t* k_up_enc,
uint8_t* k_up_int);
uint8_t security_generate_k_nr_rrc(const uint8_t* k_gnb,
const CIPHERING_ALGORITHM_ID_ENUM enc_alg_id,
const INTEGRITY_ALGORITHM_ID_ENUM int_alg_id,
uint8_t* k_rrc_enc,
uint8_t* k_rrc_int);
uint8_t security_generate_k_nr_up(const uint8_t* k_gnb,
const CIPHERING_ALGORITHM_ID_ENUM enc_alg_id,
const INTEGRITY_ALGORITHM_ID_ENUM int_alg_id,
uint8_t* k_up_enc,
uint8_t* k_up_int);
uint8_t security_generate_sk_gnb(const uint8_t* k_enb, const uint16_t scg_count, uint8_t* sk_gnb);
uint8_t security_generate_res_star(const uint8_t* ck,
const uint8_t* ik,
const char* serving_network_name,
const uint8_t* rand,
const uint8_t* res,
const size_t res_len,
uint8_t* res_star);
/******************************************************************************
* Integrity Protection
*****************************************************************************/
@ -201,5 +280,8 @@ security_milenage_f2345(uint8_t* k, uint8_t* op, uint8_t* rand, uint8_t* res, ui
uint8_t security_milenage_f5_star(uint8_t* k, uint8_t* op, uint8_t* rand, uint8_t* ak);
int security_xor_f2345(uint8_t* k, uint8_t* rand, uint8_t* res, uint8_t* ck, uint8_t* ik, uint8_t* ak);
int security_xor_f1(uint8_t* k, uint8_t* rand, uint8_t* sqn, uint8_t* amf, uint8_t* mac_a);
} // namespace srsran
#endif // SRSRAN_SECURITY_H

@ -27,12 +27,12 @@
#include "polarssl/aes.h"
#include "polarssl/sha256.h"
void sha256(const unsigned char* key,
size_t keylen,
const unsigned char* input,
size_t ilen,
unsigned char output[32],
int is224)
inline void sha256(const unsigned char* key,
size_t keylen,
const unsigned char* input,
size_t ilen,
unsigned char output[32],
int is224)
{
sha256_hmac(key, keylen, input, ilen, output, is224);
}
@ -49,33 +49,33 @@ typedef mbedtls_aes_context aes_context;
#define AES_ENCRYPT 1
#define AES_DECRYPT 0
int aes_setkey_enc(aes_context* ctx, const unsigned char* key, unsigned int keysize)
inline int aes_setkey_enc(aes_context* ctx, const unsigned char* key, unsigned int keysize)
{
return mbedtls_aes_setkey_enc(ctx, key, keysize);
}
int aes_crypt_ecb(aes_context* ctx, int mode, const unsigned char input[16], unsigned char output[16])
inline int aes_crypt_ecb(aes_context* ctx, int mode, const unsigned char input[16], unsigned char output[16])
{
return mbedtls_aes_crypt_ecb(ctx, mode, input, output);
}
int aes_crypt_ctr(aes_context* ctx,
size_t length,
size_t* nc_off,
unsigned char nonce_counter[16],
unsigned char stream_block[16],
const unsigned char* input,
unsigned char* output)
inline int aes_crypt_ctr(aes_context* ctx,
size_t length,
size_t* nc_off,
unsigned char nonce_counter[16],
unsigned char stream_block[16],
const unsigned char* input,
unsigned char* output)
{
return mbedtls_aes_crypt_ctr(ctx, length, nc_off, nonce_counter, stream_block, input, output);
}
void sha256(const unsigned char* key,
size_t keylen,
const unsigned char* input,
size_t ilen,
unsigned char output[32],
int is224)
inline void sha256(const unsigned char* key,
size_t keylen,
const unsigned char* input,
size_t ilen,
unsigned char output[32],
int is224)
{
mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), key, keylen, input, ilen, output);
}

@ -33,7 +33,7 @@ class stack_interface_rrc
public:
virtual void add_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid) = 0;
virtual void remove_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id) = 0;
virtual void reset_eps_bearers(uint16_t rnti) = 0;
virtual void remove_eps_bearers(uint16_t rnti) = 0;
};
class stack_interface_phy_lte;

@ -144,6 +144,7 @@ public:
/// User management
virtual int add_user(uint16_t rnti) = 0;
virtual int update_user(uint16_t new_rnti, uint16_t old_rnti) = 0;
};
// NR interface is almost identical to EUTRA version

@ -51,11 +51,26 @@ public:
uint8_t* res,
int* res_len,
uint8_t* k_asme) = 0;
virtual void generate_nas_keys(uint8_t* k_asme,
uint8_t* k_nas_enc,
uint8_t* k_nas_int,
srsran::CIPHERING_ALGORITHM_ID_ENUM cipher_algo,
srsran::INTEGRITY_ALGORITHM_ID_ENUM integ_algo) = 0;
virtual auth_result_t generate_authentication_response_5g(uint8_t* rand,
uint8_t* autn_enb,
const char* serving_network_name,
uint8_t* abba,
uint32_t abba_len,
uint8_t* res_star,
uint8_t* k_amf) = 0;
virtual void generate_nas_keys(uint8_t* k_asme,
uint8_t* k_nas_enc,
uint8_t* k_nas_int,
srsran::CIPHERING_ALGORITHM_ID_ENUM cipher_algo,
srsran::INTEGRITY_ALGORITHM_ID_ENUM integ_algo) = 0;
virtual bool generate_nas_keys_5g(uint8_t* k_amf,
uint8_t* k_nas_enc,
uint8_t* k_nas_int,
srsran::CIPHERING_ALGORITHM_ID_ENUM cipher_algo,
srsran::INTEGRITY_ALGORITHM_ID_ENUM integ_algo) = 0;
};
// USIM interface for RRC

@ -22,6 +22,7 @@
#ifndef SRSRAN_MAC_RAR_PDU_NR_H
#define SRSRAN_MAC_RAR_PDU_NR_H
#include "srsran/common/byte_buffer.h"
#include "srsran/common/common.h"
#include "srsran/config.h"
#include "srsran/phy/common/phy_common_nr.h"
@ -60,12 +61,19 @@ public:
uint8_t get_backoff() const;
// setter
uint32_t write_subpdu(const uint8_t* start_);
void set_backoff(const uint8_t backoff_indicator_);
void write_subpdu(const uint8_t* start_);
void set_backoff(const uint8_t backoff_indicator_);
void set_ta(const uint32_t ta_);
void set_temp_crnti(const uint16_t temp_crnti_);
void set_rapid(const uint8_t rapid_);
void set_ul_grant(std::array<uint8_t, mac_rar_subpdu_nr::UL_GRANT_NBITS> ul_grant_);
void set_is_last_subpdu();
std::string to_string();
void to_string(fmt::memory_buffer& buffer);
private:
const uint32_t MAC_RAR_NBYTES = 7; // see TS 38.321 Sec 6.2.3
int header_length = 1; // RAR PDU subheader is always 1 B
int payload_length = 0; // only used if MAC RAR is included
@ -75,7 +83,7 @@ private:
uint16_t rapid = 0;
uint8_t backoff_indicator = 0;
rar_subh_type_t type = BACKOFF;
bool E_bit = 0;
bool E_bit = true;
srslog::basic_logger& logger;
@ -88,7 +96,8 @@ public:
mac_rar_pdu_nr();
~mac_rar_pdu_nr() = default;
bool pack();
int init_tx(byte_buffer_t* buffer_, uint32_t pdu_len_);
int pack();
bool unpack(const uint8_t* payload, const uint32_t& len);
uint32_t get_num_subpdus();
// Returns reference to a single subPDU
@ -101,13 +110,20 @@ public:
void set_si_rapid(uint16_t si_rapid_); // configured through SIB1 for on-demand SI request (See 38.331 Sec 5.2.1)
bool has_si_rapid();
std::string to_string();
// returns reference to added RAR subPDU
mac_rar_subpdu_nr& add_subpdu();
void to_string(fmt::memory_buffer& buffer);
private:
std::vector<mac_rar_subpdu_nr> subpdus;
uint32_t pdu_len = 0;
uint32_t remaining_len = 0;
uint16_t si_rapid = 0;
bool si_rapid_set = false;
byte_buffer_t* buffer = nullptr;
srslog::basic_logger& logger;
};

@ -111,6 +111,8 @@ public:
// Used by BSR procedure to determine size of BSR types
static uint32_t sizeof_ce(uint32_t lcid, bool is_ul);
void to_string(fmt::memory_buffer& buffer);
private:
srslog::basic_logger* logger;
@ -118,10 +120,63 @@ private:
int header_length = 0;
int sdu_length = 0;
bool F_bit = false;
uint8_t* sdu = nullptr;
static const uint8_t mac_ce_payload_len = 8 + 1; // Long BSR has max. 9 octets (see sizeof_ce() too)
std::array<uint8_t, mac_ce_payload_len> ce_write_buffer; // Buffer for CE payload
/// This helper class manages a SDU pointer that can point to either a user provided external buffer or to a small
/// internal buffer, useful for storing very short SDUs.
class sdu_buffer
{
static const uint8_t mac_ce_payload_len = 8 + 1; // Long BSR has max. 9 octets (see sizeof_ce() too)
std::array<uint8_t, mac_ce_payload_len> ce_write_buffer; // Buffer for CE payload
uint8_t* sdu = nullptr;
public:
sdu_buffer() = default;
sdu_buffer(const sdu_buffer& other) : ce_write_buffer(other.ce_write_buffer)
{
// First check if we need to use internal storage.
if (other.sdu == other.ce_write_buffer.data()) {
sdu = ce_write_buffer.data();
return;
}
sdu = other.sdu;
}
sdu_buffer& operator=(const sdu_buffer& other)
{
if (this == &other) {
return *this;
}
ce_write_buffer = other.ce_write_buffer;
if (other.sdu == other.ce_write_buffer.data()) {
sdu = ce_write_buffer.data();
return *this;
}
sdu = other.sdu;
return *this;
}
explicit operator bool() const { return sdu; }
/// Set the SDU pointer to use the internal buffer.
uint8_t* use_internal_storage()
{
sdu = ce_write_buffer.data();
return sdu;
}
/// Set the SDU pointer to point to the provided buffer.
uint8_t* set_storage_to(uint8_t* p)
{
sdu = p;
return sdu;
}
/// Returns the SDU pointer.
uint8_t* ptr() { return sdu; }
};
sdu_buffer sdu;
mac_sch_pdu_nr* parent = nullptr;
};
@ -150,6 +205,8 @@ public:
uint32_t get_remaing_len();
void to_string(fmt::memory_buffer& buffer);
private:
uint32_t size_header_sdu(const uint32_t lcid_, const uint32_t nbytes);
/// Private helper that adds a subPDU to the MAC PDU

@ -130,6 +130,7 @@ SRSASN_CODE mobile_identity_5gs_t::pack(asn1::bit_ref& bref)
SRSASN_CODE mobile_identity_5gs_t::unpack(asn1::cbit_ref& bref)
{
// Length
uint16_t length = 0;
HANDLE_CODE(bref.unpack(length, 16));
uint8_t tmp;
HANDLE_CODE(bref.unpack(tmp, 5));
@ -456,6 +457,7 @@ SRSASN_CODE capability_5gmm_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.3.1
SRSASN_CODE capability_5gmm_t::unpack(asn1::cbit_ref& bref)
{
uint8_t length = 0;
HANDLE_CODE(bref.unpack(length, 8));
if (length < 1 || length > 13) {
asn1::log_error("Decoding Failed (5GMM capability): Length (%d) is not in range of min: 1 and max 13 bytes",
@ -557,6 +559,7 @@ SRSASN_CODE ue_security_capability_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.3.54
SRSASN_CODE ue_security_capability_t::unpack(asn1::cbit_ref& bref)
{
uint8_t length = 0;
HANDLE_CODE(bref.unpack(length, 8));
if (length < 2 || length > 8) {
asn1::log_error("Decoding Failed (UE security capability): Length (%d) is not in range of min: 2 and max 8 bytes",
@ -631,6 +634,7 @@ SRSASN_CODE nssai_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.3.37
SRSASN_CODE nssai_t::unpack(asn1::cbit_ref& bref)
{
uint8_t length = 0;
HANDLE_CODE(bref.unpack(length, 8));
if (length < 2 || length > 144) {
asn1::log_error("Decoding Failed (NSSAI): Length (%d) is not in range of min: 2 and max 144 bytes", length);
@ -758,6 +762,7 @@ SRSASN_CODE s1_ue_network_capability_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.3.48
SRSASN_CODE s1_ue_network_capability_t::unpack(asn1::cbit_ref& bref)
{
uint8_t length = 0;
HANDLE_CODE(bref.unpack(length, 8));
if (length < 2 || length > 13) {
asn1::log_error(
@ -902,6 +907,7 @@ SRSASN_CODE uplink_data_status_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.3.57
SRSASN_CODE uplink_data_status_t::unpack(asn1::cbit_ref& bref)
{
uint8_t length = 0;
HANDLE_CODE(bref.unpack(length, 8));
if (length < 2 || length > 32) {
asn1::log_error("Decoding Failed (Uplink data status): Length (%d) is not in range of min: 2 and max 32 bytes",
@ -972,6 +978,7 @@ SRSASN_CODE pdu_session_status_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.3.44
SRSASN_CODE pdu_session_status_t::unpack(asn1::cbit_ref& bref)
{
uint8_t length = 0;
HANDLE_CODE(bref.unpack(length, 8));
if (length < 2 || length > 32) {
asn1::log_error("Decoding Failed (PDU session status): Length (%d) is not in range of min: 2 and max 32 bytes",
@ -1051,6 +1058,7 @@ SRSASN_CODE ue_status_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.3.56
SRSASN_CODE ue_status_t::unpack(asn1::cbit_ref& bref)
{
uint8_t length = 0;
HANDLE_CODE(bref.unpack(length, 8));
if (length != 1) {
asn1::log_error("Decoding Failed (UE status): Length (%d) does not equal expected length 1", length);
@ -1105,6 +1113,7 @@ SRSASN_CODE allowed_pdu_session_status_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.3.13
SRSASN_CODE allowed_pdu_session_status_t::unpack(asn1::cbit_ref& bref)
{
uint8_t length = 0;
HANDLE_CODE(bref.unpack(length, 8));
if (length < 2 || length > 32) {
asn1::log_error(
@ -1161,6 +1170,7 @@ SRSASN_CODE ue_usage_setting_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.3.55
SRSASN_CODE ue_usage_setting_t::unpack(asn1::cbit_ref& bref)
{
uint8_t length = 0;
HANDLE_CODE(bref.unpack(length, 8));
if (length != 1) {
asn1::log_error("Decoding Failed (UE usage setting): Length (%d) does not equal expected length 1", length);
@ -1200,6 +1210,7 @@ SRSASN_CODE drx_parameters_5gs_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.3.2A
SRSASN_CODE drx_parameters_5gs_t::unpack(asn1::cbit_ref& bref)
{
uint8_t length = 0;
HANDLE_CODE(bref.unpack(length, 8));
if (length != 1) {
asn1::log_error("Decoding Failed (5GS DRX parameters): Length (%d) does not equal expected length 1", length);
@ -1231,6 +1242,7 @@ SRSASN_CODE eps_nas_message_container_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.3.24
SRSASN_CODE eps_nas_message_container_t::unpack(asn1::cbit_ref& bref)
{
uint16_t length = 0;
HANDLE_CODE(bref.unpack(length, 16));
eps_nas_message_container.resize(length);
HANDLE_CODE(bref.unpack_bytes(eps_nas_message_container.data(), length));
@ -1252,7 +1264,7 @@ SRSASN_CODE ladn_indication_t::pack(asn1::bit_ref& bref)
bref.align_bytes_zero();
uint16_t length = (uint16_t)(ceilf((float)bref.distance(bref_length) / 8) - 2);
// MIN 0 not check because auf uint underflow
// min. length of 0 not checked: uint underflow
if (length > 808) {
asn1::log_error("Encoding Failed (LADN indication): Packed length (%d) is not in range of max 808 bytes", length);
return asn1::SRSASN_ERROR_ENCODE_FAIL;
@ -1265,8 +1277,9 @@ SRSASN_CODE ladn_indication_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.3.29
SRSASN_CODE ladn_indication_t::unpack(asn1::cbit_ref& bref)
{
uint16_t length = 0;
HANDLE_CODE(bref.unpack(length, 16));
// MIN 0 not check because auf uint underflow
// min. length of 0 not checked: uint underflow
if (length > 808) {
asn1::log_error("Decoding Failed (LADN indication): Length (%d) is not in range of max 808 bytes", length);
return asn1::SRSASN_ERROR_DECODE_FAIL;
@ -1308,7 +1321,7 @@ SRSASN_CODE payload_container_t::pack(asn1::bit_ref& bref)
bref.align_bytes_zero();
uint16_t length = (uint16_t)(ceilf((float)bref.distance(bref_length) / 8) - 2);
// MAX 65535 not check because auf uint overflow
// max. length of 65535 not checked: uint overflow
if (length < 1) {
asn1::log_error("Encoding Failed (Payload container): Packed length (%d) is not in range of min: 1 bytes", length);
return asn1::SRSASN_ERROR_ENCODE_FAIL;
@ -1321,8 +1334,9 @@ SRSASN_CODE payload_container_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.3.39
SRSASN_CODE payload_container_t::unpack(asn1::cbit_ref& bref)
{
uint16_t length = 0;
HANDLE_CODE(bref.unpack(length, 16));
// MAX 65535 not check because auf uint overflow
// max. length of 65535 not checked: uint overflow
if (length < 1) {
asn1::log_error("Decoding Failed (Payload container): Length (%d) is not in range of min: 1 bytes", length);
return asn1::SRSASN_ERROR_DECODE_FAIL;
@ -1380,6 +1394,7 @@ SRSASN_CODE update_type_5gs_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.3.9A
SRSASN_CODE update_type_5gs_t::unpack(asn1::cbit_ref& bref)
{
uint8_t length = 0;
HANDLE_CODE(bref.unpack(length, 8)); // 2 Spare bits
bref.advance_bits(2);
HANDLE_CODE(pnb_eps_c_io_t.unpack(bref));
@ -1415,6 +1430,7 @@ SRSASN_CODE mobile_station_classmark_2_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.3.31C
SRSASN_CODE mobile_station_classmark_2_t::unpack(asn1::cbit_ref& bref)
{
uint8_t length = 0;
HANDLE_CODE(bref.unpack(length, 8));
if (length != 3) {
asn1::log_error("Decoding Failed (Mobile station classmark 2): Length (%d) does not equal expected length 3",
@ -1453,6 +1469,7 @@ SRSASN_CODE supported_codec_list_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.3.51A
SRSASN_CODE supported_codec_list_t::unpack(asn1::cbit_ref& bref)
{
uint8_t length = 0;
HANDLE_CODE(bref.unpack(length, 8));
if (length < 3) {
asn1::log_error("Decoding Failed (Supported codec list): Length (%d) is not in range of min: 3 bytes", length);
@ -1490,6 +1507,7 @@ SRSASN_CODE message_container_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.3.33
SRSASN_CODE message_container_t::unpack(asn1::cbit_ref& bref)
{
uint16_t length = 0;
HANDLE_CODE(bref.unpack(length, 16));
if (length < 1 || length > 65532) {
asn1::log_error("Decoding Failed (message container): Length (%d) is not in range of min: 1 and max 65532 bytes",
@ -1542,6 +1560,7 @@ SRSASN_CODE eps_bearer_context_status_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.3.23A
SRSASN_CODE eps_bearer_context_status_t::unpack(asn1::cbit_ref& bref)
{
uint8_t length = 0;
HANDLE_CODE(bref.unpack(length, 8));
if (length != 2) {
asn1::log_error("Decoding Failed (EPS bearer context status): Length (%d) does not equal expected length 2",
@ -1594,6 +1613,7 @@ SRSASN_CODE extended_drx_parameters_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.3.26A
SRSASN_CODE extended_drx_parameters_t::unpack(asn1::cbit_ref& bref)
{
uint8_t length = 0;
HANDLE_CODE(bref.unpack(length, 8));
if (length != 1) {
asn1::log_error("Decoding Failed (Extended DRX parameters): Length (%d) does not equal expected length 1", length);
@ -1630,6 +1650,7 @@ SRSASN_CODE gprs_timer_3_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.2.5
SRSASN_CODE gprs_timer_3_t::unpack(asn1::cbit_ref& bref)
{
uint8_t length = 0;
HANDLE_CODE(bref.unpack(length, 8));
if (length != 1) {
asn1::log_error("Decoding Failed (GPRS timer 3): Length (%d) does not equal expected length 1", length);
@ -1660,6 +1681,7 @@ SRSASN_CODE ue_radio_capability_id_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.3.68
SRSASN_CODE ue_radio_capability_id_t::unpack(asn1::cbit_ref& bref)
{
uint8_t length = 0;
HANDLE_CODE(bref.unpack(length, 8));
ue_radio_capability_id.resize(length);
HANDLE_CODE(bref.unpack_bytes(ue_radio_capability_id.data(), length));
@ -1692,6 +1714,7 @@ SRSASN_CODE mapped_nssai_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.3.31B
SRSASN_CODE mapped_nssai_t::unpack(asn1::cbit_ref& bref)
{
uint8_t length = 0;
HANDLE_CODE(bref.unpack(length, 8));
if (length < 2 || length > 40) {
asn1::log_error("Decoding Failed (Mapped NSSAI): Length (%d) is not in range of min: 2 and max 40 bytes", length);
@ -1726,6 +1749,7 @@ SRSASN_CODE additional_information_requested_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.3.12A
SRSASN_CODE additional_information_requested_t::unpack(asn1::cbit_ref& bref)
{
uint8_t length = 0;
HANDLE_CODE(bref.unpack(length, 8)); // 7 Spare bits
bref.advance_bits(7);
HANDLE_CODE(bref.unpack(cipher_key, 1));
@ -1758,6 +1782,7 @@ SRSASN_CODE wus_assistance_information_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.3.71
SRSASN_CODE wus_assistance_information_t::unpack(asn1::cbit_ref& bref)
{
uint8_t length = 0;
HANDLE_CODE(bref.unpack(length, 8));
if (length < 1) {
asn1::log_error("Decoding Failed (WUS assistance information): Length (%d) is not in range of min: 1 bytes",
@ -1818,6 +1843,7 @@ SRSASN_CODE nb_n1_mode_drx_parameters_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.3.73
SRSASN_CODE nb_n1_mode_drx_parameters_t::unpack(asn1::cbit_ref& bref)
{
uint8_t length = 0;
HANDLE_CODE(bref.unpack(length, 8));
if (length != 1) {
asn1::log_error("Decoding Failed (NB-N1 mode DRX parameters): Length (%d) does not equal expected length 1",
@ -1861,6 +1887,7 @@ SRSASN_CODE registration_result_5gs_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.3.6
SRSASN_CODE registration_result_5gs_t::unpack(asn1::cbit_ref& bref)
{
uint8_t length = 0;
HANDLE_CODE(bref.unpack(length, 8));
if (length != 1) {
asn1::log_error("Decoding Failed (5GS registration result): Length (%d) does not equal expected length 1", length);
@ -1896,6 +1923,7 @@ SRSASN_CODE plmn_list_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.3.45
SRSASN_CODE plmn_list_t::unpack(asn1::cbit_ref& bref)
{
uint8_t length = 0;
HANDLE_CODE(bref.unpack(length, 8));
// TODO proper unpacking
bref.advance_bits(length * 8);
@ -1929,6 +1957,7 @@ SRSASN_CODE tracking_area_identity_list_5gs_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.3.9
SRSASN_CODE tracking_area_identity_list_5gs_t::unpack(asn1::cbit_ref& bref)
{
uint8_t length = 0;
HANDLE_CODE(bref.unpack(length, 8));
if (length != 7) {
asn1::log_error("Decoding Failed (5GS tracking area identity list): Length (%d) does not equal expected length 7",
@ -1962,6 +1991,7 @@ SRSASN_CODE rejected_nssai_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.3.46
SRSASN_CODE rejected_nssai_t::unpack(asn1::cbit_ref& bref)
{
uint8_t length = 0;
HANDLE_CODE(bref.unpack(length, 8));
// TODO proper unpacking
bref.advance_bits(length * 8);
@ -1995,6 +2025,7 @@ SRSASN_CODE network_feature_support_5gs_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.3.5
SRSASN_CODE network_feature_support_5gs_t::unpack(asn1::cbit_ref& bref)
{
uint8_t length = 0;
HANDLE_CODE(bref.unpack(length, 8));
if (length < 1 || length > 3) {
asn1::log_error(
@ -2049,6 +2080,7 @@ SRSASN_CODE pdu_session_reactivation_result_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.3.42
SRSASN_CODE pdu_session_reactivation_result_t::unpack(asn1::cbit_ref& bref)
{
uint8_t length = 0;
HANDLE_CODE(bref.unpack(length, 8));
if (length < 2 || length > 32) {
asn1::log_error(
@ -2108,6 +2140,7 @@ SRSASN_CODE pdu_session_reactivation_result_error_cause_t::pack(asn1::bit_ref& b
// Reference: 9.11.3.43
SRSASN_CODE pdu_session_reactivation_result_error_cause_t::unpack(asn1::cbit_ref& bref)
{
uint16_t length = 0;
HANDLE_CODE(bref.unpack(length, 16));
if (length < 2 || length > 512) {
asn1::log_error("Decoding Failed (PDU session reactivation result error cause): Length (%d) is not in range of "
@ -2134,7 +2167,7 @@ SRSASN_CODE ladn_information_t::pack(asn1::bit_ref& bref)
bref.align_bytes_zero();
uint16_t length = (uint16_t)(ceilf((float)bref.distance(bref_length) / 8) - 2);
// MIN 0 not check because auf uint underflow
// min. length of 0 not checked: uint underflow
if (length > 1712) {
asn1::log_error("Encoding Failed (LADN information): Packed length (%d) is not in range of max 1712 bytes", length);
return asn1::SRSASN_ERROR_ENCODE_FAIL;
@ -2147,8 +2180,9 @@ SRSASN_CODE ladn_information_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.3.30
SRSASN_CODE ladn_information_t::unpack(asn1::cbit_ref& bref)
{
uint16_t length = 0;
HANDLE_CODE(bref.unpack(length, 16));
// MIN 0 not check because auf uint underflow
// min. length of 0 not checked: uint underflow
if (length > 1712) {
asn1::log_error("Decoding Failed (LADN information): Length (%d) is not in range of max 1712 bytes", length);
return asn1::SRSASN_ERROR_DECODE_FAIL;
@ -2180,6 +2214,7 @@ SRSASN_CODE service_area_list_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.3.49
SRSASN_CODE service_area_list_t::unpack(asn1::cbit_ref& bref)
{
uint8_t length = 0;
HANDLE_CODE(bref.unpack(length, 8));
// TODO proper unpacking
bref.advance_bits(length * 8);
@ -2211,6 +2246,7 @@ SRSASN_CODE gprs_timer_2_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.2.4
SRSASN_CODE gprs_timer_2_t::unpack(asn1::cbit_ref& bref)
{
uint8_t length = 0;
HANDLE_CODE(bref.unpack(length, 8));
if (length != 1) {
asn1::log_error("Decoding Failed (GPRS timer 2): Length (%d) does not equal expected length 1", length);
@ -2247,6 +2283,7 @@ SRSASN_CODE emergency_number_list_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.3.23
SRSASN_CODE emergency_number_list_t::unpack(asn1::cbit_ref& bref)
{
uint8_t length = 0;
HANDLE_CODE(bref.unpack(length, 8));
if (length < 3 || length > 48) {
asn1::log_error("Decoding Failed (Emergency number list): Length (%d) is not in range of min: 3 and max 48 bytes",
@ -2272,7 +2309,7 @@ SRSASN_CODE extended_emergency_number_list_t::pack(asn1::bit_ref& bref)
bref.align_bytes_zero();
uint16_t length = (uint16_t)(ceilf((float)bref.distance(bref_length) / 8) - 2);
// MAX 65535 not check because auf uint overflow
// max. length of 65535 not checked: uint overflow
if (length < 4) {
asn1::log_error(
"Encoding Failed (Extended emergency number list): Packed length (%d) is not in range of min: 4 bytes", length);
@ -2286,8 +2323,9 @@ SRSASN_CODE extended_emergency_number_list_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.3.26
SRSASN_CODE extended_emergency_number_list_t::unpack(asn1::cbit_ref& bref)
{
uint16_t length = 0;
HANDLE_CODE(bref.unpack(length, 16));
// MAX 65535 not check because auf uint overflow
// max. length of 65535 not checked: uint overflow
if (length < 4) {
asn1::log_error("Decoding Failed (Extended emergency number list): Length (%d) is not in range of min: 4 bytes",
length);
@ -2325,6 +2363,7 @@ SRSASN_CODE sor_transparent_container_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.3.51
SRSASN_CODE sor_transparent_container_t::unpack(asn1::cbit_ref& bref)
{
uint16_t length = 0;
HANDLE_CODE(bref.unpack(length, 16));
if (length < 17) {
asn1::log_error("Decoding Failed (SOR transparent container): Length (%d) is not in range of min: 17 bytes",
@ -2362,6 +2401,7 @@ SRSASN_CODE eap_message_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.2.2
SRSASN_CODE eap_message_t::unpack(asn1::cbit_ref& bref)
{
uint16_t length = 0;
HANDLE_CODE(bref.unpack(length, 16));
if (length < 4 || length > 1500) {
asn1::log_error("Decoding Failed (EAP message): Length (%d) is not in range of min: 4 and max 1500 bytes", length);
@ -2413,6 +2453,7 @@ SRSASN_CODE operator_defined_access_category_definitions_t::pack(asn1::bit_ref&
// Reference: 9.11.3.38
SRSASN_CODE operator_defined_access_category_definitions_t::unpack(asn1::cbit_ref& bref)
{
uint16_t length = 0;
HANDLE_CODE(bref.unpack(length, 16));
// TODO proper unpacking
bref.advance_bits(length * 8);
@ -2486,6 +2527,7 @@ SRSASN_CODE ciphering_key_data_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.3.18C
SRSASN_CODE ciphering_key_data_t::unpack(asn1::cbit_ref& bref)
{
uint16_t length = 0;
HANDLE_CODE(bref.unpack(length, 16));
if (length < 31 || length > 2672) {
asn1::log_error("Decoding Failed (Ciphering key data): Length (%d) is not in range of min: 31 and max 2672 bytes",
@ -2519,6 +2561,7 @@ SRSASN_CODE cag_information_list_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.3.18A
SRSASN_CODE cag_information_list_t::unpack(asn1::cbit_ref& bref)
{
uint16_t length = 0;
HANDLE_CODE(bref.unpack(length, 16));
// TODO proper unpacking
bref.advance_bits(length * 8);
@ -2553,6 +2596,7 @@ SRSASN_CODE truncated_5g_s_tmsi_configuration_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.3.70
SRSASN_CODE truncated_5g_s_tmsi_configuration_t::unpack(asn1::cbit_ref& bref)
{
uint8_t length = 0;
HANDLE_CODE(bref.unpack(length, 8));
if (length != 1) {
asn1::log_error("Decoding Failed (Truncated 5G-S-TMSI configuration): Length (%d) does not equal expected length 1",
@ -2675,6 +2719,7 @@ SRSASN_CODE network_name_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.3.35
SRSASN_CODE network_name_t::unpack(asn1::cbit_ref& bref)
{
uint8_t length = 0;
HANDLE_CODE(bref.unpack(length, 8));
// TODO proper unpacking
bref.advance_bits(length * 8);
@ -2749,6 +2794,7 @@ SRSASN_CODE daylight_saving_time_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.3.19
SRSASN_CODE daylight_saving_time_t::unpack(asn1::cbit_ref& bref)
{
uint8_t length = 0;
HANDLE_CODE(bref.unpack(length, 8));
if (length != 1) {
asn1::log_error("Decoding Failed (Daylight saving time): Length (%d) does not equal expected length 1", length);
@ -2822,6 +2868,7 @@ SRSASN_CODE abba_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.3.10
SRSASN_CODE abba_t::unpack(asn1::cbit_ref& bref)
{
uint8_t length = 0;
HANDLE_CODE(bref.unpack(length, 8));
if (length < 2) {
asn1::log_error("Decoding Failed (ABBA): Length (%d) is not in range of min: 2 bytes", length);
@ -2874,6 +2921,7 @@ SRSASN_CODE authentication_parameter_autn_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.3.15
SRSASN_CODE authentication_parameter_autn_t::unpack(asn1::cbit_ref& bref)
{
uint8_t length = 0;
HANDLE_CODE(bref.unpack(length, 8));
if (length != 16) {
asn1::log_error("Decoding Failed (Authentication parameter AUTN): Length (%d) does not equal expected length 16",
@ -2911,6 +2959,7 @@ SRSASN_CODE authentication_response_parameter_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.3.17
SRSASN_CODE authentication_response_parameter_t::unpack(asn1::cbit_ref& bref)
{
uint8_t length = 0;
HANDLE_CODE(bref.unpack(length, 8));
if (length != 16) {
asn1::log_error(
@ -2948,6 +2997,7 @@ SRSASN_CODE authentication_failure_parameter_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.3.14
SRSASN_CODE authentication_failure_parameter_t::unpack(asn1::cbit_ref& bref)
{
uint8_t length = 0;
HANDLE_CODE(bref.unpack(length, 8));
if (length != 14) {
asn1::log_error("Decoding Failed (Authentication failure parameter): Length (%d) does not equal expected length 14",
@ -3074,6 +3124,7 @@ SRSASN_CODE additional_5g_security_information_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.3.12
SRSASN_CODE additional_5g_security_information_t::unpack(asn1::cbit_ref& bref)
{
uint8_t length = 0;
HANDLE_CODE(bref.unpack(length, 8));
if (length != 1) {
asn1::log_error(
@ -3157,6 +3208,7 @@ SRSASN_CODE s1_ue_security_capability_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.3.48A
SRSASN_CODE s1_ue_security_capability_t::unpack(asn1::cbit_ref& bref)
{
uint8_t length = 0;
HANDLE_CODE(bref.unpack(length, 8));
if (length < 2 || length > 5) {
asn1::log_error(
@ -3286,15 +3338,15 @@ SRSASN_CODE s_nssai_t::pack(asn1::bit_ref& bref)
asn1::bit_ref bref_length = bref;
HANDLE_CODE(bref.advance_bits(8));
if (length == s_nssai_t::SST_type_::options::sst) {
if (type == s_nssai_t::SST_type_::options::sst) {
HANDLE_CODE(bref.pack(sst, 8));
} else if (length == s_nssai_t::SST_type_::options::sst_and_mapped_hplmn_sst) {
} else if (type == s_nssai_t::SST_type_::options::sst_and_mapped_hplmn_sst) {
HANDLE_CODE(bref.pack(sst, 8));
HANDLE_CODE(bref.pack(mapped_hplmn_sst, 8));
} else if (length == s_nssai_t::SST_type_::options::sst_and_sd) {
} else if (type == s_nssai_t::SST_type_::options::sst_and_sd) {
HANDLE_CODE(bref.pack(sst, 8));
HANDLE_CODE(bref.pack(sd, 24));
} else if (length == s_nssai_t::SST_type_::options::sst_sd_mapped_hplmn_sst_and_mapped_hplmn_sd) {
} else if (type == s_nssai_t::SST_type_::options::sst_sd_mapped_hplmn_sst_and_mapped_hplmn_sd) {
HANDLE_CODE(bref.pack(sst, 8));
HANDLE_CODE(bref.pack(sd, 24));
HANDLE_CODE(bref.pack(mapped_hplmn_sst, 8));
@ -3319,26 +3371,31 @@ SRSASN_CODE s_nssai_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.2.8
SRSASN_CODE s_nssai_t::unpack(asn1::cbit_ref& bref)
{
uint8_t length = 0;
HANDLE_CODE(bref.unpack(length, 8));
if (length < 1 || length > 8) {
asn1::log_error("Decoding Failed (S-NSSAI): Length (%d) is not in range of min: 1 and max 8 bytes", length);
return asn1::SRSASN_ERROR_DECODE_FAIL;
}
if (length == s_nssai_t::SST_type_::options::sst) {
type = s_nssai_t::SST_type_::options::sst;
HANDLE_CODE(bref.unpack(sst, 8));
} else if (length == s_nssai_t::SST_type_::options::sst_and_mapped_hplmn_sst) {
type = s_nssai_t::SST_type_::options::sst_and_mapped_hplmn_sst;
HANDLE_CODE(bref.unpack(sst, 8));
HANDLE_CODE(bref.unpack(mapped_hplmn_sst, 8));
} else if (length == s_nssai_t::SST_type_::options::sst_and_sd) {
type = s_nssai_t::SST_type_::options::sst_and_sd;
HANDLE_CODE(bref.unpack(sst, 8));
HANDLE_CODE(bref.unpack(sd, 24));
} else if (length == s_nssai_t::SST_type_::options::sst_sd_mapped_hplmn_sst_and_mapped_hplmn_sd) {
type = s_nssai_t::SST_type_::options::sst_sd_mapped_hplmn_sst_and_mapped_hplmn_sd;
HANDLE_CODE(bref.unpack(sst, 8));
HANDLE_CODE(bref.unpack(sd, 24));
HANDLE_CODE(bref.unpack(mapped_hplmn_sst, 8));
HANDLE_CODE(bref.unpack(mapped_hplmn_sd, 24));
} else {
asn1::log_error("Not such a length type for s_nssai");
asn1::log_error("Not such a type for s_nssai");
return SRSASN_ERROR_DECODE_FAIL;
}
return SRSASN_SUCCESS;
@ -3368,6 +3425,7 @@ SRSASN_CODE dnn_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.2.1B
SRSASN_CODE dnn_t::unpack(asn1::cbit_ref& bref)
{
uint8_t length = 0;
HANDLE_CODE(bref.unpack(length, 8));
if (length < 1 || length > 100) {
asn1::log_error("Decoding Failed (DNN): Length (%d) is not in range of min: 1 and max 100 bytes", length);
@ -3403,6 +3461,7 @@ SRSASN_CODE additional_information_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.2.1
SRSASN_CODE additional_information_t::unpack(asn1::cbit_ref& bref)
{
uint8_t length = 0;
HANDLE_CODE(bref.unpack(length, 8));
if (length < 1) {
asn1::log_error("Decoding Failed (Additional information): Length (%d) is not in range of min: 1 bytes", length);
@ -3533,6 +3592,7 @@ SRSASN_CODE capability_5gsm_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.4.1
SRSASN_CODE capability_5gsm_t::unpack(asn1::cbit_ref& bref)
{
uint8_t length = 0;
HANDLE_CODE(bref.unpack(length, 8));
if (length < 1 || length > 13) {
asn1::log_error("Decoding Failed (5GSM capability): Length (%d) is not in range of min: 1 and max 13 bytes",
@ -3612,6 +3672,7 @@ SRSASN_CODE sm_pdu_dn_request_container_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.4.15
SRSASN_CODE sm_pdu_dn_request_container_t::unpack(asn1::cbit_ref& bref)
{
uint8_t length = 0;
HANDLE_CODE(bref.unpack(length, 8));
if (length < 1 || length > 253) {
asn1::log_error(
@ -3637,7 +3698,7 @@ SRSASN_CODE extended_protocol_configuration_options_t::pack(asn1::bit_ref& bref)
bref.align_bytes_zero();
uint16_t length = (uint16_t)(ceilf((float)bref.distance(bref_length) / 8) - 2);
// MAX 65535 not check because auf uint overflow
// max. length of 65535 not checked: uint overflow
if (length < 1) {
asn1::log_error(
"Encoding Failed (Extended protocol configuration options): Packed length (%d) is not in range of min: 1 bytes",
@ -3652,8 +3713,9 @@ SRSASN_CODE extended_protocol_configuration_options_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.4.6
SRSASN_CODE extended_protocol_configuration_options_t::unpack(asn1::cbit_ref& bref)
{
uint16_t length = 0;
HANDLE_CODE(bref.unpack(length, 16));
// MAX 65535 not check because auf uint overflow
// max. length of 65535 not checked: uint overflow
if (length < 1) {
asn1::log_error(
"Decoding Failed (Extended protocol configuration options): Length (%d) is not in range of min: 1 bytes",
@ -3679,7 +3741,7 @@ SRSASN_CODE ip_header_compression_configuration_t::pack(asn1::bit_ref& bref)
bref.align_bytes_zero();
uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1);
// MAX 255 not check because auf uint overflow
// max. length of 255 not checked: uint overflow
if (length < 3) {
asn1::log_error(
"Encoding Failed (IP header compression configuration): Packed length (%d) is not in range of min: 3 bytes",
@ -3694,8 +3756,9 @@ SRSASN_CODE ip_header_compression_configuration_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.4.24
SRSASN_CODE ip_header_compression_configuration_t::unpack(asn1::cbit_ref& bref)
{
uint8_t length = 0;
HANDLE_CODE(bref.unpack(length, 8));
// MAX 255 not check because auf uint overflow
// max. length of 255 not checked: uint overflow
if (length < 3) {
asn1::log_error(
"Decoding Failed (IP header compression configuration): Length (%d) is not in range of min: 3 bytes", length);
@ -3734,6 +3797,7 @@ SRSASN_CODE ds_tt__ethernet_port_mac_address_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.4.25
SRSASN_CODE ds_tt__ethernet_port_mac_address_t::unpack(asn1::cbit_ref& bref)
{
uint8_t length = 0;
HANDLE_CODE(bref.unpack(length, 8));
if (length != 6) {
asn1::log_error("Decoding Failed (DS-TT Ethernet port MAC address): Length (%d) does not equal expected length 6",
@ -3770,6 +3834,7 @@ SRSASN_CODE ue_ds_tt_residence_time_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.4.26
SRSASN_CODE ue_ds_tt_residence_time_t::unpack(asn1::cbit_ref& bref)
{
uint8_t length = 0;
HANDLE_CODE(bref.unpack(length, 8));
if (length != 8) {
asn1::log_error("Decoding Failed (UE-DS-TT residence time): Length (%d) does not equal expected length 8", length);
@ -3792,7 +3857,7 @@ SRSASN_CODE port_management_information_container_t::pack(asn1::bit_ref& bref)
bref.align_bytes_zero();
uint16_t length = (uint16_t)(ceilf((float)bref.distance(bref_length) / 8) - 2);
// MAX 65535 not check because auf uint overflow
// max. length of 65535 not checked: uint overflow
if (length < 1) {
asn1::log_error(
"Encoding Failed (Port management information container): Packed length (%d) is not in range of min: 1 bytes",
@ -3807,8 +3872,9 @@ SRSASN_CODE port_management_information_container_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.4.27
SRSASN_CODE port_management_information_container_t::unpack(asn1::cbit_ref& bref)
{
uint16_t length = 0;
HANDLE_CODE(bref.unpack(length, 16));
// MAX 65535 not check because auf uint overflow
// max. length of 65535 not checked: uint overflow
if (length < 1) {
asn1::log_error(
"Decoding Failed (Port management information container): Length (%d) is not in range of min: 1 bytes", length);
@ -3848,6 +3914,7 @@ SRSASN_CODE ethernet_header_compression_configuration_t::pack(asn1::bit_ref& bre
// Reference: 9.11.4.28
SRSASN_CODE ethernet_header_compression_configuration_t::unpack(asn1::cbit_ref& bref)
{
uint8_t length = 0;
HANDLE_CODE(bref.unpack(length, 8));
if (length != 1) {
asn1::log_error(
@ -3903,6 +3970,7 @@ SRSASN_CODE pdu_address_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.4.10
SRSASN_CODE pdu_address_t::unpack(asn1::cbit_ref& bref)
{
uint8_t length = 0;
HANDLE_CODE(bref.unpack(length, 8));
if (length < 5 || length > 29) {
asn1::log_error("Decoding Failed (PDU address): Length (%d) is not in range of min: 5 and max 29 bytes", length);
@ -3949,7 +4017,7 @@ SRSASN_CODE qo_s_rules_t::pack(asn1::bit_ref& bref)
bref.align_bytes_zero();
uint16_t length = (uint16_t)(ceilf((float)bref.distance(bref_length) / 8) - 2);
// MAX 65535 not check because auf uint overflow
// max. length of 65535 not checked: uint overflow
if (length < 4) {
asn1::log_error("Encoding Failed (QoS rules): Packed length (%d) is not in range of min: 4 bytes", length);
return asn1::SRSASN_ERROR_ENCODE_FAIL;
@ -3962,8 +4030,9 @@ SRSASN_CODE qo_s_rules_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.4.13
SRSASN_CODE qo_s_rules_t::unpack(asn1::cbit_ref& bref)
{
uint16_t length = 0;
HANDLE_CODE(bref.unpack(length, 16));
// MAX 65535 not check because auf uint overflow
// max. length of 65535 not checked: uint overflow
if (length < 4) {
asn1::log_error("Decoding Failed (QoS rules): Length (%d) is not in range of min: 4 bytes", length);
return asn1::SRSASN_ERROR_DECODE_FAIL;
@ -4000,6 +4069,7 @@ SRSASN_CODE session_ambr_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.4.14
SRSASN_CODE session_ambr_t::unpack(asn1::cbit_ref& bref)
{
uint8_t length = 0;
HANDLE_CODE(bref.unpack(length, 8));
if (length != 6) {
asn1::log_error("Decoding Failed (Session-AMBR): Length (%d) does not equal expected length 6", length);
@ -4079,7 +4149,7 @@ SRSASN_CODE mapped_eps_bearer_contexts_t::pack(asn1::bit_ref& bref)
bref.align_bytes_zero();
uint16_t length = (uint16_t)(ceilf((float)bref.distance(bref_length) / 8) - 2);
// MAX 65535 not check because auf uint overflow
// max. length of 65535 not checked: uint overflow
if (length < 4) {
asn1::log_error("Encoding Failed (Mapped EPS bearer contexts): Packed length (%d) is not in range of min: 4 bytes",
length);
@ -4093,8 +4163,9 @@ SRSASN_CODE mapped_eps_bearer_contexts_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.4.8
SRSASN_CODE mapped_eps_bearer_contexts_t::unpack(asn1::cbit_ref& bref)
{
uint16_t length = 0;
HANDLE_CODE(bref.unpack(length, 16));
// MAX 65535 not check because auf uint overflow
// max. length of 65535 not checked: uint overflow
if (length < 4) {
asn1::log_error("Decoding Failed (Mapped EPS bearer contexts): Length (%d) is not in range of min: 4 bytes",
length);
@ -4119,7 +4190,7 @@ SRSASN_CODE qo_s_flow_descriptions_t::pack(asn1::bit_ref& bref)
bref.align_bytes_zero();
uint16_t length = (uint16_t)(ceilf((float)bref.distance(bref_length) / 8) - 2);
// MAX 65535 not check because auf uint overflow
// max. length of 65535 not checked: uint overflow
if (length < 3) {
asn1::log_error("Encoding Failed (QoS flow descriptions): Packed length (%d) is not in range of min: 3 bytes",
length);
@ -4133,8 +4204,9 @@ SRSASN_CODE qo_s_flow_descriptions_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.4.12
SRSASN_CODE qo_s_flow_descriptions_t::unpack(asn1::cbit_ref& bref)
{
uint16_t length = 0;
HANDLE_CODE(bref.unpack(length, 16));
// MAX 65535 not check because auf uint overflow
// max. length of 65535 not checked: uint overflow
if (length < 3) {
asn1::log_error("Decoding Failed (QoS flow descriptions): Length (%d) is not in range of min: 3 bytes", length);
return asn1::SRSASN_ERROR_DECODE_FAIL;
@ -4174,6 +4246,7 @@ SRSASN_CODE network_feature_support_5gsm_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.4.18
SRSASN_CODE network_feature_support_5gsm_t::unpack(asn1::cbit_ref& bref)
{
uint8_t length = 0;
HANDLE_CODE(bref.unpack(length, 8));
if (length < 1 || length > 13) {
asn1::log_error(
@ -4216,6 +4289,7 @@ SRSASN_CODE serving_plmn_rate_control_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.4.20
SRSASN_CODE serving_plmn_rate_control_t::unpack(asn1::cbit_ref& bref)
{
uint8_t length = 0;
HANDLE_CODE(bref.unpack(length, 8));
if (length != 2) {
asn1::log_error("Decoding Failed (Serving PLMN rate control): Length (%d) does not equal expected length 2",
@ -4238,8 +4312,8 @@ SRSASN_CODE atsss_container_t::pack(asn1::bit_ref& bref)
bref.align_bytes_zero();
uint16_t length = (uint16_t)(ceilf((float)bref.distance(bref_length) / 8) - 2);
// MIN 0 not check because auf uint underflow
// MAX 65535 not check because auf uint overflow
// min. length of 0 not checked: uint underflow
// max. length of 65535 not checked: uint overflow
HANDLE_CODE(bref_length.pack(length, 16));
return SRSASN_SUCCESS;
}
@ -4248,12 +4322,9 @@ SRSASN_CODE atsss_container_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.4.22
SRSASN_CODE atsss_container_t::unpack(asn1::cbit_ref& bref)
{
uint16_t length = 0;
HANDLE_CODE(bref.unpack(length, 16));
// MIN 0 not check because auf uint underflow
if (length > 65535) {
asn1::log_error("Decoding Failed (ATSSS container): Length (%d) is not in range of max 65535 bytes", length);
return asn1::SRSASN_ERROR_DECODE_FAIL;
}
// min. length of 0 not checked: uint underflow
nas_message_container.resize(length);
HANDLE_CODE(bref.unpack_bytes(nas_message_container.data(), length));
return SRSASN_SUCCESS;
@ -4352,6 +4423,7 @@ SRSASN_CODE re_attempt_indicator_t::pack(asn1::bit_ref& bref)
// Reference: 9.11.4.17
SRSASN_CODE re_attempt_indicator_t::unpack(asn1::cbit_ref& bref)
{
uint8_t length = 0;
HANDLE_CODE(bref.unpack(length, 8));
if (length != 1) {
asn1::log_error("Decoding Failed (Re-attempt indicator): Length (%d) does not equal expected length 1", length);

@ -3630,7 +3630,7 @@ SRSASN_CODE nas_5gs_msg::pack(unique_byte_buffer_t& buf)
return SRSASN_SUCCESS;
}
SRSASN_CODE nas_5gs_msg::pack(std::vector<uint8_t> buf)
SRSASN_CODE nas_5gs_msg::pack(std::vector<uint8_t>& buf)
{
buf.resize(SRSRAN_MAX_BUFFER_SIZE_BYTES);
asn1::bit_ref msg_bref(buf.data(), buf.size());
@ -3892,7 +3892,7 @@ SRSASN_CODE nas_5gs_msg::unpack_outer_hdr(const unique_byte_buffer_t& buf)
return SRSASN_SUCCESS;
}
SRSASN_CODE nas_5gs_msg::unpack_outer_hdr(const std::vector<uint8_t> buf)
SRSASN_CODE nas_5gs_msg::unpack_outer_hdr(const std::vector<uint8_t>& buf)
{
asn1::cbit_ref msg_bref(buf.data(), buf.size());
HANDLE_CODE(hdr.unpack_outer(msg_bref));
@ -3906,7 +3906,7 @@ SRSASN_CODE nas_5gs_msg::unpack(const unique_byte_buffer_t& buf)
return SRSASN_SUCCESS;
}
SRSASN_CODE nas_5gs_msg::unpack(const std::vector<uint8_t> buf)
SRSASN_CODE nas_5gs_msg::unpack(const std::vector<uint8_t>& buf)
{
asn1::cbit_ref msg_bref(buf.data(), buf.size());
HANDLE_CODE(unpack(msg_bref));

@ -23,140 +23,169 @@
namespace srsran {
bearer_manager::bearer_manager() : logger(srslog::fetch_basic_logger("STCK", false))
namespace detail {
const ue_bearer_manager_impl::radio_bearer_t ue_bearer_manager_impl::invalid_rb{srsran::srsran_rat_t::nulltype, 0, 0};
bool ue_bearer_manager_impl::add_eps_bearer(uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid)
{
pthread_rwlock_init(&rwlock, nullptr);
auto bearer_it = bearers.find(eps_bearer_id);
if (bearer_it != bearers.end()) {
return false;
}
bearers.emplace(eps_bearer_id, radio_bearer_t{rat, lcid, eps_bearer_id});
lcid_to_eps_bearer_id.emplace(lcid, eps_bearer_id);
return true;
}
bearer_manager::~bearer_manager()
bool ue_bearer_manager_impl::remove_eps_bearer(uint8_t eps_bearer_id)
{
pthread_rwlock_destroy(&rwlock);
auto bearer_it = bearers.find(eps_bearer_id);
if (bearer_it == bearers.end()) {
return false;
}
uint32_t lcid = bearer_it->second.lcid;
bearers.erase(bearer_it);
lcid_to_eps_bearer_id.erase(lcid);
return true;
}
void bearer_manager::add_eps_bearer(uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid)
void ue_bearer_manager_impl::reset()
{
add_eps_bearer(default_key, eps_bearer_id, rat, lcid);
lcid_to_eps_bearer_id.clear();
bearers.clear();
}
void bearer_manager::add_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid)
bool ue_bearer_manager_impl::has_active_radio_bearer(uint32_t eps_bearer_id)
{
srsran::rwlock_write_guard rw_lock(rwlock);
auto user_it = users_map.find(rnti);
if (user_it == users_map.end()) {
// add empty bearer map
auto p = users_map.emplace(rnti, user_bearers{});
user_it = p.first;
}
auto bearer_it = user_it->second.bearers.find(eps_bearer_id);
if (bearer_it != user_it->second.bearers.end()) {
logger.error("EPS bearer ID %d already registered", eps_bearer_id);
return;
}
user_it->second.bearers.emplace(eps_bearer_id, radio_bearer_t{rat, lcid, eps_bearer_id});
user_it->second.lcid_to_eps_bearer_id.emplace(lcid, eps_bearer_id);
logger.info("Registered EPS bearer ID %d for lcid=%d over %s-PDCP", eps_bearer_id, lcid, to_string(rat).c_str());
return bearers.count(eps_bearer_id) > 0;
}
void bearer_manager::remove_eps_bearer(uint8_t eps_bearer_id)
ue_bearer_manager_impl::radio_bearer_t ue_bearer_manager_impl::get_radio_bearer(uint32_t eps_bearer_id)
{
remove_eps_bearer(default_key, eps_bearer_id);
auto it = bearers.find(eps_bearer_id);
return it != bearers.end() ? it->second : invalid_rb;
}
void bearer_manager::remove_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id)
ue_bearer_manager_impl::radio_bearer_t ue_bearer_manager_impl::get_lcid_bearer(uint32_t lcid)
{
srsran::rwlock_write_guard rw_lock(rwlock);
auto lcid_it = lcid_to_eps_bearer_id.find(lcid);
return lcid_it != lcid_to_eps_bearer_id.end() ? bearers.at(lcid_it->second) : invalid_rb;
}
auto user_it = users_map.find(rnti);
if (user_it == users_map.end()) {
logger.error("No EPS bearer registered for rnti=%x", rnti);
return;
}
} // namespace detail
} // namespace srsran
auto bearer_it = user_it->second.bearers.find(eps_bearer_id);
if (bearer_it == user_it->second.bearers.end()) {
logger.error("Can't remove EPS bearer ID %d", eps_bearer_id);
return;
}
uint32_t lcid = bearer_it->second.lcid;
user_it->second.bearers.erase(bearer_it);
user_it->second.lcid_to_eps_bearer_id.erase(lcid);
logger.info("Removed mapping for EPS bearer ID %d", eps_bearer_id);
namespace srsue {
ue_bearer_manager::ue_bearer_manager() : logger(srslog::fetch_basic_logger("STCK", false))
{
pthread_rwlock_init(&rwlock, nullptr);
}
void bearer_manager::reset()
ue_bearer_manager::~ue_bearer_manager()
{
reset(default_key);
pthread_rwlock_destroy(&rwlock);
}
void bearer_manager::reset(uint16_t rnti)
void ue_bearer_manager::add_eps_bearer(uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid)
{
srsran::rwlock_write_guard rw_lock(rwlock);
auto user_it = users_map.find(rnti);
if (user_it == users_map.end()) {
logger.error("No EPS bearer registered for rnti=%x", rnti);
return;
if (impl.add_eps_bearer(eps_bearer_id, rat, lcid)) {
logger.info(
"Bearers: Registered EPS bearer ID %d for lcid=%d over %s-PDCP", eps_bearer_id, lcid, to_string(rat).c_str());
} else {
logger.error("Bearers: EPS bearer ID %d already registered", eps_bearer_id);
}
user_it->second.lcid_to_eps_bearer_id.clear();
user_it->second.bearers.clear();
logger.info("Reset EPS bearer manager");
}
// GW interface
bool bearer_manager::has_active_radio_bearer(uint32_t eps_bearer_id)
void ue_bearer_manager::remove_eps_bearer(uint8_t eps_bearer_id)
{
return has_active_radio_bearer(default_key, eps_bearer_id);
srsran::rwlock_write_guard rw_lock(rwlock);
if (impl.remove_eps_bearer(eps_bearer_id)) {
logger.info("Bearers: Removed mapping for EPS bearer ID %d", eps_bearer_id);
} else {
logger.error("Bearers: Can't remove EPS bearer ID %d", eps_bearer_id);
}
}
bool bearer_manager::has_active_radio_bearer(uint16_t rnti, uint32_t eps_bearer_id)
void ue_bearer_manager::reset()
{
srsran::rwlock_read_guard rw_lock(rwlock);
impl.reset();
logger.info("Bearers: Reset EPS bearer manager");
}
} // namespace srsue
namespace srsenb {
enb_bearer_manager::enb_bearer_manager() : logger(srslog::fetch_basic_logger("STCK", false)) {}
void enb_bearer_manager::add_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid)
{
auto user_it = users_map.find(rnti);
if (user_it == users_map.end()) {
return false;
// add empty bearer map
auto p = users_map.insert(rnti, srsran::detail::ue_bearer_manager_impl{});
user_it = p.value();
}
return user_it->second.bearers.find(eps_bearer_id) != user_it->second.bearers.end();
if (user_it->second.add_eps_bearer(eps_bearer_id, rat, lcid)) {
logger.info("Bearers: Registered eps-BearerID=%d for rnti=0x%x, lcid=%d over %s-PDCP",
eps_bearer_id,
rnti,
lcid,
to_string(rat).c_str());
} else {
logger.error("Bearers: EPS bearer ID %d for rnti=0x%x already registered", eps_bearer_id, rnti);
}
}
// Stack interface
bearer_manager::radio_bearer_t bearer_manager::get_radio_bearer(uint32_t eps_bearer_id)
void enb_bearer_manager::remove_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id)
{
return get_radio_bearer(default_key, eps_bearer_id);
auto user_it = users_map.find(rnti);
if (user_it == users_map.end()) {
logger.error("Bearers: No EPS bearer registered for rnti=0x%x", rnti);
return;
}
if (user_it->second.remove_eps_bearer(eps_bearer_id)) {
logger.info("Bearers: Removed mapping for EPS bearer ID %d for rnti=0x%x", eps_bearer_id, rnti);
} else {
logger.error("Bearers: Can't remove EPS bearer ID %d, rnti=0x%x", eps_bearer_id, rnti);
}
}
bearer_manager::radio_bearer_t bearer_manager::get_lcid_bearer(uint16_t rnti, uint32_t lcid)
void enb_bearer_manager::rem_user(uint16_t rnti)
{
srsran::rwlock_read_guard rw_lock(rwlock);
logger.info("Bearers: Removed rnti=0x%x from EPS bearer manager", rnti);
}
bool enb_bearer_manager::has_active_radio_bearer(uint16_t rnti, uint32_t eps_bearer_id)
{
auto user_it = users_map.find(rnti);
if (user_it == users_map.end()) {
return invalid_rb;
}
auto lcid_it = user_it->second.lcid_to_eps_bearer_id.find(lcid);
if (lcid_it != user_it->second.lcid_to_eps_bearer_id.end()) {
return user_it->second.bearers.at(lcid_it->second);
return false;
}
return invalid_rb;
return user_it->second.has_active_radio_bearer(eps_bearer_id);
}
bearer_manager::radio_bearer_t bearer_manager::get_radio_bearer(uint16_t rnti, uint32_t eps_bearer_id)
enb_bearer_manager::radio_bearer_t enb_bearer_manager::get_lcid_bearer(uint16_t rnti, uint32_t lcid)
{
srsran::rwlock_read_guard rw_lock(rwlock);
auto user_it = users_map.find(rnti);
if (user_it == users_map.end()) {
return invalid_rb;
return srsran::detail::ue_bearer_manager_impl::invalid_rb;
}
return user_it->second.get_lcid_bearer(lcid);
}
if (user_it->second.bearers.find(eps_bearer_id) != user_it->second.bearers.end()) {
return user_it->second.bearers.at(eps_bearer_id);
enb_bearer_manager::radio_bearer_t enb_bearer_manager::get_radio_bearer(uint16_t rnti, uint32_t eps_bearer_id)
{
auto user_it = users_map.find(rnti);
if (user_it == users_map.end()) {
return srsran::detail::ue_bearer_manager_impl::invalid_rb;
}
return invalid_rb;
return user_it->second.get_radio_bearer(eps_bearer_id);
}
} // namespace srsran
} // namespace srsenb

@ -22,6 +22,8 @@
#include "srsran/common/enb_events.h"
#include "srsran/srslog/context.h"
#include "srsran/srslog/log_channel.h"
#include <mutex>
#include <unordered_map>
using namespace srsenb;
@ -32,17 +34,34 @@ class null_event_logger : public event_logger_interface
{
public:
void log_rrc_event(uint32_t enb_cc_idx,
const std::string& asn1,
const std::string& asn1_oct_str,
const std::string& asn1_txt_str,
unsigned type,
unsigned additional_info,
uint16_t rnti) override
{}
void log_s1_ctx_create(uint32_t enb_cc_idx, uint32_t mme_id, uint32_t enb_id, uint16_t rnti) override {}
void log_s1_ctx_delete(uint32_t enb_cc_idx, uint32_t mme_id, uint32_t enb_id, uint16_t rnti) override {}
void log_sector_start(uint32_t cc_idx, uint32_t pci, uint32_t cell_id) override {}
void log_sector_stop(uint32_t cc_idx, uint32_t pci, uint32_t cell_id) override {}
void log_measurement_report(uint32_t enb_cc_idx, const std::string& asn1, uint16_t rnti) override {}
void log_rlf(uint32_t enb_cc_idx, const std::string& asn1, uint16_t rnti) override {}
void log_sector_start(uint32_t cc_idx, uint32_t pci, uint32_t cell_id, const std::string& hnb_name) override {}
void log_sector_stop(uint32_t cc_idx, uint32_t pci, uint32_t cell_id, const std::string& hnb_name) override {}
void log_measurement_report(uint32_t enb_cc_idx,
const std::string& asn1_oct_str,
const std::string& asn1_txt_str,
uint16_t rnti) override
{}
void log_rlf_report(uint32_t enb_cc_idx,
const std::string& asn1_oct_str,
const std::string& asn1_txt_str,
uint16_t rnti) override
{}
void log_rlf_detected(uint32_t enb_cc_idx, const std::string& type, uint16_t rnti) override {}
void log_handover_command(uint32_t enb_cc_idx,
uint32_t target_pci,
uint32_t target_earfcn,
uint16_t new_ue_rnti,
uint16_t rnti) override
{}
void log_connection_resume(uint32_t enb_cc_idx, uint16_t resume_rnti, uint16_t rnti) override {}
};
} // namespace
@ -59,7 +78,8 @@ namespace {
/// Common metrics to all events.
DECLARE_METRIC("type", metric_type_tag, std::string, "");
DECLARE_METRIC("timestamp", metric_timestamp_tag, double, "");
DECLARE_METRIC("sector_id", metric_sector_id, uint32_t, "");
DECLARE_METRIC("carrier_id", metric_carrier_id, uint32_t, "");
DECLARE_METRIC("cell_id", metric_cell_id, uint32_t, "");
DECLARE_METRIC("event_name", metric_event_name, std::string, "");
DECLARE_METRIC("rnti", metric_rnti, uint16_t, "");
@ -73,8 +93,12 @@ DECLARE_METRIC("pci", metric_pci, uint32_t, "");
DECLARE_METRIC("cell_identity", metric_cell_identity, std::string, "");
DECLARE_METRIC("sib9_home_enb_name", metric_sib9_home_enb_name, std::string, "");
DECLARE_METRIC_SET("event_data", mset_sector_event, metric_pci, metric_cell_identity, metric_sib9_home_enb_name);
using sector_event_t = srslog::
build_context_type<metric_type_tag, metric_timestamp_tag, metric_sector_id, metric_event_name, mset_sector_event>;
using sector_event_t = srslog::build_context_type<metric_type_tag,
metric_timestamp_tag,
metric_carrier_id,
metric_cell_id,
metric_event_name,
mset_sector_event>;
/// Context for a RRC event.
DECLARE_METRIC("asn1_type", metric_asn1_type, uint32_t, "");
@ -86,46 +110,102 @@ DECLARE_METRIC_SET("event_data",
metric_asn1_message,
metric_asn1_type,
metric_additional);
using rrc_event_t = srslog::
build_context_type<metric_type_tag, metric_timestamp_tag, metric_sector_id, metric_event_name, mset_rrc_event>;
using rrc_event_t = srslog::build_context_type<metric_type_tag,
metric_timestamp_tag,
metric_carrier_id,
metric_cell_id,
metric_event_name,
mset_rrc_event>;
/// Context for S1 context create/delete.
DECLARE_METRIC("mme_ue_s1ap_id", metric_ue_mme_id, uint32_t, "");
DECLARE_METRIC("enb_ue_s1ap_id", metric_ue_enb_id, uint32_t, "");
DECLARE_METRIC_SET("event_data", mset_s1apctx_event, metric_ue_mme_id, metric_ue_enb_id, metric_rnti);
using s1apctx_event_t = srslog::
build_context_type<metric_type_tag, metric_timestamp_tag, metric_sector_id, metric_event_name, mset_s1apctx_event>;
/// Context for the RLF event.
DECLARE_METRIC_SET("event_data", mset_rlfctx_event, metric_asn1_length, metric_asn1_message, metric_rnti);
using rlfctx_event_t = srslog::
build_context_type<metric_type_tag, metric_timestamp_tag, metric_sector_id, metric_event_name, mset_rlfctx_event>;
using s1apctx_event_t = srslog::build_context_type<metric_type_tag,
metric_timestamp_tag,
metric_carrier_id,
metric_cell_id,
metric_event_name,
mset_s1apctx_event>;
/// Context for the RLF report event.
DECLARE_METRIC_SET("event_data", mset_rlf_report_event, metric_asn1_length, metric_asn1_message, metric_rnti);
using rlf_report_event_t = srslog::build_context_type<metric_type_tag,
metric_timestamp_tag,
metric_carrier_id,
metric_cell_id,
metric_event_name,
mset_rlf_report_event>;
/// Context for measurement report.
DECLARE_METRIC_SET("event_data", mset_meas_report_event, metric_asn1_length, metric_asn1_message, metric_rnti);
using meas_report_event_t = srslog::build_context_type<metric_type_tag,
metric_timestamp_tag,
metric_sector_id,
metric_carrier_id,
metric_cell_id,
metric_event_name,
mset_meas_report_event>;
/// Context for the handover command event.
DECLARE_METRIC("target_pci", metric_target_pci, uint32_t, "");
DECLARE_METRIC("target_earfcn", metric_target_earfcn, uint32_t, "");
DECLARE_METRIC("new_ue_rnti", metric_new_ue_rnti, uint32_t, "");
DECLARE_METRIC_SET("event_data",
mset_ho_cmd_event,
metric_rnti,
metric_target_pci,
metric_target_earfcn,
metric_new_ue_rnti);
using ho_cmd_t = srslog::build_context_type<metric_type_tag,
metric_timestamp_tag,
metric_carrier_id,
metric_cell_id,
metric_event_name,
mset_ho_cmd_event>;
/// Context for the connection resume event.
DECLARE_METRIC("resume_rnti", metric_resume_rnti, uint32_t, "");
DECLARE_METRIC_SET("event_data", mset_conn_resume_event, metric_rnti, metric_resume_rnti);
using conn_resume_t = srslog::build_context_type<metric_type_tag,
metric_timestamp_tag,
metric_carrier_id,
metric_cell_id,
metric_event_name,
mset_conn_resume_event>;
/// Context for the RLF detected event.
DECLARE_METRIC("type", metric_rlf_type, std::string, "");
DECLARE_METRIC_SET("event_data", mset_rlf_detected_event, metric_rnti, metric_rlf_type);
using rlf_detected_t = srslog::build_context_type<metric_type_tag,
metric_timestamp_tag,
metric_carrier_id,
metric_cell_id,
metric_event_name,
mset_rlf_detected_event>;
/// Logs events into the configured log channel.
class logging_event_logger : public event_logger_interface
{
public:
explicit logging_event_logger(srslog::log_channel& c) : event_channel(c) {}
logging_event_logger(srslog::log_channel& c, event_logger::asn1_output_format asn1_format) :
event_channel(c), asn1_format(asn1_format)
{}
void log_rrc_event(uint32_t enb_cc_idx,
const std::string& asn1,
const std::string& asn1_oct_str,
const std::string& asn1_txt_str,
unsigned type,
unsigned additional_info,
uint16_t rnti) override
{
rrc_event_t ctx("");
const std::string& asn1 = (asn1_format == event_logger::asn1_output_format::octets) ? asn1_oct_str : asn1_txt_str;
ctx.write<metric_type_tag>("event");
ctx.write<metric_timestamp_tag>(get_time_stamp());
ctx.write<metric_sector_id>(enb_cc_idx);
ctx.write<metric_carrier_id>(enb_cc_idx);
ctx.write<metric_cell_id>(get_pci(enb_cc_idx));
ctx.write<metric_event_name>("rrc_log");
ctx.get<mset_rrc_event>().write<metric_rnti>(rnti);
ctx.get<mset_rrc_event>().write<metric_asn1_length>(asn1.size());
@ -141,7 +221,8 @@ public:
ctx.write<metric_type_tag>("event");
ctx.write<metric_timestamp_tag>(get_time_stamp());
ctx.write<metric_sector_id>(enb_cc_idx);
ctx.write<metric_carrier_id>(enb_cc_idx);
ctx.write<metric_cell_id>(get_pci(enb_cc_idx));
ctx.write<metric_event_name>("s1_context_create");
ctx.get<mset_s1apctx_event>().write<metric_ue_mme_id>(mme_id);
ctx.get<mset_s1apctx_event>().write<metric_ue_enb_id>(enb_id);
@ -155,7 +236,8 @@ public:
ctx.write<metric_type_tag>("event");
ctx.write<metric_timestamp_tag>(get_time_stamp());
ctx.write<metric_sector_id>(enb_cc_idx);
ctx.write<metric_carrier_id>(enb_cc_idx);
ctx.write<metric_cell_id>(get_pci(enb_cc_idx));
ctx.write<metric_event_name>("s1_context_delete");
ctx.get<mset_s1apctx_event>().write<metric_ue_mme_id>(mme_id);
ctx.get<mset_s1apctx_event>().write<metric_ue_enb_id>(enb_id);
@ -163,41 +245,51 @@ public:
event_channel(ctx);
}
void log_sector_start(uint32_t cc_idx, uint32_t pci, uint32_t cell_id) override
void log_sector_start(uint32_t cc_idx, uint32_t pci, uint32_t cell_id, const std::string& hnb_name) override
{
register_pci(cc_idx, pci);
sector_event_t ctx("");
ctx.write<metric_type_tag>("event");
ctx.write<metric_timestamp_tag>(get_time_stamp());
ctx.write<metric_sector_id>(cc_idx);
ctx.write<metric_carrier_id>(cc_idx);
ctx.write<metric_cell_id>(pci);
ctx.write<metric_event_name>("sector_start");
ctx.get<mset_sector_event>().write<metric_pci>(pci);
ctx.get<mset_sector_event>().write<metric_cell_identity>(fmt::to_string(cell_id));
ctx.get<mset_sector_event>().write<metric_sib9_home_enb_name>("TODO");
ctx.get<mset_sector_event>().write<metric_sib9_home_enb_name>(hnb_name);
event_channel(ctx);
}
void log_sector_stop(uint32_t cc_idx, uint32_t pci, uint32_t cell_id) override
void log_sector_stop(uint32_t cc_idx, uint32_t pci, uint32_t cell_id, const std::string& hnb_name) override
{
sector_event_t ctx("");
ctx.write<metric_type_tag>("event");
ctx.write<metric_timestamp_tag>(get_time_stamp());
ctx.write<metric_sector_id>(cc_idx);
ctx.write<metric_carrier_id>(cc_idx);
ctx.write<metric_cell_id>(get_pci(cc_idx));
ctx.write<metric_event_name>("sector_stop");
ctx.get<mset_sector_event>().write<metric_pci>(pci);
ctx.get<mset_sector_event>().write<metric_cell_identity>(fmt::to_string(cell_id));
ctx.get<mset_sector_event>().write<metric_sib9_home_enb_name>("TODO");
ctx.get<mset_sector_event>().write<metric_sib9_home_enb_name>(hnb_name);
event_channel(ctx);
}
void log_measurement_report(uint32_t enb_cc_idx, const std::string& asn1, uint16_t rnti) override
void log_measurement_report(uint32_t enb_cc_idx,
const std::string& asn1_oct_str,
const std::string& asn1_txt_str,
uint16_t rnti) override
{
meas_report_event_t ctx("");
const std::string& asn1 = (asn1_format == event_logger::asn1_output_format::octets) ? asn1_oct_str : asn1_txt_str;
ctx.write<metric_type_tag>("event");
ctx.write<metric_timestamp_tag>(get_time_stamp());
ctx.write<metric_sector_id>(enb_cc_idx);
ctx.write<metric_carrier_id>(enb_cc_idx);
ctx.write<metric_cell_id>(get_pci(enb_cc_idx));
ctx.write<metric_event_name>("measurement_report");
ctx.get<mset_meas_report_event>().write<metric_asn1_length>(asn1.size());
ctx.get<mset_meas_report_event>().write<metric_asn1_message>(asn1);
@ -205,22 +297,96 @@ public:
event_channel(ctx);
}
void log_rlf(uint32_t enb_cc_idx, const std::string& asn1, uint16_t rnti) override
void log_rlf_report(uint32_t enb_cc_idx,
const std::string& asn1_oct_str,
const std::string& asn1_txt_str,
uint16_t rnti) override
{
rlf_report_event_t ctx("");
const std::string& asn1 = (asn1_format == event_logger::asn1_output_format::octets) ? asn1_oct_str : asn1_txt_str;
ctx.write<metric_type_tag>("event");
ctx.write<metric_timestamp_tag>(get_time_stamp());
ctx.write<metric_carrier_id>(enb_cc_idx);
ctx.write<metric_cell_id>(get_pci(enb_cc_idx));
ctx.write<metric_event_name>("rlf_report");
ctx.get<mset_rlf_report_event>().write<metric_asn1_length>(asn1.size());
ctx.get<mset_rlf_report_event>().write<metric_asn1_message>(asn1);
ctx.get<mset_rlf_report_event>().write<metric_rnti>(rnti);
event_channel(ctx);
}
void log_rlf_detected(uint32_t enb_cc_idx, const std::string& type, uint16_t rnti) override
{
rlf_detected_t ctx("");
ctx.write<metric_type_tag>("event");
ctx.write<metric_timestamp_tag>(get_time_stamp());
ctx.write<metric_carrier_id>(enb_cc_idx);
ctx.write<metric_cell_id>(get_pci(enb_cc_idx));
ctx.write<metric_event_name>("rlf_detected");
ctx.get<mset_rlf_detected_event>().write<metric_rnti>(rnti);
ctx.get<mset_rlf_detected_event>().write<metric_rlf_type>(type);
event_channel(ctx);
}
void log_handover_command(uint32_t enb_cc_idx,
uint32_t target_pci,
uint32_t target_earfcn,
uint16_t new_ue_rnti,
uint16_t rnti) override
{
ho_cmd_t ctx("");
ctx.write<metric_type_tag>("event");
ctx.write<metric_timestamp_tag>(get_time_stamp());
ctx.write<metric_carrier_id>(enb_cc_idx);
ctx.write<metric_cell_id>(get_pci(enb_cc_idx));
ctx.write<metric_event_name>("ho_command");
ctx.get<mset_ho_cmd_event>().write<metric_rnti>(rnti);
ctx.get<mset_ho_cmd_event>().write<metric_target_pci>(target_pci);
ctx.get<mset_ho_cmd_event>().write<metric_target_earfcn>(target_earfcn);
ctx.get<mset_ho_cmd_event>().write<metric_new_ue_rnti>(new_ue_rnti);
event_channel(ctx);
}
void log_connection_resume(uint32_t enb_cc_idx, uint16_t resume_rnti, uint16_t rnti) override
{
rlfctx_event_t ctx("");
conn_resume_t ctx("");
ctx.write<metric_type_tag>("event");
ctx.write<metric_timestamp_tag>(get_time_stamp());
ctx.write<metric_sector_id>(enb_cc_idx);
ctx.write<metric_event_name>("radio_link_failure");
ctx.get<mset_rlfctx_event>().write<metric_asn1_length>(asn1.size());
ctx.get<mset_rlfctx_event>().write<metric_asn1_message>(asn1);
ctx.get<mset_rlfctx_event>().write<metric_rnti>(rnti);
ctx.write<metric_carrier_id>(enb_cc_idx);
ctx.write<metric_cell_id>(get_pci(enb_cc_idx));
ctx.write<metric_event_name>("connection_resume");
ctx.get<mset_conn_resume_event>().write<metric_rnti>(rnti);
ctx.get<mset_conn_resume_event>().write<metric_resume_rnti>(resume_rnti);
event_channel(ctx);
}
private:
srslog::log_channel& event_channel;
/// Associates the corresponding cc_idx with its PCI.
void register_pci(uint32_t cc_idx, uint32_t pci)
{
std::lock_guard<std::mutex> lock(m);
cc_idx_to_pci_map[cc_idx] = pci;
}
/// Returns the PCI value associated to specified cc_idx, otherwise returns an invalid PCI value if not previous
/// association has been set.
uint32_t get_pci(uint32_t cc_idx) const
{
std::lock_guard<std::mutex> lock(m);
auto it = cc_idx_to_pci_map.find(cc_idx);
return (it != cc_idx_to_pci_map.cend()) ? it->second : 999;
}
private:
srslog::log_channel& event_channel;
event_logger::asn1_output_format asn1_format;
std::unordered_map<uint32_t, uint32_t> cc_idx_to_pci_map;
mutable std::mutex m;
};
} // namespace
@ -232,7 +398,7 @@ event_logger_interface& event_logger::get()
return *pimpl;
}
void event_logger::configure(srslog::log_channel& c)
void event_logger::configure(srslog::log_channel& c, asn1_output_format asn1_format)
{
pimpl = std::unique_ptr<logging_event_logger>(new logging_event_logger(c));
pimpl = std::unique_ptr<logging_event_logger>(new logging_event_logger(c, asn1_format));
}

@ -21,6 +21,8 @@
#include "srsran/common/ssl.h"
#include "srsran/common/zuc.h"
#include <arpa/inet.h>
/*******************************************************************************
LOCAL FUNCTION PROTOTYPES
*******************************************************************************/
@ -120,6 +122,70 @@ LIBLTE_ERROR_ENUM liblte_security_generate_k_enb(uint8* k_asme, uint32 nas_count
return (err);
}
LIBLTE_ERROR_ENUM liblte_security_generate_res_star(uint8_t* ck,
uint8_t* ik,
const char* serving_network_name,
uint8_t* rand,
uint8_t* res,
size_t res_len,
uint8_t* res_star)
{
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
uint8_t key[32];
uint8_t* s;
if (ck != NULL && ik != NULL && serving_network_name != NULL && rand != NULL && res != NULL && res_star != NULL) {
// Construct S
uint16_t ssn_length = strlen(serving_network_name);
uint16_t rand_length = 16;
uint32_t s_len = 1 + ssn_length + 2 + rand_length + 2 + res_len + 2;
uint8_t output[32] = {};
s = (uint8_t*)calloc(s_len, sizeof(uint8_t));
if (s == nullptr) {
return err;
}
uint32_t i = 0;
s[i] = 0x6B; // FC
i++;
// SSN
memcpy(&s[i], serving_network_name, strlen(serving_network_name));
i += ssn_length;
uint16_t ssn_length_value = htons(ssn_length);
memcpy(&s[i], &ssn_length_value, sizeof(ssn_length));
i += sizeof(ssn_length_value);
// RAND
memcpy(&s[i], rand, rand_length);
i += rand_length;
uint16_t rand_length_value = htons(rand_length);
memcpy(&s[i], &rand_length_value, sizeof(rand_length));
i += sizeof(rand_length_value);
// RES
memcpy(&s[i], res, res_len);
i += res_len;
uint16_t res_length_value = htons(res_len);
memcpy(&s[i], &res_length_value, sizeof(res_length_value));
i += sizeof(res_length_value);
// The input key Key shall be equal to the concatenation CK || IK of CK and IK.
memcpy(key, ck, 16);
memcpy(key + 16, ik, 16);
// Derive output
sha256(key, 32, s, s_len, output, 0);
memcpy(res_star, output + 16, 16);
free(s);
err = LIBLTE_SUCCESS;
}
return (err);
}
/*********************************************************************
Name: liblte_security_generate_k_enb_star
@ -192,22 +258,18 @@ LIBLTE_ERROR_ENUM liblte_security_generate_k_nas(uint8*
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
uint8 s[7];
if (k_asme != NULL && k_nas_enc != NULL) { //{}
if (enc_alg_id != LIBLTE_SECURITY_CIPHERING_ALGORITHM_ID_EEA0) {
// Construct S for KNASenc
s[0] = 0x15; // FC
s[1] = 0x01; // P0
s[2] = 0x00; // First byte of L0
s[3] = 0x01; // Second byte of L0
s[4] = enc_alg_id; // P1
s[5] = 0x00; // First byte of L1
s[6] = 0x01; // Second byte of L1
// Derive KNASenc
sha256(k_asme, 32, s, 7, k_nas_enc, 0);
} else {
memset(k_nas_enc, 0, 32);
}
if (k_asme != NULL && k_nas_enc != NULL) {
// Construct S for KNASenc
s[0] = 0x15; // FC
s[1] = 0x01; // P0
s[2] = 0x00; // First byte of L0
s[3] = 0x01; // Second byte of L0
s[4] = enc_alg_id; // P1
s[5] = 0x00; // First byte of L1
s[6] = 0x01; // Second byte of L1
// Derive KNASenc
sha256(k_asme, 32, s, 7, k_nas_enc, 0);
}
if (k_asme != NULL && k_nas_int != NULL) {
@ -1155,13 +1217,13 @@ liblte_security_milenage_f2345(uint8* k, uint8* op_c, uint8* rand, uint8* res, u
for (i = 0; i < 16; i++) {
input[i] = rand[i] ^ op_c[i];
}
mbedtls_aes_crypt_ecb(&ctx, AES_ENCRYPT, input, temp);
aes_crypt_ecb(&ctx, AES_ENCRYPT, input, temp);
// Compute out for RES and AK
for (i = 0; i < 16; i++) {
input[i] = temp[i] ^ op_c[i];
}
input[15] ^= 1;
mbedtls_aes_crypt_ecb(&ctx, AES_ENCRYPT, input, out);
aes_crypt_ecb(&ctx, AES_ENCRYPT, input, out);
for (i = 0; i < 16; i++) {
out[i] ^= op_c[i];
}
@ -1181,7 +1243,7 @@ liblte_security_milenage_f2345(uint8* k, uint8* op_c, uint8* rand, uint8* res, u
input[(i + 12) % 16] = temp[i] ^ op_c[i];
}
input[15] ^= 2;
mbedtls_aes_crypt_ecb(&ctx, AES_ENCRYPT, input, out);
aes_crypt_ecb(&ctx, AES_ENCRYPT, input, out);
for (i = 0; i < 16; i++) {
out[i] ^= op_c[i];
}
@ -1196,7 +1258,7 @@ liblte_security_milenage_f2345(uint8* k, uint8* op_c, uint8* rand, uint8* res, u
input[(i + 8) % 16] = temp[i] ^ op_c[i];
}
input[15] ^= 4;
mbedtls_aes_crypt_ecb(&ctx, AES_ENCRYPT, input, out);
aes_crypt_ecb(&ctx, AES_ENCRYPT, input, out);
for (i = 0; i < 16; i++) {
out[i] ^= op_c[i];
}

@ -22,8 +22,11 @@
#include "srsran/common/security.h"
#include "srsran/common/liblte_security.h"
#include "srsran/common/s3g.h"
#include "srsran/common/ssl.h"
#include "srsran/config.h"
#include <arpa/inet.h>
#ifdef HAVE_MBEDTLS
#include "mbedtls/md5.h"
#endif
@ -31,108 +34,730 @@
#include "polarssl/md5.h"
#endif
#define FC_EPS_K_ASME_DERIVATION 0x10
#define FC_EPS_K_ENB_DERIVATION 0x11
#define FC_EPS_NH_DERIVATION 0x12
#define FC_EPS_K_ENB_STAR_DERIVATION 0x13
#define FC_EPS_ALGORITHM_KEY_DERIVATION 0x15
#define ALGO_EPS_DISTINGUISHER_NAS_ENC_ALG 0x01
#define ALGO_EPS_DISTINGUISHER_NAS_INT_ALG 0x02
#define ALGO_EPS_DISTINGUISHER_RRC_ENC_ALG 0x03
#define ALGO_EPS_DISTINGUISHER_RRC_INT_ALG 0x04
#define ALGO_EPS_DISTINGUISHER_UP_ENC_ALG 0x05
#define ALGO_EPS_DISTINGUISHER_UP_INT_ALG 0x06
#define FC_5G_ALGORITHM_KEY_DERIVATION 0x69
#define FC_5G_KAUSF_DERIVATION 0x6A
#define FC_5G_RES_STAR_DERIVATION 0x6B
#define FC_5G_KSEAF_DERIVATION 0x6C
#define FC_5G_KAMF_DERIVATION 0x6D
#define FC_5G_KGNB_KN3IWF_DERIVATION 0x6E
#define FC_5G_NH_GNB_DERIVATION 0x6F
#define ALGO_5G_DISTINGUISHER_NAS_ENC_ALG 0x01
#define ALGO_5G_DISTINGUISHER_NAS_INT_ALG 0x02
#define ALGO_5G_DISTINGUISHER_RRC_ENC_ALG 0x03
#define ALGO_5G_DISTINGUISHER_RRC_INT_ALG 0x04
#define ALGO_5G_DISTINGUISHER_UP_ENC_ALG 0x05
#define ALGO_5G_DISTINGUISHER_UP_INT_ALG 0x06
namespace srsran {
/******************************************************************************
* Key Generation
*****************************************************************************/
uint8_t security_generate_k_asme(uint8_t* ck,
uint8_t* ik,
uint8_t* ak,
uint8_t* sqn,
uint16_t mcc,
uint16_t mnc,
uint8_t* k_asme)
uint8_t security_generate_k_asme(const uint8_t* ck,
const uint8_t* ik,
const uint8_t* ak_xor_sqn_,
const uint16_t mcc,
const uint16_t mnc,
uint8_t* k_asme)
{
if (ck == NULL || ik == NULL || ak_xor_sqn_ == NULL || k_asme == NULL) {
log_error("Invalid inputs");
return SRSRAN_ERROR;
}
std::array<uint8_t, 32> key;
// The input key Key shall be equal to the concatenation CK || IK of CK and IK.
memcpy(key.data(), ck, 16);
memcpy(key.data() + 16, ik, 16);
// Serving Network id
std::vector<uint8_t> sn_id;
sn_id.resize(3);
sn_id[0] = (mcc & 0x00F0) | ((mcc & 0x0F00) >> 8); // First byte of P0
if ((mnc & 0xFF00) == 0xFF00) {
// 2-digit MNC
sn_id[1] = 0xF0 | (mcc & 0x000F); // Second byte of P0
sn_id[2] = ((mnc & 0x000F) << 4) | ((mnc & 0x00F0) >> 4); // Third byte of P0
} else {
// 3-digit MNC
sn_id[1] = ((mnc & 0x000F) << 4) | (mcc & 0x000F); // Second byte of P0
sn_id[2] = ((mnc & 0x00F0)) | ((mnc & 0x0F00) >> 8); // Third byte of P0
}
// AK XOR SQN
std::vector<uint8_t> ak_xor_sqn;
ak_xor_sqn.resize(AK_LEN);
memcpy(ak_xor_sqn.data(), ak_xor_sqn_, ak_xor_sqn.size());
uint8_t output[32];
if (kdf_common(FC_EPS_K_ASME_DERIVATION, key, sn_id, ak_xor_sqn, output) != SRSRAN_SUCCESS) {
log_error("Failed to run kdf_common");
return SRSRAN_ERROR;
}
memcpy(k_asme, output, 32);
return SRSRAN_SUCCESS;
}
uint8_t security_generate_k_ausf(const uint8_t* ck,
const uint8_t* ik,
const uint8_t* ak_xor_sqn_,
const char* serving_network_name,
uint8_t* k_ausf)
{
if (ck == NULL || ik == NULL || ak_xor_sqn_ == NULL || serving_network_name == NULL || k_ausf == NULL) {
log_error("Invalid inputs");
return SRSRAN_ERROR;
}
std::array<uint8_t, 32> key;
// The input key Key shall be equal to the concatenation CK || IK of CK and IK.
memcpy(key.data(), ck, 16);
memcpy(key.data() + 16, ik, 16);
// Serving Network Name
std::vector<uint8_t> ssn;
ssn.resize(strlen(serving_network_name));
memcpy(ssn.data(), serving_network_name, ssn.size());
// AK XOR SQN
std::vector<uint8_t> ak_xor_sqn;
ak_xor_sqn.resize(AK_LEN);
memcpy(ak_xor_sqn.data(), ak_xor_sqn_, ak_xor_sqn.size());
uint8_t output[32];
if (kdf_common(FC_5G_KAUSF_DERIVATION, key, ssn, ak_xor_sqn, output) != SRSRAN_SUCCESS) {
log_error("Failed to run kdf_common");
return SRSRAN_ERROR;
}
memcpy(k_ausf, output, 32);
return SRSRAN_SUCCESS;
}
uint8_t security_generate_k_seaf(const uint8_t* k_ausf, const char* serving_network_name, uint8_t* k_seaf)
{
if (k_ausf == NULL || serving_network_name == NULL || k_seaf == NULL) {
log_error("Invalid inputs");
return SRSRAN_ERROR;
}
std::array<uint8_t, 32> key;
memcpy(key.data(), k_ausf, 32);
// Serving Network Name
std::vector<uint8_t> ssn;
ssn.resize(strlen(serving_network_name));
memcpy(ssn.data(), serving_network_name, ssn.size());
if (kdf_common(FC_5G_KSEAF_DERIVATION, key, ssn, k_seaf) != SRSRAN_SUCCESS) {
log_error("Failed to run kdf_common");
return SRSRAN_ERROR;
}
return SRSRAN_SUCCESS;
}
uint8_t security_generate_k_amf(const uint8_t* k_seaf,
const char* supi_,
const uint8_t* abba_,
const uint32_t abba_len,
uint8_t* k_amf)
{
if (k_seaf == NULL || supi_ == NULL || abba_ == NULL || k_amf == NULL) {
log_error("Invalid inputs");
return SRSRAN_ERROR;
}
std::array<uint8_t, 32> key;
memcpy(key.data(), k_seaf, 32);
// SUPI
std::vector<uint8_t> supi;
supi.resize(strlen(supi_));
memcpy(supi.data(), supi_, supi.size());
// ABBA
std::vector<uint8_t> abba;
abba.resize(abba_len);
memcpy(abba.data(), abba_, abba.size());
if (kdf_common(FC_5G_KAMF_DERIVATION, key, supi, abba, k_amf) != SRSRAN_SUCCESS) {
log_error("Failed to run kdf_common");
return SRSRAN_ERROR;
}
return SRSRAN_SUCCESS;
}
uint8_t security_generate_k_enb(const uint8_t* k_asme, const uint32_t nas_count_, uint8_t* k_enb)
{
return liblte_security_generate_k_asme(ck, ik, ak, sqn, mcc, mnc, k_asme);
if (k_asme == NULL || k_enb == NULL) {
log_error("Invalid inputs");
return SRSRAN_ERROR;
}
std::array<uint8_t, 32> key;
memcpy(key.data(), k_asme, 32);
// NAS Count
std::vector<uint8_t> nas_count;
nas_count.resize(4);
nas_count[0] = (nas_count_ >> 24) & 0xFF;
nas_count[1] = (nas_count_ >> 16) & 0xFF;
nas_count[2] = (nas_count_ >> 8) & 0xFF;
nas_count[3] = nas_count_ & 0xFF;
if (kdf_common(FC_EPS_K_ENB_DERIVATION, key, nas_count, k_enb) != SRSRAN_SUCCESS) {
log_error("Failed to run kdf_common");
return SRSRAN_ERROR;
}
return SRSRAN_SUCCESS;
}
uint8_t security_generate_k_enb(uint8_t* k_asme, uint32_t nas_count, uint8_t* k_enb)
uint8_t
security_generate_k_enb_star(const uint8_t* k_enb, const uint32_t pci_, const uint32_t earfcn_, uint8_t* k_enb_star)
{
return liblte_security_generate_k_enb(k_asme, nas_count, k_enb);
if (k_enb == NULL || k_enb_star == NULL) {
log_error("Invalid inputs");
return SRSRAN_ERROR;
}
std::array<uint8_t, 32> key;
memcpy(key.data(), k_enb, 32);
// PCI
std::vector<uint8_t> pci;
pci.resize(2);
pci[0] = (pci_ >> 8) & 0xFF;
pci[1] = pci_ & 0xFF;
// EARFCN
std::vector<uint8_t> earfcn;
earfcn.resize(2);
earfcn[0] = (earfcn_ >> 8) & 0xFF;
earfcn[1] = earfcn_ & 0xFF;
if (kdf_common(FC_EPS_K_ENB_STAR_DERIVATION, key, pci, earfcn, k_enb_star) != SRSRAN_SUCCESS) {
log_error("Failed to run kdf_common");
return SRSRAN_ERROR;
}
return SRSRAN_SUCCESS;
}
uint8_t security_generate_k_enb_star(uint8_t* k_enb, uint32_t pci, uint32_t earfcn, uint8_t* k_enb_star)
uint8_t security_generate_nh(const uint8_t* k_asme, const uint8_t* sync_, uint8_t* nh)
{
return liblte_security_generate_k_enb_star(k_enb, pci, earfcn, k_enb_star);
if (k_asme == NULL || sync_ == NULL || nh == NULL) {
log_error("Invalid inputs");
return SRSRAN_ERROR;
}
std::array<uint8_t, 32> key;
memcpy(key.data(), k_asme, 32);
// PCI
std::vector<uint8_t> sync;
sync.resize(32);
memcpy(sync.data(), sync_, 32);
if (kdf_common(FC_EPS_NH_DERIVATION, key, sync, nh) != SRSRAN_SUCCESS) {
log_error("Failed to run kdf_common");
return SRSRAN_ERROR;
}
return SRSRAN_SUCCESS;
}
uint8_t security_generate_nh(uint8_t* k_asme, uint8_t* sync, uint8_t* nh)
uint8_t security_generate_k_nas(const uint8_t* k_asme,
const CIPHERING_ALGORITHM_ID_ENUM enc_alg_id,
const INTEGRITY_ALGORITHM_ID_ENUM int_alg_id,
uint8_t* k_nas_enc,
uint8_t* k_nas_int)
{
return liblte_security_generate_nh(k_asme, sync, nh);
if (k_asme == NULL || k_nas_enc == NULL || k_nas_int == NULL) {
log_error("Invalid inputs");
return SRSRAN_ERROR;
}
std::array<uint8_t, 32> key;
memcpy(key.data(), k_asme, 32);
// Derive NAS ENC
// algorithm type distinguisher
std::vector<uint8_t> algo_distinguisher;
algo_distinguisher.resize(1);
algo_distinguisher[0] = ALGO_EPS_DISTINGUISHER_NAS_ENC_ALG;
// algorithm type distinguisher
std::vector<uint8_t> algorithm_identity;
algorithm_identity.resize(1);
algorithm_identity[0] = enc_alg_id;
if (kdf_common(FC_EPS_ALGORITHM_KEY_DERIVATION, key, algo_distinguisher, algorithm_identity, k_nas_enc) !=
SRSRAN_SUCCESS) {
log_error("Failed to run kdf_common");
return SRSRAN_ERROR;
}
// Derive NAS INT
// algorithm type distinguisher
algo_distinguisher.resize(1);
algo_distinguisher[0] = ALGO_EPS_DISTINGUISHER_NAS_INT_ALG;
// algorithm type distinguisher
algorithm_identity.resize(1);
algorithm_identity[0] = int_alg_id;
// Derive NAS int
if (kdf_common(FC_EPS_ALGORITHM_KEY_DERIVATION, key, algo_distinguisher, algorithm_identity, k_nas_int) !=
SRSRAN_SUCCESS) {
log_error("Failed to run kdf_common");
return SRSRAN_ERROR;
}
return SRSRAN_SUCCESS;
}
uint8_t security_generate_k_nas_5g(const uint8_t* k_amf,
const CIPHERING_ALGORITHM_ID_ENUM enc_alg_id,
const INTEGRITY_ALGORITHM_ID_ENUM int_alg_id,
uint8_t* k_nas_enc,
uint8_t* k_nas_int)
{
if (k_amf == NULL || k_nas_enc == NULL || k_nas_int == NULL) {
log_error("Invalid inputs");
return SRSRAN_ERROR;
}
std::array<uint8_t, 32> key;
memcpy(key.data(), k_amf, 32);
// Derive NAS ENC
// algorithm type distinguisher
std::vector<uint8_t> algo_distinguisher;
algo_distinguisher.resize(1);
algo_distinguisher[0] = ALGO_5G_DISTINGUISHER_NAS_ENC_ALG;
// algorithm type distinguisher
std::vector<uint8_t> algorithm_identity;
algorithm_identity.resize(1);
algorithm_identity[0] = enc_alg_id;
if (kdf_common(FC_5G_ALGORITHM_KEY_DERIVATION, key, algo_distinguisher, algorithm_identity, k_nas_enc) !=
SRSRAN_SUCCESS) {
log_error("Failed to run kdf_common");
return SRSRAN_ERROR;
}
// Derive NAS INT
// algorithm type distinguisher
algo_distinguisher.resize(1);
algo_distinguisher[0] = ALGO_5G_DISTINGUISHER_NAS_INT_ALG;
// algorithm type distinguisher
algorithm_identity.resize(1);
algorithm_identity[0] = int_alg_id;
// Derive NAS int
if (kdf_common(FC_5G_ALGORITHM_KEY_DERIVATION, key, algo_distinguisher, algorithm_identity, k_nas_int) !=
SRSRAN_SUCCESS) {
log_error("Failed to run kdf_common");
return SRSRAN_ERROR;
}
return SRSRAN_SUCCESS;
}
uint8_t security_generate_k_nas(uint8_t* k_asme,
CIPHERING_ALGORITHM_ID_ENUM enc_alg_id,
INTEGRITY_ALGORITHM_ID_ENUM int_alg_id,
uint8_t* k_nas_enc,
uint8_t* k_nas_int)
uint8_t security_generate_k_rrc(const uint8_t* k_enb,
const CIPHERING_ALGORITHM_ID_ENUM enc_alg_id,
const INTEGRITY_ALGORITHM_ID_ENUM int_alg_id,
uint8_t* k_rrc_enc,
uint8_t* k_rrc_int)
{
return liblte_security_generate_k_nas(k_asme,
(LIBLTE_SECURITY_CIPHERING_ALGORITHM_ID_ENUM)enc_alg_id,
(LIBLTE_SECURITY_INTEGRITY_ALGORITHM_ID_ENUM)int_alg_id,
k_nas_enc,
k_nas_int);
if (k_enb == NULL || k_rrc_enc == NULL || k_rrc_int == NULL) {
log_error("Invalid inputs");
return SRSRAN_ERROR;
}
std::array<uint8_t, 32> key;
memcpy(key.data(), k_enb, 32);
// Derive RRC ENC
// algorithm type distinguisher
std::vector<uint8_t> algo_distinguisher;
algo_distinguisher.resize(1);
algo_distinguisher[0] = ALGO_EPS_DISTINGUISHER_RRC_ENC_ALG;
// algorithm type distinguisher
std::vector<uint8_t> algorithm_identity;
algorithm_identity.resize(1);
algorithm_identity[0] = enc_alg_id;
if (kdf_common(FC_EPS_ALGORITHM_KEY_DERIVATION, key, algo_distinguisher, algorithm_identity, k_rrc_enc) !=
SRSRAN_SUCCESS) {
log_error("Failed to run kdf_common");
return SRSRAN_ERROR;
}
// Derive RRC INT
// algorithm type distinguisher
algo_distinguisher.resize(1);
algo_distinguisher[0] = ALGO_EPS_DISTINGUISHER_RRC_INT_ALG;
// algorithm type distinguisher
algorithm_identity.resize(1);
algorithm_identity[0] = int_alg_id;
// Derive RRC int
if (kdf_common(FC_EPS_ALGORITHM_KEY_DERIVATION, key, algo_distinguisher, algorithm_identity, k_rrc_int) !=
SRSRAN_SUCCESS) {
log_error("Failed to run kdf_common");
return SRSRAN_ERROR;
}
return SRSRAN_SUCCESS;
}
uint8_t security_generate_k_rrc(uint8_t* k_enb,
CIPHERING_ALGORITHM_ID_ENUM enc_alg_id,
INTEGRITY_ALGORITHM_ID_ENUM int_alg_id,
uint8_t* k_rrc_enc,
uint8_t* k_rrc_int)
uint8_t security_generate_k_up(const uint8_t* k_enb,
const CIPHERING_ALGORITHM_ID_ENUM enc_alg_id,
const INTEGRITY_ALGORITHM_ID_ENUM int_alg_id,
uint8_t* k_up_enc,
uint8_t* k_up_int)
{
return liblte_security_generate_k_rrc(k_enb,
(LIBLTE_SECURITY_CIPHERING_ALGORITHM_ID_ENUM)enc_alg_id,
(LIBLTE_SECURITY_INTEGRITY_ALGORITHM_ID_ENUM)int_alg_id,
k_rrc_enc,
k_rrc_int);
if (k_enb == NULL || k_up_enc == NULL || k_up_int == NULL) {
log_error("Invalid inputs");
return SRSRAN_ERROR;
}
std::array<uint8_t, 32> key;
memcpy(key.data(), k_enb, 32);
// Derive UP ENC
// algorithm type distinguisher
std::vector<uint8_t> algo_distinguisher;
algo_distinguisher.resize(1);
algo_distinguisher[0] = ALGO_EPS_DISTINGUISHER_UP_ENC_ALG;
// algorithm type distinguisher
std::vector<uint8_t> algorithm_identity;
algorithm_identity.resize(1);
algorithm_identity[0] = enc_alg_id;
if (kdf_common(FC_EPS_ALGORITHM_KEY_DERIVATION, key, algo_distinguisher, algorithm_identity, k_up_enc) !=
SRSRAN_SUCCESS) {
log_error("Failed to run kdf_common");
return SRSRAN_ERROR;
}
// Derive UP INT
// algorithm type distinguisher
algo_distinguisher.resize(1);
algo_distinguisher[0] = ALGO_EPS_DISTINGUISHER_UP_INT_ALG;
// algorithm type distinguisher
algorithm_identity.resize(1);
algorithm_identity[0] = int_alg_id;
// Derive UP int
if (kdf_common(FC_EPS_ALGORITHM_KEY_DERIVATION, key, algo_distinguisher, algorithm_identity, k_up_int) !=
SRSRAN_SUCCESS) {
log_error("Failed to run kdf_common");
return SRSRAN_ERROR;
}
return SRSRAN_SUCCESS;
}
uint8_t security_generate_k_up(uint8_t* k_enb,
CIPHERING_ALGORITHM_ID_ENUM enc_alg_id,
INTEGRITY_ALGORITHM_ID_ENUM int_alg_id,
uint8_t* k_up_enc,
uint8_t* k_up_int)
uint8_t security_generate_sk_gnb(const uint8_t* k_enb, const uint16_t scg_count_, uint8_t* sk_gnb)
{
return liblte_security_generate_k_up(k_enb,
(LIBLTE_SECURITY_CIPHERING_ALGORITHM_ID_ENUM)enc_alg_id,
(LIBLTE_SECURITY_INTEGRITY_ALGORITHM_ID_ENUM)int_alg_id,
k_up_enc,
k_up_int);
if (k_enb == NULL || sk_gnb == NULL) {
log_error("Invalid inputs");
return SRSRAN_ERROR;
}
std::array<uint8_t, 32> key;
memcpy(key.data(), k_enb, 32);
// SCG Count
std::vector<uint8_t> scg_count;
scg_count.resize(2);
scg_count[0] = (scg_count_ >> 8) & 0xFF; // first byte of P0
scg_count[1] = scg_count_ & 0xFF; // second byte of P0
// Derive sk_gnb
uint8_t output[32];
if (kdf_common(0x1C, key, scg_count, output) != SRSRAN_SUCCESS) {
log_error("Failed to run kdf_common");
return SRSRAN_ERROR;
}
memcpy(sk_gnb, output, 32);
return SRSRAN_SUCCESS;
}
uint8_t security_generate_k_nr_rrc(uint8_t* k_gnb,
CIPHERING_ALGORITHM_ID_ENUM enc_alg_id,
INTEGRITY_ALGORITHM_ID_ENUM int_alg_id,
uint8_t* k_rrc_enc,
uint8_t* k_rrc_int)
uint8_t security_generate_k_nr_rrc(const uint8_t* k_gnb,
const CIPHERING_ALGORITHM_ID_ENUM enc_alg_id,
const INTEGRITY_ALGORITHM_ID_ENUM int_alg_id,
uint8_t* k_rrc_enc,
uint8_t* k_rrc_int)
{
return liblte_security_generate_k_nr_rrc(k_gnb,
(LIBLTE_SECURITY_CIPHERING_ALGORITHM_ID_ENUM)enc_alg_id,
(LIBLTE_SECURITY_INTEGRITY_ALGORITHM_ID_ENUM)int_alg_id,
k_rrc_enc,
k_rrc_int);
if (k_gnb == NULL || k_rrc_enc == NULL || k_rrc_int == NULL) {
log_error("Invalid inputs");
return SRSRAN_ERROR;
}
std::array<uint8_t, 32> key;
memcpy(key.data(), k_gnb, 32);
// Derive RRC ENC
// algorithm type distinguisher
std::vector<uint8_t> algo_distinguisher;
algo_distinguisher.resize(1);
algo_distinguisher[0] = ALGO_5G_DISTINGUISHER_RRC_ENC_ALG;
// algorithm type distinguisher
std::vector<uint8_t> algorithm_identity;
algorithm_identity.resize(1);
algorithm_identity[0] = enc_alg_id;
if (kdf_common(FC_5G_ALGORITHM_KEY_DERIVATION, key, algo_distinguisher, algorithm_identity, k_rrc_enc) !=
SRSRAN_SUCCESS) {
log_error("Failed to run kdf_common");
return SRSRAN_ERROR;
}
// Derive RRC INT
// algorithm type distinguisher
algo_distinguisher.resize(1);
algo_distinguisher[0] = ALGO_5G_DISTINGUISHER_RRC_INT_ALG;
// algorithm type distinguisher
algorithm_identity.resize(1);
algorithm_identity[0] = int_alg_id;
// Derive RRC int
if (kdf_common(FC_5G_ALGORITHM_KEY_DERIVATION, key, algo_distinguisher, algorithm_identity, k_rrc_int) !=
SRSRAN_SUCCESS) {
log_error("Failed to run kdf_common");
return SRSRAN_ERROR;
}
return SRSRAN_SUCCESS;
}
uint8_t security_generate_k_nr_up(uint8_t* k_gnb,
CIPHERING_ALGORITHM_ID_ENUM enc_alg_id,
INTEGRITY_ALGORITHM_ID_ENUM int_alg_id,
uint8_t* k_up_enc,
uint8_t* k_up_int)
uint8_t security_generate_k_nr_up(const uint8_t* k_gnb,
const CIPHERING_ALGORITHM_ID_ENUM enc_alg_id,
const INTEGRITY_ALGORITHM_ID_ENUM int_alg_id,
uint8_t* k_up_enc,
uint8_t* k_up_int)
{
return liblte_security_generate_k_nr_up(k_gnb,
(LIBLTE_SECURITY_CIPHERING_ALGORITHM_ID_ENUM)enc_alg_id,
(LIBLTE_SECURITY_INTEGRITY_ALGORITHM_ID_ENUM)int_alg_id,
k_up_enc,
k_up_int);
if (k_gnb == NULL || k_up_enc == NULL || k_up_int == NULL) {
log_error("Invalid inputs");
return SRSRAN_ERROR;
}
std::array<uint8_t, 32> key;
memcpy(key.data(), k_gnb, 32);
// Derive UP ENC
// algorithm type distinguisher
std::vector<uint8_t> algo_distinguisher;
algo_distinguisher.resize(1);
algo_distinguisher[0] = ALGO_5G_DISTINGUISHER_UP_ENC_ALG;
// algorithm type distinguisher
std::vector<uint8_t> algorithm_identity;
algorithm_identity.resize(1);
algorithm_identity[0] = enc_alg_id;
if (kdf_common(FC_5G_ALGORITHM_KEY_DERIVATION, key, algo_distinguisher, algorithm_identity, k_up_enc) !=
SRSRAN_SUCCESS) {
log_error("Failed to run kdf_common");
return SRSRAN_ERROR;
}
// Derive UP INT
// algorithm type distinguisher
algo_distinguisher.resize(1);
algo_distinguisher[0] = ALGO_5G_DISTINGUISHER_UP_INT_ALG;
// algorithm type distinguisher
algorithm_identity.resize(1);
algorithm_identity[0] = int_alg_id;
// Derive UP int
if (kdf_common(FC_5G_ALGORITHM_KEY_DERIVATION, key, algo_distinguisher, algorithm_identity, k_up_int) !=
SRSRAN_SUCCESS) {
log_error("Failed to run kdf_common");
return SRSRAN_ERROR;
}
return SRSRAN_SUCCESS;
}
uint8_t security_generate_sk_gnb(uint8_t* k_enb, uint8_t* sk_gnb, uint16_t scg_count)
uint8_t security_generate_res_star(const uint8_t* ck,
const uint8_t* ik,
const char* serving_network_name,
const uint8_t* rand_,
const uint8_t* res_,
const size_t res_len_,
uint8_t* res_star)
{
return liblte_security_generate_sk_gnb(k_enb, sk_gnb, scg_count);
if (ck == NULL || ik == NULL || serving_network_name == NULL || rand_ == NULL || res_ == NULL || res_star == NULL) {
log_error("Invalid inputs");
return SRSRAN_ERROR;
}
std::array<uint8_t, 32> key;
// The input key Key shall be equal to the concatenation CK || IK of CK and IK.
memcpy(key.data(), ck, 16);
memcpy(key.data() + 16, ik, 16);
// Serving Network Name
std::vector<uint8_t> ssn;
ssn.resize(strlen(serving_network_name));
memcpy(ssn.data(), serving_network_name, strlen(serving_network_name));
// RAND
std::vector<uint8_t> rand;
rand.resize(AKA_RAND_LEN);
memcpy(rand.data(), rand_, rand.size());
// RES
std::vector<uint8_t> res;
res.resize(res_len_);
memcpy(res.data(), res_, res.size());
uint8_t output[32];
if (kdf_common(FC_5G_RES_STAR_DERIVATION, key, ssn, rand, res, output) != SRSRAN_SUCCESS) {
log_error("Failed to run kdf_common");
return SRSRAN_ERROR;
}
memcpy(res_star, output + 16, 16);
return SRSRAN_SUCCESS;
}
int kdf_common(const uint8_t fc, const std::array<uint8_t, 32>& key, const std::vector<uint8_t>& P0, uint8_t* output)
{
uint8_t* s;
uint32_t s_len = 1 + P0.size() + 2;
s = (uint8_t*)calloc(s_len, sizeof(uint8_t));
if (s == nullptr) {
log_error("Unable to allocate memory in %s()", __FUNCTION__);
return SRSRAN_ERROR;
}
uint32_t i = 0;
s[i] = fc; // FC
i++;
// P0
memcpy(&s[i], P0.data(), P0.size());
i += P0.size();
uint16_t p0_length_value = htons(P0.size());
memcpy(&s[i], &p0_length_value, sizeof(p0_length_value));
i += sizeof(p0_length_value);
sha256(key.data(), key.size(), s, i, output, 0);
free(s);
return SRSRAN_SUCCESS;
}
int kdf_common(const uint8_t fc,
const std::array<uint8_t, 32>& key,
const std::vector<uint8_t>& P0,
const std::vector<uint8_t>& P1,
uint8_t* output)
{
uint8_t* s;
uint32_t s_len = 1 + P0.size() + 2 + P1.size() + 2;
s = (uint8_t*)calloc(s_len, sizeof(uint8_t));
if (s == nullptr) {
log_error("Unable to allocate memory in %s()", __FUNCTION__);
return SRSRAN_ERROR;
}
uint32_t i = 0;
s[i] = fc; // FC
i++;
// P0
memcpy(&s[i], P0.data(), P0.size());
i += P0.size();
uint16_t p0_length_value = htons(P0.size());
memcpy(&s[i], &p0_length_value, sizeof(p0_length_value));
i += sizeof(p0_length_value);
// P1
memcpy(&s[i], P1.data(), P1.size());
i += P1.size();
uint16_t p1_length_value = htons(P1.size());
memcpy(&s[i], &p1_length_value, sizeof(p1_length_value));
i += sizeof(p1_length_value);
sha256(key.data(), key.size(), s, i, output, 0);
free(s);
return SRSRAN_SUCCESS;
}
int kdf_common(const uint8_t fc,
const std::array<uint8_t, 32>& key,
const std::vector<uint8_t>& P0,
const std::vector<uint8_t>& P1,
const std::vector<uint8_t>& P2,
uint8_t* output)
{
uint8_t* s;
uint32_t s_len = 1 + P0.size() + 2 + P1.size() + 2 + P2.size() + 2;
s = (uint8_t*)calloc(s_len, sizeof(uint8_t));
if (s == nullptr) {
log_error("Unable to allocate memory in %s()", __FUNCTION__);
return SRSRAN_ERROR;
}
uint32_t i = 0;
s[i] = fc; // FC
i++;
// P0
memcpy(&s[i], P0.data(), P0.size());
i += P0.size();
uint16_t p0_length_value = htons(P0.size());
memcpy(&s[i], &p0_length_value, sizeof(p0_length_value));
i += sizeof(p0_length_value);
// P1
memcpy(&s[i], P1.data(), P1.size());
i += P1.size();
uint16_t p1_length_value = htons(P1.size());
memcpy(&s[i], &p1_length_value, sizeof(p1_length_value));
i += sizeof(p1_length_value);
// P2
memcpy(&s[i], P2.data(), P2.size());
i += P2.size();
uint16_t p2_length_value = htons(P2.size());
memcpy(&s[i], &p2_length_value, sizeof(p2_length_value));
i += sizeof(p2_length_value);
sha256(key.data(), key.size(), s, i, output, 0);
free(s);
return SRSRAN_SUCCESS;
}
/******************************************************************************
* Integrity Protection
*****************************************************************************/
@ -194,7 +819,6 @@ uint8_t security_128_eea1(uint8_t* key,
uint32_t msg_len,
uint8_t* msg_out)
{
return liblte_security_encryption_eea1(key, count, bearer, direction, msg, msg_len * 8, msg_out);
}
@ -206,7 +830,6 @@ uint8_t security_128_eea2(uint8_t* key,
uint32_t msg_len,
uint8_t* msg_out)
{
return liblte_security_encryption_eea2(key, count, bearer, direction, msg, msg_len * 8, msg_out);
}
@ -218,7 +841,6 @@ uint8_t security_128_eea3(uint8_t* key,
uint32_t msg_len,
uint8_t* msg_out)
{
return liblte_security_encryption_eea3(key, count, bearer, direction, msg, msg_len * 8, msg_out);
}
@ -251,4 +873,46 @@ uint8_t security_milenage_f5_star(uint8_t* k, uint8_t* op, uint8_t* rand, uint8_
return liblte_security_milenage_f5_star(k, op, rand, ak);
}
int security_xor_f2345(uint8_t* k, uint8_t* rand, uint8_t* res, uint8_t* ck, uint8_t* ik, uint8_t* ak)
{
uint8_t xdout[16];
uint8_t cdout[8];
// Use RAND and K to compute RES, CK, IK and AK
for (uint32_t i = 0; i < 16; i++) {
xdout[i] = k[i] ^ rand[i];
}
for (uint32_t i = 0; i < 16; i++) {
res[i] = xdout[i];
ck[i] = xdout[(i + 1) % 16];
ik[i] = xdout[(i + 2) % 16];
}
for (uint32_t i = 0; i < 6; i++) {
ak[i] = xdout[i + 3];
}
return SRSRAN_SUCCESS;
}
int security_xor_f1(uint8_t* k, uint8_t* rand, uint8_t* sqn, uint8_t* amf, uint8_t* mac_a)
{
uint8_t xdout[16];
uint8_t cdout[8];
// Use RAND and K to compute RES, CK, IK and AK
for (uint32_t i = 0; i < 16; i++) {
xdout[i] = k[i] ^ rand[i];
}
// Generate cdout
for (uint32_t i = 0; i < 6; i++) {
cdout[i] = sqn[i];
}
for (uint32_t i = 0; i < 2; i++) {
cdout[6 + i] = amf[i];
}
// Generate MAC
for (uint32_t i = 0; i < 8; i++) {
mac_a[i] = xdout[i] ^ cdout[i];
}
return SRSRAN_SUCCESS;
}
} // namespace srsran

@ -43,7 +43,6 @@ bool mac_rar_subpdu_nr::read_subpdu(const uint8_t* ptr)
rapid = *ptr & 0x3f;
// if PDU is not configured with SI request, extract MAC RAR
if (parent->has_si_rapid() == false) {
const uint32_t MAC_RAR_NBYTES = 7;
if (parent->get_remaining_len() >= MAC_RAR_NBYTES) {
uint8_t* rar = const_cast<uint8_t*>(ptr + 1);
// check reserved bits
@ -90,9 +89,42 @@ bool mac_rar_subpdu_nr::has_more_subpdus()
}
// Section 6.1.2
uint32_t mac_rar_subpdu_nr::write_subpdu(const uint8_t* start_)
void mac_rar_subpdu_nr::write_subpdu(const uint8_t* start_)
{
return 0;
uint8_t* ptr = const_cast<uint8_t*>(start_);
if (type == RAPID) {
// write E/T/RAPID MAC subheader
*ptr = (uint8_t)((E_bit ? 1 : 0) << 7) | ((int)rar_subh_type_t::RAPID << 6) | ((uint8_t)rapid & 0x3f);
ptr += 1;
// if PDU is not configured with SI request, insert MAC RAR
if (parent->has_si_rapid() == false) {
// high 7 bits of TA go into first octet
*ptr = (uint8_t)((ta >> 5) & 0x7f);
ptr += 1;
// low 5 bit of TA and first 3 bit of UL grant
*ptr = (uint8_t)((ta & 0x1f) << 3) | (ul_grant.at(0) << 2) | (ul_grant.at(1) << 1) | (ul_grant.at(2));
ptr += 1;
// add remaining 3 full octets of UL grant
uint8_t* x = &ul_grant.at(3);
*(ptr + 0) = (uint8_t)srsran_bit_pack(&x, 8);
*(ptr + 1) = (uint8_t)srsran_bit_pack(&x, 8);
*(ptr + 2) = (uint8_t)srsran_bit_pack(&x, 8);
ptr += 3;
// 2 byte C-RNTI
*(ptr + 0) = (uint8_t)((temp_crnti & 0xff00) >> 8);
*(ptr + 1) = (uint8_t)(temp_crnti & 0x00ff);
ptr += 2;
}
} else {
// write E/T/R/R/BI MAC subheader
*ptr = (uint8_t)((E_bit ? 1 : 0) << 7) | ((int)rar_subh_type_t::BACKOFF << 6) | ((uint8_t)backoff_indicator & 0xf);
ptr += 1;
}
}
uint32_t mac_rar_subpdu_nr::get_total_length()
@ -127,6 +159,8 @@ bool mac_rar_subpdu_nr::has_backoff() const
void mac_rar_subpdu_nr::set_backoff(const uint8_t backoff_indicator_)
{
type = rar_subh_type_t::BACKOFF;
payload_length = 0;
backoff_indicator = backoff_indicator_;
}
@ -140,28 +174,102 @@ std::array<uint8_t, mac_rar_subpdu_nr::UL_GRANT_NBITS> mac_rar_subpdu_nr::get_ul
return ul_grant;
}
std::string mac_rar_subpdu_nr::to_string()
void mac_rar_subpdu_nr::set_ta(const uint32_t ta_)
{
ta = ta_;
}
void mac_rar_subpdu_nr::set_temp_crnti(const uint16_t temp_crnti_)
{
std::stringstream ss;
temp_crnti = temp_crnti_;
}
void mac_rar_subpdu_nr::set_rapid(const uint8_t rapid_)
{
type = rar_subh_type_t::RAPID;
payload_length = MAC_RAR_NBYTES;
rapid = rapid_;
}
void mac_rar_subpdu_nr::set_ul_grant(std::array<uint8_t, mac_rar_subpdu_nr::UL_GRANT_NBITS> ul_grant_)
{
ul_grant = ul_grant_;
}
void mac_rar_subpdu_nr::set_is_last_subpdu()
{
E_bit = false;
}
void mac_rar_subpdu_nr::to_string(fmt::memory_buffer& buffer)
{
// Add space for new subPDU
fmt::format_to(buffer, " ");
if (has_rapid()) {
ss << "RAPID: " << rapid << ", Temp C-RNTI: " << std::hex << temp_crnti << ", TA: " << ta << ", UL Grant: ";
char tmp[16] = {};
srsran_vec_sprint_hex(tmp, sizeof(tmp), ul_grant.data(), UL_GRANT_NBITS);
fmt::format_to(buffer, "RAPID: {}, Temp C-RNTI: {:#04x}, TA: {}, UL Grant: {}", rapid, temp_crnti, ta, tmp);
} else {
ss << "Backoff Indicator: " << backoff_indicator << " ";
fmt::format_to(buffer, "Backoff Indicator: {}", backoff_indicator);
}
}
char tmp[16] = {};
srsran_vec_sprint_hex(tmp, sizeof(tmp), ul_grant.data(), UL_GRANT_NBITS);
ss << tmp;
mac_rar_pdu_nr::mac_rar_pdu_nr() : logger(srslog::fetch_basic_logger("MAC-NR")) {}
return ss.str();
int mac_rar_pdu_nr::init_tx(byte_buffer_t* buffer_, uint32_t pdu_len_)
{
if (buffer_ == nullptr || buffer_->msg == nullptr) {
logger.error("Invalid buffer");
return SRSRAN_ERROR;
}
buffer = buffer_;
subpdus.clear();
pdu_len = pdu_len_;
remaining_len = pdu_len_;
return SRSRAN_SUCCESS;
}
mac_rar_pdu_nr::mac_rar_pdu_nr() : logger(srslog::fetch_basic_logger("MAC-NR")) {}
mac_rar_subpdu_nr& mac_rar_pdu_nr::add_subpdu()
{
mac_rar_subpdu_nr rar_subpdu(this);
subpdus.push_back(rar_subpdu);
return subpdus.back();
}
bool mac_rar_pdu_nr::pack()
int mac_rar_pdu_nr::pack()
{
// not implemented yet
return false;
int ret = SRSRAN_ERROR;
if (buffer == nullptr) {
logger.error("Invalid buffer");
return ret;
}
// set E_bit for last subPDU
subpdus.back().set_is_last_subpdu();
// write subPDUs one by one
for (uint32_t i = 0; i < subpdus.size(); ++i) {
mac_rar_subpdu_nr& subpdu = subpdus.at(i);
if (remaining_len >= subpdu.get_total_length()) {
subpdu.write_subpdu(buffer->msg + buffer->N_bytes);
buffer->N_bytes += subpdu.get_total_length();
remaining_len -= subpdu.get_total_length();
} else {
logger.error("Not enough space in PDU to write subPDU");
return ret;
}
}
// fill up with padding, if any
if (remaining_len > 0) {
memset(buffer->msg + buffer->N_bytes, 0, remaining_len);
buffer->N_bytes += remaining_len;
}
ret = SRSRAN_SUCCESS;
return ret;
}
bool mac_rar_pdu_nr::has_si_rapid()
@ -221,13 +329,12 @@ uint32_t mac_rar_pdu_nr::get_remaining_len()
return remaining_len;
}
std::string mac_rar_pdu_nr::to_string()
void mac_rar_pdu_nr::to_string(fmt::memory_buffer& buffer)
{
std::stringstream ss;
fmt::format_to(buffer, "DL");
for (auto& subpdu : subpdus) {
ss << subpdu.to_string() << " ";
subpdu.to_string(buffer);
}
return ss.str();
}
} // namespace srsran

@ -74,7 +74,7 @@ int32_t mac_sch_subpdu_nr::read_subheader(const uint8_t* ptr)
} else {
sdu_length = sizeof_ce(lcid, parent->is_ulsch());
}
sdu = (uint8_t*)ptr;
sdu.set_storage_to((uint8_t*)ptr);
} else {
srslog::fetch_basic_logger("MAC-NR").warning("Invalid LCID (%d) in MAC PDU", lcid);
return SRSRAN_ERROR;
@ -84,8 +84,8 @@ int32_t mac_sch_subpdu_nr::read_subheader(const uint8_t* ptr)
void mac_sch_subpdu_nr::set_sdu(const uint32_t lcid_, const uint8_t* payload_, const uint32_t len_)
{
lcid = lcid_;
sdu = const_cast<uint8_t*>(payload_);
lcid = lcid_;
sdu.set_storage_to(const_cast<uint8_t*>(payload_));
header_length = is_ul_ccch() ? 1 : 2;
sdu_length = len_;
if (is_ul_ccch()) {
@ -113,34 +113,34 @@ void mac_sch_subpdu_nr::set_padding(const uint32_t len_)
// Turn a subPDU into a C-RNTI CE, error checking takes place in the caller
void mac_sch_subpdu_nr::set_c_rnti(const uint16_t crnti_)
{
lcid = CRNTI;
header_length = 1;
sdu_length = sizeof_ce(lcid, parent->is_ulsch());
sdu = ce_write_buffer.data();
uint16_t crnti = htole32(crnti_);
ce_write_buffer.at(0) = (uint8_t)((crnti & 0xff00) >> 8);
ce_write_buffer.at(1) = (uint8_t)((crnti & 0x00ff));
lcid = CRNTI;
header_length = 1;
sdu_length = sizeof_ce(lcid, parent->is_ulsch());
uint16_t crnti = htole16(crnti_);
uint8_t* ptr = sdu.use_internal_storage();
ptr[0] = (uint8_t)((crnti & 0xff00) >> 8);
ptr[1] = (uint8_t)((crnti & 0x00ff));
}
// Turn a subPDU into a single entry PHR CE, error checking takes place in the caller
void mac_sch_subpdu_nr::set_se_phr(const uint8_t phr_, const uint8_t pcmax_)
{
lcid = SE_PHR;
header_length = 1;
sdu_length = sizeof_ce(lcid, parent->is_ulsch());
sdu = ce_write_buffer.data();
ce_write_buffer.at(0) = (uint8_t)(phr_ & 0x3f);
ce_write_buffer.at(1) = (uint8_t)(pcmax_ & 0x3f);
lcid = SE_PHR;
header_length = 1;
sdu_length = sizeof_ce(lcid, parent->is_ulsch());
uint8_t* ptr = sdu.use_internal_storage();
ptr[0] = (uint8_t)(phr_ & 0x3f);
ptr[1] = (uint8_t)(pcmax_ & 0x3f);
}
// Turn a subPDU into a single short BSR
void mac_sch_subpdu_nr::set_sbsr(const lcg_bsr_t bsr_)
{
lcid = SHORT_BSR;
header_length = 1;
sdu_length = sizeof_ce(lcid, parent->is_ulsch());
sdu = ce_write_buffer.data();
ce_write_buffer.at(0) = ((bsr_.lcg_id & 0x07) << 5) | (bsr_.buffer_size & 0x1f);
lcid = SHORT_BSR;
header_length = 1;
sdu_length = sizeof_ce(lcid, parent->is_ulsch());
uint8_t* ptr = sdu.use_internal_storage();
ptr[0] = ((bsr_.lcg_id & 0x07) << 5) | (bsr_.buffer_size & 0x1f);
}
// Turn a subPDU into a long BSR with variable size
@ -172,7 +172,7 @@ uint32_t mac_sch_subpdu_nr::write_subpdu(const uint8_t* start_)
// copy SDU payload
if (sdu) {
memcpy(ptr, sdu, sdu_length);
memcpy(ptr, sdu.ptr(), sdu_length);
} else {
// clear memory
memset(ptr, 0, sdu_length);
@ -201,13 +201,14 @@ uint32_t mac_sch_subpdu_nr::get_lcid()
uint8_t* mac_sch_subpdu_nr::get_sdu()
{
return sdu;
return sdu.ptr();
}
uint16_t mac_sch_subpdu_nr::get_c_rnti()
{
if (parent->is_ulsch() && lcid == CRNTI) {
return le16toh((uint16_t)sdu[0] << 8 | sdu[1]);
uint8_t* ptr = sdu.ptr();
return le16toh((uint16_t)ptr[0] << 8 | ptr[1]);
}
return 0;
}
@ -215,7 +216,8 @@ uint16_t mac_sch_subpdu_nr::get_c_rnti()
uint8_t mac_sch_subpdu_nr::get_phr()
{
if (parent->is_ulsch() && lcid == SE_PHR) {
return sdu[0] & 0x3f;
uint8_t* ptr = sdu.ptr();
return ptr[0] & 0x3f;
}
return 0;
}
@ -223,7 +225,8 @@ uint8_t mac_sch_subpdu_nr::get_phr()
uint8_t mac_sch_subpdu_nr::get_pcmax()
{
if (parent->is_ulsch() && lcid == SE_PHR) {
return sdu[1] & 0x3f;
uint8_t* ptr = sdu.ptr();
return ptr[1] & 0x3f;
}
return 0;
}
@ -232,8 +235,9 @@ mac_sch_subpdu_nr::ta_t mac_sch_subpdu_nr::get_ta()
{
ta_t ta = {};
if (lcid == TA_CMD) {
ta.tag_id = (sdu[0] & 0xc0) >> 6;
ta.ta_command = sdu[0] & 0x3f;
uint8_t* ptr = sdu.ptr();
ta.tag_id = (ptr[0] & 0xc0) >> 6;
ta.ta_command = ptr[0] & 0x3f;
}
return ta;
}
@ -242,8 +246,9 @@ mac_sch_subpdu_nr::lcg_bsr_t mac_sch_subpdu_nr::get_sbsr()
{
lcg_bsr_t sbsr = {};
if (parent->is_ulsch() && lcid == SHORT_BSR) {
sbsr.lcg_id = (sdu[0] & 0xe0) >> 5;
sbsr.buffer_size = sdu[0] & 0x1f;
uint8_t* ptr = sdu.ptr();
sbsr.lcg_id = (ptr[0] & 0xe0) >> 5;
sbsr.buffer_size = ptr[0] & 0x1f;
}
return sbsr;
}
@ -287,6 +292,61 @@ inline bool mac_sch_subpdu_nr::is_ul_ccch()
return (parent->is_ulsch() && (lcid == CCCH_SIZE_48 || lcid == CCCH_SIZE_64));
}
void mac_sch_subpdu_nr::to_string(fmt::memory_buffer& buffer)
{
// print subPDU
if (is_sdu()) {
fmt::format_to(buffer, " LCID={} len={}", get_lcid(), get_sdu_length());
} else {
if (parent->is_ulsch()) {
// UL-SCH case
switch (get_lcid()) {
case mac_sch_subpdu_nr::CRNTI:
fmt::format_to(buffer, " C-RNTI: {:#04x}", get_c_rnti());
break;
case mac_sch_subpdu_nr::SHORT_TRUNC_BSR:
fmt::format_to(buffer, " SHORT_TRUNC_BSR: len={}", get_total_length());
break;
case mac_sch_subpdu_nr::LONG_TRUNC_BSR:
fmt::format_to(buffer, " LONG_TRUNC_BSR: len={}", get_total_length());
break;
case mac_sch_subpdu_nr::SHORT_BSR: {
lcg_bsr_t sbsr = get_sbsr();
fmt::format_to(buffer, " SBSR: lcg={} bs={}", sbsr.lcg_id, sbsr.buffer_size);
} break;
case mac_sch_subpdu_nr::LONG_BSR:
fmt::format_to(buffer, " LBSR: len={}", get_total_length());
break;
case mac_sch_subpdu_nr::SE_PHR:
fmt::format_to(buffer, " SE_PHR: ph={} pc={}", get_phr(), get_pcmax());
break;
case mac_sch_subpdu_nr::PADDING:
fmt::format_to(buffer, " PAD: len={}", get_sdu_length());
break;
default:
fmt::format_to(buffer, " CE={}", get_lcid());
break;
}
} else {
// DL-SCH PDU
switch (get_lcid()) {
case mac_sch_subpdu_nr::TA_CMD:
fmt::format_to(buffer, " TA: id={} command={}", get_ta().tag_id, get_ta().ta_command);
break;
case mac_sch_subpdu_nr::CON_RES_ID:
fmt::format_to(buffer, " CONRES: len={}", get_total_length());
break;
case mac_sch_subpdu_nr::PADDING:
fmt::format_to(buffer, " PAD: len={}", get_sdu_length());
break;
default:
fmt::format_to(buffer, " CE={}", get_lcid());
break;
}
}
}
}
void mac_sch_pdu_nr::pack()
{
// SDU and CEs are written in-place, only add padding if needed
@ -445,4 +505,12 @@ uint32_t mac_sch_pdu_nr::add_sudpdu(mac_sch_subpdu_nr& subpdu)
return SRSRAN_SUCCESS;
}
void mac_sch_pdu_nr::to_string(fmt::memory_buffer& buffer)
{
fmt::format_to(buffer, "{}", is_ulsch() ? "UL" : "DL");
for (auto& subpdu : subpdus) {
subpdu.to_string(buffer);
}
}
} // namespace srsran

@ -1009,7 +1009,6 @@ uint8_t sch_subh::phr_report_table(float phr_value)
void rar_pdu::to_string(fmt::memory_buffer& buffer)
{
std::string msg("MAC PDU for RAR: ");
fmt::format_to(buffer, "MAC PDU for RAR: ");
pdu::to_string(buffer);
}

@ -186,7 +186,6 @@ int registration_request_unpacking_packing_test(srsran::nas_pcap* pcap)
key_set_identifier_t::security_context_flag_type_::options::native_security_context);
TESTASSERT(reg_request_msg.ng_ksi.nas_key_set_identifier ==
key_set_identifier_t::nas_key_set_identifier_type_::options::no_key_is_available_or_reserved);
TESTASSERT(reg_request_msg.mobile_identity_5gs.length == 11);
TESTASSERT(reg_request_msg.mobile_identity_5gs.type() == mobile_identity_5gs_t::identity_types_::options::guti_5g);
mobile_identity_5gs_t::guti_5g_s guti_5g_ = reg_request_msg.mobile_identity_5gs.guti_5g();
TESTASSERT(guti_5g_.amf_pointer == 0x0);
@ -220,7 +219,6 @@ int registration_request_unpacking_packing_test(srsran::nas_pcap* pcap)
TESTASSERT(reg_request_msg.ue_security_capability.eps_caps_present == false);
TESTASSERT(reg_request_msg.s1_ue_network_capability_present == true);
TESTASSERT(reg_request_msg.s1_ue_network_capability.length == 7);
TESTASSERT(reg_request_msg.s1_ue_network_capability.eea0_supported == true);
TESTASSERT(reg_request_msg.s1_ue_network_capability.eea1_128_supported == true);
@ -385,7 +383,6 @@ int registration_request_unpacking_packing_test_2(srsran::nas_pcap* pcap)
key_set_identifier_t::security_context_flag_type_::options::native_security_context);
TESTASSERT(reg_request_msg.ng_ksi.nas_key_set_identifier ==
key_set_identifier_t::nas_key_set_identifier_type_::options::no_key_is_available_or_reserved);
TESTASSERT(reg_request_msg.mobile_identity_5gs.length == 54);
TESTASSERT(reg_request_msg.mobile_identity_5gs.type() == mobile_identity_5gs_t::identity_types_::options::suci);
TESTASSERT(reg_request_msg.mobile_identity_5gs.suci().supi_format.value ==
mobile_identity_5gs_t::suci_s::supi_format_type_::options::imsi);
@ -484,7 +481,6 @@ int deregistration_request_unpacking_packing_test(srsran::nas_pcap* pcap)
TESTASSERT(dereg_request_msg.ng_ksi.security_context_flag ==
key_set_identifier_t::security_context_flag_type_::options::native_security_context);
TESTASSERT(dereg_request_msg.ng_ksi.nas_key_set_identifier == 0);
TESTASSERT(dereg_request_msg.mobile_identity_5gs.length == 11);
TESTASSERT(dereg_request_msg.mobile_identity_5gs.type() == mobile_identity_5gs_t::identity_types_::options::guti_5g);
mobile_identity_5gs_t::guti_5g_s guti_5g_ = dereg_request_msg.mobile_identity_5gs.guti_5g();
TESTASSERT(guti_5g_.amf_pointer == 0x0);
@ -560,14 +556,14 @@ int authentication_request_unpacking_packing_test(srsran::nas_pcap* pcap)
TESTASSERT(auth_request_msg.ng_ksi.security_context_flag ==
key_set_identifier_t::security_context_flag_type_::options::native_security_context);
TESTASSERT(auth_request_msg.ng_ksi.nas_key_set_identifier == 0);
TESTASSERT(auth_request_msg.abba.length == 2);
TESTASSERT(auth_request_msg.abba.abba_contents.size() == 2);
TESTASSERT(auth_request_msg.abba.abba_contents[0] == 0x00);
TESTASSERT(auth_request_msg.abba.abba_contents[1] == 0x00);
TESTASSERT(auth_request_msg.authentication_parameter_rand_present == true);
TESTASSERT(auth_request_msg.authentication_parameter_rand.rand[0] == 0x16);
TESTASSERT(auth_request_msg.authentication_parameter_rand.rand[15] == 0x71);
TESTASSERT(auth_request_msg.authentication_parameter_autn_present == true);
TESTASSERT(auth_request_msg.authentication_parameter_autn.length == 16);
TESTASSERT(auth_request_msg.authentication_parameter_autn.autn.size() == 16);
TESTASSERT(auth_request_msg.authentication_parameter_autn.autn[0] == 0xa3);
TESTASSERT(auth_request_msg.authentication_parameter_autn.autn[15] == 0xed);
@ -618,7 +614,6 @@ int authentication_resp_request_unpacking_packing_test(srsran::nas_pcap* pcap)
authentication_response_t& auth_resp = nas_msg.authentication_response();
TESTASSERT(auth_resp.authentication_response_parameter_present == true);
TESTASSERT(auth_resp.authentication_response_parameter.length == 16);
TESTASSERT(auth_resp.authentication_response_parameter.res.size() == 16);
TESTASSERT(auth_resp.authentication_response_parameter.res[0] == 0xa1);
TESTASSERT(auth_resp.authentication_response_parameter.res[15] == 0x08);
@ -772,7 +767,6 @@ int security_command_unpacking_packing_test(srsran::nas_pcap* pcap)
TESTASSERT(sec_command_msg.imeisv_request.imeisv_request == true);
TESTASSERT(sec_command_msg.additional_5g_security_information_present == true);
TESTASSERT(sec_command_msg.additional_5g_security_information.length == 1);
TESTASSERT(sec_command_msg.additional_5g_security_information.rinmr == false);
TESTASSERT(sec_command_msg.additional_5g_security_information.hdp == false);
@ -1020,7 +1014,6 @@ int security_complete_unpacking_packing_test(srsran::nas_pcap* pcap)
TESTASSERT(imeisv.imeisv[15] == 5);
TESTASSERT(sec_complete_msg.nas_message_container_present == true);
TESTASSERT(sec_complete_msg.nas_message_container.length == 87);
TESTASSERT(sec_complete_msg.nas_message_container.nas_message_container.size() == 87);
nas_5gs_msg inner_message;
TESTASSERT(inner_message.unpack(sec_complete_msg.nas_message_container.nas_message_container) == SRSRAN_SUCCESS);
@ -1255,7 +1248,6 @@ int deregistration_request_unpacking_packing_test_2(srsran::nas_pcap* pcap)
key_set_identifier_t::security_context_flag_type_::options::native_security_context);
TESTASSERT(dereg_req_ue_o.ng_ksi.nas_key_set_identifier == 0);
TESTASSERT(dereg_req_ue_o.mobile_identity_5gs.type() == mobile_identity_5gs_t::identity_types_::options::guti_5g);
TESTASSERT(dereg_req_ue_o.mobile_identity_5gs.length == 11);
mobile_identity_5gs_t::guti_5g_s guti_5g = dereg_req_ue_o.mobile_identity_5gs.guti_5g();
TESTASSERT(guti_5g.mcc[0] == 0);
@ -1354,7 +1346,6 @@ int pdu_session_establishment_request_unpacking_packing_test(srsran::nas_pcap* p
ul_nas_transport_t& ul_nas = nas_msg.ul_nas_transport();
TESTASSERT(ul_nas.payload_container_type.payload_container_type ==
payload_container_type_t::Payload_container_type_type_::options::n1_sm_information);
TESTASSERT(ul_nas.payload_container.length == 6);
TESTASSERT(ul_nas.payload_container.payload_container_contents.size() == 6);
TESTASSERT(ul_nas.payload_container.payload_container_contents[0] == 0x2e);
TESTASSERT(ul_nas.payload_container.payload_container_contents[5] == 0xff);
@ -1391,11 +1382,9 @@ int pdu_session_establishment_request_unpacking_packing_test(srsran::nas_pcap* p
TESTASSERT(ul_nas.request_type.request_type_value ==
request_type_t::Request_type_value_type_::options::initial_request);
TESTASSERT(ul_nas.s_nssai_present == true);
TESTASSERT(ul_nas.s_nssai.length == 4);
TESTASSERT(ul_nas.s_nssai.sst == 1);
TESTASSERT(ul_nas.s_nssai.sd == 66051);
TESTASSERT(ul_nas.dnn_present == true);
TESTASSERT(ul_nas.dnn.length == 9);
TESTASSERT(ul_nas.dnn.dnn_value.size() == 9);
TESTASSERT(ul_nas.dnn.dnn_value[0] == 0x08);
TESTASSERT(ul_nas.dnn.dnn_value[1] == 0x69);
@ -1510,7 +1499,6 @@ int pdu_session_est_req_accecpt(srsran::nas_pcap* pcap)
dl_nas_transport_t& dl_nas = nas_msg.dl_nas_transport();
TESTASSERT(dl_nas.payload_container_type.payload_container_type ==
payload_container_type_t::Payload_container_type_type_::options::n1_sm_information);
TESTASSERT(dl_nas.payload_container.length == 29);
TESTASSERT(dl_nas.payload_container.payload_container_contents.size() == 29);
TESTASSERT(dl_nas.payload_container.payload_container_contents[0] == 0x2e);
TESTASSERT(dl_nas.payload_container.payload_container_contents[28] == 0x01);
@ -1530,8 +1518,6 @@ int pdu_session_est_req_accecpt(srsran::nas_pcap* pcap)
TESTASSERT(pdu_sess_est_acc.selected_pdu_session_type.pdu_session_type_value ==
pdu_session_type_t::PDU_session_type_value_type_::options::ipv4);
TESTASSERT(pdu_sess_est_acc.authorized__qo_s_rules.length == 8);
TESTASSERT(pdu_sess_est_acc.session_ambr.length == 6);
TESTASSERT(pdu_sess_est_acc.session_ambr.unit_session_ambr_for_downlink ==
session_ambr_t::unit_session_AMBR_type_::options::inc_by_1_kbps);
TESTASSERT(pdu_sess_est_acc.session_ambr.session_ambr_for_downlink == 59395);

@ -51,6 +51,10 @@ add_executable(test_f12345 test_f12345.cc)
target_link_libraries(test_f12345 srsran_common ${CMAKE_THREAD_LIBS_INIT})
add_test(test_f12345 test_f12345)
add_executable(test_security_kdf test_security_kdf.cc)
target_link_libraries(test_security_kdf srsran_common ${CMAKE_THREAD_LIBS_INIT})
add_test(test_security_kdf test_security_kdf)
add_executable(timeout_test timeout_test.cc)
target_link_libraries(timeout_test srsran_phy ${CMAKE_THREAD_LIBS_INIT})

@ -23,6 +23,7 @@
#include <stdlib.h>
#include "srsran/common/liblte_security.h"
#include "srsran/common/security.h"
#include "srsran/common/test_common.h"
/*
* Prototypes
@ -159,85 +160,69 @@ int test_set_2()
err_cmp = arrcmp(ak_star_o, ak_star, sizeof(ak_star));
TESTASSERT(err_cmp == 0);
return SRSRAN_SUCCESS;
;
}
int test_set_ksg()
/*
Own test sets
*/
int test_set_xor_own_set_1()
{
LIBLTE_ERROR_ENUM err_lte = LIBLTE_ERROR_INVALID_INPUTS;
int32 err_cmp = 0;
auto& logger = srslog::fetch_basic_logger("LOG", false);
uint8_t k_enb[] = {0xfe, 0x7d, 0xee, 0x80, 0x8d, 0x7f, 0x3b, 0x88, 0x2a, 0x08, 0x2c, 0xbd, 0xc8, 0x39, 0x0d, 0x12,
0x9e, 0x5d, 0x28, 0xaf, 0x0e, 0x83, 0x22, 0xeb, 0x57, 0x3a, 0xda, 0x36, 0xf2, 0x1a, 0x5a, 0x89};
uint8_t sk_gnb_o[32];
uint16_t scg_counter = 0;
err_lte = liblte_security_generate_sk_gnb(k_enb, sk_gnb_o, scg_counter);
TESTASSERT(err_lte == LIBLTE_SUCCESS);
arrprint(sk_gnb_o, sizeof(sk_gnb_o));
uint8_t sk_gnb[] = {0x45, 0xcb, 0xc3, 0xf8, 0xa8, 0x11, 0x93, 0xfd, 0x5c, 0x52, 0x29, 0x30, 0x0d, 0x59, 0xed, 0xf8,
0x12, 0xe9, 0x98, 0xa1, 0x15, 0xec, 0x4e, 0x0c, 0xe9, 0x03, 0xba, 0x89, 0x36, 0x7e, 0x26, 0x28};
err_cmp = arrcmp(sk_gnb_o, sk_gnb, sizeof(sk_gnb));
TESTASSERT(err_cmp == 0);
return SRSRAN_SUCCESS;
}
uint8_t k[] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff};
uint8_t rand[] = {0xf9, 0x6a, 0xe3, 0x6e, 0x2d, 0x65, 0xfa, 0x84, 0x64, 0xc4, 0x98, 0xff, 0xc8, 0x30, 0x38, 0x0f};
int test_set_nr_rrc_up()
{
LIBLTE_ERROR_ENUM err_lte = LIBLTE_ERROR_INVALID_INPUTS;
int32 err_cmp = 0;
uint8_t res_o[16];
uint8_t ck_o[16];
uint8_t ik_o[16];
uint8_t ak_o[6];
uint8_t sk_gnb[] = {0x45, 0xcb, 0xc3, 0xf8, 0xa8, 0x11, 0x93, 0xfd, 0x5c, 0x52, 0x29, 0x30, 0x0d, 0x59, 0xed, 0xf8,
0x12, 0xe9, 0x98, 0xa1, 0x15, 0xec, 0x4e, 0x0c, 0xe9, 0x03, 0xba, 0x89, 0x36, 0x7e, 0x26, 0x28};
TESTASSERT(srsran::security_xor_f2345(k, rand, res_o, ck_o, ik_o, ak_o) == SRSRAN_SUCCESS);
uint8_t sk_gnb_o[32];
uint8_t k_rrc_enc_o[32];
uint8_t k_rrc_int_o[32];
uint8_t res[] = {0xf9, 0x7b, 0xc1, 0x5d, 0x69, 0x30, 0x9c, 0xf3};
uint8_t ck[] = {0x7b, 0xc1, 0x5d, 0x69, 0x30, 0x9c, 0xf3, 0xec, 0x5d, 0x32, 0x44, 0x04, 0xed, 0xd6, 0xf0, 0xf9};
uint8_t ik[] = {0xc1, 0x5d, 0x69, 0x30, 0x9c, 0xf3, 0xec, 0x5d, 0x32, 0x44, 0x04, 0xed, 0xd6, 0xf0, 0xf9, 0x7b};
uint8_t ak[] = {0x5d, 0x69, 0x30, 0x9c, 0xf3, 0xec};
err_lte = liblte_security_generate_k_nr_rrc(sk_gnb,
LIBLTE_SECURITY_CIPHERING_ALGORITHM_ID_128_EEA2,
LIBLTE_SECURITY_INTEGRITY_ALGORITHM_ID_EIA0,
k_rrc_enc_o,
k_rrc_int_o);
logger.info(res_o, sizeof(res_o), "RES: ");
TESTASSERT(arrcmp(res_o, res, sizeof(res)) == 0);
TESTASSERT(err_lte == LIBLTE_SUCCESS);
printf("RRC ENC output:\n");
arrprint(&k_rrc_enc_o[0], sizeof(k_rrc_enc_o));
uint8_t k_rrc_enc[] = {0x52, 0xa9, 0x95, 0xdf, 0xf8, 0x9b, 0xc2, 0x94, 0xbd, 0x89, 0xff,
0xb1, 0x37, 0xa2, 0x9f, 0x24, 0x66, 0xa0, 0x9e, 0x99, 0x23, 0x86,
0xc8, 0xd1, 0xdf, 0x78, 0x92, 0x96, 0x4c, 0x6f, 0xb5, 0x22};
// CK
logger.info(ck_o, sizeof(ck_o), "CK: ");
TESTASSERT(arrcmp(ck_o, ck, sizeof(ck)) == 0);
err_cmp = arrcmp(k_rrc_enc_o, k_rrc_enc, sizeof(k_rrc_enc_o));
// IK
logger.info(ik_o, sizeof(ik_o), "IK: ");
TESTASSERT(arrcmp(ik_o, ik, sizeof(ik)) == 0);
TESTASSERT(err_cmp == 0);
// AK
logger.info(ak_o, sizeof(ak_o), "AK: ");
TESTASSERT(arrcmp(ak_o, ak, sizeof(ak)) == 0);
uint8_t k_up_enc_o[32];
uint8_t k_up_int_o[32];
uint8_t sqn[] = {0x00, 0x00, 0x00, 0x00, 0x12, 0xd9};
uint8_t amf[] = {0x90, 0x01};
uint8_t mac_o[8];
TESTASSERT(srsran::security_xor_f1(k, rand, sqn, amf, mac_o) == SRSRAN_SUCCESS);
err_lte = liblte_security_generate_k_nr_up(sk_gnb,
LIBLTE_SECURITY_CIPHERING_ALGORITHM_ID_128_EEA2,
LIBLTE_SECURITY_INTEGRITY_ALGORITHM_ID_EIA0,
k_up_enc_o,
k_up_int_o);
uint8_t mac[] = {0xf9, 0x7b, 0xc1, 0x5d, 0x7b, 0xe9, 0x0c, 0xf2};
uint8_t k_up_enc[] = {0x7c, 0xe2, 0x06, 0x70, 0xbb, 0xbc, 0xc5, 0x90, 0x40, 0x87, 0xc0, 0xd4, 0x26, 0x53, 0xc5, 0x40,
0x15, 0x20, 0x52, 0xd3, 0xdf, 0xbc, 0x3f, 0x05, 0x86, 0x9b, 0x7f, 0x92, 0x00, 0x95, 0xbe, 0x68};
printf("UP ENC output:\n");
arrprint(&k_up_enc_o[0], sizeof(k_up_enc_o));
// MAC
logger.info(mac_o, sizeof(mac_o), "MAC: ");
TESTASSERT(arrcmp(mac_o, mac, sizeof(mac)) == 0);
err_cmp = arrcmp(k_up_enc_o, k_up_enc, sizeof(k_up_enc_o));
TESTASSERT(err_cmp == 0);
return SRSRAN_SUCCESS;
}
/*
Own test sets
*/
int main(int argc, char* argv[])
{
auto& logger = srslog::fetch_basic_logger("LOG", false);
logger.set_level(srslog::basic_levels::debug);
logger.set_hex_dump_max_size(128);
srslog::init();
TESTASSERT(test_set_2() == SRSRAN_SUCCESS);
TESTASSERT(test_set_ksg() == SRSRAN_SUCCESS);
TESTASSERT(test_set_nr_rrc_up() == SRSRAN_SUCCESS);
TESTASSERT(test_set_xor_own_set_1() == SRSRAN_SUCCESS);
return SRSRAN_SUCCESS;
}

@ -0,0 +1,447 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2021 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#include "srsran/common/bcd_helpers.h"
#include "srsran/common/common.h"
#include "srsran/common/security.h"
#include "srsran/common/test_common.h"
#include "srsran/srslog/srslog.h"
using namespace srsran;
int arrcmp(uint8_t const* const a, uint8_t const* const b, uint32_t len)
{
uint32_t i = 0;
for (i = 0; i < len; i++) {
if (a[i] != b[i]) {
return a[i] - b[i];
}
}
return SRSRAN_SUCCESS;
}
int test_set_ksg()
{
auto& logger = srslog::fetch_basic_logger("LOG", false);
int err_lte = SRSRAN_ERROR;
int err_cmp = SRSRAN_ERROR;
uint8_t k_enb[] = {0xfe, 0x7d, 0xee, 0x80, 0x8d, 0x7f, 0x3b, 0x88, 0x2a, 0x08, 0x2c, 0xbd, 0xc8, 0x39, 0x0d, 0x12,
0x9e, 0x5d, 0x28, 0xaf, 0x0e, 0x83, 0x22, 0xeb, 0x57, 0x3a, 0xda, 0x36, 0xf2, 0x1a, 0x5a, 0x89};
uint8_t sk_gnb_o[32];
uint16_t scg_counter = 0;
err_lte = srsran::security_generate_sk_gnb(k_enb, scg_counter, sk_gnb_o);
TESTASSERT(err_lte == SRSRAN_SUCCESS);
logger.info(&sk_gnb_o[0], sizeof(sk_gnb_o), "sk gnb o:");
uint8_t sk_gnb[] = {0x45, 0xcb, 0xc3, 0xf8, 0xa8, 0x11, 0x93, 0xfd, 0x5c, 0x52, 0x29, 0x30, 0x0d, 0x59, 0xed, 0xf8,
0x12, 0xe9, 0x98, 0xa1, 0x15, 0xec, 0x4e, 0x0c, 0xe9, 0x03, 0xba, 0x89, 0x36, 0x7e, 0x26, 0x28};
err_cmp = arrcmp(sk_gnb_o, sk_gnb, sizeof(sk_gnb));
TESTASSERT(err_cmp == 0);
return SRSRAN_SUCCESS;
}
int test_set_nr_rrc_up()
{
auto& logger = srslog::fetch_basic_logger("LOG", false);
int err_lte = SRSRAN_ERROR;
int err_cmp = SRSRAN_ERROR;
uint8_t sk_gnb[] = {0x45, 0xcb, 0xc3, 0xf8, 0xa8, 0x11, 0x93, 0xfd, 0x5c, 0x52, 0x29, 0x30, 0x0d, 0x59, 0xed, 0xf8,
0x12, 0xe9, 0x98, 0xa1, 0x15, 0xec, 0x4e, 0x0c, 0xe9, 0x03, 0xba, 0x89, 0x36, 0x7e, 0x26, 0x28};
uint8_t sk_gnb_o[32];
uint8_t k_rrc_enc_o[32];
uint8_t k_rrc_int_o[32];
err_lte = srsran::security_generate_k_nr_rrc(sk_gnb,
srsran::CIPHERING_ALGORITHM_ID_ENUM::CIPHERING_ALGORITHM_ID_128_EEA2,
srsran::INTEGRITY_ALGORITHM_ID_ENUM::INTEGRITY_ALGORITHM_ID_EIA0,
k_rrc_enc_o,
k_rrc_int_o);
TESTASSERT(err_lte == SRSRAN_SUCCESS);
logger.info(&k_rrc_enc_o[0], sizeof(k_rrc_enc_o), "RRC ENC output:");
uint8_t k_rrc_enc[] = {0x52, 0xa9, 0x95, 0xdf, 0xf8, 0x9b, 0xc2, 0x94, 0xbd, 0x89, 0xff,
0xb1, 0x37, 0xa2, 0x9f, 0x24, 0x66, 0xa0, 0x9e, 0x99, 0x23, 0x86,
0xc8, 0xd1, 0xdf, 0x78, 0x92, 0x96, 0x4c, 0x6f, 0xb5, 0x22};
err_cmp = arrcmp(k_rrc_enc_o, k_rrc_enc, sizeof(k_rrc_enc_o));
TESTASSERT(err_cmp == 0);
uint8_t k_up_enc_o[32];
uint8_t k_up_int_o[32];
err_lte = srsran::security_generate_k_nr_up(sk_gnb,
srsran::CIPHERING_ALGORITHM_ID_ENUM::CIPHERING_ALGORITHM_ID_128_EEA2,
srsran::INTEGRITY_ALGORITHM_ID_ENUM::INTEGRITY_ALGORITHM_ID_EIA0,
k_up_enc_o,
k_up_int_o);
uint8_t k_up_enc[] = {0x7c, 0xe2, 0x06, 0x70, 0xbb, 0xbc, 0xc5, 0x90, 0x40, 0x87, 0xc0, 0xd4, 0x26, 0x53, 0xc5, 0x40,
0x15, 0x20, 0x52, 0xd3, 0xdf, 0xbc, 0x3f, 0x05, 0x86, 0x9b, 0x7f, 0x92, 0x00, 0x95, 0xbe, 0x68};
logger.info(&k_up_enc_o[0], sizeof(k_up_enc_o), "UP ENC output:");
err_cmp = arrcmp(k_up_enc_o, k_up_enc, sizeof(k_up_enc_o));
TESTASSERT(err_cmp == 0);
return SRSRAN_SUCCESS;
}
int test_generate_k_asme()
{
auto& logger = srslog::fetch_basic_logger("LOG", false);
uint8_t k_asme_o[32] = {};
uint8_t ck[] = {0x7b, 0xc1, 0x5d, 0x69, 0x30, 0x9c, 0xf3, 0xec, 0x5d, 0x32, 0x44, 0x04, 0xed, 0xd6, 0xf0, 0xf9};
uint8_t ik[] = {0xc1, 0x5d, 0x69, 0x30, 0x9c, 0xf3, 0xec, 0x5d, 0x32, 0x44, 0x04, 0xed, 0xd6, 0xf0, 0xf9, 0x7b};
uint8_t ak[] = {0x5d, 0x69, 0x30, 0x9c, 0xf3, 0xec};
uint8_t sqn[] = {0x00, 0x00, 0x00, 0x00, 0x12, 0xd9};
uint16_t mcc = 61441; // MCC 001
uint16_t mnc = 65281; // MNC 01
uint8_t ak_xor_sqn[6];
for (uint32_t i = 0; i < 6; i++) {
ak_xor_sqn[i] = sqn[i] ^ ak[i];
}
// Generate K_asme
security_generate_k_asme(ck, ik, ak_xor_sqn, mcc, mnc, k_asme_o);
uint8_t k_asme[] = {0xd5, 0xef, 0x4d, 0x8f, 0x33, 0x26, 0x69, 0x02, 0x29, 0x5d, 0x42, 0xf3, 0x22, 0xa2, 0xf2, 0xcf,
0x11, 0xfb, 0x2c, 0xcc, 0x12, 0x4c, 0x09, 0xb4, 0xd8, 0x8d, 0x36, 0x15, 0x97, 0x03, 0x79, 0x90};
logger.info(k_asme_o, 32, "K_ASME output:");
TESTASSERT(arrcmp(k_asme, k_asme_o, sizeof(k_asme_o)) == 0);
return SRSRAN_SUCCESS;
}
int test_generate_k_nas()
{
auto& logger = srslog::fetch_basic_logger("LOG", false);
uint8_t k_nas_enc_o[32];
uint8_t k_nas_int_o[32];
uint8_t k_asme[] = {0xd5, 0xef, 0x4d, 0x8f, 0x33, 0x26, 0x69, 0x02, 0x29, 0x5d, 0x42, 0xf3, 0x22, 0xa2, 0xf2, 0xcf,
0x11, 0xfb, 0x2c, 0xcc, 0x12, 0x4c, 0x09, 0xb4, 0xd8, 0x8d, 0x36, 0x15, 0x97, 0x03, 0x79, 0x90};
TESTASSERT(srsran::security_generate_k_nas(k_asme,
srsran::CIPHERING_ALGORITHM_ID_ENUM::CIPHERING_ALGORITHM_ID_EEA0,
srsran::INTEGRITY_ALGORITHM_ID_ENUM::INTEGRITY_ALGORITHM_ID_128_EIA1,
k_nas_enc_o,
k_nas_int_o) == SRSRAN_SUCCESS);
uint8_t k_nas_enc[] = {0xcf, 0x7a, 0x27, 0xbe, 0xab, 0x1e, 0x78, 0xbf, 0x5b, 0xb1, 0xf9,
0x5b, 0x05, 0x82, 0x9a, 0x72, 0xe4, 0xcf, 0x7f, 0xec, 0xba, 0xd4,
0xb8, 0xc3, 0x7d, 0xb4, 0xa1, 0x90, 0xe1, 0x19, 0x22, 0x5c};
logger.info(k_nas_enc_o, 32, "K NAS ENC output:");
TESTASSERT(arrcmp(k_nas_enc, k_nas_enc_o, sizeof(k_nas_enc_o)) == 0);
uint8_t k_nas_int[] = {0xb8, 0x55, 0x87, 0x1d, 0x17, 0xd4, 0xa7, 0x17, 0xe9, 0x31, 0xd9,
0xa6, 0x06, 0x9c, 0x6e, 0x54, 0xb7, 0x94, 0x08, 0xe2, 0x43, 0xdd,
0x36, 0x7d, 0xc8, 0xc6, 0x39, 0x22, 0x95, 0xb3, 0xb4, 0x51};
logger.info(k_nas_int_o, 32, "K NAS INT output:");
TESTASSERT(arrcmp(k_nas_int, k_nas_int_o, sizeof(k_nas_int_o)) == 0);
return SRSRAN_SUCCESS;
}
int test_generate_k_enb()
{
auto& logger = srslog::fetch_basic_logger("LOG", false);
uint8_t k_enb_o[32];
uint8_t k_asme[] = {0x61, 0x44, 0xc6, 0x81, 0xd1, 0xbe, 0xa9, 0xda, 0xe1, 0xb8, 0xcf, 0x6c, 0xd1, 0x0a, 0x68, 0x63,
0x41, 0xdb, 0x80, 0x46, 0xa1, 0xe7, 0xa9, 0xab, 0x4d, 0x1e, 0xa0, 0xe3, 0x3c, 0x99, 0x4a, 0xc0};
uint32_t nas_ul_count = 0;
TESTASSERT(srsran::security_generate_k_enb(k_asme, nas_ul_count, k_enb_o) == SRSRAN_SUCCESS);
uint8_t k_enb[] = {0xc4, 0xc7, 0xbc, 0x79, 0x8a, 0xb9, 0x4e, 0x3d, 0x35, 0x4c, 0xd6, 0x60, 0x8e, 0x79, 0xaa, 0x92,
0xf5, 0x56, 0x9d, 0xf4, 0x65, 0x19, 0x50, 0x78, 0x50, 0x05, 0x1e, 0x36, 0xf0, 0x18, 0xca, 0x5f};
logger.info(k_enb, 32, "K ENB output:");
TESTASSERT(arrcmp(k_enb, k_enb_o, sizeof(k_enb_o)) == 0);
return SRSRAN_SUCCESS;
}
int test_generate_rrc_keys()
{
auto& logger = srslog::fetch_basic_logger("LOG", false);
uint8_t k_rrc_enc_o[32];
uint8_t k_rrc_int_o[32];
uint8_t k_enb[] = {0xc4, 0xc7, 0xbc, 0x79, 0x8a, 0xb9, 0x4e, 0x3d, 0x35, 0x4c, 0xd6, 0x60, 0x8e, 0x79, 0xaa, 0x92,
0xf5, 0x56, 0x9d, 0xf4, 0x65, 0x19, 0x50, 0x78, 0x50, 0x05, 0x1e, 0x36, 0xf0, 0x18, 0xca, 0x5f};
TESTASSERT(srsran::security_generate_k_rrc(k_enb,
srsran::CIPHERING_ALGORITHM_ID_ENUM::CIPHERING_ALGORITHM_ID_EEA0,
srsran::INTEGRITY_ALGORITHM_ID_ENUM::INTEGRITY_ALGORITHM_ID_128_EIA2,
k_rrc_enc_o,
k_rrc_int_o) == SRSRAN_SUCCESS);
uint8_t k_rrc_enc[] = {0x23, 0xaf, 0xdd, 0x7b, 0x2e, 0x4a, 0x5a, 0x99, 0xc7, 0x78, 0x82,
0x78, 0x59, 0xcf, 0x45, 0x14, 0x86, 0xa2, 0x75, 0x78, 0x8b, 0x6f,
0x36, 0xa5, 0xb9, 0xb8, 0x10, 0xf5, 0xd4, 0x72, 0xa2, 0x4b};
logger.info(k_rrc_enc_o, 32, "K RRC ENC output:");
TESTASSERT(arrcmp(k_rrc_enc, k_rrc_enc_o, sizeof(k_rrc_enc_o)) == 0);
uint8_t k_rrc_int[] = {0x42, 0xf4, 0xf8, 0xc5, 0x85, 0xae, 0x89, 0x05, 0xa5, 0x0d, 0x0f,
0x32, 0xa9, 0x79, 0xd8, 0xb6, 0xfa, 0x1d, 0x6d, 0x19, 0x40, 0xf1,
0xd8, 0x79, 0xcf, 0x01, 0x89, 0x34, 0x2a, 0x8d, 0x73, 0xc2};
logger.info(k_rrc_int_o, 32, "K RRC INT output:");
TESTASSERT(arrcmp(k_rrc_int, k_rrc_int_o, sizeof(k_rrc_int_o)) == 0);
return SRSRAN_SUCCESS;
}
int test_generate_up_keys()
{
auto& logger = srslog::fetch_basic_logger("LOG", false);
uint8_t k_up_enc_o[32];
uint8_t k_up_int_o[32];
uint8_t k_enb[] = {0xc4, 0xc7, 0xbc, 0x79, 0x8a, 0xb9, 0x4e, 0x3d, 0x35, 0x4c, 0xd6, 0x60, 0x8e, 0x79, 0xaa, 0x92,
0xf5, 0x56, 0x9d, 0xf4, 0x65, 0x19, 0x50, 0x78, 0x50, 0x05, 0x1e, 0x36, 0xf0, 0x18, 0xca, 0x5f};
TESTASSERT(srsran::security_generate_k_up(k_enb,
srsran::CIPHERING_ALGORITHM_ID_ENUM::CIPHERING_ALGORITHM_ID_EEA0,
srsran::INTEGRITY_ALGORITHM_ID_ENUM::INTEGRITY_ALGORITHM_ID_128_EIA2,
k_up_enc_o,
k_up_int_o) == SRSRAN_SUCCESS);
uint8_t k_up_enc[] = {0x22, 0xbf, 0xb5, 0x87, 0x61, 0xca, 0x1d, 0xd3, 0xb2, 0x0a, 0x28, 0x1c, 0x7e, 0xab, 0x0c, 0x0b,
0x9c, 0x3c, 0x92, 0xe1, 0xdd, 0xc0, 0xc8, 0xc5, 0x70, 0x6c, 0xbb, 0x8f, 0x95, 0x5e, 0x82, 0x63};
logger.info(k_up_enc_o, 32, "K UP ENC output:");
TESTASSERT(arrcmp(k_up_enc, k_up_enc_o, sizeof(k_up_enc_o)) == 0);
uint8_t k_up_int[] = {0x82, 0x0d, 0xcd, 0xf3, 0xb9, 0xc9, 0x4b, 0x32, 0xf8, 0x41, 0xc2, 0x5c, 0xc8, 0x78, 0xaa, 0x07,
0x77, 0x16, 0xc7, 0x83, 0xa5, 0x3f, 0xd3, 0xee, 0x58, 0x2f, 0xc5, 0x69, 0xe9, 0xc3, 0x3c, 0xa7};
logger.info(k_up_int_o, 32, "K UP INT output:");
TESTASSERT(arrcmp(k_up_int, k_up_int_o, sizeof(k_up_int_o)) == 0);
return SRSRAN_SUCCESS;
}
int test_generate_k_enb_star()
{
auto& logger = srslog::fetch_basic_logger("LOG", false);
uint8_t k_enb_star_o[32];
uint8_t k_enb[] = {0xc4, 0xc7, 0xbc, 0x79, 0x8a, 0xb9, 0x4e, 0x3d, 0x35, 0x4c, 0xd6, 0x60, 0x8e, 0x79, 0xaa, 0x92,
0xf5, 0x56, 0x9d, 0xf4, 0x65, 0x19, 0x50, 0x78, 0x50, 0x05, 0x1e, 0x36, 0xf0, 0x18, 0xca, 0x5f};
TESTASSERT(srsran::security_generate_k_enb_star(k_enb, 32, 561, k_enb_star_o) == SRSRAN_SUCCESS);
uint8_t k_enb_star[] = {0x6f, 0x04, 0x54, 0x57, 0x7f, 0x55, 0x5c, 0xa7, 0x6f, 0x44, 0x9c,
0x2a, 0xc1, 0xda, 0x0f, 0x4f, 0xb7, 0xde, 0x4b, 0x94, 0x40, 0x11,
0x0f, 0xfb, 0xd1, 0x2f, 0x3a, 0x5d, 0x4d, 0xe1, 0x73, 0x50};
logger.info(k_enb_star_o, 32, "K ENB STAR:");
TESTASSERT(arrcmp(k_enb_star_o, k_enb_star, sizeof(k_enb_star)) == 0);
return SRSRAN_SUCCESS;
}
int test_generate_k_nh()
{
auto& logger = srslog::fetch_basic_logger("LOG", false);
uint8_t nh_o[32];
uint8_t k_asme[] = {0xd5, 0xef, 0x4d, 0x8f, 0x33, 0x26, 0x69, 0x02, 0x29, 0x5d, 0x42, 0xf3, 0x22, 0xa2, 0xf2, 0xcf,
0x11, 0xfb, 0x2c, 0xcc, 0x12, 0x4c, 0x09, 0xb4, 0xd8, 0x8d, 0x36, 0x15, 0x97, 0x03, 0x79, 0x90};
uint8_t sync[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12};
TESTASSERT(srsran::security_generate_nh(k_asme, sync, nh_o) == SRSRAN_SUCCESS);
uint8_t nh[] = {0xc8, 0x55, 0x86, 0x64, 0x13, 0x07, 0x1b, 0x74, 0xab, 0xa0, 0x1c, 0x13, 0x2b, 0x94, 0x3e, 0x76,
0x98, 0xaa, 0x5c, 0x11, 0x76, 0x0d, 0x9b, 0xb1, 0x16, 0x2a, 0xb3, 0x13, 0xb1, 0x1c, 0x60, 0x51};
logger.info(nh_o, 32, "NH:");
TESTASSERT(arrcmp(nh_o, nh, sizeof(nh)) == 0);
return SRSRAN_SUCCESS;
}
int test_generate_res_star()
{
auto& logger = srslog::fetch_basic_logger("LOG", false);
uint8_t res_star_o[16];
uint8_t ck[] = {0x3c, 0xba, 0x90, 0x25, 0x75, 0xed, 0x80, 0xcb, 0xfa, 0x36, 0x25, 0xaf, 0xf0, 0x9d, 0xaf, 0xfc};
uint8_t ik[] = {0xba, 0x90, 0x25, 0x75, 0xed, 0x80, 0xcb, 0xfa, 0x36, 0x25, 0xaf, 0xf0, 0x9d, 0xaf, 0xfc, 0x3c};
uint8_t rand[] = {0xfc, 0x2d, 0x98, 0xa3, 0x61, 0x20, 0x8b, 0xf7, 0x43, 0x63, 0x9c, 0x9e, 0x63, 0x2d, 0x73, 0x50};
uint8_t res[] = {0xfc, 0x3c, 0xba, 0x90, 0x25, 0x75, 0xed, 0x80};
std::string ssn = "5G:mnc001.mcc001.3gppnetwork.org";
TESTASSERT(srsran::security_generate_res_star(ck, ik, ssn.c_str(), rand, res, sizeof(res), res_star_o) ==
SRSRAN_SUCCESS);
uint8_t res_star[] = {0xb0, 0xe3, 0x5b, 0x23, 0xdb, 0xd7, 0xa1, 0x8c, 0x84, 0x8b, 0xfa, 0xd9, 0x11, 0x35, 0xe3, 0xfd};
logger.info(res_star_o, 16, "RES STAR:");
TESTASSERT(arrcmp(res_star_o, res_star, sizeof(res_star)) == 0);
return SRSRAN_SUCCESS;
}
int test_generate_k_ausf()
{
auto& logger = srslog::fetch_basic_logger("LOG", false);
uint8_t k_ausf_o[32];
uint8_t ck[] = {0x56, 0x1e, 0x05, 0xef, 0xbd, 0xf2, 0xef, 0xeb, 0x2d, 0x55, 0x8f, 0x04, 0x1c, 0x53, 0xc4, 0x45};
uint8_t ik[] = {0x01, 0xe0, 0xf2, 0xf5, 0x53, 0x54, 0x31, 0x31, 0x2d, 0x57, 0x27, 0x98, 0x14, 0xcf, 0xcd, 0x89};
uint8_t ak_xor_sqn[] = {0x30, 0x5e, 0xb0, 0x6b, 0x73, 0x07};
std::string ssn = "5G:mnc070.mcc901.3gppnetwork.org";
TESTASSERT(srsran::security_generate_k_ausf(ck, ik, ak_xor_sqn, ssn.c_str(), k_ausf_o) == SRSRAN_SUCCESS);
uint8_t k_ausf[] = {0xa2, 0xce, 0xb2, 0x0f, 0x79, 0x28, 0xbf, 0x15, 0x4d, 0x4b, 0x54, 0x8a, 0xee, 0x6d, 0x10, 0xa9,
0x76, 0x01, 0x84, 0x7f, 0xd7, 0x2d, 0x2b, 0xc9, 0x01, 0x98, 0x2c, 0x08, 0x6e, 0xa0, 0xf3, 0x46};
// TODO check the out put with k AMF
logger.info(k_ausf_o, 32, "K AUSF:");
TESTASSERT(arrcmp(k_ausf_o, k_ausf, sizeof(k_ausf)) == 0);
return SRSRAN_SUCCESS;
}
int test_generate_k_seaf()
{
auto& logger = srslog::fetch_basic_logger("LOG", false);
uint8_t k_seaf_o[32];
uint8_t k_ausf[] = {0xd9, 0xc8, 0xff, 0x91, 0xb6, 0x9e, 0x25, 0x0e, 0x25, 0x6e, 0x92, 0x46, 0x6a, 0xcf, 0x80, 0xa1,
0xd8, 0x2b, 0x65, 0xf0, 0x94, 0xb7, 0xc0, 0x71, 0x19, 0x9c, 0x03, 0x12, 0xe0, 0x67, 0xff, 0x3b};
std::string ssn = "5G:mnc070.mcc901.3gppnetwork.org";
TESTASSERT(srsran::security_generate_k_seaf(k_ausf, ssn.c_str(), k_seaf_o) == SRSRAN_SUCCESS);
uint8_t k_seaf[] = {0x6c, 0x50, 0xbf, 0xa5, 0xf3, 0x2a, 0x89, 0xad, 0xe1, 0xee, 0x6c, 0x70, 0x7d, 0xe6, 0xdc, 0xfe,
0xa0, 0x79, 0x0a, 0xfb, 0x6d, 0x14, 0xf9, 0xe5, 0x59, 0x43, 0xae, 0xda, 0x58, 0x33, 0x45, 0x48};
logger.info(k_seaf_o, 32, "K SEAF:");
TESTASSERT(arrcmp(k_seaf_o, k_seaf, sizeof(k_seaf)) == 0);
return SRSRAN_SUCCESS;
}
int test_generate_k_amf()
{
auto& logger = srslog::fetch_basic_logger("LOG", false);
uint8_t k_amf_o[32];
uint8_t k_seaf[] = {0x6c, 0x50, 0xbf, 0xa5, 0xf3, 0x2a, 0x89, 0xad, 0xe1, 0xee, 0x6c, 0x70, 0x7d, 0xe6, 0xdc, 0xfe,
0xa0, 0x79, 0x0a, 0xfb, 0x6d, 0x14, 0xf9, 0xe5, 0x59, 0x43, 0xae, 0xda, 0x58, 0x33, 0x45, 0x48};
uint8_t abba[] = {0x00, 0x00};
std::string supi = "901700000021309";
TESTASSERT(srsran::security_generate_k_amf(k_seaf, supi.c_str(), abba, sizeof(abba), k_amf_o) == SRSRAN_SUCCESS);
uint8_t k_amf[] = {0x46, 0x23, 0x7e, 0xf0, 0x51, 0xd6, 0xa1, 0x6a, 0x39, 0x27, 0x52, 0x5f, 0xa6, 0x5c, 0xc3, 0x95,
0x44, 0xcd, 0xfd, 0x79, 0x90, 0xb9, 0x46, 0xad, 0x79, 0x65, 0x30, 0xe6, 0xd7, 0x87, 0xa0, 0xda};
logger.info(k_amf_o, 32, "K AMF:");
TESTASSERT(arrcmp(k_amf_o, k_amf, sizeof(k_amf)) == 0);
return SRSRAN_SUCCESS;
}
int test_generate_k_amf_2()
{
auto& logger = srslog::fetch_basic_logger("LOG", false);
uint8_t k_amf_o[32];
uint8_t k_seaf[] = {0x30, 0x2a, 0xb7, 0xc9, 0x4f, 0xae, 0x97, 0xe0, 0x43, 0xb3, 0x70, 0xd3, 0xeb, 0x1f, 0x54, 0x68,
0xf6, 0xa1, 0xd4, 0x55, 0xd6, 0x56, 0xa4, 0xca, 0xb3, 0x51, 0xea, 0xcf, 0xb9, 0xf7, 0xe1, 0x36};
uint8_t abba[] = {0x00, 0x00};
std::string supi = "001010123456780";
TESTASSERT(srsran::security_generate_k_amf(k_seaf, supi.c_str(), abba, sizeof(abba), k_amf_o) == SRSRAN_SUCCESS);
uint8_t k_amf[] = {0x8f, 0x2a, 0x5d, 0x6c, 0x12, 0x60, 0x8d, 0x8a, 0x0a, 0x8d, 0x33, 0x0a, 0x71, 0x9d, 0xee, 0x07,
0x22, 0x6b, 0x47, 0x41, 0x7b, 0x66, 0x1a, 0xf5, 0x84, 0x90, 0xea, 0xb0, 0x7a, 0xa4, 0x37, 0xa4};
logger.info(k_amf_o, 32, "K AMF:");
TESTASSERT(arrcmp(k_amf_o, k_amf, sizeof(k_amf)) == 0);
return SRSRAN_SUCCESS;
}
int test_generate_nas_5g()
{
auto& logger = srslog::fetch_basic_logger("LOG", false);
uint8_t k_nas_int_o[32];
uint8_t k_nas_enc_o[32];
uint8_t k_amf[] = {0x7d, 0x86, 0x18, 0x52, 0xb4, 0x2a, 0x86, 0xb5, 0x96, 0xfe, 0x22, 0xc8, 0xf5, 0x0b, 0x9b, 0x89,
0x5a, 0x1e, 0x21, 0x71, 0x6b, 0x61, 0xb8, 0xd1, 0x22, 0x78, 0x5e, 0x25, 0xba, 0xfc, 0x0d, 0x07};
TESTASSERT(srsran::security_generate_k_nas_5g(k_amf,
srsran::CIPHERING_ALGORITHM_ID_ENUM::CIPHERING_ALGORITHM_ID_EEA0,
srsran::INTEGRITY_ALGORITHM_ID_ENUM::INTEGRITY_ALGORITHM_ID_128_EIA2,
k_nas_enc_o,
k_nas_int_o) == SRSRAN_SUCCESS);
uint8_t k_nas_enc[] = {0x83, 0x85, 0x6a, 0x01, 0x81, 0x59, 0x55, 0x21, 0xc9, 0xd3, 0x2a,
0x19, 0x3f, 0x59, 0xc8, 0xa8, 0xfc, 0x7e, 0x99, 0xb9, 0x8b, 0x8c,
0x04, 0x20, 0x1f, 0x4f, 0x9d, 0x81, 0x43, 0x3b, 0x6b, 0x38};
uint8_t k_nas_int[] = {0x25, 0xc5, 0x8e, 0x27, 0xe7, 0xd2, 0xc4, 0x95, 0xf3, 0xd7, 0x35,
0x29, 0x3a, 0x82, 0xbf, 0xfa, 0xa5, 0x3e, 0xe8, 0x84, 0xb9, 0x8d,
0x36, 0x6b, 0x02, 0x89, 0x23, 0x1e, 0xc4, 0x19, 0x1e, 0xd3};
logger.info(k_nas_enc_o, 32, "k_nas_enc_o:");
TESTASSERT(arrcmp(k_nas_enc_o, k_nas_enc, sizeof(k_nas_enc)) == 0);
logger.info(k_nas_int_o, 32, "k_nas_int_o:");
TESTASSERT(arrcmp(k_nas_int_o, k_nas_int, sizeof(k_nas_int)) == 0);
return SRSRAN_SUCCESS;
}
int main(int argc, char** argv)
{
auto& logger = srslog::fetch_basic_logger("LOG", false);
logger.set_level(srslog::basic_levels::debug);
logger.set_hex_dump_max_size(256);
srslog::init();
TESTASSERT(test_generate_k_asme() == SRSRAN_SUCCESS);
TESTASSERT(test_generate_k_nas() == SRSRAN_SUCCESS);
TESTASSERT(test_generate_k_enb() == SRSRAN_SUCCESS);
TESTASSERT(test_generate_rrc_keys() == SRSRAN_SUCCESS);
TESTASSERT(test_generate_up_keys() == SRSRAN_SUCCESS);
TESTASSERT(test_generate_k_enb_star() == SRSRAN_SUCCESS);
TESTASSERT(test_generate_k_nh() == SRSRAN_SUCCESS);
TESTASSERT(test_generate_res_star() == SRSRAN_SUCCESS);
TESTASSERT(test_generate_k_ausf() == SRSRAN_SUCCESS);
TESTASSERT(test_generate_k_seaf() == SRSRAN_SUCCESS);
TESTASSERT(test_generate_k_amf() == SRSRAN_SUCCESS);
TESTASSERT(test_generate_k_amf_2() == SRSRAN_SUCCESS);
TESTASSERT(test_generate_nas_5g() == SRSRAN_SUCCESS);
TESTASSERT(test_set_ksg() == SRSRAN_SUCCESS);
TESTASSERT(test_set_nr_rrc_up() == SRSRAN_SUCCESS);
return SRSRAN_SUCCESS;
}

@ -20,6 +20,7 @@
*/
#include "srsran/common/mac_pcap.h"
#include "srsran/common/string_helpers.h"
#include "srsran/common/test_common.h"
#include "srsran/config.h"
#include "srsran/mac/mac_rar_pdu_nr.h"
@ -32,6 +33,7 @@
#define PCAP 0
#define PCAP_CRNTI (0x1001)
#define PCAP_RAR_RNTI (0x0016)
#define PCAP_TTI (666)
using namespace srsran;
@ -226,8 +228,13 @@ int mac_dl_sch_pdu_pack_test5()
pcap_handle->write_dl_crnti_nr(tx_buffer.msg, tx_buffer.N_bytes, PCAP_CRNTI, true, PCAP_TTI);
}
// pretty print PDU
fmt::memory_buffer buff;
tx_pdu.to_string(buff);
auto& mac_logger = srslog::fetch_basic_logger("MAC");
mac_logger.info(tx_buffer.msg, tx_buffer.N_bytes, "Generated MAC PDU (%d B)", tx_buffer.N_bytes);
mac_logger.info(
tx_buffer.msg, tx_buffer.N_bytes, "Generated MAC PDU (%d B): %s", tx_buffer.N_bytes, srsran::to_c_str(buff));
return SRSRAN_SUCCESS;
}
@ -254,7 +261,7 @@ int mac_dl_sch_pdu_unpack_test6()
return SRSRAN_SUCCESS;
}
int mac_rar_pdu_unpack_test7()
int mac_rar_pdu_test7()
{
// MAC PDU with RAR PDU with single RAPID=0
// rapid=0
@ -282,13 +289,17 @@ int mac_rar_pdu_unpack_test7()
uint8_t mac_dl_rar_pdu[] = {0x40, 0x05, 0xa0, 0x00, 0x11, 0x46, 0x46, 0x16, 0x00, 0x00, 0x00};
if (pcap_handle) {
pcap_handle->write_dl_ra_rnti_nr(mac_dl_rar_pdu, sizeof(mac_dl_rar_pdu), 0x0016, true, PCAP_TTI);
pcap_handle->write_dl_ra_rnti_nr(mac_dl_rar_pdu, sizeof(mac_dl_rar_pdu), PCAP_RAR_RNTI, true, PCAP_TTI);
}
srsran::mac_rar_pdu_nr pdu;
TESTASSERT(pdu.unpack(mac_dl_rar_pdu, sizeof(mac_dl_rar_pdu)) == true);
std::cout << pdu.to_string() << std::endl;
fmt::memory_buffer buff;
pdu.to_string(buff);
auto& mac_logger = srslog::fetch_basic_logger("MAC");
mac_logger.info("Rx PDU: %s", srsran::to_c_str(buff));
TESTASSERT(pdu.get_num_subpdus() == 1);
@ -302,6 +313,30 @@ int mac_rar_pdu_unpack_test7()
std::array<uint8_t, mac_rar_subpdu_nr::UL_GRANT_NBITS> msg3_grant = subpdu.get_ul_grant();
TESTASSERT(memcmp(msg3_grant.data(), tv_msg3_grant, msg3_grant.size()) == 0);
// pack again
byte_buffer_t tx_buffer;
tx_buffer.clear();
srsran::mac_rar_pdu_nr tx_pdu;
tx_pdu.init_tx(&tx_buffer, sizeof(mac_dl_rar_pdu));
mac_rar_subpdu_nr& rar_subpdu = tx_pdu.add_subpdu();
rar_subpdu.set_ta(tv_ta);
rar_subpdu.set_rapid(tv_rapid);
rar_subpdu.set_temp_crnti(tv_tcrnti);
rar_subpdu.set_ul_grant(msg3_grant);
TESTASSERT(tx_pdu.pack() == SRSRAN_SUCCESS);
TESTASSERT(tx_buffer.N_bytes == sizeof(mac_dl_rar_pdu));
TESTASSERT(memcmp(tx_buffer.msg, mac_dl_rar_pdu, tx_buffer.N_bytes) == 0);
tx_pdu.to_string(buff);
mac_logger.info("Tx PDU: %s", srsran::to_c_str(buff));
if (pcap_handle) {
pcap_handle->write_dl_ra_rnti_nr(tx_buffer.msg, tx_buffer.N_bytes, PCAP_RAR_RNTI, true, PCAP_TTI);
}
return SRSRAN_SUCCESS;
}
@ -596,6 +631,13 @@ int mac_dl_sch_pdu_unpack_and_pack_test6()
// 4th is padding
subpdu = pdu_rx.get_subpdu(3);
TESTASSERT(subpdu.get_lcid() == mac_sch_subpdu_nr::PADDING);
// pretty print PDU
fmt::memory_buffer buff;
pdu_rx.to_string(buff);
auto& mac_logger = srslog::fetch_basic_logger("MAC");
mac_logger.info("Rx PDU: %s", srsran::to_c_str(buff));
}
// Let's pack the entire PDU again
@ -621,6 +663,13 @@ int mac_dl_sch_pdu_unpack_and_pack_test6()
// finish PDU packing
pdu_tx.pack();
// pretty print PDU
fmt::memory_buffer buff;
pdu_tx.to_string(buff);
auto& mac_logger = srslog::fetch_basic_logger("MAC");
mac_logger.info("Tx PDU: %s", srsran::to_c_str(buff));
// compare PDUs
TESTASSERT(tx_buffer.N_bytes == sizeof(tv));
TESTASSERT(memcmp(tx_buffer.msg, tv, tx_buffer.N_bytes) == 0);
@ -701,7 +750,7 @@ int main(int argc, char** argv)
return SRSRAN_ERROR;
}
if (mac_rar_pdu_unpack_test7()) {
if (mac_rar_pdu_test7()) {
fprintf(stderr, "mac_rar_pdu_unpack_test7() failed.\n");
return SRSRAN_ERROR;
}
@ -755,5 +804,7 @@ int main(int argc, char** argv)
pcap_handle->close();
}
srslog::flush();
return SRSRAN_SUCCESS;
}

@ -325,7 +325,8 @@ enable = false
# metrics_csv_filename: File path to use for CSV metrics.
# report_json_enable: Write eNB report to JSON file (default disabled)
# report_json_filename: Report JSON filename (default /tmp/enb_report.json)
# alarms_log_enable: Enable Alarms logging (default diabled)
# report_json_asn1_oct: Prints ASN1 messages encoded as an octet string instead of plain text in the JSON report file
# alarms_log_enable: Enable Alarms logging (default disabled)
# alarms_filename: Alarms logging filename (default /tmp/alarms.log)
# tracing_enable: Write source code tracing information to a file.
# tracing_filename: File path to use for tracing information.
@ -357,6 +358,7 @@ enable = false
#metrics_csv_filename = /tmp/enb_metrics.csv
#report_json_enable = true
#report_json_filename = /tmp/enb_report.json
#report_json_asn1_oct = false
#alarms_log_enable = true
#alarms_filename = /tmp/enb_alarms.log
#tracing_enable = true

@ -94,6 +94,7 @@ struct general_args_t {
std::string metrics_csv_filename;
bool report_json_enable;
std::string report_json_filename;
bool report_json_asn1_oct;
bool alarms_log_enable;
std::string alarms_filename;
bool print_buffer_state;

@ -47,7 +47,6 @@ public:
private:
std::string float_to_string(float f, int digits, int field_width = 6);
std::string int_to_hex_string(int value, int field_width);
std::string float_to_eng_string(float f, int digits);
std::atomic<bool> do_print = {false};

@ -50,7 +50,6 @@ class gtpu_pdcp_adapter;
class enb_stack_lte final : public enb_stack_base,
public stack_interface_phy_lte,
public stack_interface_phy_nr,
public stack_interface_rrc,
public srsran::thread
{
public:
@ -145,11 +144,6 @@ public:
}
void rach_detected(const rach_info_t& rach_info) override { mac_nr.rach_detected(rach_info); }
// interface for bearer manager
void add_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid) override;
void remove_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id) override;
void reset_eps_bearers(uint16_t rnti) override;
private:
static const int STACK_MAIN_THREAD_PRIO = 4;
// thread loop
@ -185,7 +179,7 @@ private:
srsran::task_queue_handle enb_task_queue, sync_task_queue, metrics_task_queue;
// bearer management
srsran::bearer_manager bearers; // helper to manage mapping between EPS and radio bearers
enb_bearer_manager bearers; // helper to manage mapping between EPS and radio bearers
std::unique_ptr<gtpu_pdcp_adapter> gtpu_adapter;
srsenb::mac mac;

@ -46,10 +46,18 @@ struct mac_ue_metrics_t {
float phr;
};
/// MAC misc information for each cc.
struct mac_cc_info_t {
/// PCI value.
uint32_t pci;
/// RACH preamble counter per cc.
uint32_t cc_rach_counter;
};
/// Main MAC metrics.
struct mac_metrics_t {
/// RACH preamble counter per cc.
std::vector<uint32_t> cc_rach_counter;
/// Per CC info.
std::vector<mac_cc_info_t> cc_info;
/// Per UE MAC metrics.
std::vector<mac_ue_metrics_t> ues;
};

@ -95,6 +95,7 @@ private:
// Encoding
srsran::byte_buffer_t* assemble_rar(srsran::const_span<sched_nr_interface::sched_rar_grant_t> grants);
srsran::unique_byte_buffer_t rar_pdu_buffer = nullptr;
// Interaction with other components
phy_interface_stack_nr* phy = nullptr;
@ -133,7 +134,7 @@ private:
std::vector<sib_info_t> bcch_dlsch_payload;
srsran::unique_byte_buffer_t bcch_bch_payload = nullptr;
// Number of rach preambles detected for a cc.
// Number of rach preambles detected for a CC
std::vector<uint32_t> detected_rachs;
};

@ -49,13 +49,14 @@ public:
~sched_nr() override;
int cell_cfg(srsran::const_span<cell_cfg_t> cell_list) override;
void ue_cfg(uint16_t rnti, const ue_cfg_t& cfg) override;
void ue_rem(uint16_t rnti) override;
int dl_rach_info(uint32_t cc, const dl_sched_rar_info_t& rar_info);
void dl_ack_info(uint16_t rnti, uint32_t cc, uint32_t pid, uint32_t tb_idx, bool ack) override;
void ul_crc_info(uint16_t rnti, uint32_t cc, uint32_t pid, bool crc) override;
void ul_sr_info(slot_point slot_rx, uint16_t rnti) override;
void ul_bsr(uint16_t rnti, uint32_t lcg_id, uint32_t bsr);
void ul_bsr(uint16_t rnti, uint32_t lcg_id, uint32_t bsr) override;
void dl_buffer_state(uint16_t rnti, uint32_t lcid, uint32_t newtx, uint32_t retx);
int get_dl_sched(slot_point pdsch_tti, uint32_t cc, dl_sched_res_t& result) override;

@ -24,10 +24,11 @@
#include "sched_nr_interface.h"
#include "sched_nr_rb.h"
#include "srsenb/hdr/common/common_enb.h"
namespace srsenb {
const static size_t SCHED_NR_MAX_USERS = 4;
const static size_t SCHED_NR_MAX_USERS = SRSENB_MAX_UES;
const static size_t SCHED_NR_NOF_SUBFRAMES = 10;
const static size_t SCHED_NR_NOF_HARQS = 16;
static const size_t MAX_NOF_AGGR_LEVELS = 5;

@ -97,7 +97,7 @@ public:
////// RACH //////
struct dl_sched_rar_info_t {
uint32_t preamble_idx;
uint32_t preamble_idx; // is this the RAPID?
uint32_t ofdm_symbol_idx;
uint32_t freq_idx;
uint32_t ta_cmd;
@ -112,8 +112,8 @@ public:
using ul_sched_t = mac_interface_phy_nr::ul_sched_t;
struct sched_rar_grant_t {
dl_sched_rar_info_t data;
srsran_dci_rar_grant_t grant = {};
dl_sched_rar_info_t data;
srsran_dci_ul_nr_t msg3_dci = {};
};
struct sched_rar_t {
srsran::bounded_vector<sched_rar_grant_t, MAX_GRANTS> grants;
@ -127,12 +127,14 @@ public:
virtual ~sched_nr_interface() = default;
virtual int cell_cfg(srsran::const_span<sched_nr_interface::cell_cfg_t> ue_cfg) = 0;
virtual void ue_cfg(uint16_t rnti, const ue_cfg_t& ue_cfg) = 0;
virtual void ue_rem(uint16_t rnti) = 0;
virtual int get_dl_sched(slot_point slot_rx, uint32_t cc, dl_sched_res_t& result) = 0;
virtual int get_ul_sched(slot_point slot_rx, uint32_t cc, ul_sched_t& result) = 0;
virtual void dl_ack_info(uint16_t rnti, uint32_t cc, uint32_t pid, uint32_t tb_idx, bool ack) = 0;
virtual void ul_crc_info(uint16_t rnti, uint32_t cc, uint32_t pid, bool crc) = 0;
virtual void ul_sr_info(slot_point, uint16_t rnti) = 0;
virtual void ul_bsr(uint16_t rnti, uint32_t lcg_id, uint32_t bsr) = 0;
};
} // namespace srsenb

@ -123,8 +123,8 @@ private:
ue_cfg_t ue_cfg;
};
using ue_map_t = srsran::static_circular_map<uint16_t, std::unique_ptr<ue>, SCHED_NR_MAX_USERS>;
using slot_ue_map_t = srsran::static_circular_map<uint16_t, slot_ue, SCHED_NR_MAX_USERS>;
using ue_map_t = rnti_map_t<std::unique_ptr<ue> >;
using slot_ue_map_t = rnti_map_t<slot_ue>;
} // namespace sched_nr_impl

@ -110,7 +110,7 @@ public:
}
private:
void update_ue_db(slot_point slot_tx, bool update_ca_users);
void update_ue_db(slot_point slot_tx, bool locked_context);
bool save_sched_result(slot_point pdcch_slot, uint32_t cc, dl_sched_res_t& dl_res, ul_sched_t& ul_res);

@ -23,7 +23,7 @@
#define SRSENB_UE_NR_H
#include "srsenb/hdr/stack/mac/common/mac_metrics.h"
#include "srsenb/hdr/stack/mac/sched_interface.h"
#include "srsenb/hdr/stack/mac/nr/sched_nr_interface.h"
#include "srsran/common/block_queue.h"
#include "srsran/common/interfaces_common.h"
#include "srsran/interfaces/enb_rlc_interfaces.h"
@ -42,7 +42,7 @@ class ue_nr : public srsran::read_pdu_interface
public:
ue_nr(uint16_t rnti,
uint32_t enb_cc_idx,
sched_interface* sched_,
sched_nr_interface* sched_,
rrc_interface_mac_nr* rrc_,
rlc_interface_mac* rlc,
phy_interface_stack_nr* phy_,
@ -77,7 +77,7 @@ private:
rrc_interface_mac_nr* rrc = nullptr;
phy_interface_stack_nr* phy = nullptr;
srslog::basic_logger& logger;
sched_interface* sched = nullptr;
sched_nr_interface* sched = nullptr;
uint64_t conres_id = 0;
uint16_t rnti = 0;

@ -28,6 +28,7 @@
#include "srsenb/hdr/common/common_enb.h"
#include "srsenb/hdr/common/rnti_pool.h"
#include "srsran/adt/circular_buffer.h"
#include "srsran/common/bearer_manager.h"
#include "srsran/common/buffer_pool.h"
#include "srsran/common/common.h"
#include "srsran/common/stack_procedure.h"
@ -62,7 +63,7 @@ class rrc final : public rrc_interface_pdcp,
public rrc_eutra_interface_rrc_nr
{
public:
explicit rrc(stack_interface_rrc* stack_, srsran::task_sched_handle task_sched_);
explicit rrc(srsran::task_sched_handle task_sched_, enb_bearer_manager& manager_);
~rrc();
int32_t init(const rrc_cfg_t& cfg_,
@ -175,13 +176,13 @@ public:
private:
// args
srsran::task_sched_handle task_sched;
stack_interface_rrc* stack = nullptr;
phy_interface_rrc_lte* phy = nullptr;
mac_interface_rrc* mac = nullptr;
rlc_interface_rrc* rlc = nullptr;
pdcp_interface_rrc* pdcp = nullptr;
gtpu_interface_rrc* gtpu = nullptr;
s1ap_interface_rrc* s1ap = nullptr;
enb_bearer_manager& bearer_manager;
phy_interface_rrc_lte* phy = nullptr;
mac_interface_rrc* mac = nullptr;
rlc_interface_rrc* rlc = nullptr;
pdcp_interface_rrc* pdcp = nullptr;
gtpu_interface_rrc* gtpu = nullptr;
s1ap_interface_rrc* s1ap = nullptr;
rrc_nr_interface_rrc* rrc_nr = nullptr;
srslog::basic_logger& logger;

@ -37,7 +37,6 @@ inline const char* to_string(rrc_cfg_cqi_mode_t mode)
struct rrc_cfg_cqi_t {
uint32_t sf_mapping[80];
uint32_t nof_subframes;
uint32_t nof_prb;
uint32_t period;
uint32_t m_ri;
bool is_subband_enabled;

@ -127,11 +127,17 @@ public:
int pack_secondary_cell_group_config(asn1::dyn_octstring& packed_secondary_cell_config);
int pack_nr_radio_bearer_config(asn1::dyn_octstring& packed_nr_bearer_config);
int add_drb();
// state
rrc_nr_state_t state = rrc_nr_state_t::RRC_IDLE;
uint8_t transaction_id = 0;
uint32_t drb1_lcid = 4;
// RRC configs for UEs
asn1::rrc_nr::cell_group_cfg_s cell_group_cfg;
asn1::rrc_nr::radio_bearer_cfg_s radio_bearer_cfg;
const uint32_t drb1_lcid = 4;
};
private:

@ -160,6 +160,8 @@ public:
void save_ul_message(srsran::unique_byte_buffer_t pdu) { last_ul_msg = std::move(pdu); }
const ue_cell_ded_list& get_cell_list() const { return ue_cell_list; }
uint16_t rnti = 0;
rrc* parent = nullptr;

@ -45,7 +45,6 @@ phy_cnfg =
simultaneousAckCQI = true;
period = 40; // in ms
//subframe = [0, 10, 20, 30]; // Optional vector of subframe indices every period where CQI resources will be allocated (default uses all)
nof_prb = 1;
m_ri = 8; // RI period in CQI period
//subband_k = 1; // If enabled and > 0, configures sub-band CQI reporting and defines K (see 36.213 7.2.2). If disabled, configures wideband CQI
};

@ -111,8 +111,10 @@ int enb::init(const all_args_t& args_)
started = true; // set to true in any case to allow stopping the eNB if an error happened
// Now that everything is setup, log sector start events.
const std::string& sib9_hnb_name =
rrc_cfg.sibs[8].sib9().hnb_name_present ? rrc_cfg.sibs[8].sib9().hnb_name.to_string() : "";
for (unsigned i = 0, e = rrc_cfg.cell_list.size(); i != e; ++i) {
event_logger::get().log_sector_start(i, rrc_cfg.cell_list[i].pci, rrc_cfg.cell_list[i].cell_id);
event_logger::get().log_sector_start(i, rrc_cfg.cell_list[i].pci, rrc_cfg.cell_list[i].cell_id, sib9_hnb_name);
}
if (ret == SRSRAN_SUCCESS) {
@ -143,8 +145,10 @@ void enb::stop()
}
// Now that everything is teared down, log sector stop events.
const std::string& sib9_hnb_name =
rrc_cfg.sibs[8].sib9().hnb_name_present ? rrc_cfg.sibs[8].sib9().hnb_name.to_string() : "";
for (unsigned i = 0, e = rrc_cfg.cell_list.size(); i != e; ++i) {
event_logger::get().log_sector_stop(i, rrc_cfg.cell_list[i].pci, rrc_cfg.cell_list[i].cell_id);
event_logger::get().log_sector_stop(i, rrc_cfg.cell_list[i].pci, rrc_cfg.cell_list[i].cell_id, sib9_hnb_name);
}
started = false;

@ -745,7 +745,6 @@ int parse_rr(all_args_t* args_, rrc_cfg_t* rrc_cfg_)
"mode", &rrc_cfg_->cqi_cfg.mode, rrc_cfg_cqi_mode_text, RRC_CFG_CQI_MODE_N_ITEMS));
cqi_report_cnfg.add_field(new parser::field<uint32>("period", &rrc_cfg_->cqi_cfg.period));
cqi_report_cnfg.add_field(new parser::field<uint32>("m_ri", &rrc_cfg_->cqi_cfg.m_ri));
cqi_report_cnfg.add_field(new parser::field<uint32>("nof_prb", &rrc_cfg_->cqi_cfg.nof_prb));
cqi_report_cnfg.add_field(
new parser::field<uint32>("subband_k", &rrc_cfg_->cqi_cfg.subband_k, &rrc_cfg_->cqi_cfg.is_subband_enabled));
cqi_report_cnfg.add_field(new parser::field<bool>("simultaneousAckCQI", &rrc_cfg_->cqi_cfg.simultaneousAckCQI));
@ -1236,7 +1235,8 @@ int set_derived_args(all_args_t* args_, rrc_cfg_t* rrc_cfg_, phy_cfg_t* phy_cfg_
}
// Check PUCCH and PRACH configuration
uint32_t nrb_pucch = std::max(rrc_cfg_->sr_cfg.nof_prb, rrc_cfg_->cqi_cfg.nof_prb);
uint32_t nrb_pucch =
std::max(rrc_cfg_->sr_cfg.nof_prb, (uint32_t)rrc_cfg_->sibs[1].sib2().rr_cfg_common.pucch_cfg_common.nrb_cqi);
uint32_t prach_freq_offset = rrc_cfg_->sibs[1].sib2().rr_cfg_common.prach_cfg.prach_cfg_info.prach_freq_offset;
if (args_->enb.n_prb > 6) {
uint32_t lower_bound = nrb_pucch;

@ -231,6 +231,7 @@ void parse_args(all_args_t* args, int argc, char* argv[])
("expert.lte_sample_rates", bpo::value<bool>(&use_standard_lte_rates)->default_value(false), "Whether to use default LTE sample rates instead of shorter variants.")
("expert.report_json_enable", bpo::value<bool>(&args->general.report_json_enable)->default_value(false), "Write eNB report to JSON file (default disabled)")
("expert.report_json_filename", bpo::value<string>(&args->general.report_json_filename)->default_value("/tmp/enb_report.json"), "Report JSON filename (default /tmp/enb_report.json)")
("expert.report_json_asn1_oct", bpo::value<bool>(&args->general.report_json_asn1_oct)->default_value(false), "Prints ASN1 messages encoded as an octet string instead of plain text in the JSON report file")
("expert.alarms_log_enable", bpo::value<bool>(&args->general.alarms_log_enable)->default_value(false), "Enable Alarms logging (default diabled)")
("expert.alarms_filename", bpo::value<string>(&args->general.alarms_filename)->default_value("/tmp/enb_alarms.log"), "Alarms logging filename (default /tmp/alarms.log)")
("expert.tracing_enable", bpo::value<bool>(&args->general.tracing_enable)->default_value(false), "Events tracing")
@ -587,7 +588,10 @@ int main(int argc, char* argv[])
// Configure the event logger just before starting the eNB class.
if (args.general.report_json_enable) {
event_logger::configure(json_channel);
event_logger::asn1_output_format format = (args.general.report_json_asn1_oct)
? event_logger::asn1_output_format::octets
: event_logger::asn1_output_format::text;
event_logger::configure(json_channel, format);
}
if (mlockall((uint32_t)MCL_CURRENT | (uint32_t)MCL_FUTURE) == -1) {

@ -79,19 +79,20 @@ DECLARE_METRIC_SET("ue_container",
metric_bsr,
mlist_bearers);
/// Sector container metrics.
DECLARE_METRIC("sector_id", metric_sector_id, uint32_t, "");
DECLARE_METRIC("sector_rach", metric_sector_rach, uint32_t, "");
/// Cell container metrics.
DECLARE_METRIC("carrier_id", metric_carrier_id, uint32_t, "");
DECLARE_METRIC("pci", metric_pci, uint32_t, "");
DECLARE_METRIC("nof_rach", metric_nof_rach, uint32_t, "");
DECLARE_METRIC_LIST("ue_list", mlist_ues, std::vector<mset_ue_container>);
DECLARE_METRIC_SET("sector_container", mset_sector_container, metric_sector_id, metric_sector_rach, mlist_ues);
DECLARE_METRIC_SET("cell_container", mset_cell_container, metric_carrier_id, metric_pci, metric_nof_rach, mlist_ues);
/// Metrics root object.
DECLARE_METRIC("type", metric_type_tag, std::string, "");
DECLARE_METRIC("timestamp", metric_timestamp_tag, double, "");
DECLARE_METRIC_LIST("sector_list", mlist_sector, std::vector<mset_sector_container>);
DECLARE_METRIC_LIST("cell_list", mlist_cell, std::vector<mset_cell_container>);
/// Metrics context.
using metric_context_t = srslog::build_context_type<metric_type_tag, metric_timestamp_tag, mlist_sector>;
using metric_context_t = srslog::build_context_type<metric_type_tag, metric_timestamp_tag, mlist_cell>;
} // namespace
@ -179,7 +180,7 @@ void metrics_json::set_metrics(const enb_metrics_t& m, const uint32_t period_use
if (!enb) {
return;
}
if (m.stack.mac.cc_rach_counter.empty()) {
if (m.stack.mac.cc_info.empty()) {
return;
}
@ -187,27 +188,28 @@ void metrics_json::set_metrics(const enb_metrics_t& m, const uint32_t period_use
// Fill root object.
ctx.write<metric_type_tag>("metrics");
auto& sector_list = ctx.get<mlist_sector>();
sector_list.resize(m.stack.mac.cc_rach_counter.size());
auto& cell_list = ctx.get<mlist_cell>();
cell_list.resize(m.stack.mac.cc_info.size());
// For each sector...
for (unsigned cc_idx = 0, e = sector_list.size(); cc_idx != e; ++cc_idx) {
auto& sector = sector_list[cc_idx];
sector.write<metric_sector_id>(cc_idx);
sector.write<metric_sector_rach>(m.stack.mac.cc_rach_counter[cc_idx]);
// For each cell...
for (unsigned cc_idx = 0, e = cell_list.size(); cc_idx != e; ++cc_idx) {
auto& cell = cell_list[cc_idx];
cell.write<metric_carrier_id>(cc_idx);
cell.write<metric_nof_rach>(m.stack.mac.cc_info[cc_idx].cc_rach_counter);
cell.write<metric_pci>(m.stack.mac.cc_info[cc_idx].pci);
// For each UE in this sector...
// For each UE in this cell...
for (unsigned i = 0; i != m.stack.rrc.ues.size(); ++i) {
if (!has_valid_metric_ranges(m, i)) {
continue;
}
// Only record UEs that belong to this sector.
// Only record UEs that belong to this cell.
if (m.stack.mac.ues[i].cc_idx != cc_idx) {
continue;
}
sector.get<mlist_ues>().emplace_back();
fill_ue_metrics(sector.get<mlist_ues>().back(), m, i);
cell.get<mlist_ues>().emplace_back();
fill_ue_metrics(cell.get<mlist_ues>().back(), m, i);
}
}

@ -87,20 +87,18 @@ void metrics_stdout::set_metrics(const enb_metrics_t& metrics, const uint32_t pe
}
if (metrics.rf.rf_error) {
printf("RF status: O=%d, U=%d, L=%d\n", metrics.rf.rf_o, metrics.rf.rf_u, metrics.rf.rf_l);
fmt::print("RF status: O={}, U={}, L={}\n", metrics.rf.rf_o, metrics.rf.rf_u, metrics.rf.rf_l);
}
if (metrics.stack.rrc.ues.size() == 0) {
return;
}
std::ios::fmtflags f(cout.flags()); // For avoiding Coverity defect: Not restoring ostream format
if (++n_reports > 10) {
n_reports = 0;
cout << endl;
cout << "------DL-------------------------------UL--------------------------------------------" << endl;
cout << "rnti cqi ri mcs brate ok nok (%) pusch pucch phr mcs brate ok nok (%) bsr" << endl;
fmt::print("\n");
fmt::print("-------------------DL--------------------|-------------------------UL-------------------------\n");
fmt::print("rnti cqi ri mcs brate ok nok (%) | pusch pucch phr mcs brate ok nok (%) bsr\n");
}
for (size_t i = 0; i < metrics.stack.rrc.ues.size(); i++) {
@ -109,77 +107,87 @@ void metrics_stdout::set_metrics(const enb_metrics_t& metrics, const uint32_t pe
break;
}
if (metrics.stack.mac.ues[i].tx_errors > metrics.stack.mac.ues[i].tx_pkts) {
printf("tx caution errors %d > %d\n", metrics.stack.mac.ues[i].tx_errors, metrics.stack.mac.ues[i].tx_pkts);
fmt::print("tx caution errors {} > {}\n", metrics.stack.mac.ues[i].tx_errors, metrics.stack.mac.ues[i].tx_pkts);
}
if (metrics.stack.mac.ues[i].rx_errors > metrics.stack.mac.ues[i].rx_pkts) {
printf("rx caution errors %d > %d\n", metrics.stack.mac.ues[i].rx_errors, metrics.stack.mac.ues[i].rx_pkts);
fmt::print("rx caution errors {} > {}\n", metrics.stack.mac.ues[i].rx_errors, metrics.stack.mac.ues[i].rx_pkts);
}
cout << int_to_hex_string(metrics.stack.mac.ues[i].rnti, 4) << " ";
fmt::print("{:>4x}", metrics.stack.mac.ues[i].rnti);
if (not iszero(metrics.stack.mac.ues[i].dl_cqi)) {
cout << float_to_string(metrics.stack.mac.ues[i].dl_cqi, 1, 3);
fmt::print(" {:>3}", int(metrics.stack.mac.ues[i].dl_cqi));
} else {
cout << "n/a";
fmt::print(" {:>3.3}", "n/a");
}
cout << float_to_string(metrics.stack.mac.ues[i].dl_ri, 1, 4);
fmt::print(" {:>1}", int(metrics.stack.mac.ues[i].dl_ri));
if (not isnan(metrics.phy[i].dl.mcs)) {
cout << float_to_string(metrics.phy[i].dl.mcs, 1, 4);
fmt::print(" {:>2}", int(metrics.phy[i].dl.mcs));
} else {
cout << float_to_string(0, 2, 4);
fmt::print(" {:>2}", 0);
}
if (metrics.stack.mac.ues[i].tx_brate > 0) {
cout << float_to_eng_string((float)metrics.stack.mac.ues[i].tx_brate / (metrics.stack.mac.ues[i].nof_tti * 1e-3), 1);
fmt::print(
" {:>6.6}",
float_to_eng_string((float)metrics.stack.mac.ues[i].tx_brate / (metrics.stack.mac.ues[i].nof_tti * 1e-3), 1));
} else {
cout << float_to_string(0, 1, 6) << "";
fmt::print(" {:>6}", 0);
}
cout << std::setw(5) << metrics.stack.mac.ues[i].tx_pkts - metrics.stack.mac.ues[i].tx_errors;
cout << std::setw(5) << metrics.stack.mac.ues[i].tx_errors;
fmt::print(" {:>4}", metrics.stack.mac.ues[i].tx_pkts - metrics.stack.mac.ues[i].tx_errors);
fmt::print(" {:>4}", metrics.stack.mac.ues[i].tx_errors);
if (metrics.stack.mac.ues[i].tx_pkts > 0 && metrics.stack.mac.ues[i].tx_errors) {
cout << float_to_string((float)100 * metrics.stack.mac.ues[i].tx_errors / metrics.stack.mac.ues[i].tx_pkts, 1, 4)
<< "%";
fmt::print(" {:>3}%", int((float)100 * metrics.stack.mac.ues[i].tx_errors / metrics.stack.mac.ues[i].tx_pkts));
} else {
cout << float_to_string(0, 1, 4) << "%";
fmt::print(" {:>3}%", 0);
}
cout << " ";
fmt::print(" |");
auto clamp_sinr = [](float sinr) {
if (sinr > 99.9f) {
return 99.9f;
}
if (sinr < -99.9f) {
return -99.9f;
}
return sinr;
};
if (not isnan(metrics.phy[i].ul.pusch_sinr) and not iszero(metrics.phy[i].ul.pusch_sinr)) {
cout << float_to_string(metrics.phy[i].ul.pusch_sinr, 2, 5);
fmt::print(" {:>5.1f}", clamp_sinr(metrics.phy[i].ul.pusch_sinr));
} else {
cout << " n/a";
fmt::print(" {:>5.5}", "n/a");
}
if (not isnan(metrics.phy[i].ul.pucch_sinr) and not iszero(metrics.phy[i].ul.pucch_sinr)) {
cout << float_to_string(metrics.phy[i].ul.pucch_sinr, 2, 6);
fmt::print(" {:>5.1f}", clamp_sinr(metrics.phy[i].ul.pucch_sinr));
} else {
cout << " n/a";
fmt::print(" {:>5.5}", "n/a");
}
cout << " ";
cout << float_to_string(metrics.stack.mac.ues[i].phr, 2, 5);
fmt::print(" {:>3}", int(metrics.stack.mac.ues[i].phr));
if (not isnan(metrics.phy[i].ul.mcs)) {
cout << float_to_string(metrics.phy[i].ul.mcs, 1, 4);
fmt::print(" {:>2}", int(metrics.phy[i].ul.mcs));
} else {
cout << float_to_string(0, 1, 4);
fmt::print(" {:>2}", 0);
}
if (metrics.stack.mac.ues[i].rx_brate > 0) {
cout << float_to_eng_string((float)metrics.stack.mac.ues[i].rx_brate / (metrics.stack.mac.ues[i].nof_tti * 1e-3), 1);
fmt::print(
" {:>6.6}",
float_to_eng_string((float)metrics.stack.mac.ues[i].rx_brate / (metrics.stack.mac.ues[i].nof_tti * 1e-3), 1));
} else {
cout << float_to_string(0, 1) << "";
fmt::print(" {:>6}", 0);
}
cout << std::setw(5) << metrics.stack.mac.ues[i].rx_pkts - metrics.stack.mac.ues[i].rx_errors;
cout << std::setw(5) << metrics.stack.mac.ues[i].rx_errors;
fmt::print(" {:>4}", metrics.stack.mac.ues[i].rx_pkts - metrics.stack.mac.ues[i].rx_errors);
fmt::print(" {:>4}", metrics.stack.mac.ues[i].rx_errors);
if (metrics.stack.mac.ues[i].rx_pkts > 0 && metrics.stack.mac.ues[i].rx_errors > 0) {
cout << float_to_string((float)100 * metrics.stack.mac.ues[i].rx_errors / metrics.stack.mac.ues[i].rx_pkts, 1, 4)
<< "%";
fmt::print(" {:>3}%", int((float)100 * metrics.stack.mac.ues[i].rx_errors / metrics.stack.mac.ues[i].rx_pkts));
} else {
cout << float_to_string(0, 1, 4) << "%";
fmt::print(" {:>3}%", 0);
}
cout << float_to_eng_string(metrics.stack.mac.ues[i].ul_buffer, 2);
cout << endl;
fmt::print(" {:>6.6}", float_to_eng_string(metrics.stack.mac.ues[i].ul_buffer, 2));
fmt::print("\n");
}
cout.flags(f); // For avoiding Coverity defect: Not restoring ostream format
}
std::string metrics_stdout::float_to_string(float f, int digits, int field_width)
@ -199,13 +207,6 @@ std::string metrics_stdout::float_to_string(float f, int digits, int field_width
return os.str();
}
std::string metrics_stdout::int_to_hex_string(int value, int field_width)
{
std::ostringstream os;
os << std::hex << std::setw(field_width) << value;
return os.str();
}
std::string metrics_stdout::float_to_eng_string(float f, int digits)
{
const int degree = (f == 0.0) ? 0 : lrint(floor(log10f(fabs(f)) / 3));

@ -34,11 +34,11 @@ namespace srsenb {
class gtpu_pdcp_adapter final : public gtpu_interface_pdcp, public pdcp_interface_gtpu
{
public:
gtpu_pdcp_adapter(srslog::basic_logger& logger_,
pdcp* pdcp_lte,
pdcp* pdcp_nr,
gtpu* gtpu_,
srsran::bearer_manager& bearers_) :
gtpu_pdcp_adapter(srslog::basic_logger& logger_,
pdcp* pdcp_lte,
pdcp* pdcp_nr,
gtpu* gtpu_,
enb_bearer_manager& bearers_) :
logger(logger_), pdcp_obj(pdcp_lte), pdcp_nr_obj(pdcp_nr), gtpu_obj(gtpu_), bearers(&bearers_)
{}
@ -78,11 +78,11 @@ public:
}
private:
srslog::basic_logger& logger;
gtpu* gtpu_obj = nullptr;
pdcp* pdcp_obj = nullptr;
pdcp* pdcp_nr_obj = nullptr;
srsran::bearer_manager* bearers = nullptr;
srslog::basic_logger& logger;
gtpu* gtpu_obj = nullptr;
pdcp* pdcp_obj = nullptr;
pdcp* pdcp_nr_obj = nullptr;
enb_bearer_manager* bearers = nullptr;
};
enb_stack_lte::enb_stack_lte(srslog::sink& log_sink) :
@ -107,7 +107,7 @@ enb_stack_lte::enb_stack_lte(srslog::sink& log_sink) :
rlc_nr(rlc_nr_logger),
gtpu(&task_sched, gtpu_logger, &rx_sockets),
s1ap(&task_sched, s1ap_logger, &rx_sockets),
rrc(this, &task_sched),
rrc(&task_sched, bearers),
rrc_nr(&task_sched),
mac_pcap(),
pending_stack_metrics(64)
@ -344,19 +344,4 @@ void enb_stack_lte::run_thread()
}
}
void enb_stack_lte::add_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid)
{
bearers.add_eps_bearer(rnti, eps_bearer_id, rat, lcid);
}
void enb_stack_lte::remove_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id)
{
bearers.remove_eps_bearer(rnti, eps_bearer_id);
}
void enb_stack_lte::reset_eps_bearers(uint16_t rnti)
{
bearers.reset(rnti);
}
} // namespace srsenb

@ -253,7 +253,11 @@ void mac::get_metrics(mac_metrics_t& metrics)
metrics.ues.emplace_back();
u.second->metrics_read(&metrics.ues.back());
}
metrics.cc_rach_counter = detected_rachs;
metrics.cc_info.resize(detected_rachs.size());
for (unsigned cc = 0, e = detected_rachs.size(); cc != e; ++cc) {
metrics.cc_info[cc].cc_rach_counter = detected_rachs[cc];
metrics.cc_info[cc].pci = (cc < cell_config.size()) ? cell_config[cc].cell.id : 0;
}
}
void mac::toggle_padding()
@ -837,9 +841,9 @@ int mac::get_mch_sched(uint32_t tti, bool is_mcch, dl_sched_list_t& dl_sched_res
int requested_bytes = (mcs_data.tbs / 8 > (int)mch.mtch_sched[mtch_index].lcid_buffer_size)
? (mch.mtch_sched[mtch_index].lcid_buffer_size)
: ((mcs_data.tbs / 8) - 2);
int bytes_received = ue_db[SRSRAN_MRNTI]->read_pdu(current_lcid, mtch_payload_buffer, requested_bytes);
mch.pdu[0].lcid = current_lcid;
mch.pdu[0].nbytes = bytes_received;
int bytes_received = ue_db[SRSRAN_MRNTI]->read_pdu(current_lcid, mtch_payload_buffer, requested_bytes);
mch.pdu[0].lcid = current_lcid;
mch.pdu[0].nbytes = bytes_received;
mch.mtch_sched[0].mtch_payload = mtch_payload_buffer;
dl_sched_res->pdsch[0].dci.rnti = SRSRAN_MRNTI;
if (bytes_received) {

@ -25,7 +25,9 @@
#include "srsran/common/log_helper.h"
#include "srsran/common/rwlock_guard.h"
#include "srsran/common/standard_streams.h"
#include "srsran/common/string_helpers.h"
#include "srsran/common/time_prof.h"
#include "srsran/mac/mac_rar_pdu_nr.h"
#include <pthread.h>
#include <string.h>
#include <strings.h>
@ -37,7 +39,8 @@ mac_nr::mac_nr(srsran::task_sched_handle task_sched_, const sched_nr_interface::
logger(srslog::fetch_basic_logger("MAC-NR")),
task_sched(task_sched_),
sched(sched_cfg),
bcch_bch_payload(srsran::make_byte_buffer())
bcch_bch_payload(srsran::make_byte_buffer()),
rar_pdu_buffer(srsran::make_byte_buffer())
{
stack_task_queue = task_sched.make_task_queue();
}
@ -148,9 +151,6 @@ void mac_nr::rach_detected(const rach_info_t& rach_info)
rach_tprof_meas.defer_stop();
uint16_t rnti = reserve_rnti(enb_cc_idx);
// TODO: Generate RAR data
// ..
// Log this event.
++detected_rachs[enb_cc_idx];
@ -196,8 +196,7 @@ uint16_t mac_nr::alloc_ue(uint32_t enb_cc_idx)
}
// Allocate and initialize UE object
// TODO: add sched interface
std::unique_ptr<ue_nr> ue_ptr = std::unique_ptr<ue_nr>(new ue_nr(rnti, enb_cc_idx, nullptr, rrc, rlc, phy, logger));
std::unique_ptr<ue_nr> ue_ptr = std::unique_ptr<ue_nr>(new ue_nr(rnti, enb_cc_idx, &sched, rrc, rlc, phy, logger));
// Add UE to rnti map
srsran::rwlock_write_guard rw_lock(rwlock);
@ -298,6 +297,7 @@ int mac_nr::get_dl_sched(const srsran_slot_cfg_t& slot_cfg, dl_sched_t& dl_sched
}
} else if (pdsch.sch.grant.rnti_type == srsran_rnti_type_ra) {
sched_nr_interface::sched_rar_t& rar = dl_res.rar[rar_count++];
// for RARs we could actually move the byte_buffer to the PHY, as there are no retx
pdsch.data[0] = assemble_rar(rar.grants);
}
}
@ -370,7 +370,49 @@ int mac_nr::pusch_info(const srsran_slot_cfg_t& slot_cfg, mac_interface_phy_nr::
srsran::byte_buffer_t* mac_nr::assemble_rar(srsran::const_span<sched_nr_interface::sched_rar_grant_t> grants)
{
return nullptr;
srsran::mac_rar_pdu_nr rar_pdu;
uint32_t pdsch_tbs = 10; // FIXME: how big is the PDSCH?
rar_pdu.init_tx(rar_pdu_buffer.get(), pdsch_tbs);
for (auto& rar_grant : grants) {
srsran::mac_rar_subpdu_nr& rar_subpdu = rar_pdu.add_subpdu();
// set values directly coming from scheduler
rar_subpdu.set_ta(rar_grant.data.ta_cmd);
rar_subpdu.set_rapid(rar_grant.data.preamble_idx);
rar_subpdu.set_temp_crnti(rar_grant.data.temp_crnti);
// convert Msg3 grant to raw UL grant
srsran_dci_nr_t dci = {};
srsran_dci_msg_nr_t dci_msg = {};
if (srsran_dci_nr_ul_pack(&dci, &rar_grant.msg3_dci, &dci_msg) != SRSRAN_SUCCESS) {
logger.error("Couldn't pack Msg3 UL grant");
return nullptr;
}
if (logger.info.enabled()) {
std::array<char, 512> str;
srsran_dci_ul_nr_to_str(&dci, &rar_grant.msg3_dci, str.data(), str.size());
logger.info("Setting RAR Grant %s", str.data());
}
// copy only the required bits
std::array<uint8_t, SRSRAN_RAR_UL_GRANT_NBITS> packed_ul_grant = {};
std::copy(std::begin(dci_msg.payload), std::begin(dci_msg.payload)+SRSRAN_RAR_UL_GRANT_NBITS, packed_ul_grant.begin());
rar_subpdu.set_ul_grant(packed_ul_grant);
}
if (rar_pdu.pack() != SRSRAN_SUCCESS) {
logger.error("Couldn't assemble RAR PDU");
return nullptr;
}
fmt::memory_buffer buff;
rar_pdu.to_string(buff);
logger.info("DL %s", srsran::to_c_str(buff));
return rar_pdu_buffer.get();
}
} // namespace srsenb

@ -104,10 +104,20 @@ void sched_nr::ue_cfg(uint16_t rnti, const ue_cfg_t& uecfg)
sched_workers->enqueue_event(rnti, [this, rnti, uecfg]() { ue_cfg_impl(rnti, uecfg); });
}
void sched_nr::ue_rem(uint16_t rnti)
{
sched_workers->enqueue_event(rnti, [this, rnti]() { ue_db.erase(rnti); });
}
void sched_nr::ue_cfg_impl(uint16_t rnti, const ue_cfg_t& uecfg)
{
if (not ue_db.contains(rnti)) {
ue_db.insert(rnti, std::unique_ptr<ue>(new ue{rnti, uecfg, cfg}));
auto ret = ue_db.insert(rnti, std::unique_ptr<ue>(new ue{rnti, uecfg, cfg}));
if (ret.has_value()) {
logger.info("SCHED: New user rnti=0x%x, cc=%d", rnti, cfg.cells[0].cc);
} else {
logger.error("SCHED: Failed to create new user rnti=0x%x", rnti);
}
} else {
ue_db[rnti]->set_cfg(uecfg);
}

@ -158,34 +158,27 @@ alloc_result bwp_slot_allocator::alloc_rar_and_msg3(uint16_t
// Generate Msg3 grants in PUSCH
uint32_t last_msg3 = msg3_rbs.start();
const int mcs = 0, max_harq_msg3_retx = 4;
int dai = 0;
slot_cfg.idx = msg3_slot.slot_idx();
slot_cfg.idx = msg3_slot.slot_idx();
bwp_pdcch_slot.rar.emplace_back();
sched_nr_interface::sched_rar_t& rar_out = bwp_pdcch_slot.rar.back();
for (const dl_sched_rar_info_t& grant : pending_rars) {
slot_ue& ue = (*slot_ues)[grant.temp_crnti];
// Allocate Msg3
// Generate RAR grant
rar_out.grants.emplace_back();
auto& rar_grant = rar_out.grants.back();
rar_grant.data = grant;
prb_interval msg3_interv{last_msg3, last_msg3 + msg3_nof_prbs};
last_msg3 += msg3_nof_prbs;
ue.h_ul = ue.harq_ent->find_empty_ul_harq();
success = ue.h_ul->new_tx(msg3_slot, msg3_slot, msg3_interv, mcs, 100, max_harq_msg3_retx);
srsran_assert(success, "Failed to allocate Msg3");
last_msg3 += msg3_nof_prbs;
pdcch_ul_t msg3_pdcch; // dummy PDCCH for retx=0
fill_dci_msg3(ue, *bwp_grid.cfg, msg3_pdcch.dci);
msg3_pdcch.dci.time_domain_assigment = dai++;
// Generate RAR grant
rar_out.grants.emplace_back();
auto& rar_grant = rar_out.grants.back();
rar_grant.data = grant;
rar_grant.grant.rba = msg3_pdcch.dci.freq_domain_assigment;
rar_grant.grant.trunc_mcs = msg3_pdcch.dci.mcs;
fill_dci_msg3(ue, *bwp_grid.cfg, rar_grant.msg3_dci);
// Generate PUSCH
bwp_msg3_slot.puschs.emplace_back();
pusch_t& pusch = bwp_msg3_slot.puschs.back();
success = ue.cfg->phy().get_pusch_cfg(slot_cfg, msg3_pdcch.dci, pusch.sch);
success = ue.cfg->phy().get_pusch_cfg(slot_cfg, rar_grant.msg3_dci, pusch.sch);
srsran_assert(success, "Error converting DCI to PUSCH grant");
pusch.sch.grant.tb[0].softbuffer.rx = ue.h_ul->get_softbuffer().get();
ue.h_ul->set_tbs(pusch.sch.grant.tb[0].tbs);

@ -172,12 +172,12 @@ void log_sched_bwp_result(srslog::basic_logger& logger,
const slot_ue& ue = slot_ues[pdcch.dci.ctx.rnti];
fmt::format_to(fmtbuf,
"SCHED: UL {}, cc={}, rnti=0x{:x}, pid={}, f={}, nrtx={}, tbs={}, tti_pusch={}",
ue.h_dl->nof_retx() == 0 ? "tx" : "retx",
ue.h_ul->nof_retx() == 0 ? "tx" : "retx",
res_grid.cfg->cc,
ue.rnti,
pdcch.dci.pid,
srsran_dci_format_nr_string(pdcch.dci.ctx.format),
ue.h_dl->nof_retx(),
ue.h_ul->nof_retx(),
ue.h_ul->tbs(),
ue.pusch_slot);
} else if (pdcch.dci.ctx.rnti_type == srsran_rnti_type_tc) {
@ -187,7 +187,7 @@ void log_sched_bwp_result(srslog::basic_logger& logger,
res_grid.cfg->cc,
ue.rnti,
pdcch.dci.pid,
ue.h_dl->nof_retx(),
ue.h_ul->nof_retx(),
srsran_dci_format_nr_string(pdcch.dci.ctx.format),
ue.pusch_slot);
} else {

@ -149,12 +149,7 @@ slot_ue ue::try_reserve(slot_point pdcch_slot, uint32_t cc)
return slot_ue();
}
slot_ue sfu = carriers[cc]->try_reserve(pdcch_slot, cfg(), dl_pending_bytes, ul_pending_bytes);
if (sfu.empty()) {
return slot_ue();
}
return sfu;
return carriers[cc]->try_reserve(pdcch_slot, cfg(), dl_pending_bytes, ul_pending_bytes);
}
} // namespace sched_nr_impl

@ -156,20 +156,21 @@ void sched_worker_manager::enqueue_cc_event(uint32_t cc, srsran::move_callback<v
/**
* Update UEs state that is non-CC specific (e.g. SRs, buffer status, UE configuration)
* @param slot_tx
* @param update_ca_users to update only UEs with CA enabled or not
* @param locked_context to update only UEs with CA enabled or not
*/
void sched_worker_manager::update_ue_db(slot_point slot_tx, bool update_ca_users)
void sched_worker_manager::update_ue_db(slot_point slot_tx, bool locked_context)
{
// process non-cc specific feedback if pending (e.g. SRs, buffer updates, UE config)
for (ue_event_t& ev : slot_events) {
if (not ue_db.contains(ev.rnti) or ue_db[ev.rnti]->has_ca() == update_ca_users) {
if ((locked_context and not ue_db.contains(ev.rnti)) or
(ue_db.contains(ev.rnti) and ue_db[ev.rnti]->has_ca() == locked_context)) {
ev.callback();
}
}
// prepare UEs internal state for new slot
for (auto& u : ue_db) {
if (u.second->has_ca() == update_ca_users) {
if (u.second->has_ca() == locked_context) {
u.second->new_slot(slot_tx);
}
}

@ -33,7 +33,7 @@ namespace srsenb {
ue_nr::ue_nr(uint16_t rnti_,
uint32_t enb_cc_idx,
sched_interface* sched_,
sched_nr_interface* sched_,
rrc_interface_mac_nr* rrc_,
rlc_interface_mac* rlc_,
phy_interface_stack_nr* phy_,
@ -67,7 +67,7 @@ void ue_nr::set_tti(uint32_t tti)
int ue_nr::process_pdu(srsran::unique_byte_buffer_t pdu)
{
logger.info(pdu->msg, pdu->N_bytes, "Handling MAC PDU (%d B)", pdu->N_bytes);
logger.debug(pdu->msg, pdu->N_bytes, "Handling MAC PDU (%d B)", pdu->N_bytes);
mac_pdu_ul.init_rx(true);
if (mac_pdu_ul.unpack(pdu->msg, pdu->N_bytes) != SRSRAN_SUCCESS) {
@ -76,23 +76,34 @@ int ue_nr::process_pdu(srsran::unique_byte_buffer_t pdu)
if (logger.info.enabled()) {
fmt::memory_buffer str_buffer;
// mac_pdu_ul.to_string(str_buffer);
mac_pdu_ul.to_string(str_buffer);
logger.info("0x%x %s", rnti, srsran::to_c_str(str_buffer));
}
for (uint32_t i = 0; i < mac_pdu_ul.get_num_subpdus(); ++i) {
srsran::mac_sch_subpdu_nr subpdu = mac_pdu_ul.get_subpdu(i);
logger.info("Handling subPDU %d/%d: lcid=%d, sdu_len=%d",
i,
mac_pdu_ul.get_num_subpdus(),
subpdu.get_lcid(),
subpdu.get_sdu_length());
logger.debug("Handling subPDU %d/%d: lcid=%d, sdu_len=%d",
i,
mac_pdu_ul.get_num_subpdus(),
subpdu.get_lcid(),
subpdu.get_sdu_length());
// Handle MAC CEs
switch (subpdu.get_lcid()) {
case srsran::mac_sch_subpdu_nr::nr_lcid_sch_t::CRNTI:
logger.info("CRNTI CE not implemented.");
break;
case srsran::mac_sch_subpdu_nr::nr_lcid_sch_t::CRNTI: {
uint16_t c_rnti = subpdu.get_c_rnti();
if (true /*sched->ue_exists(c_crnti)*/) {
rrc->update_user(rnti, c_rnti);
rnti = c_rnti;
sched->ul_bsr(rnti, 0, 1); // provide UL grant regardless of other BSR content for UE to complete RA
} else {
logger.warning("Updating user C-RNTI: rnti=0x%x already released.", c_rnti);
// Disable scheduling for all bearers. The new rnti will be removed on msg3 timer expiry in the RRC
for (uint32_t lcid = 0; lcid < sched_interface::MAX_LC; ++lcid) {
// sched->bearer_ue_rem(rnti, lcid);
}
}
} break;
case srsran::mac_sch_subpdu_nr::nr_lcid_sch_t::SHORT_BSR:
logger.info("SHORT_BSR CE not implemented.");
break;
@ -144,7 +155,7 @@ int ue_nr::generate_pdu(srsran::byte_buffer_t* pdu, uint32_t grant_size)
if (logger.info.enabled()) {
fmt::memory_buffer str_buffer;
// mac_pdu_dl.to_string(str_buffer);
mac_pdu_dl.to_string(str_buffer);
logger.info("0x%x %s", rnti, srsran::to_c_str(str_buffer));
}
return SRSRAN_SUCCESS;
@ -153,8 +164,8 @@ int ue_nr::generate_pdu(srsran::byte_buffer_t* pdu, uint32_t grant_size)
/******* METRICS interface ***************/
void ue_nr::metrics_read(mac_ue_metrics_t* metrics_)
{
uint32_t ul_buffer = sched->get_ul_buffer(rnti);
uint32_t dl_buffer = sched->get_dl_buffer(rnti);
uint32_t ul_buffer = 0; // sched->get_ul_buffer(rnti);
uint32_t dl_buffer = 0; // sched->get_dl_buffer(rnti);
std::lock_guard<std::mutex> lock(metrics_mutex);
ue_metrics.rnti = rnti;
@ -162,7 +173,7 @@ void ue_nr::metrics_read(mac_ue_metrics_t* metrics_)
ue_metrics.dl_buffer = dl_buffer;
// set PCell sector id
std::array<int, SRSRAN_MAX_CARRIERS> cc_list = sched->get_enb_ue_cc_map(rnti);
std::array<int, SRSRAN_MAX_CARRIERS> cc_list; //= sched->get_enb_ue_cc_map(rnti);
auto it = std::find(cc_list.begin(), cc_list.end(), 0);
ue_metrics.cc_idx = std::distance(cc_list.begin(), it);

@ -29,6 +29,7 @@
#include "srsran/asn1/asn1_utils.h"
#include "srsran/asn1/rrc_utils.h"
#include "srsran/common/bcd_helpers.h"
#include "srsran/common/enb_events.h"
#include "srsran/common/standard_streams.h"
#include "srsran/common/string_helpers.h"
#include "srsran/interfaces/enb_mac_interfaces.h"
@ -41,8 +42,8 @@ using namespace asn1::rrc;
namespace srsenb {
rrc::rrc(stack_interface_rrc* stack_, srsran::task_sched_handle task_sched_) :
logger(srslog::fetch_basic_logger("RRC")), stack(stack_), task_sched(task_sched_), rx_pdu_queue(128)
rrc::rrc(srsran::task_sched_handle task_sched_, enb_bearer_manager& manager_) :
logger(srslog::fetch_basic_logger("RRC")), bearer_manager(manager_), task_sched(task_sched_), rx_pdu_queue(128)
{}
rrc::~rrc() {}
@ -285,6 +286,10 @@ void rrc::upd_user(uint16_t new_rnti, uint16_t old_rnti)
old_it->second->send_connection_reconf();
}
}
// Log event.
event_logger::get().log_connection_resume(
ue_ptr->get_cell_list().get_ue_cc_idx(UE_PCELL_CC_IDX)->cell_common->enb_cc_idx, old_rnti, new_rnti);
}
// Note: this method is not part of UE methods, because the UE context may not exist anymore when reject is sent
@ -664,6 +669,7 @@ void rrc::rem_user(uint16_t rnti)
gtpu->rem_user(rnti);
// Now remove RLC and PDCP
bearer_manager.rem_user(rnti);
rlc->rem_user(rnti);
pdcp->rem_user(rnti);
@ -711,11 +717,12 @@ void rrc::config_mac()
item.n1pucch_an = cfg.sibs[1].sib2().rr_cfg_common.pucch_cfg_common.n1_pucch_an;
item.nrb_cqi = cfg.sibs[1].sib2().rr_cfg_common.pucch_cfg_common.nrb_cqi;
item.nrb_pucch = SRSRAN_MAX(cfg.sr_cfg.nof_prb, cfg.cqi_cfg.nof_prb);
item.nrb_pucch = SRSRAN_MAX(cfg.sr_cfg.nof_prb, item.nrb_cqi);
logger.info("Allocating %d PRBs for PUCCH", item.nrb_pucch);
// Copy base cell configuration
item.cell = cfg.cell;
item.cell = cfg.cell;
item.cell.id = cfg.cell_list[ccidx].pci;
// copy secondary cell list info
sched_cfg[ccidx].scell_list.reserve(cfg.cell_list[ccidx].scell_list.size());

@ -415,12 +415,7 @@ srsran::expected<uint32_t> bearer_cfg_handler::add_gtpu_bearer(uint32_t
void bearer_cfg_handler::rem_gtpu_bearer(uint32_t erab_id)
{
auto it = erabs.find(erab_id);
if (it == erabs.end()) {
logger->warning("Removing erab_id=%d from GTPU", erab_id);
return;
}
gtpu->rem_bearer(rnti, it->second.id);
gtpu->rem_bearer(rnti, erab_id);
}
void bearer_cfg_handler::fill_pending_nas_info(asn1::rrc::rrc_conn_recfg_r8_ies_s* msg)

@ -364,17 +364,13 @@ bool ue_cell_ded_list::alloc_cqi_resources(uint32_t ue_cc_idx, uint32_t period)
return false;
}
const auto& pcell_pucch_cfg = get_ue_cc_idx(UE_PCELL_CC_IDX)->cell_common->sib2.rr_cfg_common.pucch_cfg_common;
uint32_t c = SRSRAN_CP_ISNORM(cfg.cell.cp) ? 3 : 2;
uint32_t delta_pucch_shift = pcell_pucch_cfg.delta_pucch_shift.to_number();
delta_pucch_shift = SRSRAN_MAX(1, delta_pucch_shift);
uint32_t max_users = 12 * c / delta_pucch_shift;
uint32_t max_users = 12;
// Allocate all CQI resources for all carriers now
// Find freq-time resources with least number of users
int i_min = 0, j_min = 0;
uint32_t min_users = std::numeric_limits<uint32_t>::max();
for (uint32_t i = 0; i < cfg.cqi_cfg.nof_prb; i++) {
for (uint32_t i = 0; i < cfg.sibs[1].sib2().rr_cfg_common.pucch_cfg_common.nrb_cqi; i++) {
for (uint32_t j = 0; j < cfg.cqi_cfg.nof_subframes; j++) {
if (pucch_res->cqi_sched.nof_users[i][j] < min_users) {
i_min = i;
@ -419,9 +415,6 @@ bool ue_cell_ded_list::alloc_cqi_resources(uint32_t ue_cc_idx, uint32_t period)
// Compute n_pucch_2
uint16_t n_pucch = i_min * max_users + pucch_res->cqi_sched.nof_users[i_min][j_min];
if (pcell_pucch_cfg.ncs_an) {
n_pucch += pcell_pucch_cfg.ncs_an;
}
cell->cqi_res_present = true;
cell->cqi_res.pmi_idx = pmi_idx;

@ -159,7 +159,7 @@ uint16_t rrc::start_ho_ue_resource_alloc(const asn1::s1ap::ho_request_s&
const enb_cell_common* target_cell = cell_common_list->get_cell_id(rrc_details::eci_to_cellid(target_eci));
if (target_cell == nullptr) {
logger.error("The S1-handover target cell_id=0x%x does not exist", rrc_details::eci_to_cellid(target_eci));
cause.set_radio_network().value = asn1::s1ap::cause_radio_network_opts::ho_target_not_allowed;
cause.set_radio_network().value = asn1::s1ap::cause_radio_network_opts::cell_not_available;
return SRSRAN_INVALID_RNTI;
}
@ -175,7 +175,7 @@ uint16_t rrc::start_ho_ue_resource_alloc(const asn1::s1ap::ho_request_s&
uint16_t rnti = mac->reserve_new_crnti(ue_cfg);
if (rnti == SRSRAN_INVALID_RNTI) {
logger.error("Failed to allocate C-RNTI resources");
cause.set_radio_network().value = asn1::s1ap::cause_radio_network_opts::radio_res_not_available;
cause.set_radio_network().value = asn1::s1ap::cause_radio_network_opts::no_radio_res_available_in_target_cell;
return SRSRAN_INVALID_RNTI;
}
@ -237,7 +237,7 @@ void rrc::ue::rrc_mobility::handle_ue_meas_report(const meas_report_s& msg, srsr
}
if (meas_res.meas_result_neigh_cells.type().value !=
meas_results_s::meas_result_neigh_cells_c_::types::meas_result_list_eutra) {
Info("Skipping MeasReport for non-EUTRA neighbor.");
Error("MeasReports regarding non-EUTRA are not supported!");
return;
}
const meas_id_list& measid_list = rrc_ue->current_ue_cfg.meas_cfg.meas_id_to_add_mod_list;
@ -278,9 +278,12 @@ void rrc::ue::rrc_mobility::handle_ue_meas_report(const meas_report_s& msg, srsr
}
}
asn1::json_writer json_writer;
msg.to_json(json_writer);
event_logger::get().log_measurement_report(
rrc_ue->ue_cell_list.get_ue_cc_idx(UE_PCELL_CC_IDX)->cell_common->enb_cc_idx,
asn1::octstring_to_string(pdu->msg, pdu->N_bytes),
json_writer.to_string(),
rrc_ue->rnti);
}
@ -520,7 +523,7 @@ void rrc::ue::rrc_mobility::fill_mobility_reconf_common(asn1::rrc::dl_dcch_msg_s
mob_info.rr_cfg_common.p_max = rrc_enb->cfg.sib1.p_max;
mob_info.rr_cfg_common.ul_cp_len = target_cell.sib2.rr_cfg_common.ul_cp_len;
mob_info.carrier_freq_present = false; // same frequency handover for now
mob_info.carrier_freq_present = false; // same frequency handover for now
asn1::number_to_enum(mob_info.carrier_bw.dl_bw, target_cell.mib.dl_bw.to_number());
if (target_cell.cell_cfg.dl_earfcn != src_dl_earfcn) {
mob_info.carrier_freq_present = true;
@ -709,12 +712,23 @@ void rrc::ue::rrc_mobility::s1_source_ho_st::handle_ho_cmd(wait_ho_cmd& s, const
}
// Log rrc release event.
asn1::json_writer json_writer;
dl_dcch_msg.to_json(json_writer);
event_logger::get().log_rrc_event(rrc_ue->ue_cell_list.get_ue_cc_idx(UE_PCELL_CC_IDX)->cell_common->enb_cc_idx,
octet_str,
json_writer.to_string(),
static_cast<unsigned>(rrc_event_type::con_reconf),
static_cast<unsigned>(procedure_result_code::none),
rrc_ue->rnti);
// Log HO command.
event_logger::get().log_handover_command(
rrc_ue->ue_cell_list.get_ue_cc_idx(UE_PCELL_CC_IDX)->cell_common->enb_cc_idx,
reconf.crit_exts.c1().rrc_conn_recfg_r8().mob_ctrl_info.target_pci,
reconf.crit_exts.c1().rrc_conn_recfg_r8().mob_ctrl_info.carrier_freq.dl_carrier_freq,
reconf.crit_exts.c1().rrc_conn_recfg_r8().mob_ctrl_info.new_ue_id.to_number(),
rrc_ue->rnti);
/* Start S1AP eNBStatusTransfer Procedure */
asn1::s1ap::cause_c cause = start_enb_status_transfer(*ho_cmd.s1ap_ho_cmd);
if (cause.type().value != asn1::s1ap::cause_c::types_opts::nulltype) {
@ -845,11 +859,11 @@ void rrc::ue::rrc_mobility::handle_ho_requested(idle_st& s, const ho_req_rx_ev&
if (ho_req.transparent_container->erab_info_list_present) {
const auto& lst = ho_req.transparent_container->erab_info_list;
const auto* it = std::find_if(
lst.begin(),
lst.end(),
[&erab](const asn1::s1ap::protocol_ie_single_container_s<asn1::s1ap::erab_info_list_ies_o>& fwd_erab) {
lst.begin(),
lst.end(),
[&erab](const asn1::s1ap::protocol_ie_single_container_s<asn1::s1ap::erab_info_list_ies_o>& fwd_erab) {
return fwd_erab.value.erab_info_list_item().erab_id == erab.second.id;
});
});
if (it == lst.end()) {
continue;
}
@ -1028,7 +1042,7 @@ void rrc::ue::rrc_mobility::handle_status_transfer(s1_target_ho_st& s, const sta
const auto& drbs = rrc_ue->bearer_list.get_established_drbs();
lte_drb drbid = lte_lcid_to_drb(erab_it->second.lcid);
auto drb_it = std::find_if(
drbs.begin(), drbs.end(), [drbid](const drb_to_add_mod_s& drb) { return (lte_drb)drb.drb_id == drbid; });
drbs.begin(), drbs.end(), [drbid](const drb_to_add_mod_s& drb) { return (lte_drb)drb.drb_id == drbid; });
if (drb_it == drbs.end()) {
logger.warning("The DRB id=%d does not exist", drbid);
}
@ -1106,6 +1120,14 @@ void rrc::ue::rrc_mobility::intraenb_ho_st::enter(rrc_mobility* f, const ho_meas
f->trigger(srsran::failure_ev{});
return;
}
// Log HO command.
event_logger::get().log_handover_command(
f->rrc_ue->get_cell_list().get_ue_cc_idx(UE_PCELL_CC_IDX)->cell_common->enb_cc_idx,
reconf_r8.mob_ctrl_info.target_pci,
reconf_r8.mob_ctrl_info.carrier_freq.dl_carrier_freq,
reconf_r8.mob_ctrl_info.new_ue_id.to_number(),
f->rrc_ue->rnti);
}
void rrc::ue::rrc_mobility::handle_crnti_ce(intraenb_ho_st& s, const user_crnti_upd_ev& ev)

@ -231,7 +231,7 @@ void rrc_nr::config_mac()
}
// PUCCH width
cell_cfg.nrb_pucch = SRSRAN_MAX(cfg.sr_cfg.nof_prb, cfg.cqi_cfg.nof_prb);
cell_cfg.nrb_pucch = SRSRAN_MAX(cfg.sr_cfg.nof_prb, /* TODO: where is n_rb2 in NR? */ 0);
logger.info("Allocating %d PRBs for PUCCH", cell_cfg.nrb_pucch);
// Copy Cell configuration
@ -501,7 +501,7 @@ void rrc_nr::ue::send_dl_ccch(dl_ccch_msg_s* dl_ccch_msg)
// Helper for the RRC Reconfiguration sender to pack hard-coded config
int rrc_nr::ue::pack_secondary_cell_group_config(asn1::dyn_octstring& packed_secondary_cell_config)
{
cell_group_cfg_s cell_group_cfg_pack;
auto& cell_group_cfg_pack = cell_group_cfg;
// RLC for DRB1 (with fixed LCID)
cell_group_cfg_pack.rlc_bearer_to_add_mod_list_present = true;
@ -854,7 +854,7 @@ int rrc_nr::ue::pack_secondary_cell_group_config(asn1::dyn_octstring& packed_sec
// Reconfig with Sync
cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync_present = true;
cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.new_ue_id = 0x4602; // first RNTI assigned to new UE
cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.new_ue_id = rnti;
cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.smtc.release();
cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.t304 = recfg_with_sync_s::t304_opts::ms1000;
@ -994,7 +994,7 @@ int rrc_nr::ue::pack_secondary_cell_group_config(asn1::dyn_octstring& packed_sec
asn1::rrc_nr::rach_cfg_common_s::ra_contention_resolution_timer_opts::sf64;
rach_cfg_common_pack.setup().prach_root_seq_idx.set(
asn1::rrc_nr::rach_cfg_common_s::prach_root_seq_idx_c_::types_opts::l839);
rach_cfg_common_pack.setup().prach_root_seq_idx.set_l839() = 1;
rach_cfg_common_pack.setup().prach_root_seq_idx.set_l839() = 0; // matches value in phy_cfg_nr_default_t()
rach_cfg_common_pack.setup().restricted_set_cfg =
asn1::rrc_nr::rach_cfg_common_s::restricted_set_cfg_opts::unrestricted_set;
@ -1087,38 +1087,19 @@ int rrc_nr::ue::pack_rrc_reconfiguraiton(asn1::dyn_octstring& packed_rrc_reconfi
// Packs a hard-coded NR radio bearer config with fixed params for RLC/PDCP (for now)
int rrc_nr::ue::pack_nr_radio_bearer_config(asn1::dyn_octstring& packed_nr_bearer_config)
{
radio_bearer_cfg_s radio_bearer_cfg;
radio_bearer_cfg.drb_to_add_mod_list_present = true;
radio_bearer_cfg.drb_to_add_mod_list.resize(1);
// configure fixed DRB1
auto& drb_item = radio_bearer_cfg.drb_to_add_mod_list[0];
drb_item.drb_id = 1;
drb_item.cn_assoc_present = true;
drb_item.cn_assoc.set_eps_bearer_id() = 5;
drb_item.pdcp_cfg_present = true;
drb_item.pdcp_cfg.ciphering_disabled_present = true;
drb_item.pdcp_cfg.drb_present = true;
drb_item.pdcp_cfg.drb.pdcp_sn_size_dl_present = true;
drb_item.pdcp_cfg.drb.pdcp_sn_size_dl = asn1::rrc_nr::pdcp_cfg_s::drb_s_::pdcp_sn_size_dl_opts::len18bits;
drb_item.pdcp_cfg.drb.pdcp_sn_size_ul_present = true;
drb_item.pdcp_cfg.drb.pdcp_sn_size_ul = asn1::rrc_nr::pdcp_cfg_s::drb_s_::pdcp_sn_size_ul_opts::len18bits;
drb_item.pdcp_cfg.drb.discard_timer_present = true;
drb_item.pdcp_cfg.drb.discard_timer = asn1::rrc_nr::pdcp_cfg_s::drb_s_::discard_timer_opts::ms100;
drb_item.pdcp_cfg.drb.hdr_compress.set_not_used();
drb_item.pdcp_cfg.t_reordering_present = true;
drb_item.pdcp_cfg.t_reordering = asn1::rrc_nr::pdcp_cfg_s::t_reordering_opts::ms0;
radio_bearer_cfg.security_cfg_present = true;
radio_bearer_cfg.security_cfg.key_to_use_present = true;
radio_bearer_cfg.security_cfg.key_to_use = asn1::rrc_nr::security_cfg_s::key_to_use_opts::secondary;
radio_bearer_cfg.security_cfg.security_algorithm_cfg_present = true;
radio_bearer_cfg.security_cfg.security_algorithm_cfg.ciphering_algorithm = ciphering_algorithm_opts::nea2;
// set security config
auto& radio_bearer_cfg_pack = radio_bearer_cfg;
radio_bearer_cfg_pack.security_cfg_present = true;
auto& sec_cfg = radio_bearer_cfg_pack.security_cfg;
sec_cfg.key_to_use_present = true;
sec_cfg.key_to_use = asn1::rrc_nr::security_cfg_s::key_to_use_opts::secondary;
sec_cfg.security_algorithm_cfg_present = true;
sec_cfg.security_algorithm_cfg.ciphering_algorithm = ciphering_algorithm_opts::nea2;
// pack it
packed_nr_bearer_config.resize(128);
asn1::bit_ref bref_pack(packed_nr_bearer_config.data(), packed_nr_bearer_config.size());
if (radio_bearer_cfg.pack(bref_pack) != asn1::SRSASN_SUCCESS) {
if (radio_bearer_cfg_pack.pack(bref_pack) != asn1::SRSASN_SUCCESS) {
parent->logger.error("Failed to pack NR radio bearer config");
return SRSRAN_ERROR;
}
@ -1131,6 +1112,13 @@ int rrc_nr::ue::pack_nr_radio_bearer_config(asn1::dyn_octstring& packed_nr_beare
int rrc_nr::ue::handle_sgnb_addition_request(uint16_t eutra_rnti)
{
// Add DRB1 to RLC and PDCP
if (add_drb() != SRSRAN_SUCCESS) {
parent->logger.error("Failed to configure DRB");
parent->rrc_eutra->sgnb_addition_reject(eutra_rnti);
return SRSRAN_ERROR;
}
// provide hard-coded NR configs
asn1::dyn_octstring nr_secondary_cell_group_cfg;
if (pack_rrc_reconfiguraiton(nr_secondary_cell_group_cfg) == SRSRAN_ERROR) {
@ -1152,4 +1140,84 @@ int rrc_nr::ue::handle_sgnb_addition_request(uint16_t eutra_rnti)
return SRSRAN_SUCCESS;
}
/**
* @brief Set DRB configuration
*
* The function sets and configures all relavant fields for the DRB configuration (MAC, RLC, PDCP) in the
* cellGroupConfig and also adds the bearer to the local RLC and PDCP entities.
*
* @return int SRSRAN_SUCCESS on success
*/
int rrc_nr::ue::add_drb()
{
// RLC for DRB1 (with fixed LCID) inside cell_group_cfg
auto& cell_group_cfg_pack = cell_group_cfg;
cell_group_cfg_pack.rlc_bearer_to_add_mod_list_present = true;
cell_group_cfg_pack.rlc_bearer_to_add_mod_list.resize(1);
auto& rlc = cell_group_cfg_pack.rlc_bearer_to_add_mod_list[0];
rlc.lc_ch_id = drb1_lcid;
rlc.served_radio_bearer_present = true;
rlc.served_radio_bearer.set_drb_id();
rlc.served_radio_bearer.drb_id() = 1;
rlc.rlc_cfg_present = true;
rlc.rlc_cfg.set_um_bi_dir();
rlc.rlc_cfg.um_bi_dir().ul_um_rlc.sn_field_len_present = true;
rlc.rlc_cfg.um_bi_dir().ul_um_rlc.sn_field_len = sn_field_len_um_opts::size12;
rlc.rlc_cfg.um_bi_dir().dl_um_rlc.sn_field_len_present = true;
rlc.rlc_cfg.um_bi_dir().dl_um_rlc.sn_field_len = sn_field_len_um_opts::size12;
rlc.rlc_cfg.um_bi_dir().dl_um_rlc.t_reassembly = t_reassembly_opts::ms50;
// add RLC bearer
srsran::rlc_config_t rlc_cfg;
if (srsran::make_rlc_config_t(cell_group_cfg.rlc_bearer_to_add_mod_list[0].rlc_cfg, &rlc_cfg) != SRSRAN_SUCCESS) {
parent->logger.error("Failed to build RLC config");
return SRSRAN_ERROR;
}
parent->rlc->add_bearer(rnti, drb1_lcid, rlc_cfg);
// MAC logical channel config
rlc.mac_lc_ch_cfg_present = true;
rlc.mac_lc_ch_cfg.ul_specific_params_present = true;
rlc.mac_lc_ch_cfg.ul_specific_params.prio = 11;
rlc.mac_lc_ch_cfg.ul_specific_params.prioritised_bit_rate =
asn1::rrc_nr::lc_ch_cfg_s::ul_specific_params_s_::prioritised_bit_rate_opts::kbps0;
rlc.mac_lc_ch_cfg.ul_specific_params.bucket_size_dur =
asn1::rrc_nr::lc_ch_cfg_s::ul_specific_params_s_::bucket_size_dur_opts::ms100;
rlc.mac_lc_ch_cfg.ul_specific_params.lc_ch_group_present = true;
rlc.mac_lc_ch_cfg.ul_specific_params.lc_ch_group = 6;
rlc.mac_lc_ch_cfg.ul_specific_params.sched_request_id_present = true;
rlc.mac_lc_ch_cfg.ul_specific_params.sched_request_id = 0;
// TODO: add LC config to MAC
// PDCP config goes into radio_bearer_cfg
auto& radio_bearer_cfg_pack = radio_bearer_cfg;
radio_bearer_cfg_pack.drb_to_add_mod_list_present = true;
radio_bearer_cfg_pack.drb_to_add_mod_list.resize(1);
// configure fixed DRB1
auto& drb_item = radio_bearer_cfg_pack.drb_to_add_mod_list[0];
drb_item.drb_id = 1;
drb_item.cn_assoc_present = true;
drb_item.cn_assoc.set_eps_bearer_id() = 5;
drb_item.pdcp_cfg_present = true;
drb_item.pdcp_cfg.ciphering_disabled_present = true;
drb_item.pdcp_cfg.drb_present = true;
drb_item.pdcp_cfg.drb.pdcp_sn_size_dl_present = true;
drb_item.pdcp_cfg.drb.pdcp_sn_size_dl = asn1::rrc_nr::pdcp_cfg_s::drb_s_::pdcp_sn_size_dl_opts::len18bits;
drb_item.pdcp_cfg.drb.pdcp_sn_size_ul_present = true;
drb_item.pdcp_cfg.drb.pdcp_sn_size_ul = asn1::rrc_nr::pdcp_cfg_s::drb_s_::pdcp_sn_size_ul_opts::len18bits;
drb_item.pdcp_cfg.drb.discard_timer_present = true;
drb_item.pdcp_cfg.drb.discard_timer = asn1::rrc_nr::pdcp_cfg_s::drb_s_::discard_timer_opts::ms100;
drb_item.pdcp_cfg.drb.hdr_compress.set_not_used();
drb_item.pdcp_cfg.t_reordering_present = true;
drb_item.pdcp_cfg.t_reordering = asn1::rrc_nr::pdcp_cfg_s::t_reordering_opts::ms0;
// Add DRB1 to PDCP
srsran::pdcp_config_t pdcp_cnfg = srsran::make_drb_pdcp_config_t(drb_item.drb_id, false, drb_item.pdcp_cfg);
parent->pdcp->add_bearer(rnti, rlc.lc_ch_id, pdcp_cnfg);
return SRSRAN_SUCCESS;
}
} // namespace srsenb

@ -237,11 +237,16 @@ void rrc::ue::activity_timer_expired(const activity_timeout_type_t type)
void rrc::ue::rlf_timer_expired(uint32_t timeout_id)
{
activity_timer.stop();
std::string event_type = "Unknown";
if (timeout_id == phy_dl_rlf_timer.id()) {
event_type = "dl_rlf";
parent->logger.info("DL RLF timer for rnti=0x%x expired after %d ms", rnti, phy_dl_rlf_timer.time_elapsed());
} else if (timeout_id == phy_ul_rlf_timer.id()) {
event_type = "ul_rlf";
parent->logger.info("UL RLF timer for rnti=0x%x expired after %d ms", rnti, phy_ul_rlf_timer.time_elapsed());
} else if (timeout_id == rlc_rlf_timer.id()) {
event_type = "rlc_rlf";
parent->logger.info("RLC RLF timer for rnti=0x%x expired after %d ms", rnti, rlc_rlf_timer.time_elapsed());
}
@ -252,6 +257,10 @@ void rrc::ue::rlf_timer_expired(uint32_t timeout_id)
parent->s1ap->user_release(rnti, asn1::s1ap::cause_radio_network_opts::radio_conn_with_ue_lost);
con_release_result = procedure_result_code::radio_conn_with_ue_lost;
// Log event.
event_logger::get().log_rlf_detected(
ue_cell_list.get_ue_cc_idx(UE_PCELL_CC_IDX)->cell_common->enb_cc_idx, event_type, rnti);
}
void rrc::ue::max_rlc_retx_reached()
@ -421,8 +430,11 @@ std::string rrc::ue::to_string(const activity_timeout_type_t& type)
void rrc::ue::handle_rrc_con_req(rrc_conn_request_s* msg)
{
// Log event.
asn1::json_writer json_writer;
msg->to_json(json_writer);
event_logger::get().log_rrc_event(ue_cell_list.get_ue_cc_idx(UE_PCELL_CC_IDX)->cell_common->enb_cc_idx,
asn1::octstring_to_string(last_ul_msg->msg, last_ul_msg->N_bytes),
json_writer.to_string(),
static_cast<unsigned>(rrc_event_type::con_request),
static_cast<unsigned>(procedure_result_code::none),
rnti);
@ -486,8 +498,11 @@ void rrc::ue::send_connection_setup()
send_dl_ccch(&dl_ccch_msg, &octet_str);
// Log event.
asn1::json_writer json_writer;
dl_ccch_msg.to_json(json_writer);
event_logger::get().log_rrc_event(ue_cell_list.get_ue_cc_idx(UE_PCELL_CC_IDX)->cell_common->enb_cc_idx,
octet_str,
json_writer.to_string(),
static_cast<unsigned>(rrc_event_type::con_setup),
static_cast<unsigned>(procedure_result_code::none),
rnti);
@ -498,8 +513,11 @@ void rrc::ue::send_connection_setup()
void rrc::ue::handle_rrc_con_setup_complete(rrc_conn_setup_complete_s* msg, srsran::unique_byte_buffer_t pdu)
{
// Log event.
asn1::json_writer json_writer;
msg->to_json(json_writer);
event_logger::get().log_rrc_event(ue_cell_list.get_ue_cc_idx(UE_PCELL_CC_IDX)->cell_common->enb_cc_idx,
asn1::octstring_to_string(last_ul_msg->msg, last_ul_msg->N_bytes),
json_writer.to_string(),
static_cast<unsigned>(rrc_event_type::con_setup_complete),
static_cast<unsigned>(procedure_result_code::none),
rnti);
@ -551,8 +569,11 @@ void rrc::ue::send_connection_reject(procedure_result_code cause)
send_dl_ccch(&dl_ccch_msg, &octet_str);
// Log event.
asn1::json_writer json_writer;
dl_ccch_msg.to_json(json_writer);
event_logger::get().log_rrc_event(ue_cell_list.get_ue_cc_idx(UE_PCELL_CC_IDX)->cell_common->enb_cc_idx,
octet_str,
json_writer.to_string(),
static_cast<unsigned>(rrc_event_type::con_reject),
static_cast<unsigned>(cause),
rnti);
@ -564,8 +585,11 @@ void rrc::ue::send_connection_reject(procedure_result_code cause)
void rrc::ue::handle_rrc_con_reest_req(rrc_conn_reest_request_s* msg)
{
// Log event.
asn1::json_writer json_writer;
msg->to_json(json_writer);
event_logger::get().log_rrc_event(ue_cell_list.get_ue_cc_idx(UE_PCELL_CC_IDX)->cell_common->enb_cc_idx,
asn1::octstring_to_string(last_ul_msg->msg, last_ul_msg->N_bytes),
json_writer.to_string(),
static_cast<unsigned>(rrc_event_type::con_reest_req),
static_cast<unsigned>(procedure_result_code::none),
rnti);
@ -698,8 +722,11 @@ void rrc::ue::send_connection_reest(uint8_t ncc)
apply_rr_cfg_ded_diff(current_ue_cfg.rr_cfg, rr_cfg);
// Log event.
asn1::json_writer json_writer;
dl_ccch_msg.to_json(json_writer);
event_logger::get().log_rrc_event(ue_cell_list.get_ue_cc_idx(UE_PCELL_CC_IDX)->cell_common->enb_cc_idx,
octet_str,
json_writer.to_string(),
static_cast<unsigned>(rrc_event_type::con_reest),
static_cast<unsigned>(procedure_result_code::none),
rnti);
@ -708,8 +735,11 @@ void rrc::ue::send_connection_reest(uint8_t ncc)
void rrc::ue::handle_rrc_con_reest_complete(rrc_conn_reest_complete_s* msg, srsran::unique_byte_buffer_t pdu)
{
// Log event.
asn1::json_writer json_writer;
msg->to_json(json_writer);
event_logger::get().log_rrc_event(ue_cell_list.get_ue_cc_idx(UE_PCELL_CC_IDX)->cell_common->enb_cc_idx,
asn1::octstring_to_string(last_ul_msg->msg, last_ul_msg->N_bytes),
json_writer.to_string(),
static_cast<unsigned>(rrc_event_type::con_reest_complete),
static_cast<unsigned>(procedure_result_code::none),
rnti);
@ -749,8 +779,11 @@ void rrc::ue::send_connection_reest_rej(procedure_result_code cause)
send_dl_ccch(&dl_ccch_msg, &octet_str);
// Log event.
asn1::json_writer json_writer;
dl_ccch_msg.to_json(json_writer);
event_logger::get().log_rrc_event(ue_cell_list.get_ue_cc_idx(UE_PCELL_CC_IDX)->cell_common->enb_cc_idx,
octet_str,
json_writer.to_string(),
static_cast<unsigned>(rrc_event_type::con_reest_reject),
static_cast<unsigned>(cause),
rnti);
@ -825,8 +858,11 @@ void rrc::ue::send_connection_reconf(srsran::unique_byte_buffer_t pdu,
send_dl_dcch(&dl_dcch_msg, std::move(pdu), &octet_str);
// Log event.
asn1::json_writer json_writer;
dl_dcch_msg.to_json(json_writer);
event_logger::get().log_rrc_event(ue_cell_list.get_ue_cc_idx(UE_PCELL_CC_IDX)->cell_common->enb_cc_idx,
octet_str,
json_writer.to_string(),
static_cast<unsigned>(rrc_event_type::con_reconf),
static_cast<unsigned>(procedure_result_code::none),
rnti);
@ -846,8 +882,11 @@ void rrc::ue::handle_rrc_reconf_complete(rrc_conn_recfg_complete_s* msg, srsran:
}
// Log event.
asn1::json_writer json_writer;
msg->to_json(json_writer);
event_logger::get().log_rrc_event(ue_cell_list.get_ue_cc_idx(UE_PCELL_CC_IDX)->cell_common->enb_cc_idx,
asn1::octstring_to_string(last_ul_msg->msg, last_ul_msg->N_bytes),
json_writer.to_string(),
static_cast<unsigned>(rrc_event_type::con_reconf_complete),
static_cast<unsigned>(procedure_result_code::none),
rnti);
@ -886,8 +925,12 @@ void rrc::ue::handle_ue_info_resp(const asn1::rrc::ue_info_resp_r9_s& msg, srsra
{
auto& resp_r9 = msg.crit_exts.c1().ue_info_resp_r9();
if (resp_r9.rlf_report_r9_present) {
std::string msg_str = asn1::octstring_to_string(pdu->msg, pdu->N_bytes);
event_logger::get().log_rlf(ue_cell_list.get_ue_cc_idx(UE_PCELL_CC_IDX)->cell_common->enb_cc_idx, msg_str, rnti);
asn1::json_writer json_writer;
msg.to_json(json_writer);
event_logger::get().log_rlf_report(ue_cell_list.get_ue_cc_idx(UE_PCELL_CC_IDX)->cell_common->enb_cc_idx,
asn1::octstring_to_string(pdu->msg, pdu->N_bytes),
json_writer.to_string(),
rnti);
}
if (resp_r9.rach_report_r9_present) {
// TODO: Handle RACH-Report
@ -1028,8 +1071,11 @@ void rrc::ue::send_connection_release()
send_dl_dcch(&dl_dcch_msg, nullptr, &octet_str);
// Log rrc release event.
asn1::json_writer json_writer;
dl_dcch_msg.to_json(json_writer);
event_logger::get().log_rrc_event(ue_cell_list.get_ue_cc_idx(UE_PCELL_CC_IDX)->cell_common->enb_cc_idx,
octet_str,
json_writer.to_string(),
static_cast<unsigned>(rrc_event_type::con_release),
static_cast<unsigned>(con_release_result),
rnti);
@ -1452,8 +1498,8 @@ void rrc::ue::apply_rlc_rb_updates(const rr_cfg_ded_s& pending_rr_cfg)
parent->rlc->del_bearer(rnti, drb_to_lcid((lte_drb)drb_id));
// deregister EPS bearer
uint8_t eps_bearer_id = 0; // FIXME: lookup EPS bearer ID for drb_id
parent->stack->remove_eps_bearer(rnti, eps_bearer_id);
uint8_t eps_bearer_id = parent->bearer_manager.get_lcid_bearer(rnti, drb_to_lcid((lte_drb)drb_id)).eps_bearer_id;
parent->bearer_manager.remove_eps_bearer(rnti, eps_bearer_id);
}
}
for (const drb_to_add_mod_s& drb : pending_rr_cfg.drb_to_add_mod_list) {
@ -1469,7 +1515,7 @@ void rrc::ue::apply_rlc_rb_updates(const rr_cfg_ded_s& pending_rr_cfg)
parent->rlc->add_bearer(rnti, drb.lc_ch_id, rlc_cfg);
// register EPS bearer over LTE PDCP
parent->stack->add_eps_bearer(rnti, drb.eps_bearer_id, srsran::srsran_rat_t::lte, drb.lc_ch_id);
parent->bearer_manager.add_eps_bearer(rnti, drb.eps_bearer_id, srsran::srsran_rat_t::lte, drb.lc_ch_id);
}
}

@ -33,6 +33,7 @@ public:
int read_pdu_bcch_bch(const uint32_t tti, srsran::unique_byte_buffer_t& buffer) { return SRSRAN_SUCCESS; }
int read_pdu_bcch_dlsch(uint32_t sib_index, srsran::unique_byte_buffer_t& buffer) { return SRSRAN_SUCCESS; }
int add_user(uint16_t rnti) { return SRSRAN_SUCCESS; }
int update_user(uint16_t new_rnti, uint16_t old_rnti) { return SRSRAN_SUCCESS; }
};
class rlc_nr_dummy : public rlc_interface_mac_nr

@ -42,8 +42,8 @@ int test_erab_setup(srsran::log_sink_spy& spy, bool qci_exists)
logger.set_hex_dump_max_size(1024);
logger.set_level(srslog::basic_levels::info);
test_dummies::enb_stack_dummy stack;
srsenb::rrc rrc{&stack, &task_sched};
enb_bearer_manager bearers;
srsenb::rrc rrc{&task_sched, bearers};
mac_dummy mac;
rlc_dummy rlc;
test_dummies::pdcp_mobility_dummy pdcp;

@ -66,7 +66,7 @@ const char* to_string(test_event event)
struct mobility_tester {
explicit mobility_tester(const test_event& args_) :
args(args_), logger(srslog::fetch_basic_logger("RRC")), rrc(&stack, &task_sched)
args(args_), logger(srslog::fetch_basic_logger("RRC")), rrc(&task_sched, bearers)
{
logger.set_level(srslog::basic_levels::info);
logger.set_hex_dump_max_size(1024);
@ -102,7 +102,7 @@ struct mobility_tester {
test_dummies::pdcp_mobility_dummy pdcp;
test_dummies::phy_mobility_dummy phy;
test_dummies::s1ap_mobility_dummy s1ap;
test_dummies::enb_stack_dummy stack;
enb_bearer_manager bearers;
gtpu_dummy gtpu;
void tic()
@ -314,9 +314,9 @@ int test_s1ap_tenb_mobility(test_event test_params)
asn1::s1ap::cause_c cause;
int rnti = tester.rrc.start_ho_ue_resource_alloc(ho_req, container, cause);
if (test_params == test_event::wrong_target_cell) {
TESTASSERT(rnti == SRSRAN_INVALID_RNTI);
TESTASSERT_EQ(SRSRAN_INVALID_RNTI, rnti);
TESTASSERT(cause.type().value == asn1::s1ap::cause_c::types_opts::radio_network);
TESTASSERT(cause.radio_network().value == asn1::s1ap::cause_radio_network_opts::ho_target_not_allowed);
TESTASSERT_EQ(asn1::s1ap::cause_radio_network_opts::cell_not_available, cause.radio_network().value);
TESTASSERT(tester.rrc.get_nof_users() == 0);
return SRSRAN_SUCCESS;
}

@ -210,13 +210,6 @@ public:
phy_rrc_cfg_list_t last_cfg;
};
class enb_stack_dummy : public stack_interface_rrc
{
void add_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid) {}
void remove_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id) {}
void reset_eps_bearers(uint16_t rnti){};
};
} // namespace test_dummies
namespace test_helpers {

@ -311,8 +311,12 @@ void hss::gen_auth_info_answer_milenage(hss_ue_ctx_t* ue_ctx,
m_logger.debug(sqn, 6, "User SQN : ");
m_logger.debug(mac, 8, "User MAC : ");
uint8_t ak_xor_sqn[6];
for (int i = 0; i < 6; i++) {
ak_xor_sqn[i] = sqn[i] ^ ak[i];
}
// Generate K_asme
srsran::security_generate_k_asme(ck, ik, ak, sqn, mcc, mnc, k_asme);
srsran::security_generate_k_asme(ck, ik, ak_xor_sqn, mcc, mnc, k_asme);
m_logger.debug("User MCC : %x MNC : %x ", mcc, mnc);
m_logger.debug(k_asme, 32, "User k_asme : ");
@ -405,8 +409,12 @@ void hss::gen_auth_info_answer_xor(hss_ue_ctx_t* ue_ctx, uint8_t* k_asme, uint8_
autn[8 + i] = mac[i];
}
uint8_t ak_xor_sqn[6];
for (int i = 0; i < 6; i++) {
ak_xor_sqn[i] = sqn[i] ^ ak[i];
}
// Generate K_asme
srsran::security_generate_k_asme(ck, ik, ak, sqn, mcc, mnc, k_asme);
srsran::security_generate_k_asme(ck, ik, ak_xor_sqn, mcc, mnc, k_asme);
m_logger.debug("User MCC : %x MNC : %x ", mcc, mnc);
m_logger.debug(k_asme, 32, "User k_asme : ");

@ -240,7 +240,7 @@ private:
srsue::nas nas;
std::unique_ptr<usim_base> usim;
bearer_manager bearers; // helper to manage mapping between EPS and radio bearers
ue_bearer_manager bearers; // helper to manage mapping between EPS and radio bearers
// Metrics helper
uint32_t ul_dropped_sdus = 0;

@ -53,7 +53,14 @@ public:
uint8_t* res,
int* res_len,
uint8_t* k_asme);
// NAS interface
auth_result_t generate_authentication_response_5g(uint8_t* rand,
uint8_t* autn_enb,
const char* serving_network_name,
uint8_t* abba,
uint32_t abba_len,
uint8_t* res_star,
uint8_t* k_amf);
// Helpers
virtual std::string get_mnc_str(const uint8_t* imsi_vec, std::string mcc_str) final;

@ -45,21 +45,18 @@ public:
int* res_len,
uint8_t* k_asme);
auth_result_t generate_authentication_response_5g(uint8_t* rand,
uint8_t* autn_enb,
const char* serving_network_name,
uint8_t* abba,
uint32_t abba_len,
uint8_t* res_star,
uint8_t* k_amf);
private:
auth_result_t gen_auth_res_milenage(uint8_t* rand,
uint8_t* autn_enb,
uint16_t mcc,
uint16_t mnc,
uint8_t* res,
int* res_len,
uint8_t* k_asme);
auth_result_t gen_auth_res_xor(uint8_t* rand,
uint8_t* autn_enb,
uint16_t mcc,
uint16_t mnc,
uint8_t* res,
int* res_len,
uint8_t* k_asme);
auth_result_t
gen_auth_res_milenage(uint8_t* rand, uint8_t* autn_enb, uint8_t* res, int* res_len, uint8_t* ak_xor_sqn);
auth_result_t gen_auth_res_xor(uint8_t* rand, uint8_t* autn_enb, uint8_t* res, int* res_len, uint8_t* ak_xor_sqn);
// Helpers
virtual std::string get_mnc_str(const uint8_t* imsi_vec, std::string mcc_str) final;

@ -109,6 +109,20 @@ public:
bool generate_nr_context(uint16_t sk_counter, srsran::as_security_config_t* sec_cfg) final;
bool update_nr_context(srsran::as_security_config_t* sec_cfg) final;
// 5G NAS interface
virtual auth_result_t generate_authentication_response_5g(uint8_t* rand,
uint8_t* autn_enb,
const char* serving_network_name,
uint8_t* abba,
uint32_t abba_len,
uint8_t* res_star,
uint8_t* k_amf) = 0;
bool generate_nas_keys_5g(uint8_t* k_amf,
uint8_t* k_nas_enc,
uint8_t* k_nas_int,
srsran::CIPHERING_ALGORITHM_ID_ENUM cipher_algo,
srsran::INTEGRITY_ALGORITHM_ID_ENUM integ_algo);
// Helpers
std::string get_mcc_str(const uint8_t* imsi_vec);
virtual std::string get_mnc_str(const uint8_t* imsi_vec, std::string mcc_str) = 0;

@ -124,14 +124,16 @@ int worker_pool::set_ul_grant(std::array<uint8_t, SRSRAN_RAR_UL_GRANT_NBITS> pac
srsran_dci_ul_nr_t dci_ul = {};
if (srsran_dci_nr_ul_unpack(NULL, &dci_msg, &dci_ul) < SRSRAN_SUCCESS) {
logger.error("Couldn't unpack UL grant");
return SRSRAN_ERROR;
}
if (logger.info.enabled()) {
std::array<char, 512> str;
srsran_dci_ul_nr_to_str(NULL, &dci_ul, str.data(), str.size());
srsran_dci_nr_t dci = {};
srsran_dci_ul_nr_to_str(&dci, &dci_ul, str.data(), str.size());
logger.set_context(phy_state.rar_grant_slot.idx);
logger.info("Setting RAR Grant %s", str.data());
logger.info("Setting RAR Grant: %s", str.data());
}
phy_state.set_ul_pending_grant(phy_state.rar_grant_slot, dci_ul);

@ -21,6 +21,7 @@
#include "srsue/hdr/stack/mac_nr/demux_nr.h"
#include "srsran/common/buffer_pool.h"
#include "srsran/common/string_helpers.h"
#include "srsran/interfaces/ue_rlc_interfaces.h"
namespace srsue {
@ -52,21 +53,27 @@ void demux_nr::process_pdus()
/// Handling of DLSCH PDUs only
void demux_nr::handle_pdu(srsran::unique_byte_buffer_t pdu)
{
logger.info(pdu->msg, pdu->N_bytes, "Handling MAC PDU (%d B)", pdu->N_bytes);
logger.debug(pdu->msg, pdu->N_bytes, "Handling MAC PDU (%d B)", pdu->N_bytes);
rx_pdu.init_rx();
if (rx_pdu.unpack(pdu->msg, pdu->N_bytes) != SRSRAN_SUCCESS) {
return;
}
if (logger.info.enabled()) {
fmt::memory_buffer str_buffer;
rx_pdu.to_string(str_buffer);
logger.info("%s", srsran::to_c_str(str_buffer));
}
for (uint32_t i = 0; i < rx_pdu.get_num_subpdus(); ++i) {
srsran::mac_sch_subpdu_nr subpdu = rx_pdu.get_subpdu(i);
logger.info("Handling subPDU %d/%d: rnti=0x%x lcid=%d, sdu_len=%d",
i + 1,
rx_pdu.get_num_subpdus(),
subpdu.get_c_rnti(),
subpdu.get_lcid(),
subpdu.get_sdu_length());
logger.debug("Handling subPDU %d/%d: rnti=0x%x lcid=%d, sdu_len=%d",
i + 1,
rx_pdu.get_num_subpdus(),
subpdu.get_c_rnti(),
subpdu.get_lcid(),
subpdu.get_sdu_length());
// Handle Timing Advance CE
switch (subpdu.get_lcid()) {

@ -22,6 +22,7 @@
#include "srsue/hdr/stack/mac_nr/mux_nr.h"
#include "srsran/common/buffer_pool.h"
#include "srsran/interfaces/ue_rlc_interfaces.h"
namespace srsue {
mux_nr::mux_nr(mac_interface_mux_nr& mac_, srslog::basic_logger& logger_) : mac(mac_), logger(logger_) {}
@ -136,7 +137,13 @@ srsran::unique_byte_buffer_t mux_nr::get_pdu(uint32_t max_pdu_len)
// Pack PDU
tx_pdu.pack();
logger.debug(phy_tx_pdu->msg, phy_tx_pdu->N_bytes, "Generated MAC PDU (%d B)", phy_tx_pdu->N_bytes);
if (logger.info.enabled()) {
// log pretty printed PDU
fmt::memory_buffer buff;
tx_pdu.to_string(buff);
logger.info("%s", srsran::to_c_str(buff));
logger.debug(phy_tx_pdu->msg, phy_tx_pdu->N_bytes, "Generated MAC PDU (%d B)", phy_tx_pdu->N_bytes);
}
return phy_tx_pdu;
}

@ -205,7 +205,10 @@ void proc_ra_nr::ra_response_reception(const mac_interface_phy_nr::tb_action_dl_
logger.warning("Error unpacking RAR PDU");
return;
}
logger.info("%s", pdu.to_string());
fmt::memory_buffer buff;
pdu.to_string(buff);
logger.info("%s", srsran::to_c_str(buff));
for (auto& subpdu : pdu.get_subpdus()) {
if (subpdu.has_rapid() && subpdu.get_rapid() == preamble_index) {

@ -717,5 +717,7 @@ int main()
TESTASSERT(mac_nr_ul_periodic_bsr_test() == SRSRAN_SUCCESS);
TESTASSERT(mac_nr_dl_retx_test() == SRSRAN_SUCCESS);
srslog::flush();
return SRSRAN_SUCCESS;
}

@ -110,9 +110,9 @@ class mac_test : public srsue::mac_interface_rrc
{
public:
srsran::task_sched_handle task_sched;
rrc* rrc_ptr;
srsue::rrc* rrc_ptr;
mac_test(rrc* rrc_, srsran::task_sched_handle task_sched_) : rrc_ptr(rrc_), task_sched(task_sched_) {}
mac_test(srsue::rrc* rrc_, srsran::task_sched_handle task_sched_) : rrc_ptr(rrc_), task_sched(task_sched_) {}
int get_dlsch_with_sib1(bcch_dl_sch_msg_s& dlsch_msg)
{

@ -1089,6 +1089,7 @@ void nas::parse_authentication_request(uint32_t lcid, unique_byte_buffer_t pdu,
logger.debug(auth_req.autn, 16, "Authentication request AUTN");
auth_result_t auth_result =
usim->generate_authentication_response(auth_req.rand, auth_req.autn, mcc, mnc, res, &res_len, ctxt.k_asme);
logger.debug(res, res_len, "Authentication request RES");
if (LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_NATIVE == auth_req.nas_ksi.tsc_flag) {
ctxt.ksi = auth_req.nas_ksi.nas_ksi;
} else {

@ -152,7 +152,7 @@ auth_result_t pcsc_usim::generate_authentication_response(uint8_t* rand,
logger.debug(ak, AK_LEN, "AK:");
logger.debug(sqn, SQN_LEN, "SQN:");
logger.debug("mcc=%d, mnc=%d", mcc, mnc);
security_generate_k_asme(ck, ik, ak, sqn, mcc, mnc, k_asme);
security_generate_k_asme(ck, ik, sqn, mcc, mnc, k_asme);
logger.info(k_asme, KEY_LEN, "K_ASME:");
ret = AUTH_OK;
@ -160,6 +160,76 @@ auth_result_t pcsc_usim::generate_authentication_response(uint8_t* rand,
return ret;
}
auth_result_t pcsc_usim::generate_authentication_response_5g(uint8_t* rand,
uint8_t* autn_enb,
const char* serving_network_name,
uint8_t* abba,
uint32_t abba_len,
uint8_t* res_star,
uint8_t* k_amf)
{
uint8_t res[16];
uint8_t k_ausf[32];
uint8_t k_seaf[32];
int res_len;
auth_result_t ret = AUTH_FAILED;
if (!initiated) {
ERROR("USIM not initiated!");
return ret;
}
// Use RAND and AUTN to compute RES, CK, IK using SIM card
switch (sc.umts_auth(rand, autn_enb, res, &res_len, ik, ck, auts)) {
case 0:
logger.info("SCARD: USIM authentication successful.");
break;
case -1:
logger.error("SCARD: Failure during USIM UMTS authentication");
return ret;
case -2:
logger.info("SCARD: USIM synchronization failure, AUTS generated");
logger.debug(auts, AKA_AUTS_LEN, "AUTS");
memcpy(res, auts, AKA_AUTS_LEN);
res_len = AKA_AUTS_LEN;
return AUTH_SYNCH_FAILURE;
default:
logger.warning("SCARD: Unknown USIM failure.");
return ret;
}
// TODO: Extract ak and seq from auts
memset(ak, 0x00, AK_LEN);
// Extract sqn from autn
uint8_t sqn[SQN_LEN];
for (int i = 0; i < 6; i++) {
sqn[i] = autn_enb[i] ^ ak[i];
}
// Generate K_asme
logger.debug(ck, CK_LEN, "CK:");
logger.debug(ik, IK_LEN, "IK:");
logger.debug(ak, AK_LEN, "AK:");
logger.debug(sqn, SQN_LEN, "SQN:");
logger.debug("SSN=%s", serving_network_name);
// Generate RES STAR
security_generate_res_star(ck, ik, serving_network_name, rand, res, res_len, res_star);
logger.debug(res_star, 16, "RES STAR");
// Generate K_ausf
security_generate_k_ausf(ck, ik, sqn, serving_network_name, k_ausf);
logger.debug(k_ausf, 32, "K AUSF");
// Generate K_seaf
security_generate_k_seaf(k_ausf, serving_network_name, k_seaf);
logger.debug(k_seaf, 32, "K SEAF");
// Generate K_seaf
security_generate_k_amf(k_ausf, imsi_str.c_str(), abba, abba_len, k_amf);
logger.debug(k_amf, 32, "K AMF");
ret = AUTH_OK;
return ret;
}
std::string pcsc_usim::get_mnc_str(const uint8_t* imsi_vec, std::string mcc_str)
{
uint32_t mcc_len = 3;

@ -110,24 +110,68 @@ auth_result_t usim::generate_authentication_response(uint8_t* rand,
int* res_len,
uint8_t* k_asme_)
{
auth_result_t auth_result;
uint8_t ak_xor_sqn[6];
if (auth_algo_xor == auth_algo) {
return gen_auth_res_xor(rand, autn_enb, mcc, mnc, res, res_len, k_asme_);
auth_result = gen_auth_res_xor(rand, autn_enb, res, res_len, ak_xor_sqn);
} else {
return gen_auth_res_milenage(rand, autn_enb, mcc, mnc, res, res_len, k_asme_);
auth_result = gen_auth_res_milenage(rand, autn_enb, res, res_len, ak_xor_sqn);
}
if (auth_result == AUTH_OK) {
// Generate K_asme
security_generate_k_asme(ck, ik, ak_xor_sqn, mcc, mnc, k_asme_);
}
return auth_result;
}
auth_result_t usim::generate_authentication_response_5g(uint8_t* rand,
uint8_t* autn_enb,
const char* serving_network_name,
uint8_t* abba,
uint32_t abba_len,
uint8_t* res_star,
uint8_t* k_amf)
{
auth_result_t auth_result;
uint8_t ak_xor_sqn[6];
uint8_t res[16];
uint8_t k_ausf[32];
uint8_t k_seaf[32];
int res_len;
if (auth_algo_xor == auth_algo) {
auth_result = gen_auth_res_xor(rand, autn_enb, res, &res_len, ak_xor_sqn);
} else {
auth_result = gen_auth_res_milenage(rand, autn_enb, res, &res_len, ak_xor_sqn);
}
if (auth_result == AUTH_OK) {
// Generate RES STAR
security_generate_res_star(ck, ik, serving_network_name, rand, res, res_len, res_star);
logger.debug(res_star, 16, "RES STAR");
// Generate K_ausf
security_generate_k_ausf(ck, ik, ak_xor_sqn, serving_network_name, k_ausf);
logger.debug(k_ausf, 32, "K AUSF");
// Generate K_seaf
security_generate_k_seaf(k_ausf, serving_network_name, k_seaf);
logger.debug(k_seaf, 32, "K SEAF");
// Generate K_seaf
logger.debug(abba, abba_len, "ABBA:");
logger.debug("IMSI: %s", imsi_str.c_str());
security_generate_k_amf(k_seaf, imsi_str.c_str(), abba, abba_len, k_amf);
logger.debug(k_amf, 32, "K AMF");
}
return auth_result;
}
/*******************************************************************************
Helpers
*******************************************************************************/
auth_result_t usim::gen_auth_res_milenage(uint8_t* rand,
uint8_t* autn_enb,
uint16_t mcc,
uint16_t mnc,
uint8_t* res,
int* res_len,
uint8_t* k_asme)
auth_result_t
usim::gen_auth_res_milenage(uint8_t* rand, uint8_t* autn_enb, uint8_t* res, int* res_len, uint8_t* ak_xor_sqn)
{
auth_result_t result = AUTH_OK;
uint32_t i;
@ -168,37 +212,34 @@ auth_result_t usim::gen_auth_res_milenage(uint8_t* rand,
}
}
// Generate K_asme
security_generate_k_asme(ck, ik, ak, sqn, mcc, mnc, k_asme);
for (i = 0; i < 6; i++) {
ak_xor_sqn[i] = sqn[i] ^ ak[i];
}
logger.debug(ck, CK_LEN, "CK:");
logger.debug(ik, IK_LEN, "IK:");
logger.debug(ak, AK_LEN, "AK:");
logger.debug(sqn, 6, "sqn:");
logger.debug(amf, 2, "amf:");
logger.debug(mac, 8, "mac:");
return result;
}
// 3GPP TS 34.108 version 10.0.0 Section 8
auth_result_t usim::gen_auth_res_xor(uint8_t* rand,
uint8_t* autn_enb,
uint16_t mcc,
uint16_t mnc,
uint8_t* res,
int* res_len,
uint8_t* k_asme_)
auth_result_t usim::gen_auth_res_xor(uint8_t* rand, uint8_t* autn_enb, uint8_t* res, int* res_len, uint8_t* ak_xor_sqn)
{
auth_result_t result = AUTH_OK;
uint8_t sqn[6];
uint8_t xdout[16];
uint8_t cdout[8];
uint8_t res_[16];
logger.debug(k, 16, "K:");
// Use RAND and K to compute RES, CK, IK and AK
for (uint32_t i = 0; i < 16; i++) {
xdout[i] = k[i] ^ rand[i];
}
for (uint32_t i = 0; i < 16; i++) {
res[i] = xdout[i];
ck[i] = xdout[(i + 1) % 16];
ik[i] = xdout[(i + 2) % 16];
}
for (uint32_t i = 0; i < 6; i++) {
ak[i] = xdout[i + 3];
security_xor_f2345(k, rand, res_, ck, ik, ak);
for (uint32_t i = 0; i < 8; i++) {
res[i] = res_[i];
}
*res_len = 8;
@ -212,18 +253,8 @@ auth_result_t usim::gen_auth_res_xor(uint8_t* rand,
amf[i] = autn_enb[6 + i];
}
// Generate cdout
for (uint32_t i = 0; i < 6; i++) {
cdout[i] = sqn[i];
}
for (uint32_t i = 0; i < 2; i++) {
cdout[6 + i] = amf[i];
}
// Generate MAC
for (uint32_t i = 0; i < 8; i++) {
mac[i] = xdout[i] ^ cdout[i];
}
security_xor_f1(k, rand, sqn, amf, mac);
// Construct AUTN
for (uint32_t i = 0; i < 6; i++) {
@ -243,8 +274,16 @@ auth_result_t usim::gen_auth_res_xor(uint8_t* rand,
}
}
// Generate K_asme
security_generate_k_asme(ck, ik, ak, sqn, mcc, mnc, k_asme_);
logger.debug(ck, CK_LEN, "CK:");
logger.debug(ik, IK_LEN, "IK:");
logger.debug(ak, AK_LEN, "AK:");
logger.debug(sqn, 6, "sqn:");
logger.debug(amf, 2, "amf:");
logger.debug(mac, 8, "mac:");
for (uint32_t i = 0; i < 6; i++) {
ak_xor_sqn[i] = sqn[i] ^ ak[i];
}
return result;
}

@ -357,6 +357,21 @@ void usim_base::restore_keys_from_failed_ho(srsran::as_security_config_t* as_ctx
return;
}
bool usim_base::generate_nas_keys_5g(uint8_t* k_amf,
uint8_t* k_nas_enc,
uint8_t* k_nas_int,
srsran::CIPHERING_ALGORITHM_ID_ENUM cipher_algo,
srsran::INTEGRITY_ALGORITHM_ID_ENUM integ_algo)
{
if (!initiated) {
logger.error("USIM not initiated!");
return false;
}
// Generate K_nas_enc and K_nas_int
security_generate_k_nas_5g(k_amf, cipher_algo, integ_algo, k_nas_enc, k_nas_int);
return true;
}
/*
* NR RRC Interface
*/
@ -369,7 +384,7 @@ bool usim_base::generate_nr_context(uint16_t sk_counter, srsran::as_security_con
}
logger.info("Generating Keys. SCG Counter %d", sk_counter);
srsran::security_generate_sk_gnb(k_enb_ctx.k_enb.data(), k_gnb_ctx.sk_gnb.data(), sk_counter);
srsran::security_generate_sk_gnb(k_enb_ctx.k_enb.data(), sk_counter, k_gnb_ctx.sk_gnb.data());
logger.info(k_gnb_ctx.sk_gnb.data(), 32, "k_sk_gnb");
if (update_nr_context(sec_cfg) == false) {
return false;

Loading…
Cancel
Save