2017-05-18 03:52:29 -07:00
/**
*
* \ section COPYRIGHT
*
* Copyright 2013 - 2015 Software Radio Systems Limited
*
* \ section LICENSE
*
* This file is part of the srsUE library .
*
* srsUE is free software : you can redistribute it and / or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation , either version 3 of
* the License , or ( at your option ) any later version .
*
* srsUE is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU Affero General Public License for more details .
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top - level directory of this distribution
* and at http : //www.gnu.org/licenses/.
*
*/
2017-05-31 14:39:17 -07:00
# include "srslte/upper/pdcp.h"
2017-05-18 03:52:29 -07:00
2017-06-01 03:25:42 -07:00
namespace srslte {
2017-05-18 03:52:29 -07:00
pdcp : : pdcp ( )
2018-01-31 07:48:50 -08:00
{
rlc = NULL ;
rrc = NULL ;
gw = NULL ;
pdcp_log = NULL ;
2018-07-16 12:17:01 -07:00
default_lcid = 0 ;
2018-07-17 06:27:04 -07:00
pthread_rwlock_init ( & rwlock , NULL ) ;
2018-07-16 12:17:01 -07:00
}
pdcp : : ~ pdcp ( )
{
// destroy all remaining entities
2018-07-17 06:27:04 -07:00
pthread_rwlock_wrlock ( & rwlock ) ;
2018-07-16 12:17:01 -07:00
for ( pdcp_map_t : : iterator it = pdcp_array . begin ( ) ; it ! = pdcp_array . end ( ) ; + + it ) {
delete ( it - > second ) ;
}
pdcp_array . clear ( ) ;
2018-07-17 06:27:04 -07:00
2018-12-30 13:57:33 -08:00
for ( pdcp_map_t : : iterator it = pdcp_array_mrb . begin ( ) ; it ! = pdcp_array_mrb . end ( ) ; + + it ) {
delete ( it - > second ) ;
}
pdcp_array_mrb . clear ( ) ;
2018-07-17 06:27:04 -07:00
pthread_rwlock_unlock ( & rwlock ) ;
pthread_rwlock_destroy ( & rwlock ) ;
2018-01-31 07:48:50 -08:00
}
2017-05-18 03:52:29 -07:00
2017-06-28 04:31:43 -07:00
void pdcp : : init ( srsue : : rlc_interface_pdcp * rlc_ , srsue : : rrc_interface_pdcp * rrc_ , srsue : : gw_interface_pdcp * gw_ , log * pdcp_log_ , uint32_t lcid_ , uint8_t direction_ )
2017-05-18 03:52:29 -07:00
{
2018-07-16 12:17:01 -07:00
rlc = rlc_ ;
rrc = rrc_ ;
gw = gw_ ;
pdcp_log = pdcp_log_ ;
default_lcid = lcid_ ;
2017-05-18 03:52:29 -07:00
2017-07-06 07:42:16 -07:00
// Default config
2018-07-16 12:17:01 -07:00
default_cnfg . is_control = false ;
default_cnfg . is_data = false ;
default_cnfg . direction = direction_ ;
2017-07-06 07:42:16 -07:00
2018-07-16 12:17:01 -07:00
// create default PDCP entity for SRB0
2018-07-17 06:27:04 -07:00
add_bearer ( 0 , default_cnfg ) ;
2017-05-18 03:52:29 -07:00
}
void pdcp : : stop ( )
2017-11-30 09:09:12 -08:00
{
2018-07-16 12:17:01 -07:00
// destroy default entity
2018-07-17 06:27:04 -07:00
pthread_rwlock_wrlock ( & rwlock ) ;
2018-07-16 12:17:01 -07:00
if ( valid_lcid ( 0 ) ) {
2018-07-17 06:27:04 -07:00
pdcp_map_t : : iterator it = pdcp_array . find ( 0 ) ;
2018-07-16 12:17:01 -07:00
delete ( it - > second ) ;
pdcp_array . erase ( it ) ;
}
2018-07-17 06:27:04 -07:00
pthread_rwlock_unlock ( & rwlock ) ;
2017-11-30 09:09:12 -08:00
}
2017-05-18 03:52:29 -07:00
2017-11-23 10:46:34 -08:00
void pdcp : : reestablish ( ) {
2018-07-17 06:27:04 -07:00
pthread_rwlock_rdlock ( & rwlock ) ;
2018-07-19 01:23:15 -07:00
for ( pdcp_map_t : : iterator it = pdcp_array . begin ( ) ; it ! = pdcp_array . end ( ) ; + + it ) {
it - > second - > reestablish ( ) ;
2017-11-23 10:46:34 -08:00
}
2018-07-17 06:27:04 -07:00
pthread_rwlock_unlock ( & rwlock ) ;
2017-11-23 10:46:34 -08:00
}
2017-05-18 03:52:29 -07:00
void pdcp : : reset ( )
{
2018-07-25 06:08:35 -07:00
// destroy all bearers
pthread_rwlock_wrlock ( & rwlock ) ;
2018-12-14 03:01:44 -08:00
for ( pdcp_map_t : : iterator it = pdcp_array . begin ( ) ; it ! = pdcp_array . end ( ) ; /* post increment in erase */ ) {
2018-08-06 06:48:52 -07:00
it - > second - > reset ( ) ;
2018-07-25 06:08:35 -07:00
delete ( it - > second ) ;
2018-12-14 03:01:44 -08:00
pdcp_array . erase ( it + + ) ;
2018-07-16 12:17:01 -07:00
}
2018-07-17 06:27:04 -07:00
pthread_rwlock_unlock ( & rwlock ) ;
2018-07-25 06:08:35 -07:00
// add default SRB0 again
add_bearer ( 0 , default_cnfg ) ;
2017-05-18 03:52:29 -07:00
}
/*******************************************************************************
RRC / GW interface
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2018-07-25 06:09:19 -07:00
bool pdcp : : is_lcid_enabled ( uint32_t lcid )
2017-09-18 05:02:31 -07:00
{
2018-07-17 06:27:04 -07:00
pthread_rwlock_rdlock ( & rwlock ) ;
bool ret = false ;
2018-07-19 01:23:15 -07:00
if ( valid_lcid ( lcid ) ) {
ret = pdcp_array . at ( lcid ) - > is_active ( ) ;
2018-07-16 12:17:01 -07:00
}
2018-07-17 06:27:04 -07:00
pthread_rwlock_unlock ( & rwlock ) ;
return ret ;
2017-09-18 05:02:31 -07:00
}
2018-07-24 06:49:09 -07:00
void pdcp : : write_sdu ( uint32_t lcid , byte_buffer_t * sdu , bool blocking )
2017-05-18 03:52:29 -07:00
{
2018-07-17 06:27:04 -07:00
pthread_rwlock_rdlock ( & rwlock ) ;
2018-07-16 12:17:01 -07:00
if ( valid_lcid ( lcid ) ) {
2018-07-24 06:49:09 -07:00
pdcp_array . at ( lcid ) - > write_sdu ( sdu , blocking ) ;
2018-03-06 03:41:44 -08:00
} else {
pdcp_log - > warning ( " Writing sdu: lcid=%d. Deallocating sdu \n " , lcid ) ;
byte_buffer_pool : : get_instance ( ) - > deallocate ( sdu ) ;
}
2018-07-17 06:27:04 -07:00
pthread_rwlock_unlock ( & rwlock ) ;
2017-05-18 03:52:29 -07:00
}
2018-05-15 07:57:23 -07:00
void pdcp : : write_sdu_mch ( uint32_t lcid , byte_buffer_t * sdu )
{
2018-07-17 06:27:04 -07:00
pthread_rwlock_rdlock ( & rwlock ) ;
2018-07-16 12:17:01 -07:00
if ( valid_mch_lcid ( lcid ) ) {
2018-07-24 06:49:09 -07:00
pdcp_array_mrb . at ( lcid ) - > write_sdu ( sdu , true ) ;
2018-05-15 07:57:23 -07:00
}
2018-07-17 06:27:04 -07:00
pthread_rwlock_unlock ( & rwlock ) ;
2018-05-15 07:57:23 -07:00
}
2018-08-03 07:28:06 -07:00
2017-06-28 04:31:43 -07:00
void pdcp : : add_bearer ( uint32_t lcid , srslte_pdcp_config_t cfg )
2017-05-18 03:52:29 -07:00
{
2018-07-24 00:43:33 -07:00
pthread_rwlock_wrlock ( & rwlock ) ;
2018-07-16 12:17:01 -07:00
if ( not valid_lcid ( lcid ) ) {
if ( not pdcp_array . insert ( pdcp_map_pair_t ( lcid , new pdcp_entity ( ) ) ) . second ) {
pdcp_log - > error ( " Error inserting PDCP entity in to array \n . " ) ;
2018-07-24 06:49:09 -07:00
goto unlock_and_exit ;
2018-07-16 12:17:01 -07:00
}
pdcp_array . at ( lcid ) - > init ( rlc , rrc , gw , pdcp_log , lcid , cfg ) ;
2018-01-12 05:55:58 -08:00
pdcp_log - > info ( " Added bearer %s \n " , rrc - > get_rb_name ( lcid ) . c_str ( ) ) ;
2017-05-18 03:52:29 -07:00
} else {
2018-01-12 05:55:58 -08:00
pdcp_log - > warning ( " Bearer %s already configured. Reconfiguration not supported \n " , rrc - > get_rb_name ( lcid ) . c_str ( ) ) ;
2017-05-18 03:52:29 -07:00
}
2018-07-24 06:49:09 -07:00
unlock_and_exit :
2018-07-17 06:27:04 -07:00
pthread_rwlock_unlock ( & rwlock ) ;
2017-05-18 03:52:29 -07:00
}
2018-05-15 07:57:23 -07:00
void pdcp : : add_bearer_mrb ( uint32_t lcid , srslte_pdcp_config_t cfg )
{
2018-07-24 00:43:33 -07:00
pthread_rwlock_wrlock ( & rwlock ) ;
2018-07-16 12:17:01 -07:00
if ( not valid_mch_lcid ( lcid ) ) {
2018-07-17 06:27:04 -07:00
if ( not pdcp_array_mrb . insert ( pdcp_map_pair_t ( lcid , new pdcp_entity ( ) ) ) . second ) {
2018-07-16 12:17:01 -07:00
pdcp_log - > error ( " Error inserting PDCP entity in to array \n . " ) ;
2018-07-24 06:49:09 -07:00
goto unlock_and_exit ;
2018-07-16 12:17:01 -07:00
}
pdcp_array_mrb . at ( lcid ) - > init ( rlc , rrc , gw , pdcp_log , lcid , cfg ) ;
2018-05-15 07:57:23 -07:00
pdcp_log - > info ( " Added bearer %s \n " , rrc - > get_rb_name ( lcid ) . c_str ( ) ) ;
} else {
pdcp_log - > warning ( " Bearer %s already configured. Reconfiguration not supported \n " , rrc - > get_rb_name ( lcid ) . c_str ( ) ) ;
}
2018-07-24 06:49:09 -07:00
unlock_and_exit :
2018-07-17 06:27:04 -07:00
pthread_rwlock_unlock ( & rwlock ) ;
2018-05-15 07:57:23 -07:00
}
2018-08-03 07:28:06 -07:00
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 ) ;
}
2018-09-17 04:10:44 -07:00
void pdcp : : change_lcid ( uint32_t old_lcid , uint32_t new_lcid )
{
pthread_rwlock_wrlock ( & rwlock ) ;
// make sure old LCID exists and new LCID is still free
if ( valid_lcid ( old_lcid ) & & not valid_lcid ( new_lcid ) ) {
// insert old PDCP entity into new LCID
pdcp_map_t : : iterator it = pdcp_array . find ( old_lcid ) ;
pdcp_entity_interface * pdcp_entity = it - > second ;
if ( not pdcp_array . insert ( pdcp_map_pair_t ( new_lcid , pdcp_entity ) ) . second ) {
pdcp_log - > error ( " Error inserting PDCP entity into array \n . " ) ;
goto exit ;
}
// erase from old position
pdcp_array . erase ( it ) ;
pdcp_log - > warning ( " Changed LCID of PDCP bearer from %d to %d \n " , old_lcid , new_lcid ) ;
} else {
pdcp_log - > error ( " Can't change PDCP of bearer %s from %d to %d. Bearer doesn't exist or new LCID already occupied. \n " , rrc - > get_rb_name ( old_lcid ) . c_str ( ) , old_lcid , new_lcid ) ;
}
exit :
pthread_rwlock_unlock ( & rwlock ) ;
}
2018-08-03 07:28:06 -07:00
2017-05-18 03:52:29 -07:00
void pdcp : : config_security ( uint32_t lcid ,
2019-01-28 12:30:12 -08:00
uint8_t * k_rrc_enc ,
uint8_t * k_rrc_int ,
uint8_t * k_up_enc ,
2017-05-18 03:52:29 -07:00
CIPHERING_ALGORITHM_ID_ENUM cipher_algo ,
INTEGRITY_ALGORITHM_ID_ENUM integ_algo )
{
2018-07-17 06:27:04 -07:00
pthread_rwlock_rdlock ( & rwlock ) ;
2018-07-16 12:17:01 -07:00
if ( valid_lcid ( lcid ) ) {
2019-01-28 12:30:12 -08:00
pdcp_array . at ( lcid ) - > config_security ( k_rrc_enc , k_rrc_int , k_up_enc , cipher_algo , integ_algo ) ;
2018-07-16 12:17:01 -07:00
}
2018-07-17 06:27:04 -07:00
pthread_rwlock_unlock ( & rwlock ) ;
2017-12-01 11:19:38 -08:00
}
2019-01-28 12:30:12 -08:00
void pdcp : : config_security_all ( uint8_t * k_rrc_enc , uint8_t * k_rrc_int , uint8_t * k_up_enc ,
CIPHERING_ALGORITHM_ID_ENUM cipher_algo , INTEGRITY_ALGORITHM_ID_ENUM integ_algo )
2017-12-02 13:43:35 -08:00
{
2018-07-17 06:27:04 -07:00
pthread_rwlock_rdlock ( & rwlock ) ;
2018-07-19 01:23:15 -07:00
for ( pdcp_map_t : : iterator it = pdcp_array . begin ( ) ; it ! = pdcp_array . end ( ) ; + + it ) {
2019-01-28 12:30:12 -08:00
it - > second - > config_security ( k_rrc_enc , k_rrc_int , k_up_enc , cipher_algo , integ_algo ) ;
2017-12-02 13:43:35 -08:00
}
2018-07-17 06:27:04 -07:00
pthread_rwlock_unlock ( & rwlock ) ;
2017-12-02 13:43:35 -08:00
}
2017-12-01 11:19:38 -08:00
void pdcp : : enable_integrity ( uint32_t lcid )
{
2018-07-17 06:27:04 -07:00
pthread_rwlock_rdlock ( & rwlock ) ;
2018-07-16 12:17:01 -07:00
if ( valid_lcid ( lcid ) ) {
pdcp_array . at ( lcid ) - > enable_integrity ( ) ;
}
2018-07-17 06:27:04 -07:00
pthread_rwlock_unlock ( & rwlock ) ;
2017-05-18 03:52:29 -07:00
}
2017-11-30 09:09:12 -08:00
void pdcp : : enable_encryption ( uint32_t lcid )
{
2018-07-17 06:27:04 -07:00
pthread_rwlock_rdlock ( & rwlock ) ;
2018-07-16 12:17:01 -07:00
if ( valid_lcid ( lcid ) ) {
pdcp_array . at ( lcid ) - > enable_encryption ( ) ;
}
2018-07-17 06:27:04 -07:00
pthread_rwlock_unlock ( & rwlock ) ;
2017-05-18 03:52:29 -07:00
}
2018-08-08 07:03:17 -07:00
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 ;
}
2017-05-18 03:52:29 -07:00
/*******************************************************************************
RLC interface
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void pdcp : : write_pdu ( uint32_t lcid , byte_buffer_t * pdu )
{
2018-07-17 06:27:04 -07:00
pthread_rwlock_rdlock ( & rwlock ) ;
2018-07-16 12:17:01 -07:00
if ( valid_lcid ( lcid ) ) {
pdcp_array . at ( lcid ) - > write_pdu ( pdu ) ;
2018-03-06 03:41:44 -08:00
} else {
pdcp_log - > warning ( " Writing pdu: lcid=%d. Deallocating pdu \n " , lcid ) ;
byte_buffer_pool : : get_instance ( ) - > deallocate ( pdu ) ;
}
2018-07-17 06:27:04 -07:00
pthread_rwlock_unlock ( & rwlock ) ;
2017-05-18 03:52:29 -07:00
}
void pdcp : : write_pdu_bcch_bch ( byte_buffer_t * sdu )
{
rrc - > write_pdu_bcch_bch ( sdu ) ;
}
2018-07-17 06:27:04 -07:00
2017-05-18 03:52:29 -07:00
void pdcp : : write_pdu_bcch_dlsch ( byte_buffer_t * sdu )
{
rrc - > write_pdu_bcch_dlsch ( sdu ) ;
}
void pdcp : : write_pdu_pcch ( byte_buffer_t * sdu )
{
rrc - > write_pdu_pcch ( sdu ) ;
}
2018-05-15 07:57:23 -07:00
void pdcp : : write_pdu_mch ( uint32_t lcid , byte_buffer_t * sdu )
{
2018-07-16 12:17:01 -07:00
if ( 0 = = lcid ) {
2018-05-15 07:57:23 -07:00
rrc - > write_pdu_mch ( lcid , sdu ) ;
} else {
gw - > write_pdu_mch ( lcid , sdu ) ;
}
}
2017-05-18 03:52:29 -07:00
/*******************************************************************************
2018-07-17 06:27:04 -07:00
Helpers ( Lock must be hold when calling those )
2017-05-18 03:52:29 -07:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
bool pdcp : : valid_lcid ( uint32_t lcid )
{
2018-07-16 12:17:01 -07:00
if ( lcid > = SRSLTE_N_RADIO_BEARERS ) {
2017-06-06 11:34:09 -07:00
pdcp_log - > error ( " Radio bearer id must be in [0:%d] - %d " , SRSLTE_N_RADIO_BEARERS , lcid ) ;
2017-05-18 03:52:29 -07:00
return false ;
}
2018-07-16 12:17:01 -07:00
if ( pdcp_array . find ( lcid ) = = pdcp_array . end ( ) ) {
2017-05-18 03:52:29 -07:00
return false ;
}
2018-07-16 12:17:01 -07:00
2017-05-18 03:52:29 -07:00
return true ;
}
2018-05-15 07:57:23 -07:00
bool pdcp : : valid_mch_lcid ( uint32_t lcid )
{
2018-07-16 12:17:01 -07:00
if ( lcid > = SRSLTE_N_MCH_LCIDS ) {
2018-05-15 07:57:23 -07:00
pdcp_log - > error ( " Radio bearer id must be in [0:%d] - %d " , SRSLTE_N_RADIO_BEARERS , lcid ) ;
return false ;
}
2018-07-16 12:17:01 -07:00
if ( pdcp_array_mrb . find ( lcid ) = = pdcp_array_mrb . end ( ) ) {
2018-05-15 07:57:23 -07:00
return false ;
}
2018-07-16 12:17:01 -07:00
2018-05-15 07:57:23 -07:00
return true ;
}
2017-05-18 03:52:29 -07:00
} // namespace srsue