Merge branch 'next' of github.com:softwareradiosystems/srsLTE into next

This commit is contained in:
Ismael Gomez 2018-08-10 22:22:07 +02:00
commit e1870963c7
17 changed files with 267 additions and 22 deletions

View File

@ -146,7 +146,7 @@ class nas_interface_ue
{
public:
virtual bool attach_request() = 0;
virtual bool deattach_request() = 0;
virtual bool detach_request() = 0;
};
// NAS interface for UE
@ -251,6 +251,8 @@ public:
srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo_) = 0;
virtual void enable_integrity(uint32_t lcid) = 0;
virtual void enable_encryption(uint32_t lcid) = 0;
virtual uint32_t get_dl_count(uint32_t lcid) = 0;
virtual uint32_t get_ul_count(uint32_t lcid) = 0;
};
// PDCP interface for RLC
@ -274,6 +276,7 @@ public:
virtual void add_bearer(uint32_t lcid) = 0;
virtual void add_bearer(uint32_t lcid, srslte::srslte_rlc_config_t cnfg) = 0;
virtual void add_bearer_mrb(uint32_t lcid) = 0;
virtual void del_bearer(uint32_t lcid) = 0;
};
// RLC interface for PDCP

View File

@ -60,6 +60,7 @@ public:
void write_sdu_mch(uint32_t lcid, byte_buffer_t *sdu);
void add_bearer(uint32_t lcid, srslte_pdcp_config_t cnfg = srslte_pdcp_config_t());
void add_bearer_mrb(uint32_t lcid, srslte_pdcp_config_t cnfg = srslte_pdcp_config_t());
void del_bearer(uint32_t lcid);
void config_security(uint32_t lcid,
uint8_t *k_enc,
uint8_t *k_int,
@ -71,6 +72,8 @@ public:
INTEGRITY_ALGORITHM_ID_ENUM integ_algo);
void enable_integrity(uint32_t lcid);
void enable_encryption(uint32_t lcid);
uint32_t get_dl_count(uint32_t lcid);
uint32_t get_ul_count(uint32_t lcid);
// RLC interface
void write_pdu(uint32_t lcid, byte_buffer_t *sdu);

View File

@ -83,6 +83,8 @@ public:
INTEGRITY_ALGORITHM_ID_ENUM integ_algo_);
void enable_integrity();
void enable_encryption();
uint32_t get_dl_count();
uint32_t get_ul_count();
// RLC interface
void write_pdu(byte_buffer_t *pdu);

View File

@ -62,6 +62,8 @@ public:
INTEGRITY_ALGORITHM_ID_ENUM integ_algo_) = 0;
virtual void enable_integrity() = 0;
virtual void enable_encryption() = 0;
virtual uint32_t get_dl_count() = 0;
virtual uint32_t get_ul_count() = 0;
// RLC interface
virtual void write_pdu(byte_buffer_t *pdu) = 0;

View File

@ -86,6 +86,7 @@ public:
void add_bearer(uint32_t lcid);
void add_bearer(uint32_t lcid, srslte_rlc_config_t cnfg);
void add_bearer_mrb(uint32_t lcid);
void del_bearer(uint32_t lcid);
private:
void reset_metrics();

View File

