Commit f1419356 authored by Cedric Roux's avatar Cedric Roux

minimal pdcp: initial commit

traffic goes through, no security, no integrity verification
no reestablishment
parent cba6c72f
......@@ -1372,13 +1372,18 @@ set(RRC_DIR ${OPENAIR2_DIR}/RRC/LTE)
set(PDCP_DIR ${OPENAIR2_DIR}/LAYER2/PDCP_v10.1.0)
set(L2_SRC
${OPENAIR2_DIR}/LAYER2/openair2_proc.c
${PDCP_DIR}/pdcp.c
${PDCP_DIR}/pdcp_fifo.c
${PDCP_DIR}/pdcp_sequence_manager.c
${PDCP_DIR}/pdcp_primitives.c
${PDCP_DIR}/pdcp_util.c
${PDCP_DIR}/pdcp_security.c
${PDCP_DIR}/pdcp_netlink.c
# ${PDCP_DIR}/pdcp.c
# ${PDCP_DIR}/pdcp_fifo.c
# ${PDCP_DIR}/pdcp_sequence_manager.c
# ${PDCP_DIR}/pdcp_primitives.c
# ${PDCP_DIR}/pdcp_util.c
# ${PDCP_DIR}/pdcp_security.c
# ${PDCP_DIR}/pdcp_netlink.c
${OPENAIR2_DIR}/LAYER2/pdcp_v2/pdcp_oai_api.c
${OPENAIR2_DIR}/LAYER2/pdcp_v2/pdcp_ue_manager.c
${OPENAIR2_DIR}/LAYER2/pdcp_v2/pdcp_entity.c
${OPENAIR2_DIR}/LAYER2/pdcp_v2/pdcp_entity_srb.c
${OPENAIR2_DIR}/LAYER2/pdcp_v2/pdcp_entity_drb_am.c
${RLC_V2}
# ${RRC_DIR}/rrc_UE.c
${RRC_DIR}/rrc_eNB.c
......
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
#include "pdcp_entity.h"
#include "pdcp_entity_srb.h"
#include "pdcp_entity_drb_am.h"
#include "LOG/log.h"
pdcp_entity_t *new_pdcp_entity_srb(
int rb_id,
void (*deliver_sdu)(void *deliver_sdu_data, struct pdcp_entity_t *entity,
char *buf, int size),
void *deliver_sdu_data,
void (*deliver_pdu)(void *deliver_pdu_data, struct pdcp_entity_t *entity,
char *buf, int size, int sdu_id),
void *deliver_pdu_data)
{
pdcp_entity_srb_t *ret;
ret = calloc(1, sizeof(pdcp_entity_srb_t));
if (ret == NULL) {
LOG_E(PDCP, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__);
exit(1);
}
ret->common.recv_pdu = pdcp_entity_srb_recv_pdu;
ret->common.recv_sdu = pdcp_entity_srb_recv_sdu;
ret->common.set_integrity_key = pdcp_entity_srb_set_integrity_key;
ret->common.delete = pdcp_entity_srb_delete;
ret->common.deliver_sdu = deliver_sdu;
ret->common.deliver_sdu_data = deliver_sdu_data;
ret->common.deliver_pdu = deliver_pdu;
ret->common.deliver_pdu_data = deliver_pdu_data;
ret->rb_id = rb_id;
ret->common.maximum_pdcp_sn = 31;
return (pdcp_entity_t *)ret;
#if 0
ret->common.recv_pdu = rlc_entity_am_recv_pdu;
ret->common.buffer_status = rlc_entity_am_buffer_status;
ret->common.generate_pdu = rlc_entity_am_generate_pdu;
ret->common.recv_sdu = rlc_entity_am_recv_sdu;
ret->common.set_time = rlc_entity_am_set_time;
ret->common.discard_sdu = rlc_entity_am_discard_sdu;
ret->common.reestablishment = rlc_entity_am_reestablishment;
ret->common.delete = rlc_entity_am_delete;
ret->common.deliver_sdu = deliver_sdu;
ret->common.deliver_sdu_data = deliver_sdu_data;
ret->common.sdu_successful_delivery = sdu_successful_delivery;
ret->common.sdu_successful_delivery_data = sdu_successful_delivery_data;
ret->common.max_retx_reached = max_retx_reached;
ret->common.max_retx_reached_data = max_retx_reached_data;
ret->rx_maxsize = rx_maxsize;
ret->tx_maxsize = tx_maxsize;
ret->t_reordering = t_reordering;
ret->t_status_prohibit = t_status_prohibit;
ret->t_poll_retransmit = t_poll_retransmit;
ret->poll_pdu = poll_pdu;
ret->poll_byte = poll_byte;
ret->max_retx_threshold = max_retx_threshold;
return (rlc_entity_t *)ret;
#endif
}
pdcp_entity_t *new_pdcp_entity_drb_am(
int rb_id,
void (*deliver_sdu)(void *deliver_sdu_data, struct pdcp_entity_t *entity,
char *buf, int size),
void *deliver_sdu_data,
void (*deliver_pdu)(void *deliver_pdu_data, struct pdcp_entity_t *entity,
char *buf, int size, int sdu_id),
void *deliver_pdu_data)
{
pdcp_entity_drb_am_t *ret;
ret = calloc(1, sizeof(pdcp_entity_drb_am_t));
if (ret == NULL) {
LOG_E(PDCP, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__);
exit(1);
}
ret->common.recv_pdu = pdcp_entity_drb_am_recv_pdu;
ret->common.recv_sdu = pdcp_entity_drb_am_recv_sdu;
ret->common.set_integrity_key = pdcp_entity_drb_am_set_integrity_key;
ret->common.delete = pdcp_entity_drb_am_delete;
ret->common.deliver_sdu = deliver_sdu;
ret->common.deliver_sdu_data = deliver_sdu_data;
ret->common.deliver_pdu = deliver_pdu;
ret->common.deliver_pdu_data = deliver_pdu_data;
ret->rb_id = rb_id;
ret->common.maximum_pdcp_sn = 4095;
return (pdcp_entity_t *)ret;
}
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
#ifndef _PDCP_ENTITY_H_
#define _PDCP_ENTITY_H_
typedef struct pdcp_entity_t {
/* functions provided by the PDCP module */
void (*recv_pdu)(struct pdcp_entity_t *entity, char *buffer, int size);
void (*recv_sdu)(struct pdcp_entity_t *entity, char *buffer, int size,
int sdu_id);
void (*delete)(struct pdcp_entity_t *entity);
void (*set_integrity_key)(struct pdcp_entity_t *entity, char *key);
/* callbacks provided to the PDCP module */
void (*deliver_sdu)(void *deliver_sdu_data, struct pdcp_entity_t *entity,
char *buf, int size);
void *deliver_sdu_data;
void (*deliver_pdu)(void *deliver_pdu_data, struct pdcp_entity_t *entity,
char *buf, int size, int sdu_id);
void *deliver_pdu_data;
int tx_hfn;
int next_pdcp_tx_sn;
int maximum_pdcp_sn;
} pdcp_entity_t;
pdcp_entity_t *new_pdcp_entity_srb(
int rb_id,
void (*deliver_sdu)(void *deliver_sdu_data, struct pdcp_entity_t *entity,
char *buf, int size),
void *deliver_sdu_data,
void (*deliver_pdu)(void *deliver_pdu_data, struct pdcp_entity_t *entity,
char *buf, int size, int sdu_id),
void *deliver_pdu_data);
pdcp_entity_t *new_pdcp_entity_drb_am(
int rb_id,
void (*deliver_sdu)(void *deliver_sdu_data, struct pdcp_entity_t *entity,
char *buf, int size),
void *deliver_sdu_data,
void (*deliver_pdu)(void *deliver_pdu_data, struct pdcp_entity_t *entity,
char *buf, int size, int sdu_id),
void *deliver_pdu_data);
#endif /* _PDCP_ENTITY_H_ */
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
#include "pdcp_entity_drb_am.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void pdcp_entity_drb_am_recv_pdu(pdcp_entity_t *_entity, char *buffer, int size)
{
pdcp_entity_drb_am_t *entity = (pdcp_entity_drb_am_t *)_entity;
if (size < 3) abort();
if (!(buffer[0] & 0x80)) { printf("%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); exit(1); }
entity->common.deliver_sdu(entity->common.deliver_sdu_data,
(pdcp_entity_t *)entity, buffer+2, size-2);
}
void pdcp_entity_drb_am_recv_sdu(pdcp_entity_t *_entity, char *buffer, int size,
int sdu_id)
{
pdcp_entity_drb_am_t *entity = (pdcp_entity_drb_am_t *)_entity;
int sn;
char buf[size+2];
sn = entity->common.next_pdcp_tx_sn;
entity->common.next_pdcp_tx_sn++;
if (entity->common.next_pdcp_tx_sn > entity->common.maximum_pdcp_sn) {
entity->common.next_pdcp_tx_sn = 0;
entity->common.tx_hfn++;
}
buf[0] = 0x80 | ((sn >> 8) & 0x0f);
buf[1] = sn & 0xff;
memcpy(buf+2, buffer, size);
entity->common.deliver_pdu(entity->common.deliver_pdu_data,
(pdcp_entity_t *)entity, buf, size+2, sdu_id);
}
void pdcp_entity_drb_am_set_integrity_key(pdcp_entity_t *_entity, char *key)
{
/* nothing to do */
}
void pdcp_entity_drb_am_delete(pdcp_entity_t *_entity)
{
pdcp_entity_drb_am_t *entity = (pdcp_entity_drb_am_t *)_entity;
free(entity);
}
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
#ifndef _PDCP_ENTITY_DRB_AM_H_
#define _PDCP_ENTITY_DRB_AM_H_
#include "pdcp_entity.h"
typedef struct {
pdcp_entity_t common;
int rb_id;
} pdcp_entity_drb_am_t;
void pdcp_entity_drb_am_recv_pdu(pdcp_entity_t *entity, char *buffer, int size);
void pdcp_entity_drb_am_recv_sdu(pdcp_entity_t *entity, char *buffer, int size,
int sdu_id);
void pdcp_entity_drb_am_set_integrity_key(pdcp_entity_t *entity, char *key);
void pdcp_entity_drb_am_delete(pdcp_entity_t *entity);
#endif /* _PDCP_ENTITY_DRB_AM_H_ */
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
#include "pdcp_entity_srb.h"
#include <stdlib.h>
void pdcp_entity_srb_recv_pdu(pdcp_entity_t *_entity, char *buffer, int size)
{
pdcp_entity_srb_t *entity = (pdcp_entity_srb_t *)_entity;
entity->common.deliver_sdu(entity->common.deliver_sdu_data,
(pdcp_entity_t *)entity, buffer+1, size-5);
}
#include <string.h>
#include <stdint.h>
#include "UTIL/OSA/osa_defs.h"
void pdcp_entity_srb_recv_sdu(pdcp_entity_t *_entity, char *buffer, int size,
int sdu_id)
{
pdcp_entity_srb_t *entity = (pdcp_entity_srb_t *)_entity;
int sn;
char buf[size+5];
sn = entity->common.next_pdcp_tx_sn;
entity->common.next_pdcp_tx_sn++;
if (entity->common.next_pdcp_tx_sn > entity->common.maximum_pdcp_sn) {
entity->common.next_pdcp_tx_sn = 0;
entity->common.tx_hfn++;
}
buf[0] = sn & 0x1f;
memcpy(buf+1, buffer, size);
if (entity->integrity_active) {
stream_cipher_t params;
params.message = (unsigned char *)buf;
params.blength = (size + 1) << 3;
params.key = (unsigned char *)entity->key_integrity + 16;
params.key_length = 16;
params.count = (entity->common.tx_hfn << 5) | sn;
params.bearer = entity->rb_id - 1;
params.direction = SECU_DIRECTION_DOWNLINK;
printf("call stream_compute_integrity\n");
stream_compute_integrity(EIA2_128_ALG_ID, &params,
(unsigned char *)&buf[size+1]);
} else {
printf("no integrity\n");
buf[size+1] = 0;
buf[size+2] = 0;
buf[size+3] = 0;
buf[size+4] = 0;
}
entity->common.deliver_pdu(entity->common.deliver_pdu_data,
(pdcp_entity_t *)entity, buf, size+5, sdu_id);
}
void pdcp_entity_srb_set_integrity_key(pdcp_entity_t *_entity, char *key)
{
printf("activate integrity\n");
pdcp_entity_srb_t *entity = (pdcp_entity_srb_t *)_entity;
memcpy(entity->key_integrity, key, 32);
entity->integrity_active = 1;
}
void pdcp_entity_srb_delete(pdcp_entity_t *_entity)
{
pdcp_entity_srb_t *entity = (pdcp_entity_srb_t *)_entity;
free(entity);
}
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
#ifndef _PDCP_ENTITY_SRB_H_
#define _PDCP_ENTITY_SRB_H_
#include "pdcp_entity.h"
typedef struct {
pdcp_entity_t common;
int rb_id;
char key_integrity[32];
int integrity_active;
} pdcp_entity_srb_t;
void pdcp_entity_srb_recv_pdu(pdcp_entity_t *entity, char *buffer, int size);
void pdcp_entity_srb_recv_sdu(pdcp_entity_t *entity, char *buffer, int size,
int sdu_id);
void pdcp_entity_srb_set_integrity_key(pdcp_entity_t *entity, char *key);
void pdcp_entity_srb_delete(pdcp_entity_t *entity);
#endif /* _PDCP_ENTITY_SRB_H_ */
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
#include "pdcp_ue_manager.h"
/* from OAI */
#include "pdcp.h"
#include "targets/RT/USER/lte-softmodem.h"
#define TODO do { \
printf("%s:%d:%s: todo\n", __FILE__, __LINE__, __FUNCTION__); \
exit(1); \
} while (0)
static pdcp_ue_manager_t *pdcp_ue_manager;
/* necessary globals for OAI, not used internally */
hash_table_t *pdcp_coll_p;
static uint64_t pdcp_optmask;
/****************************************************************************/
/* rlc_data_req queue - begin */
/****************************************************************************/
#include <pthread.h>
/* New PDCP and RLC both use "big locks". In some cases a thread may do
* lock(rlc) followed by lock(pdcp) (typically when running 'rx_sdu').
* Another thread may first do lock(pdcp) and then lock(rlc) (typically
* the GTP module calls 'pdcp_data_req' that, in a previous implementation
* was indirectly calling 'rlc_data_req' which does lock(rlc)).
* To avoid the resulting deadlock it is enough to ensure that a call
* to lock(pdcp) will never be followed by a call to lock(rlc). So,
* here we chose to have a separate thread that deals with rlc_data_req,
* out of the PDCP lock. Other solutions may be possible.
* So instead of calling 'rlc_data_req' directly we have a queue and a
* separate thread emptying it.
*/
typedef struct {
protocol_ctxt_t ctxt_pP;
srb_flag_t srb_flagP;
MBMS_flag_t MBMS_flagP;
rb_id_t rb_idP;
mui_t muiP;
confirm_t confirmP;
sdu_size_t sdu_sizeP;
mem_block_t *sdu_pP;
} rlc_data_req_queue_item;
#define RLC_DATA_REQ_QUEUE_SIZE 10000
typedef struct {
rlc_data_req_queue_item q[RLC_DATA_REQ_QUEUE_SIZE];
volatile int start;
volatile int length;
pthread_mutex_t m;
pthread_cond_t c;
} rlc_data_req_queue;
static rlc_data_req_queue q;
static void *rlc_data_req_thread(void *_)
{
int i;
while (1) {
if (pthread_mutex_lock(&q.m) != 0) abort();
while (q.length == 0)
if (pthread_cond_wait(&q.c, &q.m) != 0) abort();
i = q.start;
if (pthread_mutex_unlock(&q.m) != 0) abort();
rlc_data_req(&q.q[i].ctxt_pP,
q.q[i].srb_flagP,
q.q[i].MBMS_flagP,
q.q[i].rb_idP,
q.q[i].muiP,
q.q[i].confirmP,
q.q[i].sdu_sizeP,
q.q[i].sdu_pP,
NULL,
NULL);
if (pthread_mutex_lock(&q.m) != 0) abort();
q.length--;
q.start = (q.start + 1) % RLC_DATA_REQ_QUEUE_SIZE;
if (pthread_cond_signal(&q.c) != 0) abort();
if (pthread_mutex_unlock(&q.m) != 0) abort();
}
}
static void init_rlc_data_req_queue(void)
{
pthread_t t;
pthread_mutex_init(&q.m, NULL);
pthread_cond_init(&q.c, NULL);
if (pthread_create(&t, NULL, rlc_data_req_thread, NULL) != 0) {
LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
exit(1);
}
}
static void enqueue_rlc_data_req(const protocol_ctxt_t *const ctxt_pP,
const srb_flag_t srb_flagP,
const MBMS_flag_t MBMS_flagP,
const rb_id_t rb_idP,
const mui_t muiP,
confirm_t confirmP,
sdu_size_t sdu_sizeP,
mem_block_t *sdu_pP,
void *_unused1, void *_unused2)
{
int i;
int logged = 0;
if (pthread_mutex_lock(&q.m) != 0) abort();
while (q.length == RLC_DATA_REQ_QUEUE_SIZE) {
if (!logged) {
logged = 1;
LOG_W(PDCP, "%s: rlc_data_req queue is full\n", __FUNCTION__);
}
if (pthread_cond_wait(&q.c, &q.m) != 0) abort();
}
i = (q.start + q.length) % RLC_DATA_REQ_QUEUE_SIZE;
q.length++;
q.q[i].ctxt_pP = *ctxt_pP;
q.q[i].srb_flagP = srb_flagP;
q.q[i].MBMS_flagP = MBMS_flagP;
q.q[i].rb_idP = rb_idP;
q.q[i].muiP = muiP;
q.q[i].confirmP = confirmP;
q.q[i].sdu_sizeP = sdu_sizeP;
q.q[i].sdu_pP = sdu_pP;
if (pthread_cond_signal(&q.c) != 0) abort();
if (pthread_mutex_unlock(&q.m) != 0) abort();
}
/****************************************************************************/
/* rlc_data_req queue - end */
/****************************************************************************/
void pdcp_layer_init(void)
{
/* be sure to initialize only once */
static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
static int initialized = 0;
if (pthread_mutex_lock(&m) != 0) abort();
if (initialized) {
if (pthread_mutex_unlock(&m) != 0) abort();
return;
}
initialized = 1;
if (pthread_mutex_unlock(&m) != 0) abort();
pdcp_ue_manager = new_pdcp_ue_manager(1);
init_rlc_data_req_queue();
}
uint64_t pdcp_module_init(uint64_t _pdcp_optmask)
{
pdcp_optmask = _pdcp_optmask;
return pdcp_optmask;
}
static void deliver_sdu_drb(void *_ue, pdcp_entity_t *entity,
char *buf, int size)
{
pdcp_ue_t *ue = _ue;
MessageDef *message_p;
uint8_t *gtpu_buffer_p;
int rb_id;
int i;
for (i = 0; i < 5; i++) {
if (entity == ue->drb[i]) {
rb_id = i+1;
goto rb_found;
}
}
LOG_E(PDCP, "%s:%d:%s: fatal, no RB found for ue %d\n",
__FILE__, __LINE__, __FUNCTION__, ue->rnti);
exit(1);
rb_found:
gtpu_buffer_p = itti_malloc(TASK_PDCP_ENB, TASK_GTPV1_U,
size + GTPU_HEADER_OVERHEAD_MAX);
AssertFatal(gtpu_buffer_p != NULL, "OUT OF MEMORY");
memcpy(&gtpu_buffer_p[GTPU_HEADER_OVERHEAD_MAX], buf, size);
message_p = itti_alloc_new_message(TASK_PDCP_ENB, GTPV1U_ENB_TUNNEL_DATA_REQ);
AssertFatal(message_p != NULL, "OUT OF MEMORY");
GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).buffer = gtpu_buffer_p;
GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).length = size;
GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).offset = GTPU_HEADER_OVERHEAD_MAX;
GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).rnti = ue->rnti;
GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).rab_id = rb_id + 4;
printf("!!!!!!! deliver_sdu_drb (drb %d) sending message to gtp size %d: ", rb_id, size);
//for (i = 0; i < size; i++) printf(" %2.2x", (unsigned char)buf[i]);
printf("\n");
itti_send_msg_to_task(TASK_GTPV1_U, INSTANCE_DEFAULT, message_p);
}
static void deliver_pdu_drb(void *_ue, pdcp_entity_t *entity,
char *buf, int size, int sdu_id)
{
pdcp_ue_t *ue = _ue;
int rb_id;
protocol_ctxt_t ctxt;
int i;
mem_block_t *memblock;
for (i = 0; i < 5; i++) {
if (entity == ue->drb[i]) {
rb_id = i+1;
goto rb_found;
}
}
LOG_E(PDCP, "%s:%d:%s: fatal, no RB found for ue %d\n",
__FILE__, __LINE__, __FUNCTION__, ue->rnti);
exit(1);
rb_found:
ctxt.module_id = 0;
ctxt.enb_flag = 1;
ctxt.instance = 0;
ctxt.frame = 0;
ctxt.subframe = 0;
ctxt.eNB_index = 0;
ctxt.configured = 1;
ctxt.brOption = 0;
ctxt.rnti = ue->rnti;
memblock = get_free_mem_block(size, __FUNCTION__);
memcpy(memblock->data, buf, size);
printf("!!!!!!! deliver_pdu_drb (srb %d) calling rlc_data_req size %d: ", rb_id, size);
//for (i = 0; i < size; i++) printf(" %2.2x", (unsigned char)memblock->data[i]);
printf("\n");
enqueue_rlc_data_req(&ctxt, 0, MBMS_FLAG_NO, rb_id, sdu_id, 0, size, memblock, NULL, NULL);
}
static void deliver_sdu_srb(void *_ue, pdcp_entity_t *entity,
char *buf, int size)
{
pdcp_ue_t *ue = _ue;
int rb_id;
protocol_ctxt_t ctxt;
int i;
for (i = 0; i < 2; i++) {
if (entity == ue->srb[i]) {
rb_id = i+1;
goto rb_found;
}
}
LOG_E(PDCP, "%s:%d:%s: fatal, no RB found for ue %d\n",
__FILE__, __LINE__, __FUNCTION__, ue->rnti);
exit(1);
rb_found:
ctxt.module_id = 0;
ctxt.enb_flag = 1;
ctxt.instance = 0;
ctxt.frame = 0;
ctxt.subframe = 0;
ctxt.eNB_index = 0;
ctxt.configured = 1;
ctxt.brOption = 0;
ctxt.rnti = ue->rnti;
printf("!!!!!!! deliver_sdu_srb (srb %d) calling rrc_data_ind size %d: ", rb_id, size);
//for (i = 0; i < size; i++) printf(" %2.2x", (unsigned char)buf[i]);
printf("\n");
rrc_data_ind(&ctxt, rb_id, size, (unsigned char *)buf);
}
static void deliver_pdu_srb(void *_ue, pdcp_entity_t *entity,
char *buf, int size, int sdu_id)
{
pdcp_ue_t *ue = _ue;
int rb_id;
protocol_ctxt_t ctxt;
int i;
mem_block_t *memblock;
for (i = 0; i < 2; i++) {
if (entity == ue->srb[i]) {
rb_id = i+1;
goto rb_found;
}
}
LOG_E(PDCP, "%s:%d:%s: fatal, no RB found for ue %d\n",
__FILE__, __LINE__, __FUNCTION__, ue->rnti);
exit(1);
rb_found:
ctxt.module_id = 0;
ctxt.enb_flag = 1;
ctxt.instance = 0;
ctxt.frame = 0;
ctxt.subframe = 0;
ctxt.eNB_index = 0;
ctxt.configured = 1;
ctxt.brOption = 0;
ctxt.rnti = ue->rnti;
memblock = get_free_mem_block(size, __FUNCTION__);
memcpy(memblock->data, buf, size);
printf("!!!!!!! deliver_pdu_srb (srb %d) calling rlc_data_req size %d: ", rb_id, size);
//for (i = 0; i < size; i++) printf(" %2.2x", (unsigned char)memblock->data[i]);
printf("\n");
enqueue_rlc_data_req(&ctxt, 1, MBMS_FLAG_NO, rb_id, sdu_id, 0, size, memblock, NULL, NULL);
}
boolean_t pdcp_data_ind(
const protocol_ctxt_t *const ctxt_pP,
const srb_flag_t srb_flagP,
const MBMS_flag_t MBMS_flagP,
const rb_id_t rb_id,
const sdu_size_t sdu_buffer_size,
mem_block_t *const sdu_buffer)
{
pdcp_ue_t *ue;
pdcp_entity_t *rb;
int rnti = ctxt_pP->rnti;
if (ctxt_pP->module_id != 0 ||
ctxt_pP->enb_flag != 1 ||
ctxt_pP->instance != 0 ||
ctxt_pP->eNB_index != 0 ||
ctxt_pP->configured != 1 ||
ctxt_pP->brOption != 0) {
LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
exit(1);
}
if (ctxt_pP->enb_flag)
T(T_ENB_PDCP_UL, T_INT(ctxt_pP->module_id), T_INT(rnti),
T_INT(rb_id), T_INT(sdu_buffer_size));
pdcp_manager_lock(pdcp_ue_manager);
ue = pdcp_manager_get_ue(pdcp_ue_manager, rnti);
if (srb_flagP == 1) {
if (rb_id < 1 || rb_id > 2)
rb = NULL;
else
rb = ue->srb[rb_id - 1];
} else {
if (rb_id < 1 || rb_id > 5)
rb = NULL;
else
rb = ue->drb[rb_id - 1];
}
if (rb != NULL) {
rb->recv_pdu(rb, (char *)sdu_buffer->data, sdu_buffer_size);
} else {
LOG_E(PDCP, "%s:%d:%s: fatal: no RB found (rb_id %d, srb_flag %d)\n",
__FILE__, __LINE__, __FUNCTION__, rb_id, srb_flagP);
exit(1);
}
pdcp_manager_unlock(pdcp_ue_manager);
free_mem_block(sdu_buffer, __FUNCTION__);
return 1;
}
void pdcp_run(const protocol_ctxt_t *const ctxt_pP)
{
MessageDef *msg_p;
int result;
protocol_ctxt_t ctxt;
while (1) {
itti_poll_msg(ctxt_pP->enb_flag ? TASK_PDCP_ENB : TASK_PDCP_UE, &msg_p);
if (msg_p == NULL)
break;
switch (ITTI_MSG_ID(msg_p)) {
case RRC_DCCH_DATA_REQ:
PROTOCOL_CTXT_SET_BY_MODULE_ID(
&ctxt,
RRC_DCCH_DATA_REQ(msg_p).module_id,
RRC_DCCH_DATA_REQ(msg_p).enb_flag,
RRC_DCCH_DATA_REQ(msg_p).rnti,
RRC_DCCH_DATA_REQ(msg_p).frame,
0,
RRC_DCCH_DATA_REQ(msg_p).eNB_index);
result = pdcp_data_req(&ctxt,
SRB_FLAG_YES,
RRC_DCCH_DATA_REQ(msg_p).rb_id,
RRC_DCCH_DATA_REQ(msg_p).muip,
RRC_DCCH_DATA_REQ(msg_p).confirmp,
RRC_DCCH_DATA_REQ(msg_p).sdu_size,
RRC_DCCH_DATA_REQ(msg_p).sdu_p,
RRC_DCCH_DATA_REQ(msg_p).mode,
NULL, NULL);
if (result != TRUE)
LOG_E(PDCP, "PDCP data request failed!\n");
result = itti_free(ITTI_MSG_ORIGIN_ID(msg_p), RRC_DCCH_DATA_REQ(msg_p).sdu_p);
AssertFatal(result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
break;
default:
LOG_E(PDCP, "Received unexpected message %s\n", ITTI_MSG_NAME(msg_p));
break;
}
}
}
static void add_srb(int rnti, struct LTE_SRB_ToAddMod *s)
{
pdcp_entity_t *pdcp_srb;
pdcp_ue_t *ue;
int srb_id = s->srb_Identity;
printf("\n\n################# add srb %d\n\n\n", srb_id);
if (srb_id != 1 && srb_id != 2) {
LOG_E(PDCP, "%s:%d:%s: fatal, bad srb id %d\n",
__FILE__, __LINE__, __FUNCTION__, srb_id);
exit(1);
}
pdcp_manager_lock(pdcp_ue_manager);
ue = pdcp_manager_get_ue(pdcp_ue_manager, rnti);
if (ue->srb[srb_id-1] != NULL) {
LOG_D(PDCP, "%s:%d:%s: warning SRB %d already exist for ue %d, do nothing\n",
__FILE__, __LINE__, __FUNCTION__, srb_id, rnti);
} else {
pdcp_srb = new_pdcp_entity_srb(srb_id, deliver_sdu_srb, ue, deliver_pdu_srb, ue);
pdcp_ue_add_srb_pdcp_entity(ue, srb_id, pdcp_srb);
LOG_D(PDCP, "%s:%d:%s: added srb %d to ue %d\n",
__FILE__, __LINE__, __FUNCTION__, srb_id, rnti);
}
pdcp_manager_unlock(pdcp_ue_manager);
}
static void add_drb_am(int rnti, struct LTE_DRB_ToAddMod *s)
{
pdcp_entity_t *pdcp_drb;
pdcp_ue_t *ue;
int drb_id = s->drb_Identity;
printf("\n\n################# add drb %d\n\n\n", drb_id);
if (drb_id != 1) {
LOG_E(PDCP, "%s:%d:%s: fatal, bad drb id %d\n",
__FILE__, __LINE__, __FUNCTION__, drb_id);
exit(1);
}
pdcp_manager_lock(pdcp_ue_manager);
ue = pdcp_manager_get_ue(pdcp_ue_manager, rnti);
if (ue->drb[drb_id-1] != NULL) {
LOG_D(PDCP, "%s:%d:%s: warning SRB %d already exist for ue %d, do nothing\n",
__FILE__, __LINE__, __FUNCTION__, drb_id, rnti);
} else {
pdcp_drb = new_pdcp_entity_drb_am(drb_id, deliver_sdu_drb, ue, deliver_pdu_drb, ue);
pdcp_ue_add_drb_pdcp_entity(ue, drb_id, pdcp_drb);
LOG_D(PDCP, "%s:%d:%s: added drb %d to ue %d\n",
__FILE__, __LINE__, __FUNCTION__, drb_id, rnti);
}
pdcp_manager_unlock(pdcp_ue_manager);
}
static void add_drb(int rnti, struct LTE_DRB_ToAddMod *s)
{
switch (s->rlc_Config->present) {
case LTE_RLC_Config_PR_am:
add_drb_am(rnti, s);
break;
case LTE_RLC_Config_PR_um_Bi_Directional:
//add_drb_um(rnti, s);
TODO;
break;
default:
LOG_E(PDCP, "%s:%d:%s: fatal: unhandled DRB type\n",
__FILE__, __LINE__, __FUNCTION__);
exit(1);
}
}
boolean_t rrc_pdcp_config_asn1_req(
const protocol_ctxt_t *const ctxt_pP,
LTE_SRB_ToAddModList_t *const srb2add_list,
LTE_DRB_ToAddModList_t *const drb2add_list,
LTE_DRB_ToReleaseList_t *const drb2release_list,
const uint8_t security_modeP,
uint8_t *const kRRCenc,
uint8_t *const kRRCint,
uint8_t *const kUPenc
#if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0))
,LTE_PMCH_InfoList_r9_t *pmch_InfoList_r9
#endif
,rb_id_t *const defaultDRB)
{
int rnti = ctxt_pP->rnti;
int i;
if (ctxt_pP->enb_flag != 1 ||
ctxt_pP->module_id != 0 ||
ctxt_pP->instance != 0 ||
ctxt_pP->eNB_index != 0 ||
//ctxt_pP->configured != 2 ||
//srb2add_list == NULL ||
//drb2add_list != NULL ||
drb2release_list != NULL ||
security_modeP != 255 ||
//kRRCenc != NULL ||
//kRRCint != NULL ||
//kUPenc != NULL ||
pmch_InfoList_r9 != NULL ||
defaultDRB != NULL) {
TODO;
}
if (srb2add_list != NULL) {
for (i = 0; i < srb2add_list->list.count; i++) {
add_srb(rnti, srb2add_list->list.array[i]);
}
}
if (drb2add_list != NULL) {
for (i = 0; i < drb2add_list->list.count; i++) {
add_drb(rnti, drb2add_list->list.array[i]);
}
}
/* update security */
if (kRRCint != NULL) {
/* todo */
}
free(kRRCenc);
free(kRRCint);
free(kUPenc);
return 0;
}
uint64_t get_pdcp_optmask(void)
{
TODO;
}
boolean_t pdcp_remove_UE(
const protocol_ctxt_t *const ctxt_pP)
{
LOG_D(RLC, "%s:%d:%s: remove UE %d\n", __FILE__, __LINE__, __FUNCTION__, ctxt_pP->rnti);
pdcp_manager_lock(pdcp_ue_manager);
pdcp_manager_remove_ue(pdcp_ue_manager, ctxt_pP->rnti);
pdcp_manager_unlock(pdcp_ue_manager);
return 1;
}
void pdcp_config_set_security(const protocol_ctxt_t* const ctxt_pP, pdcp_t *pdcp_pP, rb_id_t rb_id,
uint16_t lc_idP, uint8_t security_modeP, uint8_t *kRRCenc_pP, uint8_t *kRRCint_pP, uint8_t *kUPenc_pP)
{
pdcp_ue_t *ue;
pdcp_entity_t *rb;
int rnti = ctxt_pP->rnti;
if (ctxt_pP->module_id != 0 ||
ctxt_pP->enb_flag != 1 ||
ctxt_pP->instance != 0 ||
ctxt_pP->eNB_index != 0) {
LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
exit(1);
}
pdcp_manager_lock(pdcp_ue_manager);
ue = pdcp_manager_get_ue(pdcp_ue_manager, rnti);
if (rb_id < 1 || rb_id > 2)
rb = NULL;
else
rb = ue->srb[rb_id - 1];
if (rb == NULL) {
LOG_E(PDCP, "%s:%d:%s: fatal: no SRB found (rb_id %d)\n",
__FILE__, __LINE__, __FUNCTION__, rb_id);
exit(1);
}
if (kRRCint_pP != NULL)
rb->set_integrity_key(rb, (char *)kRRCint_pP);
pdcp_manager_unlock(pdcp_ue_manager);
free(kRRCenc_pP);
free(kRRCint_pP);
free(kUPenc_pP);
}
static boolean_t pdcp_data_req_srb(
protocol_ctxt_t *ctxt_pP,
const rb_id_t rb_id,
const mui_t muiP,
const confirm_t confirmP,
const sdu_size_t sdu_buffer_size,
unsigned char *const sdu_buffer)
{
pdcp_ue_t *ue;
pdcp_entity_t *rb;
int rnti = ctxt_pP->rnti;
if (ctxt_pP->module_id != 0 ||
ctxt_pP->enb_flag != 1 ||
ctxt_pP->instance != 0 ||
ctxt_pP->eNB_index != 0 /*||
ctxt_pP->configured != 1 ||
ctxt_pP->brOption != 0*/) {
LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
exit(1);
}
pdcp_manager_lock(pdcp_ue_manager);
ue = pdcp_manager_get_ue(pdcp_ue_manager, rnti);
if (rb_id < 1 || rb_id > 2)
rb = NULL;
else
rb = ue->srb[rb_id - 1];
if (rb == NULL) {
LOG_E(PDCP, "%s:%d:%s: fatal: no SRB found (rb_id %d)\n",
__FILE__, __LINE__, __FUNCTION__, rb_id);
exit(1);
}
rb->recv_sdu(rb, (char *)sdu_buffer, sdu_buffer_size, muiP);
pdcp_manager_unlock(pdcp_ue_manager);
return 1;
}
static boolean_t pdcp_data_req_drb(
protocol_ctxt_t *ctxt_pP,
const rb_id_t rb_id,
const mui_t muiP,
const confirm_t confirmP,
const sdu_size_t sdu_buffer_size,
unsigned char *const sdu_buffer)
{
pdcp_ue_t *ue;
pdcp_entity_t *rb;
int rnti = ctxt_pP->rnti;
if (ctxt_pP->module_id != 0 ||
ctxt_pP->enb_flag != 1 ||
ctxt_pP->instance != 0 ||
ctxt_pP->eNB_index != 0 /*||
ctxt_pP->configured != 1 ||
ctxt_pP->brOption != 0*/) {
LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
exit(1);
}
pdcp_manager_lock(pdcp_ue_manager);
ue = pdcp_manager_get_ue(pdcp_ue_manager, rnti);
if (rb_id < 1 || rb_id > 5)
rb = NULL;
else
rb = ue->drb[rb_id - 1];
if (rb == NULL) {
LOG_E(PDCP, "%s:%d:%s: fatal: no DRB found (rb_id %d)\n",
__FILE__, __LINE__, __FUNCTION__, rb_id);
exit(1);
}
rb->recv_sdu(rb, (char *)sdu_buffer, sdu_buffer_size, muiP);
pdcp_manager_unlock(pdcp_ue_manager);
return 1;
}
boolean_t pdcp_data_req(
protocol_ctxt_t *ctxt_pP,
const srb_flag_t srb_flagP,
const rb_id_t rb_id,
const mui_t muiP,
const confirm_t confirmP,
const sdu_size_t sdu_buffer_size,
unsigned char *const sdu_buffer,
const pdcp_transmission_mode_t mode
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
,const uint32_t *const sourceL2Id
,const uint32_t *const destinationL2Id
#endif
)
{
if (srb_flagP)
return pdcp_data_req_srb(ctxt_pP, rb_id, muiP, confirmP, sdu_buffer_size,
sdu_buffer);
return pdcp_data_req_drb(ctxt_pP, rb_id, muiP, confirmP, sdu_buffer_size,
sdu_buffer);
}
void pdcp_set_pdcp_data_ind_func(pdcp_data_ind_func_t pdcp_data_ind)
{
/* nothing to do */
}
void pdcp_set_rlc_data_req_func(send_rlc_data_req_func_t send_rlc_data_req)
{
/* nothing to do */
}
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
#include "pdcp_ue_manager.h"
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include "LOG/log.h"
typedef struct {
pthread_mutex_t lock;
pdcp_ue_t **ue_list;
int ue_count;
int enb_flag;
} pdcp_ue_manager_internal_t;
pdcp_ue_manager_t *new_pdcp_ue_manager(int enb_flag)
{
pdcp_ue_manager_internal_t *ret;
ret = calloc(1, sizeof(pdcp_ue_manager_internal_t));
if (ret == NULL) {
LOG_E(PDCP, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__);
exit(1);
}
if (pthread_mutex_init(&ret->lock, NULL)) abort();
ret->enb_flag = enb_flag;
return ret;
}
int pdcp_manager_get_enb_flag(pdcp_ue_manager_t *_m)
{
pdcp_ue_manager_internal_t *m = _m;
return m->enb_flag;
}
void pdcp_manager_lock(pdcp_ue_manager_t *_m)
{
pdcp_ue_manager_internal_t *m = _m;
if (pthread_mutex_lock(&m->lock)) {
LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
exit(1);
}
}
void pdcp_manager_unlock(pdcp_ue_manager_t *_m)
{
pdcp_ue_manager_internal_t *m = _m;
if (pthread_mutex_unlock(&m->lock)) {
LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
exit(1);
}
}
/* must be called with lock acquired */
pdcp_ue_t *pdcp_manager_get_ue(pdcp_ue_manager_t *_m, int rnti)
{
/* TODO: optimze */
pdcp_ue_manager_internal_t *m = _m;
int i;
for (i = 0; i < m->ue_count; i++)
if (m->ue_list[i]->rnti == rnti)
return m->ue_list[i];
LOG_D(PDCP, "%s:%d:%s: new UE %d\n", __FILE__, __LINE__, __FUNCTION__, rnti);
m->ue_count++;
m->ue_list = realloc(m->ue_list, sizeof(pdcp_ue_t *) * m->ue_count);
if (m->ue_list == NULL) {
LOG_E(PDCP, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__);
exit(1);
}
m->ue_list[m->ue_count-1] = calloc(1, sizeof(pdcp_ue_t));
if (m->ue_list[m->ue_count-1] == NULL) {
LOG_E(PDCP, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__);
exit(1);
}
m->ue_list[m->ue_count-1]->rnti = rnti;
return m->ue_list[m->ue_count-1];
}
/* must be called with lock acquired */
void pdcp_manager_remove_ue(pdcp_ue_manager_t *_m, int rnti)
{
pdcp_ue_manager_internal_t *m = _m;
pdcp_ue_t *ue;
int i;
int j;
for (i = 0; i < m->ue_count; i++)
if (m->ue_list[i]->rnti == rnti)
break;
if (i == m->ue_count) {
LOG_D(PDCP, "%s:%d:%s: warning: ue %d not found\n",
__FILE__, __LINE__, __FUNCTION__,
rnti);
return;
}
ue = m->ue_list[i];
for (j = 0; j < 2; j++)
if (ue->srb[j] != NULL)
ue->srb[j]->delete(ue->srb[j]);
for (j = 0; j < 5; j++)
if (ue->drb[j] != NULL)
ue->drb[j]->delete(ue->drb[j]);
free(ue);
m->ue_count--;
if (m->ue_count == 0) {
free(m->ue_list);
m->ue_list = NULL;
return;
}
memmove(&m->ue_list[i], &m->ue_list[i+1],
(m->ue_count - i) * sizeof(pdcp_ue_t *));
m->ue_list = realloc(m->ue_list, m->ue_count * sizeof(pdcp_ue_t *));
if (m->ue_list == NULL) {
LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
exit(1);
}
}
/* must be called with lock acquired */
void pdcp_ue_add_srb_pdcp_entity(pdcp_ue_t *ue, int srb_id, pdcp_entity_t *entity)
{
if (srb_id < 1 || srb_id > 2) {
LOG_E(PDCP, "%s:%d:%s: fatal, bad srb id\n", __FILE__, __LINE__, __FUNCTION__);
exit(1);
}
srb_id--;
if (ue->srb[srb_id] != NULL) {
LOG_E(PDCP, "%s:%d:%s: fatal, srb already present\n",
__FILE__, __LINE__, __FUNCTION__);
exit(1);
}
ue->srb[srb_id] = entity;
}
/* must be called with lock acquired */
void pdcp_ue_add_drb_pdcp_entity(pdcp_ue_t *ue, int drb_id, pdcp_entity_t *entity)
{
if (drb_id < 1 || drb_id > 5) {
LOG_E(PDCP, "%s:%d:%s: fatal, bad drb id\n", __FILE__, __LINE__, __FUNCTION__);
exit(1);
}
drb_id--;
if (ue->drb[drb_id] != NULL) {
LOG_E(PDCP, "%s:%d:%s: fatal, drb already present\n",
__FILE__, __LINE__, __FUNCTION__);
exit(1);
}
ue->drb[drb_id] = entity;
}
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
#ifndef _PDCP_UE_MANAGER_H_
#define _PDCP_UE_MANAGER_H_
#include "pdcp_entity.h"
typedef void pdcp_ue_manager_t;
typedef struct pdcp_ue_t {
int rnti;
pdcp_entity_t *srb[2];
pdcp_entity_t *drb[5];
} pdcp_ue_t;
/***********************************************************************/
/* manager functions */
/***********************************************************************/
pdcp_ue_manager_t *new_pdcp_ue_manager(int enb_flag);
int pdcp_manager_get_enb_flag(pdcp_ue_manager_t *m);
void pdcp_manager_lock(pdcp_ue_manager_t *m);
void pdcp_manager_unlock(pdcp_ue_manager_t *m);
pdcp_ue_t *pdcp_manager_get_ue(pdcp_ue_manager_t *m, int rnti);
void pdcp_manager_remove_ue(pdcp_ue_manager_t *m, int rnti);
/***********************************************************************/
/* ue functions */
/***********************************************************************/
void pdcp_ue_add_srb_pdcp_entity(pdcp_ue_t *ue, int srb_id,
pdcp_entity_t *entity);
void pdcp_ue_add_drb_pdcp_entity(pdcp_ue_t *ue, int drb_id,
pdcp_entity_t *entity);
#endif /* _PDCP_UE_MANAGER_H_ */
......@@ -561,7 +561,7 @@ rrc_pdcp_config_security(
key = PDCP_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, DCCH, SRB_FLAG_YES);
h_rc = hashtable_get(pdcp_coll_p, key, (void **)&pdcp_p);
if (h_rc == HASH_TABLE_OK) {
if (1 || h_rc == HASH_TABLE_OK) {
pdcp_config_set_security(
ctxt_pP,
pdcp_p,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment