Commit 384f899b authored by hardy's avatar hardy

Merge remote-tracking branch 'origin/nr-pdcp-improvements' into integration_2021_wk10

parents 04e8df62 9edc8cce
...@@ -1967,7 +1967,8 @@ set(NR_PDCP_SRC ...@@ -1967,7 +1967,8 @@ set(NR_PDCP_SRC
${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_oai_api.c ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_oai_api.c
${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_ue_manager.c ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_ue_manager.c
${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_entity.c ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_entity.c
${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.c ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_sdu.c
${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_timer_thread.c
${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_security_nea2.c ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_security_nea2.c
${OPENAIR2_DIR}/LAYER2/nr_pdcp/asn1_utils.c ${OPENAIR2_DIR}/LAYER2/nr_pdcp/asn1_utils.c
) )
......
...@@ -364,7 +364,9 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, ...@@ -364,7 +364,9 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP,
/* send tick to RLC and RRC every ms */ /* send tick to RLC and RRC every ms */
if ((slot & ((1 << *scc->ssbSubcarrierSpacing) - 1)) == 0) { if ((slot & ((1 << *scc->ssbSubcarrierSpacing) - 1)) == 0) {
void nr_rlc_tick(int frame, int subframe); void nr_rlc_tick(int frame, int subframe);
void nr_pdcp_tick(int frame, int subframe);
nr_rlc_tick(frame, slot >> *scc->ssbSubcarrierSpacing); nr_rlc_tick(frame, slot >> *scc->ssbSubcarrierSpacing);
nr_pdcp_tick(frame, slot >> *scc->ssbSubcarrierSpacing);
nr_rrc_trigger(&ctxt, 0 /*CC_id*/, frame, slot >> *scc->ssbSubcarrierSpacing); nr_rrc_trigger(&ctxt, 0 /*CC_id*/, frame, slot >> *scc->ssbSubcarrierSpacing);
} }
......
...@@ -21,24 +21,222 @@ ...@@ -21,24 +21,222 @@
#include "nr_pdcp_entity.h" #include "nr_pdcp_entity.h"
#include "nr_pdcp_entity_drb_am.h" #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "nr_pdcp_security_nea2.h" #include "nr_pdcp_security_nea2.h"
#include "nr_pdcp_sdu.h"
#include "LOG/log.h" #include "LOG/log.h"
nr_pdcp_entity_t *new_nr_pdcp_entity_srb( static void nr_pdcp_entity_recv_pdu(nr_pdcp_entity_t *entity,
int is_gnb, int rb_id, char *_buffer, int size)
void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity,
char *buf, int size),
void *deliver_sdu_data,
void (*deliver_pdu)(void *deliver_pdu_data, struct nr_pdcp_entity_t *entity,
char *buf, int size, int sdu_id),
void *deliver_pdu_data)
{ {
abort(); unsigned char *buffer = (unsigned char *)_buffer;
nr_pdcp_sdu_t *sdu;
int rcvd_sn;
uint32_t rcvd_hfn;
uint32_t rcvd_count;
int header_size;
int integrity_size;
int rx_deliv_sn;
uint32_t rx_deliv_hfn;
if (size < 1) {
LOG_E(PDCP, "bad PDU received (size = %d)\n", size);
return;
}
if (!(buffer[0] & 0x80)) {
LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
exit(1);
}
if (entity->sn_size == 12) {
rcvd_sn = (((unsigned char)buffer[0] & 0xf) << 8) |
(unsigned char)buffer[1];
header_size = 2;
} else {
rcvd_sn = (((unsigned char)buffer[0] & 0x3) << 16) |
((unsigned char)buffer[1] << 8) |
(unsigned char)buffer[2];
header_size = 3;
}
integrity_size = 0;
if (size < header_size + integrity_size + 1) {
LOG_E(PDCP, "bad PDU received (size = %d)\n", size);
return;
}
rx_deliv_sn = entity->rx_deliv & entity->sn_max;
rx_deliv_hfn = (entity->rx_deliv >> entity->sn_size) & ~entity->sn_max;
if (rcvd_sn < rx_deliv_sn - entity->window_size) {
rcvd_hfn = rx_deliv_hfn + 1;
} else if (rcvd_sn >= rx_deliv_sn + entity->window_size) {
rcvd_hfn = rx_deliv_hfn - 1;
} else {
rcvd_hfn = rx_deliv_hfn;
}
rcvd_count = (rcvd_hfn << entity->sn_size) | rcvd_sn;
if (entity->has_ciphering)
entity->cipher(entity->security_context,
(unsigned char *)buffer+header_size, size-header_size,
entity->rb_id, rcvd_count, entity->is_gnb ? 0 : 1);
if (rcvd_count < entity->rx_deliv
|| nr_pdcp_sdu_in_list(entity->rx_list, rcvd_count)) {
LOG_D(PDCP, "discard NR PDU rcvd_count=%d\n", rcvd_count);
return;
}
sdu = nr_pdcp_new_sdu(rcvd_count,
(char *)buffer + header_size,
size - header_size - integrity_size);
entity->rx_list = nr_pdcp_sdu_list_add(entity->rx_list, sdu);
entity->rx_size += size-header_size;
if (rcvd_count >= entity->rx_next) {
entity->rx_next = rcvd_count + 1;
}
/* TODO(?): out of order delivery */
if (rcvd_count == entity->rx_deliv) {
/* deliver all SDUs starting from rx_deliv up to discontinuity or end of list */
uint32_t count = entity->rx_deliv;
while (entity->rx_list != NULL && count == entity->rx_list->count) {
nr_pdcp_sdu_t *cur = entity->rx_list;
entity->deliver_sdu(entity->deliver_sdu_data, entity,
cur->buffer, cur->size);
entity->rx_list = cur->next;
entity->rx_size -= cur->size;
nr_pdcp_free_sdu(cur);
count++;
}
entity->rx_deliv = count;
}
if (entity->t_reordering_start != 0 && entity->rx_deliv > entity->rx_reord) {
/* stop and reset t-Reordering */
entity->t_reordering_start = 0;
}
if (entity->t_reordering_start == 0 && entity->rx_deliv < entity->rx_next) {
entity->rx_reord = entity->rx_next;
entity->t_reordering_start = entity->t_current;
}
} }
nr_pdcp_entity_t *new_nr_pdcp_entity_drb_am( static void nr_pdcp_entity_recv_sdu(nr_pdcp_entity_t *entity,
char *buffer, int size, int sdu_id)
{
uint32_t count;
int sn;
int header_size;
char buf[size+3+4];
count = entity->tx_next;
sn = entity->tx_next & entity->sn_max;
if (entity->sn_size == 12) {
buf[0] = 0x80 | ((sn >> 8) & 0xf);
buf[1] = sn & 0xff;
header_size = 2;
} else {
buf[0] = 0x80 | ((sn >> 16) & 0x3);
buf[1] = (sn >> 8) & 0xff;
buf[2] = sn & 0xff;
header_size = 3;
}
memcpy(buf+header_size, buffer, size);
if (entity->has_ciphering)
entity->cipher(entity->security_context,
(unsigned char *)buf+header_size, size,
entity->rb_id, count, entity->is_gnb ? 1 : 0);
entity->tx_next++;
entity->deliver_pdu(entity->deliver_pdu_data, entity, buf,
size+header_size, sdu_id);
}
static void nr_pdcp_entity_set_integrity_key(nr_pdcp_entity_t *entity,
char *key)
{
memcpy(entity->integrity_key, key, 16);
}
static void check_t_reordering(nr_pdcp_entity_t *entity)
{
uint32_t count;
if (entity->t_reordering_start == 0
|| entity->t_current <= entity->t_reordering_start + entity->t_reordering)
return;
/* stop timer */
entity->t_reordering_start = 0;
/* deliver all SDUs with count < rx_reord */
while (entity->rx_list != NULL && entity->rx_list->count < entity->rx_reord) {
nr_pdcp_sdu_t *cur = entity->rx_list;
entity->deliver_sdu(entity->deliver_sdu_data, entity,
cur->buffer, cur->size);
entity->rx_list = cur->next;
entity->rx_size -= cur->size;
nr_pdcp_free_sdu(cur);
}
/* deliver all SDUs starting from rx_reord up to discontinuity or end of list */
count = entity->rx_reord;
while (entity->rx_list != NULL && count == entity->rx_list->count) {
nr_pdcp_sdu_t *cur = entity->rx_list;
entity->deliver_sdu(entity->deliver_sdu_data, entity,
cur->buffer, cur->size);
entity->rx_list = cur->next;
entity->rx_size -= cur->size;
nr_pdcp_free_sdu(cur);
count++;
}
entity->rx_deliv = count;
if (entity->rx_deliv < entity->rx_next) {
entity->rx_reord = entity->rx_next;
entity->t_reordering_start = entity->t_current;
}
}
void nr_pdcp_entity_set_time(struct nr_pdcp_entity_t *entity, uint64_t now)
{
entity->t_current = now;
check_t_reordering(entity);
}
void nr_pdcp_entity_delete(nr_pdcp_entity_t *entity)
{
nr_pdcp_sdu_t *cur = entity->rx_list;
while (cur != NULL) {
nr_pdcp_sdu_t *next = cur->next;
nr_pdcp_free_sdu(cur);
cur = next;
}
if (entity->free_security != NULL)
entity->free_security(entity->security_context);
free(entity);
}
nr_pdcp_entity_t *new_nr_pdcp_entity(
nr_pdcp_entity_type_t type,
int is_gnb, int rb_id, int is_gnb, int rb_id,
void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity, void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity,
char *buf, int size), char *buf, int size),
...@@ -54,52 +252,56 @@ nr_pdcp_entity_t *new_nr_pdcp_entity_drb_am( ...@@ -54,52 +252,56 @@ nr_pdcp_entity_t *new_nr_pdcp_entity_drb_am(
unsigned char *ciphering_key, unsigned char *ciphering_key,
unsigned char *integrity_key) unsigned char *integrity_key)
{ {
nr_pdcp_entity_drb_am_t *ret; nr_pdcp_entity_t *ret;
ret = calloc(1, sizeof(nr_pdcp_entity_drb_am_t)); ret = calloc(1, sizeof(nr_pdcp_entity_t));
if (ret == NULL) { if (ret == NULL) {
LOG_E(PDCP, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__); LOG_E(PDCP, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__);
exit(1); exit(1);
} }
ret->common.recv_pdu = nr_pdcp_entity_drb_am_recv_pdu; ret->type = type;
ret->common.recv_sdu = nr_pdcp_entity_drb_am_recv_sdu;
ret->common.set_integrity_key = nr_pdcp_entity_drb_am_set_integrity_key; ret->recv_pdu = nr_pdcp_entity_recv_pdu;
ret->recv_sdu = nr_pdcp_entity_recv_sdu;
ret->set_integrity_key = nr_pdcp_entity_set_integrity_key;
ret->set_time = nr_pdcp_entity_set_time;
ret->common.delete = nr_pdcp_entity_drb_am_delete; ret->delete = nr_pdcp_entity_delete;
ret->common.deliver_sdu = deliver_sdu; ret->deliver_sdu = deliver_sdu;
ret->common.deliver_sdu_data = deliver_sdu_data; ret->deliver_sdu_data = deliver_sdu_data;
ret->common.deliver_pdu = deliver_pdu; ret->deliver_pdu = deliver_pdu;
ret->common.deliver_pdu_data = deliver_pdu_data; ret->deliver_pdu_data = deliver_pdu_data;
ret->rb_id = rb_id; ret->rb_id = rb_id;
ret->sn_size = sn_size; ret->sn_size = sn_size;
ret->t_reordering = t_reordering; ret->t_reordering = t_reordering;
ret->discard_timer = discard_timer; ret->discard_timer = discard_timer;
ret->common.maximum_nr_pdcp_sn = (1 << sn_size) - 1; ret->sn_max = (1 << sn_size) - 1;
ret->window_size = 1 << (sn_size - 1);
if (ciphering_key != NULL && ciphering_algorithm != 0) { if (ciphering_key != NULL && ciphering_algorithm != 0) {
if (ciphering_algorithm != 2) { if (ciphering_algorithm != 2) {
LOG_E(PDCP, "FATAL: only nea2 supported for the moment\n"); LOG_E(PDCP, "FATAL: only nea2 supported for the moment\n");
exit(1); exit(1);
} }
ret->common.has_ciphering = 1; ret->has_ciphering = 1;
ret->common.ciphering_algorithm = ciphering_algorithm; ret->ciphering_algorithm = ciphering_algorithm;
memcpy(ret->common.ciphering_key, ciphering_key, 16); memcpy(ret->ciphering_key, ciphering_key, 16);
ret->common.security_context = nr_pdcp_security_nea2_init(ciphering_key); ret->security_context = nr_pdcp_security_nea2_init(ciphering_key);
ret->common.cipher = nr_pdcp_security_nea2_cipher; ret->cipher = nr_pdcp_security_nea2_cipher;
ret->common.free_security = nr_pdcp_security_nea2_free_security; ret->free_security = nr_pdcp_security_nea2_free_security;
} }
ret->common.is_gnb = is_gnb; ret->is_gnb = is_gnb;
if (integrity_key != NULL) { if (integrity_key != NULL) {
printf("%s:%d:%s: TODO\n", __FILE__, __LINE__, __FUNCTION__); printf("%s:%d:%s: TODO\n", __FILE__, __LINE__, __FUNCTION__);
exit(1); exit(1);
} }
return (nr_pdcp_entity_t *)ret; return ret;
} }
...@@ -19,18 +19,29 @@ ...@@ -19,18 +19,29 @@
* contact@openairinterface.org * contact@openairinterface.org
*/ */
#include <stdint.h>
#ifndef _NR_PDCP_ENTITY_H_ #ifndef _NR_PDCP_ENTITY_H_
#define _NR_PDCP_ENTITY_H_ #define _NR_PDCP_ENTITY_H_
#include <stdint.h>
#include "nr_pdcp_sdu.h"
typedef enum {
NR_PDCP_DRB_AM,
NR_PDCP_DRB_UM,
NR_PDCP_SRB
} nr_pdcp_entity_type_t;
typedef struct nr_pdcp_entity_t { typedef struct nr_pdcp_entity_t {
nr_pdcp_entity_type_t type;
/* functions provided by the PDCP module */ /* functions provided by the PDCP module */
void (*recv_pdu)(struct nr_pdcp_entity_t *entity, char *buffer, int size); void (*recv_pdu)(struct nr_pdcp_entity_t *entity, char *buffer, int size);
void (*recv_sdu)(struct nr_pdcp_entity_t *entity, char *buffer, int size, void (*recv_sdu)(struct nr_pdcp_entity_t *entity, char *buffer, int size,
int sdu_id); int sdu_id);
void (*delete)(struct nr_pdcp_entity_t *entity); void (*delete)(struct nr_pdcp_entity_t *entity);
void (*set_integrity_key)(struct nr_pdcp_entity_t *entity, char *key); void (*set_integrity_key)(struct nr_pdcp_entity_t *entity, char *key);
void (*set_time)(struct nr_pdcp_entity_t *entity, uint64_t now);
/* callbacks provided to the PDCP module */ /* callbacks provided to the PDCP module */
void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity, void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity,
...@@ -39,9 +50,28 @@ typedef struct nr_pdcp_entity_t { ...@@ -39,9 +50,28 @@ typedef struct nr_pdcp_entity_t {
void (*deliver_pdu)(void *deliver_pdu_data, struct nr_pdcp_entity_t *entity, void (*deliver_pdu)(void *deliver_pdu_data, struct nr_pdcp_entity_t *entity,
char *buf, int size, int sdu_id); char *buf, int size, int sdu_id);
void *deliver_pdu_data; void *deliver_pdu_data;
int tx_hfn;
int next_nr_pdcp_tx_sn; /* configuration variables */
int maximum_nr_pdcp_sn; int rb_id;
int sn_size; /* SN size, in bits */
int t_reordering; /* unit: ms */
int discard_timer; /* unit: ms */
int sn_max; /* (2^SN_size) - 1 */
int window_size; /* 2^(SN_size - 1) */
/* state variables */
uint32_t tx_next;
uint32_t rx_next;
uint32_t rx_deliv;
uint32_t rx_reord;
/* set to the latest know time by the user of the module. Unit: ms */
uint64_t t_current;
/* timers (stores the ms of activation, 0 means not active) */
int t_reordering_start;
/* security */ /* security */
int has_ciphering; int has_ciphering;
...@@ -60,18 +90,15 @@ typedef struct nr_pdcp_entity_t { ...@@ -60,18 +90,15 @@ typedef struct nr_pdcp_entity_t {
* pdcp entity is for a gnb or an ue * pdcp entity is for a gnb or an ue
*/ */
int is_gnb; int is_gnb;
} nr_pdcp_entity_t;
nr_pdcp_entity_t *new_nr_pdcp_entity_srb( /* rx management */
int is_gnb, int rb_id, nr_pdcp_sdu_t *rx_list;
void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity, int rx_size;
char *buf, int size), int rx_maxsize;
void *deliver_sdu_data, } nr_pdcp_entity_t;
void (*deliver_pdu)(void *deliver_pdu_data, struct nr_pdcp_entity_t *entity,
char *buf, int size, int sdu_id),
void *deliver_pdu_data);
nr_pdcp_entity_t *new_nr_pdcp_entity_drb_am( nr_pdcp_entity_t *new_nr_pdcp_entity(
nr_pdcp_entity_type_t type,
int is_gnb, int rb_id, int is_gnb, int rb_id,
void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity, void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity,
char *buf, int size), char *buf, int size),
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#endif #endif
#include "asn1_utils.h" #include "asn1_utils.h"
#include "nr_pdcp_ue_manager.h" #include "nr_pdcp_ue_manager.h"
#include "nr_pdcp_timer_thread.h"
#include "NR_RadioBearerConfig.h" #include "NR_RadioBearerConfig.h"
#include "NR_RLC-BearerConfig.h" #include "NR_RLC-BearerConfig.h"
#include "NR_RLC-Config.h" #include "NR_RLC-Config.h"
...@@ -41,6 +42,11 @@ ...@@ -41,6 +42,11 @@
static nr_pdcp_ue_manager_t *nr_pdcp_ue_manager; static nr_pdcp_ue_manager_t *nr_pdcp_ue_manager;
/* TODO: handle time a bit more properly */
static uint64_t nr_pdcp_current_time;
static int nr_pdcp_current_time_last_frame;
static int nr_pdcp_current_time_last_subframe;
/* necessary globals for OAI, not used internally */ /* necessary globals for OAI, not used internally */
hash_table_t *pdcp_coll_p; hash_table_t *pdcp_coll_p;
static uint64_t pdcp_optmask; static uint64_t pdcp_optmask;
...@@ -339,6 +345,8 @@ void pdcp_layer_init(void) ...@@ -339,6 +345,8 @@ void pdcp_layer_init(void)
nr_pdcp_ue_manager = new_nr_pdcp_ue_manager(1); nr_pdcp_ue_manager = new_nr_pdcp_ue_manager(1);
init_nr_rlc_data_req_queue(); init_nr_rlc_data_req_queue();
nr_pdcp_init_timer_thread(nr_pdcp_ue_manager);
} }
#include "nfapi/oai_integration/vendor_ext.h" #include "nfapi/oai_integration/vendor_ext.h"
...@@ -625,7 +633,7 @@ static void add_drb_am(int is_gnb, int rnti, struct NR_DRB_ToAddMod *s, ...@@ -625,7 +633,7 @@ static void add_drb_am(int is_gnb, int rnti, struct NR_DRB_ToAddMod *s,
LOG_D(PDCP, "%s:%d:%s: warning DRB %d already exist for ue %d, do nothing\n", LOG_D(PDCP, "%s:%d:%s: warning DRB %d already exist for ue %d, do nothing\n",
__FILE__, __LINE__, __FUNCTION__, drb_id, rnti); __FILE__, __LINE__, __FUNCTION__, drb_id, rnti);
} else { } else {
pdcp_drb = new_nr_pdcp_entity_drb_am(is_gnb, drb_id, pdcp_drb = new_nr_pdcp_entity(NR_PDCP_DRB_AM, is_gnb, drb_id,
deliver_sdu_drb, ue, deliver_pdu_drb, ue, deliver_sdu_drb, ue, deliver_pdu_drb, ue,
sn_size_dl, t_reordering, discard_timer, sn_size_dl, t_reordering, discard_timer,
ciphering_algorithm, integrity_algorithm, ciphering_algorithm, integrity_algorithm,
...@@ -976,3 +984,14 @@ void ...@@ -976,3 +984,14 @@ void
pdcp_mbms_run ( const protocol_ctxt_t *const ctxt_pP){ pdcp_mbms_run ( const protocol_ctxt_t *const ctxt_pP){
/* nothing to do */ /* nothing to do */
} }
void nr_pdcp_tick(int frame, int subframe)
{
if (frame != nr_pdcp_current_time_last_frame ||
subframe != nr_pdcp_current_time_last_subframe) {
nr_pdcp_current_time_last_frame = frame;
nr_pdcp_current_time_last_subframe = subframe;
nr_pdcp_current_time++;
nr_pdcp_wakeup_timer_thread(nr_pdcp_current_time);
}
}
/*
* 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 "nr_pdcp_sdu.h"
#include <stdlib.h>
#include <string.h>
nr_pdcp_sdu_t *nr_pdcp_new_sdu(uint32_t count, char *buffer, int size)
{
nr_pdcp_sdu_t *ret = calloc(1, sizeof(nr_pdcp_sdu_t));
if (ret == NULL)
exit(1);
ret->count = count;
ret->buffer = malloc(size);
if (ret->buffer == NULL)
exit(1);
memcpy(ret->buffer, buffer, size);
ret->size = size;
return ret;
}
nr_pdcp_sdu_t *nr_pdcp_sdu_list_add(nr_pdcp_sdu_t *l, nr_pdcp_sdu_t *sdu)
{
nr_pdcp_sdu_t head;
nr_pdcp_sdu_t *cur;
nr_pdcp_sdu_t *prev;
head.next = l;
cur = l;
prev = &head;
/* order is by 'count' */
while (cur != NULL) {
/* check if 'sdu' is before 'cur' in the list */
if (sdu->count < cur->count)
break;
prev = cur;
cur = cur->next;
}
prev->next = sdu;
sdu->next = cur;
return head.next;
}
int nr_pdcp_sdu_in_list(nr_pdcp_sdu_t *l, uint32_t count)
{
while (l != NULL) {
if (l->count == count)
return 1;
l = l->next;
}
return 0;
}
void nr_pdcp_free_sdu(nr_pdcp_sdu_t *sdu)
{
free(sdu->buffer);
free(sdu);
}
...@@ -19,23 +19,21 @@ ...@@ -19,23 +19,21 @@
* contact@openairinterface.org * contact@openairinterface.org
*/ */
#ifndef _NR_PDCP_ENTITY_DRB_AM_H_ #ifndef _NR_PDCP_SDU_H_
#define _NR_PDCP_ENTITY_DRB_AM_H_ #define _NR_PDCP_SDU_H_
#include "nr_pdcp_entity.h" #include <stdint.h>
typedef struct { typedef struct nr_pdcp_sdu_t {
nr_pdcp_entity_t common; uint32_t count;
int rb_id; char *buffer;
int sn_size; /* unit: bits */ int size;
int t_reordering; /* unit: ms */ struct nr_pdcp_sdu_t *next;
int discard_timer; /* unit: ms, -1 means infinity */ } nr_pdcp_sdu_t;
} nr_pdcp_entity_drb_am_t;
void nr_pdcp_entity_drb_am_recv_pdu(nr_pdcp_entity_t *entity, char *buffer, int size); nr_pdcp_sdu_t *nr_pdcp_new_sdu(uint32_t count, char *buffer, int size);
void nr_pdcp_entity_drb_am_recv_sdu(nr_pdcp_entity_t *entity, char *buffer, int size, nr_pdcp_sdu_t *nr_pdcp_sdu_list_add(nr_pdcp_sdu_t *l, nr_pdcp_sdu_t *sdu);
int sdu_id); int nr_pdcp_sdu_in_list(nr_pdcp_sdu_t *l, uint32_t count);
void nr_pdcp_entity_drb_am_set_integrity_key(nr_pdcp_entity_t *entity, char *key); void nr_pdcp_free_sdu(nr_pdcp_sdu_t *sdu);
void nr_pdcp_entity_drb_am_delete(nr_pdcp_entity_t *entity);
#endif /* _NR_PDCP_ENTITY_DRB_AM_H_ */ #endif /* _NR_PDCP_SDU_H_ */
...@@ -19,72 +19,69 @@ ...@@ -19,72 +19,69 @@
* contact@openairinterface.org * contact@openairinterface.org
*/ */
#include "nr_pdcp_entity_drb_am.h" #include "nr_pdcp_timer_thread.h"
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <pthread.h>
#include "common/utils/LOG/log.h" #include <stdint.h>
void nr_pdcp_entity_drb_am_recv_pdu(nr_pdcp_entity_t *_entity, char *buffer, int size) #include "LOG/log.h"
{
nr_pdcp_entity_drb_am_t *entity = (nr_pdcp_entity_drb_am_t *)_entity;
int sn;
if (size < 3) abort();
if (!(buffer[0] & 0x80))
LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
sn = (((unsigned char)buffer[0] & 0x3) << 16) | static pthread_mutex_t timer_thread_mutex = PTHREAD_MUTEX_INITIALIZER;
((unsigned char)buffer[1] << 8) | static pthread_cond_t timer_thread_cond = PTHREAD_COND_INITIALIZER;
(unsigned char)buffer[2]; static volatile uint64_t timer_thread_curtime = 0;
if (entity->common.has_ciphering) static void *nr_pdcp_timer_thread(void *_nr_pdcp_ue_manager)
entity->common.cipher(entity->common.security_context, (unsigned char *)buffer+3, size-3,
entity->rb_id, sn, entity->common.is_gnb ? 0 : 1);
entity->common.deliver_sdu(entity->common.deliver_sdu_data,
(nr_pdcp_entity_t *)entity, buffer+3, size-3);
}
void nr_pdcp_entity_drb_am_recv_sdu(nr_pdcp_entity_t *_entity, char *buffer, int size,
int sdu_id)
{ {
nr_pdcp_entity_drb_am_t *entity = (nr_pdcp_entity_drb_am_t *)_entity; nr_pdcp_ue_manager_t *nr_pdcp_ue_manager = (nr_pdcp_ue_manager_t *)_nr_pdcp_ue_manager;
int sn; nr_pdcp_ue_t **ue_list;
char buf[size+3]; int ue_count;
int i;
sn = entity->common.next_nr_pdcp_tx_sn; int j;
uint64_t curtime = 0;
entity->common.next_nr_pdcp_tx_sn++;
if (entity->common.next_nr_pdcp_tx_sn > entity->common.maximum_nr_pdcp_sn) { while (1) {
entity->common.next_nr_pdcp_tx_sn = 0; if (pthread_mutex_lock(&timer_thread_mutex) != 0) abort();
entity->common.tx_hfn++; while (curtime == timer_thread_curtime)
if (pthread_cond_wait(&timer_thread_cond, &timer_thread_mutex) != 0) abort();
curtime = timer_thread_curtime;
if (pthread_mutex_unlock(&timer_thread_mutex) != 0) abort();
nr_pdcp_manager_lock(nr_pdcp_ue_manager);
ue_list = nr_pdcp_manager_get_ue_list(nr_pdcp_ue_manager);
ue_count = nr_pdcp_manager_get_ue_count(nr_pdcp_ue_manager);
for (i = 0; i < ue_count; i++) {
for (j = 0; j < 2; j++) {
if (ue_list[i]->srb[j] != NULL)
ue_list[i]->srb[j]->set_time(ue_list[i]->srb[j], curtime);
}
for (j = 0; j < 5; j++) {
if (ue_list[i]->drb[j] != NULL)
ue_list[i]->drb[j]->set_time(ue_list[i]->drb[j], curtime);
}
} }
buf[0] = 0x80 | ((sn >> 16) & 0x3); nr_pdcp_manager_unlock(nr_pdcp_ue_manager);
buf[1] = (sn >> 8) & 0xff; }
buf[2] = sn & 0xff;
memcpy(buf+3, buffer, size);
if (entity->common.has_ciphering)
entity->common.cipher(entity->common.security_context, (unsigned char *)buf+3, size,
entity->rb_id, sn, entity->common.is_gnb ? 1 : 0);
entity->common.deliver_pdu(entity->common.deliver_pdu_data, return NULL;
(nr_pdcp_entity_t *)entity, buf, size+3, sdu_id);
} }
void nr_pdcp_entity_drb_am_set_integrity_key(nr_pdcp_entity_t *_entity, char *key) void nr_pdcp_init_timer_thread(nr_pdcp_ue_manager_t *nr_pdcp_ue_manager)
{ {
/* nothing to do */ pthread_t t;
if (pthread_create(&t, NULL, nr_pdcp_timer_thread, nr_pdcp_ue_manager) != 0) {
LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
exit(1);
}
} }
void nr_pdcp_entity_drb_am_delete(nr_pdcp_entity_t *_entity) void nr_pdcp_wakeup_timer_thread(uint64_t time)
{ {
nr_pdcp_entity_drb_am_t *entity = (nr_pdcp_entity_drb_am_t *)_entity; if (pthread_mutex_lock(&timer_thread_mutex)) abort();
if (entity->common.free_security != NULL) timer_thread_curtime = time;
entity->common.free_security(entity->common.security_context); if (pthread_cond_broadcast(&timer_thread_cond)) abort();
free(entity); if (pthread_mutex_unlock(&timer_thread_mutex)) abort();
} }
/*
* 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 _NR_PDCP_TIMER_THREAD_H_
#define _NR_PDCP_TIMER_THREAD_H_
#include "nr_pdcp_ue_manager.h"
#include <stdint.h>
void nr_pdcp_init_timer_thread(nr_pdcp_ue_manager_t *nr_pdcp_ue_manager);
void nr_pdcp_wakeup_timer_thread(uint64_t time);
#endif /* _NR_PDCP_TIMER_THREAD_H_ */
...@@ -189,6 +189,20 @@ void nr_pdcp_ue_add_drb_pdcp_entity(nr_pdcp_ue_t *ue, int drb_id, nr_pdcp_entity ...@@ -189,6 +189,20 @@ void nr_pdcp_ue_add_drb_pdcp_entity(nr_pdcp_ue_t *ue, int drb_id, nr_pdcp_entity
ue->drb[drb_id] = entity; ue->drb[drb_id] = entity;
} }
/* must be called with lock acquired */
nr_pdcp_ue_t **nr_pdcp_manager_get_ue_list(nr_pdcp_ue_manager_t *_m)
{
nr_pdcp_ue_manager_internal_t *m = _m;
return m->ue_list;
}
/* must be called with lock acquired */
int nr_pdcp_manager_get_ue_count(nr_pdcp_ue_manager_t *_m)
{
nr_pdcp_ue_manager_internal_t *m = _m;
return m->ue_count;
}
int nr_pdcp_get_first_rnti(nr_pdcp_ue_manager_t *_m) int nr_pdcp_get_first_rnti(nr_pdcp_ue_manager_t *_m)
{ {
nr_pdcp_ue_manager_internal_t *m = _m; nr_pdcp_ue_manager_internal_t *m = _m;
......
...@@ -46,6 +46,9 @@ void nr_pdcp_manager_unlock(nr_pdcp_ue_manager_t *m); ...@@ -46,6 +46,9 @@ void nr_pdcp_manager_unlock(nr_pdcp_ue_manager_t *m);
nr_pdcp_ue_t *nr_pdcp_manager_get_ue(nr_pdcp_ue_manager_t *m, int rnti); nr_pdcp_ue_t *nr_pdcp_manager_get_ue(nr_pdcp_ue_manager_t *m, int rnti);
void nr_pdcp_manager_remove_ue(nr_pdcp_ue_manager_t *m, int rnti); void nr_pdcp_manager_remove_ue(nr_pdcp_ue_manager_t *m, int rnti);
nr_pdcp_ue_t **nr_pdcp_manager_get_ue_list(nr_pdcp_ue_manager_t *_m);
int nr_pdcp_manager_get_ue_count(nr_pdcp_ue_manager_t *_m);
/***********************************************************************/ /***********************************************************************/
/* ue functions */ /* ue functions */
/***********************************************************************/ /***********************************************************************/
......
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