@ -94,6 +94,7 @@ void pdcp::reset()
// destroy all bearers
pthread_rwlock_wrlock(&rwlock);
for (pdcp_map_t::iterator it = pdcp_array.begin(); it != pdcp_array.end(); ++it) {
it->second->reset();
delete(it->second);
pdcp_array.erase(it);
}
@ -137,6 +138,7 @@ void pdcp::write_sdu_mch(uint32_t lcid, byte_buffer_t *sdu)
}
pthread_rwlock_unlock(&rwlock);
}
void pdcp::add_bearer(uint32_t lcid, srslte_pdcp_config_t cfg)
{
pthread_rwlock_wrlock(&rwlock);
@ -154,7 +156,6 @@ unlock_and_exit:
pthread_rwlock_unlock(&rwlock);
}
void pdcp::add_bearer_mrb(uint32_t lcid, srslte_pdcp_config_t cfg)
{
pthread_rwlock_wrlock(&rwlock);
@ -172,6 +173,21 @@ unlock_and_exit:
pthread_rwlock_unlock(&rwlock);
}
void pdcp::del_bearer(uint32_t lcid)
{
pthread_rwlock_wrlock(&rwlock);
if (valid_lcid(lcid)) {
pdcp_map_t::iterator it = pdcp_array.find(lcid);
delete(it->second);
pdcp_array.erase(it);
pdcp_log->warning("Deleted PDCP bearer %s\n", rrc->get_rb_name(lcid).c_str());
} else {
pdcp_log->warning("Can't delete bearer %s. Bearer doesn't exist.\n", rrc->get_rb_name(lcid).c_str());
}
pthread_rwlock_unlock(&rwlock);
}
void pdcp::config_security(uint32_t lcid,
uint8_t *k_enc,
uint8_t *k_int,
@ -215,6 +231,29 @@ void pdcp::enable_encryption(uint32_t lcid)
pthread_rwlock_unlock(&rwlock);
}
uint32_t pdcp::get_dl_count(uint32_t lcid)
{
int ret = 0;
pthread_rwlock_rdlock(&rwlock);
if (valid_lcid(lcid)) {
ret = pdcp_array.at(lcid)->get_dl_count();
}
pthread_rwlock_unlock(&rwlock);
return ret;
}
uint32_t pdcp::get_ul_count(uint32_t lcid)
{
int ret = 0;
pthread_rwlock_rdlock(&rwlock);
if (valid_lcid(lcid)) {
ret = pdcp_array.at(lcid)->get_ul_count();
}
pthread_rwlock_unlock(&rwlock);
return ret;
}
/*******************************************************************************
RLC interface
*******************************************************************************/

View File

@ -214,10 +214,13 @@ void pdcp_entity::write_pdu(byte_buffer_t *pdu)
}
if (do_integrity) {
integrity_verify(pdu->msg,
if (not integrity_verify(pdu->msg,
rx_count,
pdu->N_bytes - 4,
&(pdu->msg[pdu->N_bytes - 4]));
&(pdu->msg[pdu->N_bytes - 4]))) {
log->error_hex(pdu->msg, pdu->N_bytes, "RX %s PDU SN: %d", rrc->get_rb_name(lcid).c_str(), sn);
goto exit;
}
}
pdcp_unpack_control_pdu(pdu, &sn);
@ -226,6 +229,7 @@ void pdcp_entity::write_pdu(byte_buffer_t *pdu)
// pass to RRC
rrc->write_pdu(lcid, pdu);
}
exit:
rx_count++;
}
@ -404,6 +408,17 @@ uint8_t pdcp_entity::get_bearer_id(uint8_t lcid)
}
uint32_t pdcp_entity::get_dl_count()
{
return rx_count;
}
uint32_t pdcp_entity::get_ul_count()
{
return tx_count;
}
/****************************************************************************
* Pack/Unpack helper functions
* Ref: 3GPP TS 36.323 v10.1.0

View File

@ -494,6 +494,24 @@ unlock_and_exit:
}
void rlc::del_bearer(uint32_t lcid)
{
pthread_rwlock_wrlock(&rwlock);
if (valid_lcid_mrb(lcid)) {
rlc_map_t::iterator it = rlc_array.find(lcid);
it->second->stop();
delete(it->second);
rlc_array.erase(it);
rlc_log->warning("Deleted RLC bearer %s\n", rrc->get_rb_name(lcid).c_str());
} else {
rlc_log->warning("Can't delete bearer %s. Bearer doesn't exist.\n", rrc->get_rb_name(lcid).c_str());
}
pthread_rwlock_unlock(&rwlock);
}
/*******************************************************************************
Helpers (Lock must be hold when calling those)
*******************************************************************************/

View File

