Merge remote-tracking branch 'origin/nr-pdcp-improvements' into integration_2021_wk10
This commit is contained in:
@@ -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_ue_manager.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/asn1_utils.c
|
||||
)
|
||||
|
||||
@@ -364,7 +364,9 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP,
|
||||
/* send tick to RLC and RRC every ms */
|
||||
if ((slot & ((1 << *scc->ssbSubcarrierSpacing) - 1)) == 0) {
|
||||
void nr_rlc_tick(int frame, int subframe);
|
||||
void nr_pdcp_tick(int frame, int subframe);
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,24 +21,222 @@
|
||||
|
||||
#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_sdu.h"
|
||||
|
||||
#include "LOG/log.h"
|
||||
|
||||
nr_pdcp_entity_t *new_nr_pdcp_entity_srb(
|
||||
int is_gnb, int rb_id,
|
||||
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)
|
||||
static void nr_pdcp_entity_recv_pdu(nr_pdcp_entity_t *entity,
|
||||
char *_buffer, int size)
|
||||
{
|
||||
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,
|
||||
void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity,
|
||||
char *buf, int size),
|
||||
@@ -54,52 +252,56 @@ nr_pdcp_entity_t *new_nr_pdcp_entity_drb_am(
|
||||
unsigned char *ciphering_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) {
|
||||
LOG_E(PDCP, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ret->common.recv_pdu = nr_pdcp_entity_drb_am_recv_pdu;
|
||||
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->type = type;
|
||||
|
||||
ret->common.delete = nr_pdcp_entity_drb_am_delete;
|
||||
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.deliver_sdu = deliver_sdu;
|
||||
ret->common.deliver_sdu_data = deliver_sdu_data;
|
||||
ret->delete = nr_pdcp_entity_delete;
|
||||
|
||||
ret->common.deliver_pdu = deliver_pdu;
|
||||
ret->common.deliver_pdu_data = deliver_pdu_data;
|
||||
ret->deliver_sdu = deliver_sdu;
|
||||
ret->deliver_sdu_data = deliver_sdu_data;
|
||||
|
||||
ret->deliver_pdu = deliver_pdu;
|
||||
ret->deliver_pdu_data = deliver_pdu_data;
|
||||
|
||||
ret->rb_id = rb_id;
|
||||
ret->sn_size = sn_size;
|
||||
ret->t_reordering = t_reordering;
|
||||
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_algorithm != 2) {
|
||||
LOG_E(PDCP, "FATAL: only nea2 supported for the moment\n");
|
||||
exit(1);
|
||||
}
|
||||
ret->common.has_ciphering = 1;
|
||||
ret->common.ciphering_algorithm = ciphering_algorithm;
|
||||
memcpy(ret->common.ciphering_key, ciphering_key, 16);
|
||||
ret->has_ciphering = 1;
|
||||
ret->ciphering_algorithm = ciphering_algorithm;
|
||||
memcpy(ret->ciphering_key, ciphering_key, 16);
|
||||
|
||||
ret->common.security_context = nr_pdcp_security_nea2_init(ciphering_key);
|
||||
ret->common.cipher = nr_pdcp_security_nea2_cipher;
|
||||
ret->common.free_security = nr_pdcp_security_nea2_free_security;
|
||||
ret->security_context = nr_pdcp_security_nea2_init(ciphering_key);
|
||||
ret->cipher = nr_pdcp_security_nea2_cipher;
|
||||
ret->free_security = nr_pdcp_security_nea2_free_security;
|
||||
}
|
||||
ret->common.is_gnb = is_gnb;
|
||||
ret->is_gnb = is_gnb;
|
||||
|
||||
if (integrity_key != NULL) {
|
||||
printf("%s:%d:%s: TODO\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return (nr_pdcp_entity_t *)ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -19,18 +19,29 @@
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef _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 {
|
||||
nr_pdcp_entity_type_t type;
|
||||
|
||||
/* functions provided by the PDCP module */
|
||||
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,
|
||||
int sdu_id);
|
||||
void (*delete)(struct nr_pdcp_entity_t *entity);
|
||||
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 */
|
||||
void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity,
|
||||
@@ -39,9 +50,28 @@ typedef struct 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;
|
||||
int tx_hfn;
|
||||
int next_nr_pdcp_tx_sn;
|
||||
int maximum_nr_pdcp_sn;
|
||||
|
||||
/* configuration variables */
|
||||
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 */
|
||||
int has_ciphering;
|
||||
@@ -60,18 +90,15 @@ typedef struct nr_pdcp_entity_t {
|
||||
* pdcp entity is for a gnb or an ue
|
||||
*/
|
||||
int is_gnb;
|
||||
|
||||
/* rx management */
|
||||
nr_pdcp_sdu_t *rx_list;
|
||||
int rx_size;
|
||||
int rx_maxsize;
|
||||
} nr_pdcp_entity_t;
|
||||
|
||||
nr_pdcp_entity_t *new_nr_pdcp_entity_srb(
|
||||
int is_gnb, int rb_id,
|
||||
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);
|
||||
|
||||
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,
|
||||
void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity,
|
||||
char *buf, int size),
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
/*
|
||||
* 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_entity_drb_am.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "common/utils/LOG/log.h"
|
||||
|
||||
void nr_pdcp_entity_drb_am_recv_pdu(nr_pdcp_entity_t *_entity, char *buffer, int size)
|
||||
{
|
||||
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) |
|
||||
((unsigned char)buffer[1] << 8) |
|
||||
(unsigned char)buffer[2];
|
||||
|
||||
if (entity->common.has_ciphering)
|
||||
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;
|
||||
int sn;
|
||||
char buf[size+3];
|
||||
|
||||
sn = entity->common.next_nr_pdcp_tx_sn;
|
||||
|
||||
entity->common.next_nr_pdcp_tx_sn++;
|
||||
if (entity->common.next_nr_pdcp_tx_sn > entity->common.maximum_nr_pdcp_sn) {
|
||||
entity->common.next_nr_pdcp_tx_sn = 0;
|
||||
entity->common.tx_hfn++;
|
||||
}
|
||||
|
||||
buf[0] = 0x80 | ((sn >> 16) & 0x3);
|
||||
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,
|
||||
(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)
|
||||
{
|
||||
/* nothing to do */
|
||||
}
|
||||
|
||||
void nr_pdcp_entity_drb_am_delete(nr_pdcp_entity_t *_entity)
|
||||
{
|
||||
nr_pdcp_entity_drb_am_t *entity = (nr_pdcp_entity_drb_am_t *)_entity;
|
||||
if (entity->common.free_security != NULL)
|
||||
entity->common.free_security(entity->common.security_context);
|
||||
free(entity);
|
||||
}
|
||||
@@ -24,6 +24,7 @@
|
||||
#endif
|
||||
#include "asn1_utils.h"
|
||||
#include "nr_pdcp_ue_manager.h"
|
||||
#include "nr_pdcp_timer_thread.h"
|
||||
#include "NR_RadioBearerConfig.h"
|
||||
#include "NR_RLC-BearerConfig.h"
|
||||
#include "NR_RLC-Config.h"
|
||||
@@ -41,6 +42,11 @@
|
||||
|
||||
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 */
|
||||
hash_table_t *pdcp_coll_p;
|
||||
static uint64_t pdcp_optmask;
|
||||
@@ -339,6 +345,8 @@ void pdcp_layer_init(void)
|
||||
|
||||
nr_pdcp_ue_manager = new_nr_pdcp_ue_manager(1);
|
||||
init_nr_rlc_data_req_queue();
|
||||
|
||||
nr_pdcp_init_timer_thread(nr_pdcp_ue_manager);
|
||||
}
|
||||
|
||||
#include "nfapi/oai_integration/vendor_ext.h"
|
||||
@@ -625,11 +633,11 @@ 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",
|
||||
__FILE__, __LINE__, __FUNCTION__, drb_id, rnti);
|
||||
} else {
|
||||
pdcp_drb = new_nr_pdcp_entity_drb_am(is_gnb, drb_id,
|
||||
deliver_sdu_drb, ue, deliver_pdu_drb, ue,
|
||||
sn_size_dl, t_reordering, discard_timer,
|
||||
ciphering_algorithm, integrity_algorithm,
|
||||
ciphering_key, integrity_key);
|
||||
pdcp_drb = new_nr_pdcp_entity(NR_PDCP_DRB_AM, is_gnb, drb_id,
|
||||
deliver_sdu_drb, ue, deliver_pdu_drb, ue,
|
||||
sn_size_dl, t_reordering, discard_timer,
|
||||
ciphering_algorithm, integrity_algorithm,
|
||||
ciphering_key, integrity_key);
|
||||
nr_pdcp_ue_add_drb_pdcp_entity(ue, drb_id, pdcp_drb);
|
||||
|
||||
LOG_D(PDCP, "%s:%d:%s: added drb %d to ue rnti %x\n", __FILE__, __LINE__, __FUNCTION__, drb_id, rnti);
|
||||
@@ -976,3 +984,14 @@ void
|
||||
pdcp_mbms_run ( const protocol_ctxt_t *const ctxt_pP){
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
+14
-16
@@ -19,23 +19,21 @@
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#ifndef _NR_PDCP_ENTITY_DRB_AM_H_
|
||||
#define _NR_PDCP_ENTITY_DRB_AM_H_
|
||||
#ifndef _NR_PDCP_SDU_H_
|
||||
#define _NR_PDCP_SDU_H_
|
||||
|
||||
#include "nr_pdcp_entity.h"
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
nr_pdcp_entity_t common;
|
||||
int rb_id;
|
||||
int sn_size; /* unit: bits */
|
||||
int t_reordering; /* unit: ms */
|
||||
int discard_timer; /* unit: ms, -1 means infinity */
|
||||
} nr_pdcp_entity_drb_am_t;
|
||||
typedef struct nr_pdcp_sdu_t {
|
||||
uint32_t count;
|
||||
char *buffer;
|
||||
int size;
|
||||
struct nr_pdcp_sdu_t *next;
|
||||
} nr_pdcp_sdu_t;
|
||||
|
||||
void nr_pdcp_entity_drb_am_recv_pdu(nr_pdcp_entity_t *entity, char *buffer, int size);
|
||||
void nr_pdcp_entity_drb_am_recv_sdu(nr_pdcp_entity_t *entity, char *buffer, int size,
|
||||
int sdu_id);
|
||||
void nr_pdcp_entity_drb_am_set_integrity_key(nr_pdcp_entity_t *entity, char *key);
|
||||
void nr_pdcp_entity_drb_am_delete(nr_pdcp_entity_t *entity);
|
||||
nr_pdcp_sdu_t *nr_pdcp_new_sdu(uint32_t count, char *buffer, int size);
|
||||
nr_pdcp_sdu_t *nr_pdcp_sdu_list_add(nr_pdcp_sdu_t *l, nr_pdcp_sdu_t *sdu);
|
||||
int nr_pdcp_sdu_in_list(nr_pdcp_sdu_t *l, uint32_t count);
|
||||
void nr_pdcp_free_sdu(nr_pdcp_sdu_t *sdu);
|
||||
|
||||
#endif /* _NR_PDCP_ENTITY_DRB_AM_H_ */
|
||||
#endif /* _NR_PDCP_SDU_H_ */
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* 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_timer_thread.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "LOG/log.h"
|
||||
|
||||
static pthread_mutex_t timer_thread_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_cond_t timer_thread_cond = PTHREAD_COND_INITIALIZER;
|
||||
static volatile uint64_t timer_thread_curtime = 0;
|
||||
|
||||
static void *nr_pdcp_timer_thread(void *_nr_pdcp_ue_manager)
|
||||
{
|
||||
nr_pdcp_ue_manager_t *nr_pdcp_ue_manager = (nr_pdcp_ue_manager_t *)_nr_pdcp_ue_manager;
|
||||
nr_pdcp_ue_t **ue_list;
|
||||
int ue_count;
|
||||
int i;
|
||||
int j;
|
||||
uint64_t curtime = 0;
|
||||
|
||||
while (1) {
|
||||
if (pthread_mutex_lock(&timer_thread_mutex) != 0) abort();
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
nr_pdcp_manager_unlock(nr_pdcp_ue_manager);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void nr_pdcp_init_timer_thread(nr_pdcp_ue_manager_t *nr_pdcp_ue_manager)
|
||||
{
|
||||
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_wakeup_timer_thread(uint64_t time)
|
||||
{
|
||||
if (pthread_mutex_lock(&timer_thread_mutex)) abort();
|
||||
timer_thread_curtime = time;
|
||||
if (pthread_cond_broadcast(&timer_thread_cond)) abort();
|
||||
if (pthread_mutex_unlock(&timer_thread_mutex)) abort();
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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
|
||||
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)
|
||||
{
|
||||
nr_pdcp_ue_manager_internal_t *m = _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);
|
||||
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 */
|
||||
/***********************************************************************/
|
||||
|
||||
Reference in New Issue
Block a user