@ -238,7 +238,7 @@ uint32_t rlc_am::get_total_buffer_state()
check_reordering_timeout();
if(do_status && !status_prohibited()) {
n_bytes += prepare_status();
log->debug("Buffer state - status report: %d bytes\n", n_bytes);
log->debug("%s Buffer state - total status report: %d bytes\n", rrc->get_rb_name(lcid).c_str(), n_bytes);
}
// Bytes needed for retx
@ -292,7 +292,7 @@ uint32_t rlc_am::get_buffer_state()
check_reordering_timeout();
if(do_status && !status_prohibited()) {
n_bytes = prepare_status();
log->debug("Buffer state - status report: %d bytes\n", n_bytes);
log->debug("%s Buffer state - status report: %d bytes\n", rrc->get_rb_name(lcid).c_str(), n_bytes);
goto unlock_and_return;
}

View File

@ -69,8 +69,8 @@ public:
bool init(all_args_t *args_);
void stop();
bool attach();
bool deattach();
bool switch_on();
bool switch_off();
bool is_attached();
void start_plot();
void print_mbms();

View File

@ -159,8 +159,8 @@ public:
virtual bool init(all_args_t *args_) = 0;
virtual void stop() = 0;
virtual bool attach() = 0;
virtual bool deattach() = 0;
virtual bool switch_on() = 0;
virtual bool switch_off() = 0;
virtual bool is_attached() = 0;
virtual void start_plot() = 0;

View File

@ -90,7 +90,7 @@ public:
// UE interface
bool attach_request();
bool deattach_request();
bool detach_request();
// PCAP
void start_pcap(srslte::nas_pcap *pcap_);
@ -173,6 +173,7 @@ private:
void parse_service_reject(uint32_t lcid, byte_buffer_t *pdu);
void parse_esm_information_request(uint32_t lcid, byte_buffer_t *pdu);
void parse_emm_information(uint32_t lcid, byte_buffer_t *pdu);
void parse_detach_request(uint32_t lcid, byte_buffer_t *pdu);
// Packet generators
void gen_attach_request(byte_buffer_t *msg);
@ -186,6 +187,8 @@ private:
void send_authentication_failure(const uint8_t cause, const uint8_t* auth_fail_param);
void gen_pdn_connectivity_request(LIBLTE_BYTE_MSG_STRUCT *msg);
void send_security_mode_reject(uint8_t cause);
void send_detach_request(bool switch_off);
void send_detach_accept();
// security context persistence file
bool read_ctxt_file(nas_sec_ctxt *ctxt);

View File

@ -638,8 +638,8 @@ private:
void handle_rrc_con_reconfig(uint32_t lcid, LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT *reconfig);
void add_srb(LIBLTE_RRC_SRB_TO_ADD_MOD_STRUCT *srb_cnfg);
void add_drb(LIBLTE_RRC_DRB_TO_ADD_MOD_STRUCT *drb_cnfg);
void release_drb(uint8_t lcid);
void add_mrb(uint32_t lcid, uint32_t port);
void release_drb(uint32_t drb_id);
void add_mrb(uint32_t lcid, uint32_t port);
bool apply_rr_config_dedicated(LIBLTE_RRC_RR_CONFIG_DEDICATED_STRUCT *cnfg);
void apply_phy_config_dedicated(LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT *phy_cnfg, bool apply_defaults);
void apply_mac_config_dedicated(LIBLTE_RRC_MAC_MAIN_CONFIG_STRUCT *mac_cfg, bool apply_defaults);

View File

@ -545,7 +545,7 @@ int main(int argc, char *argv[])
pthread_create(&input, NULL, &input_loop, &args);
printf("Attaching UE...\n");
while (!ue->attach() && running) {
while (!ue->switch_on() && running) {
sleep(1);
}
if (running) {
@ -585,6 +585,7 @@ int main(int argc, char *argv[])
}
sleep(1);
}
ue->switch_off();
pthread_cancel(input);
metricshub.stop();
ue->stop();

View File

@ -301,12 +301,27 @@ void ue::stop()
}
}
bool ue::attach() {
bool ue::switch_on() {
return nas.attach_request();
}
bool ue::deattach() {
return nas.deattach_request();
bool ue::switch_off() {
// generate detach request
nas.detach_request();
// wait for max. 5s for it to be sent (according to TS 24.301 Sec 25.5.2.2)
const uint32_t RB_ID_SRB1 = 1;
int cnt = 0, timeout = 5;
while (rlc.get_buffer_state(RB_ID_SRB1) && ++cnt <= timeout) {
sleep(1);
}
bool detach_sent = true;
if (rlc.get_buffer_state(RB_ID_SRB1)) {
nas_log.warning("Detach couldn't be sent after %ds.\n", timeout);
detach_sent = false;
}
return detach_sent;
}
bool ue::is_attached()

View File

@ -172,9 +172,25 @@ bool nas::attach_request() {
return false;
}
bool nas::deattach_request() {
state = EMM_STATE_DEREGISTERED_INITIATED;
nas_log->info("Dettach request not supported\n");
bool nas::detach_request() {
// attempt detach for 5s
nas_log->info("Detach Request\n");
switch (state) {
case EMM_STATE_DEREGISTERED:
// do nothing ..
break;
case EMM_STATE_REGISTERED:
// send detach request
send_detach_request(true);
state = EMM_STATE_DEREGISTERED_INITIATED;
break;
case EMM_STATE_DEREGISTERED_INITIATED:
// do nothing ..
break;
default:
break;
}
return false;
}
@ -355,6 +371,9 @@ void nas::write_pdu(uint32_t lcid, byte_buffer_t *pdu) {
case LIBLTE_MME_MSG_TYPE_EMM_INFORMATION:
parse_emm_information(lcid, pdu);
break;
case LIBLTE_MME_MSG_TYPE_DETACH_REQUEST:
parse_detach_request(lcid, pdu);
break;
default:
nas_log->error("Not handling NAS message with MSG_TYPE=%02X\n", msg_type);
pool->deallocate(pdu);
@ -959,6 +978,23 @@ void nas::parse_emm_information(uint32_t lcid, byte_buffer_t *pdu) {
pool->deallocate(pdu);
}
void nas::parse_detach_request(uint32_t lcid, byte_buffer_t *pdu)
{
LIBLTE_MME_DETACH_REQUEST_MSG_STRUCT detach_request;
liblte_mme_unpack_detach_request_msg((LIBLTE_BYTE_MSG_STRUCT *) pdu, &detach_request);
ctxt.rx_count++;
pool->deallocate(pdu);
if (state == EMM_STATE_REGISTERED) {
nas_log->info("Received Detach request (type=%d)\n", detach_request.detach_type.type_of_detach);
state = EMM_STATE_DEREGISTERED;
// send accept
send_detach_accept();
} else {
nas_log->warning("Received detach request in invalid state (state=%d)\n", state);
}
}
/*******************************************************************************
* Senders
******************************************************************************/
@ -1132,6 +1168,104 @@ void nas::send_security_mode_reject(uint8_t cause) {
rrc->write_sdu(cfg.lcid, msg);
}
void nas::send_detach_request(bool switch_off)
{
byte_buffer_t *pdu = pool_allocate_blocking;
if (!pdu) {
nas_log->error("Fatal Error: Couldn't allocate PDU in %s().\n", __FUNCTION__);
return;
}
LIBLTE_MME_DETACH_REQUEST_MSG_STRUCT detach_request = {};
if (switch_off) {
detach_request.detach_type.switch_off = 1;
detach_request.detach_type.type_of_detach = LIBLTE_MME_SO_FLAG_SWITCH_OFF;
} else {
detach_request.detach_type.switch_off = 0;
detach_request.detach_type.type_of_detach = LIBLTE_MME_SO_FLAG_NORMAL_DETACH;
}
// GUTI or IMSI detach
if (have_guti && have_ctxt) {
detach_request.eps_mobile_id.type_of_id = LIBLTE_MME_EPS_MOBILE_ID_TYPE_GUTI;
memcpy(&detach_request.eps_mobile_id.guti, &ctxt.guti, sizeof(LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT));
detach_request.nas_ksi.tsc_flag = LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_NATIVE;
detach_request.nas_ksi.nas_ksi = ctxt.ksi;
nas_log->info("Requesting Detach with GUTI\n");
liblte_mme_pack_detach_request_msg(&detach_request,
LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED,
ctxt.tx_count,
(LIBLTE_BYTE_MSG_STRUCT *) pdu);
if(pcap != NULL) {
pcap->write_nas(pdu->msg, pdu->N_bytes);
}
// Add MAC
if (pdu->N_bytes > 5) {
cipher_encrypt(pdu);
integrity_generate(&k_nas_int[16],
ctxt.tx_count,
SECURITY_DIRECTION_UPLINK,
&pdu->msg[5],
pdu->N_bytes - 5,
&pdu->msg[1]);
} else {
nas_log->error("Invalid PDU size %d\n", pdu->N_bytes);
}
} else {
detach_request.eps_mobile_id.type_of_id = LIBLTE_MME_EPS_MOBILE_ID_TYPE_IMSI;
detach_request.nas_ksi.tsc_flag = LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_NATIVE;
detach_request.nas_ksi.nas_ksi = 0;
usim->get_imsi_vec(detach_request.eps_mobile_id.imsi, 15);
nas_log->info("Requesting IMSI detach (IMSI=%s)\n", usim->get_imsi_str().c_str());
liblte_mme_pack_detach_request_msg(&detach_request, LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS, ctxt.tx_count, (LIBLTE_BYTE_MSG_STRUCT *) pdu);
if(pcap != NULL) {
pcap->write_nas(pdu->msg, pdu->N_bytes);
}
}
nas_log->info("Sending detach request\n");
rrc->write_sdu(cfg.lcid, pdu);
}
void nas::send_detach_accept()
{
byte_buffer_t *pdu = pool_allocate_blocking;
if (!pdu) {
nas_log->error("Fatal Error: Couldn't allocate PDU in %s().\n", __FUNCTION__);
return;
}
LIBLTE_MME_DETACH_ACCEPT_MSG_STRUCT detach_accept;
bzero(&detach_accept, sizeof(detach_accept));
liblte_mme_pack_detach_accept_msg(&detach_accept,
LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED,
ctxt.tx_count,
(LIBLTE_BYTE_MSG_STRUCT *) pdu);
if(pcap != NULL) {
pcap->write_nas(pdu->msg, pdu->N_bytes);
}
// Encrypt and add MAC
if (pdu->N_bytes > 5) {
cipher_encrypt(pdu);
integrity_generate(&k_nas_int[16],
ctxt.tx_count,
SECURITY_DIRECTION_UPLINK,
&pdu->msg[5],
pdu->N_bytes - 5,
&pdu->msg[1]);
} else {
nas_log->error("Invalid PDU size %d\n", pdu->N_bytes);
}
nas_log->info("Sending detach accept\n");
rrc->write_sdu(cfg.lcid, pdu);
}
void nas::send_authentication_response(const uint8_t* res, const size_t res_len, const uint8_t sec_hdr_type) {
byte_buffer_t *pdu = pool_allocate_blocking;

View File

@ -2021,6 +2021,7 @@ void rrc::parse_dl_ccch(byte_buffer_t *pdu) {
void rrc::parse_dl_dcch(uint32_t lcid, byte_buffer_t *pdu) {
srslte_bit_unpack_vector(pdu->msg, bit_buf.msg, pdu->N_bytes * 8);
bit_buf.N_bits = pdu->N_bytes * 8;
bzero(&dl_dcch_msg, sizeof(dl_dcch_msg));
liblte_rrc_unpack_dl_dcch_msg((LIBLTE_BIT_MSG_STRUCT *) &bit_buf, &dl_dcch_msg);
rrc_log->info("%s - Received %s\n",
@ -2699,8 +2700,16 @@ void rrc::add_drb(LIBLTE_RRC_DRB_TO_ADD_MOD_STRUCT *drb_cnfg) {
rrc_log->info("Added radio bearer %s\n", get_rb_name(lcid).c_str());
}
void rrc::release_drb(uint8_t lcid) {
// TODO
void rrc::release_drb(uint32_t drb_id)
{
uint32_t lcid = RB_ID_SRB2 + drb_id;
if (drbs.find(drb_id) != drbs.end()) {
rrc_log->info("Releasing radio bearer %s\n", get_rb_name(lcid).c_str());
drbs.erase(lcid);
} else {
rrc_log->error("Couldn't release radio bearer %s. Doesn't exist.\n", get_rb_name(lcid).c_str());
}
}
void rrc::add_mrb(uint32_t lcid, uint32_t port)