Commit c21b593f authored by Cedric Roux's avatar Cedric Roux

nr rlc: speedup buffer status computation

TX and ReTX should be faster now (for RLC AM, UM and TM).

RLC AM Status (function nr_rlc_entity_am.c:status_size()) was not modified,
so its CPU usage is the same as before. (It's more complicated to change
than for TX and ReTX.)
parent a718ba33
...@@ -63,6 +63,8 @@ typedef struct nr_rlc_entity_t { ...@@ -63,6 +63,8 @@ typedef struct nr_rlc_entity_t {
void (*max_retx_reached)(void *max_retx_reached_data, void (*max_retx_reached)(void *max_retx_reached_data,
struct nr_rlc_entity_t *entity); struct nr_rlc_entity_t *entity);
void *max_retx_reached_data; void *max_retx_reached_data;
/* buffer status computation */
nr_rlc_entity_buffer_status_t bstatus;
} nr_rlc_entity_t; } nr_rlc_entity_t;
nr_rlc_entity_t *new_nr_rlc_entity_am( nr_rlc_entity_t *new_nr_rlc_entity_am(
......
...@@ -28,6 +28,19 @@ ...@@ -28,6 +28,19 @@
#include "LOG/log.h" #include "LOG/log.h"
/* for a given SDU/SDU segment, computes the corresponding PDU header size */
static int compute_pdu_header_size(nr_rlc_entity_am_t *entity,
nr_rlc_sdu_segment_t *sdu)
{
int header_size = 2;
/* one more byte if SN field length is 18 */
if (entity->sn_field_length == 18)
header_size++;
/* two more bytes for SO if SDU segment is not the first */
if (!sdu->is_first) header_size += 2;
return header_size;
}
/*************************************************************************/ /*************************************************************************/
/* PDU RX functions */ /* PDU RX functions */
/*************************************************************************/ /*************************************************************************/
...@@ -114,6 +127,10 @@ static void consider_retransmission(nr_rlc_entity_am_t *entity, ...@@ -114,6 +127,10 @@ static void consider_retransmission(nr_rlc_entity_am_t *entity,
nr_rlc_sdu_segment_list_append(&entity->retransmit_list, nr_rlc_sdu_segment_list_append(&entity->retransmit_list,
&entity->retransmit_end, &entity->retransmit_end,
cur); cur);
/* update buffer status */
entity->common.bstatus.retx_size += compute_pdu_header_size(entity, cur)
+ cur->size;
} }
/* checks that all the bytes of the SDU sn have been received (but SDU /* checks that all the bytes of the SDU sn have been received (but SDU
...@@ -351,6 +368,9 @@ static void process_received_ack(nr_rlc_entity_am_t *entity, int ack_sn) ...@@ -351,6 +368,9 @@ static void process_received_ack(nr_rlc_entity_am_t *entity, int ack_sn)
} }
/* remove from retransmit list */ /* remove from retransmit list */
prev->next = cur->next; prev->next = cur->next;
/* update buffer status */
entity->common.bstatus.retx_size -= compute_pdu_header_size(entity, cur)
+ cur->size;
/* put the PDU in the ack list */ /* put the PDU in the ack list */
entity->ack_list = nr_rlc_sdu_segment_list_add(sn_compare_tx, entity, entity->ack_list = nr_rlc_sdu_segment_list_add(sn_compare_tx, entity,
entity->ack_list, cur); entity->ack_list, cur);
...@@ -840,19 +860,6 @@ static int serialize_sdu(nr_rlc_entity_am_t *entity, ...@@ -840,19 +860,6 @@ static int serialize_sdu(nr_rlc_entity_am_t *entity,
return encoder.byte + sdu->size; return encoder.byte + sdu->size;
} }
/* for a given SDU/SDU segment, computes the corresponding PDU header size */
static int compute_pdu_header_size(nr_rlc_entity_am_t *entity,
nr_rlc_sdu_segment_t *sdu)
{
int header_size = 2;
/* one more byte if SN field length is 18 */
if (entity->sn_field_length == 18)
header_size++;
/* two more bytes for SO if SDU segment is not the first */
if (!sdu->is_first) header_size += 2;
return header_size;
}
/* resize SDU/SDU segment for the corresponding PDU to fit into 'pdu_size' /* resize SDU/SDU segment for the corresponding PDU to fit into 'pdu_size'
* bytes * bytes
* - modifies SDU/SDU segment to become an SDU segment * - modifies SDU/SDU segment to become an SDU segment
...@@ -1426,8 +1433,12 @@ static int generate_retx_pdu(nr_rlc_entity_am_t *entity, char *buffer, ...@@ -1426,8 +1433,12 @@ static int generate_retx_pdu(nr_rlc_entity_am_t *entity, char *buffer,
sdu->next = NULL; sdu->next = NULL;
/* segment if necessary */
pdu_size = pdu_header_size + sdu->size; pdu_size = pdu_header_size + sdu->size;
/* update buffer status */
entity->common.bstatus.retx_size -= pdu_size;
/* segment if necessary */
if (pdu_size > size) { if (pdu_size > size) {
nr_rlc_sdu_segment_t *next_sdu; nr_rlc_sdu_segment_t *next_sdu;
next_sdu = resegment(sdu, entity, size); next_sdu = resegment(sdu, entity, size);
...@@ -1436,6 +1447,9 @@ static int generate_retx_pdu(nr_rlc_entity_am_t *entity, char *buffer, ...@@ -1436,6 +1447,9 @@ static int generate_retx_pdu(nr_rlc_entity_am_t *entity, char *buffer,
entity->retransmit_list = next_sdu; entity->retransmit_list = next_sdu;
if (entity->retransmit_end == NULL) if (entity->retransmit_end == NULL)
entity->retransmit_end = entity->retransmit_list; entity->retransmit_end = entity->retransmit_list;
/* update buffer status */
entity->common.bstatus.retx_size += compute_pdu_header_size(entity, next_sdu)
+ next_sdu->size;
} }
/* put SDU/SDU segment in the wait list */ /* put SDU/SDU segment in the wait list */
...@@ -1479,11 +1493,15 @@ static int generate_tx_pdu(nr_rlc_entity_am_t *entity, char *buffer, int size) ...@@ -1479,11 +1493,15 @@ static int generate_tx_pdu(nr_rlc_entity_am_t *entity, char *buffer, int size)
sdu->next = NULL; sdu->next = NULL;
pdu_size = pdu_header_size + sdu->size;
/* update buffer status */
entity->common.bstatus.tx_size -= pdu_size;
/* assign SN to SDU */ /* assign SN to SDU */
sdu->sdu->sn = entity->tx_next; sdu->sdu->sn = entity->tx_next;
/* segment if necessary */ /* segment if necessary */
pdu_size = pdu_header_size + sdu->size;
if (pdu_size > size) { if (pdu_size > size) {
nr_rlc_sdu_segment_t *next_sdu; nr_rlc_sdu_segment_t *next_sdu;
next_sdu = resegment(sdu, entity, size); next_sdu = resegment(sdu, entity, size);
...@@ -1492,6 +1510,9 @@ static int generate_tx_pdu(nr_rlc_entity_am_t *entity, char *buffer, int size) ...@@ -1492,6 +1510,9 @@ static int generate_tx_pdu(nr_rlc_entity_am_t *entity, char *buffer, int size)
entity->tx_list = next_sdu; entity->tx_list = next_sdu;
if (entity->tx_end == NULL) if (entity->tx_end == NULL)
entity->tx_end = entity->tx_list; entity->tx_end = entity->tx_list;
/* update buffer status */
entity->common.bstatus.tx_size += compute_pdu_header_size(entity, next_sdu)
+ next_sdu->size;
} }
/* update tx_next if the SDU segment is the last */ /* update tx_next if the SDU segment is the last */
...@@ -1520,24 +1541,6 @@ static int generate_tx_pdu(nr_rlc_entity_am_t *entity, char *buffer, int size) ...@@ -1520,24 +1541,6 @@ static int generate_tx_pdu(nr_rlc_entity_am_t *entity, char *buffer, int size)
return serialize_sdu(entity, sdu, buffer, size, p); return serialize_sdu(entity, sdu, buffer, size, p);
} }
/* Pretend to serialize all the SDUs in a list and return the size
* of all the PDUs it would produce, limited to 'maxsize'.
* Used for buffer status reporting.
*/
static int tx_list_size(nr_rlc_entity_am_t *entity,
nr_rlc_sdu_segment_t *l, int maxsize)
{
int ret = 0;
while (l != NULL && ret < maxsize) {
ret += compute_pdu_header_size(entity, l) + l->size;
l = l->next;
}
if (ret > maxsize) ret = maxsize;
return ret;
}
nr_rlc_entity_buffer_status_t nr_rlc_entity_am_buffer_status( nr_rlc_entity_buffer_status_t nr_rlc_entity_am_buffer_status(
nr_rlc_entity_t *_entity, int maxsize) nr_rlc_entity_t *_entity, int maxsize)
{ {
...@@ -1549,8 +1552,8 @@ nr_rlc_entity_buffer_status_t nr_rlc_entity_am_buffer_status( ...@@ -1549,8 +1552,8 @@ nr_rlc_entity_buffer_status_t nr_rlc_entity_am_buffer_status(
else else
ret.status_size = 0; ret.status_size = 0;
ret.tx_size = tx_list_size(entity, entity->tx_list, maxsize); ret.tx_size = entity->common.bstatus.tx_size;
ret.retx_size = tx_list_size(entity, entity->retransmit_list, maxsize); ret.retx_size = entity->common.bstatus.retx_size;
return ret; return ret;
} }
...@@ -1606,6 +1609,10 @@ void nr_rlc_entity_am_recv_sdu(nr_rlc_entity_t *_entity, ...@@ -1606,6 +1609,10 @@ void nr_rlc_entity_am_recv_sdu(nr_rlc_entity_t *_entity,
LOG_D(RLC, "Created new RLC SDU and append it to the RLC list \n"); LOG_D(RLC, "Created new RLC SDU and append it to the RLC list \n");
nr_rlc_sdu_segment_list_append(&entity->tx_list, &entity->tx_end, sdu); nr_rlc_sdu_segment_list_append(&entity->tx_list, &entity->tx_end, sdu);
/* update buffer status */
entity->common.bstatus.tx_size += compute_pdu_header_size(entity, sdu)
+ sdu->size;
} }
/*************************************************************************/ /*************************************************************************/
...@@ -1793,6 +1800,10 @@ void nr_rlc_entity_am_discard_sdu(nr_rlc_entity_t *_entity, int sdu_id) ...@@ -1793,6 +1800,10 @@ void nr_rlc_entity_am_discard_sdu(nr_rlc_entity_t *_entity, int sdu_id)
entity->tx_end = NULL; entity->tx_end = NULL;
} }
/* update buffer status */
entity->common.bstatus.tx_size -= compute_pdu_header_size(entity, cur)
+ cur->size;
nr_rlc_free_sdu_segment(cur); nr_rlc_free_sdu_segment(cur);
} }
...@@ -1845,6 +1856,9 @@ static void clear_entity(nr_rlc_entity_am_t *entity) ...@@ -1845,6 +1856,9 @@ static void clear_entity(nr_rlc_entity_am_t *entity)
entity->retransmit_end = NULL; entity->retransmit_end = NULL;
entity->ack_list = NULL; entity->ack_list = NULL;
entity->common.bstatus.tx_size = 0;
entity->common.bstatus.retx_size = 0;
} }
void nr_rlc_entity_am_reestablishment(nr_rlc_entity_t *_entity) void nr_rlc_entity_am_reestablishment(nr_rlc_entity_t *_entity)
......
...@@ -68,22 +68,12 @@ static int generate_tx_pdu(nr_rlc_entity_tm_t *entity, char *buffer, int size) ...@@ -68,22 +68,12 @@ static int generate_tx_pdu(nr_rlc_entity_tm_t *entity, char *buffer, int size)
memcpy(buffer, sdu->sdu->data, sdu->size); memcpy(buffer, sdu->sdu->data, sdu->size);
entity->tx_size -= sdu->size; entity->tx_size -= sdu->size;
nr_rlc_free_sdu_segment(sdu);
return ret; /* update buffer status */
} entity->common.bstatus.tx_size -= sdu->size;
static int tx_list_size(nr_rlc_entity_tm_t *entity,
nr_rlc_sdu_segment_t *l, int maxsize)
{
int ret = 0;
while (l != NULL && ret < maxsize) { nr_rlc_free_sdu_segment(sdu);
ret += l->size;
l = l->next;
}
if (ret > maxsize) ret = maxsize;
return ret; return ret;
} }
...@@ -94,7 +84,7 @@ nr_rlc_entity_buffer_status_t nr_rlc_entity_tm_buffer_status( ...@@ -94,7 +84,7 @@ nr_rlc_entity_buffer_status_t nr_rlc_entity_tm_buffer_status(
nr_rlc_entity_buffer_status_t ret; nr_rlc_entity_buffer_status_t ret;
ret.status_size = 0; ret.status_size = 0;
ret.tx_size = tx_list_size(entity, entity->tx_list, maxsize); ret.tx_size = entity->common.bstatus.tx_size;
ret.retx_size = 0; ret.retx_size = 0;
return ret; return ret;
...@@ -136,6 +126,9 @@ void nr_rlc_entity_tm_recv_sdu(nr_rlc_entity_t *_entity, ...@@ -136,6 +126,9 @@ void nr_rlc_entity_tm_recv_sdu(nr_rlc_entity_t *_entity,
sdu = nr_rlc_new_sdu(buffer, size, sdu_id); sdu = nr_rlc_new_sdu(buffer, size, sdu_id);
nr_rlc_sdu_segment_list_append(&entity->tx_list, &entity->tx_end, sdu); nr_rlc_sdu_segment_list_append(&entity->tx_list, &entity->tx_end, sdu);
/* update buffer status */
entity->common.bstatus.tx_size += sdu->size;
} }
/*************************************************************************/ /*************************************************************************/
...@@ -165,6 +158,8 @@ static void clear_entity(nr_rlc_entity_tm_t *entity) ...@@ -165,6 +158,8 @@ static void clear_entity(nr_rlc_entity_tm_t *entity)
entity->tx_list = NULL; entity->tx_list = NULL;
entity->tx_end = NULL; entity->tx_end = NULL;
entity->tx_size = 0; entity->tx_size = 0;
entity->common.bstatus.tx_size = 0;
} }
void nr_rlc_entity_tm_reestablishment(nr_rlc_entity_t *_entity) void nr_rlc_entity_tm_reestablishment(nr_rlc_entity_t *_entity)
......
...@@ -28,6 +28,20 @@ ...@@ -28,6 +28,20 @@
#include "LOG/log.h" #include "LOG/log.h"
/* for a given SDU/SDU segment, computes the corresponding PDU header size */
static int compute_pdu_header_size(nr_rlc_entity_um_t *entity,
nr_rlc_sdu_segment_t *sdu)
{
int header_size = 1;
/* if SN to be included then one more byte if SN field length is 12 */
if (!(sdu->is_first && sdu->is_last) && entity->sn_field_length == 12)
header_size++;
/* two more bytes for SO if SDU segment is not the first */
if (!sdu->is_first) header_size += 2;
return header_size;
}
/*************************************************************************/ /*************************************************************************/
/* PDU RX functions */ /* PDU RX functions */
/*************************************************************************/ /*************************************************************************/
...@@ -375,20 +389,6 @@ static int serialize_sdu(nr_rlc_entity_um_t *entity, ...@@ -375,20 +389,6 @@ static int serialize_sdu(nr_rlc_entity_um_t *entity,
return encoder.byte + sdu->size; return encoder.byte + sdu->size;
} }
/* for a given SDU/SDU segment, computes the corresponding PDU header size */
static int compute_pdu_header_size(nr_rlc_entity_um_t *entity,
nr_rlc_sdu_segment_t *sdu)
{
int header_size = 1;
/* if SN to be included then one more byte if SN field length is 12 */
if (!(sdu->is_first && sdu->is_last) && entity->sn_field_length == 12)
header_size++;
/* two more bytes for SO if SDU segment is not the first */
if (!sdu->is_first) header_size += 2;
return header_size;
}
/* resize SDU/SDU segment for the corresponding PDU to fit into 'pdu_size' /* resize SDU/SDU segment for the corresponding PDU to fit into 'pdu_size'
* bytes * bytes
* - modifies SDU/SDU segment to become an SDU segment * - modifies SDU/SDU segment to become an SDU segment
...@@ -462,8 +462,12 @@ static int generate_tx_pdu(nr_rlc_entity_um_t *entity, char *buffer, int size) ...@@ -462,8 +462,12 @@ static int generate_tx_pdu(nr_rlc_entity_um_t *entity, char *buffer, int size)
/* assign SN to SDU */ /* assign SN to SDU */
sdu->sdu->sn = entity->tx_next; sdu->sdu->sn = entity->tx_next;
/* segment if necessary */
pdu_size = pdu_header_size + sdu->size; pdu_size = pdu_header_size + sdu->size;
/* update buffer status */
entity->common.bstatus.tx_size -= pdu_size;
/* segment if necessary */
if (pdu_size > size) { if (pdu_size > size) {
nr_rlc_sdu_segment_t *next_sdu; nr_rlc_sdu_segment_t *next_sdu;
next_sdu = resegment(sdu, entity, size); next_sdu = resegment(sdu, entity, size);
...@@ -474,6 +478,9 @@ static int generate_tx_pdu(nr_rlc_entity_um_t *entity, char *buffer, int size) ...@@ -474,6 +478,9 @@ static int generate_tx_pdu(nr_rlc_entity_um_t *entity, char *buffer, int size)
entity->tx_list = next_sdu; entity->tx_list = next_sdu;
if (entity->tx_end == NULL) if (entity->tx_end == NULL)
entity->tx_end = entity->tx_list; entity->tx_end = entity->tx_list;
/* update buffer status */
entity->common.bstatus.tx_size += compute_pdu_header_size(entity, next_sdu)
+ next_sdu->size;
} }
/* update tx_next if the SDU is an SDU segment and is the last */ /* update tx_next if the SDU is an SDU segment and is the last */
...@@ -488,24 +495,6 @@ static int generate_tx_pdu(nr_rlc_entity_um_t *entity, char *buffer, int size) ...@@ -488,24 +495,6 @@ static int generate_tx_pdu(nr_rlc_entity_um_t *entity, char *buffer, int size)
return ret; return ret;
} }
/* Pretend to serialize all the SDUs in a list and return the size
* of all the PDUs it would produce, limited to 'maxsize'.
* Used for buffer status reporting.
*/
static int tx_list_size(nr_rlc_entity_um_t *entity,
nr_rlc_sdu_segment_t *l, int maxsize)
{
int ret = 0;
while (l != NULL && ret < maxsize) {
ret += compute_pdu_header_size(entity, l) + l->size;
l = l->next;
}
if (ret > maxsize) ret = maxsize;
return ret;
}
nr_rlc_entity_buffer_status_t nr_rlc_entity_um_buffer_status( nr_rlc_entity_buffer_status_t nr_rlc_entity_um_buffer_status(
nr_rlc_entity_t *_entity, int maxsize) nr_rlc_entity_t *_entity, int maxsize)
{ {
...@@ -513,7 +502,7 @@ nr_rlc_entity_buffer_status_t nr_rlc_entity_um_buffer_status( ...@@ -513,7 +502,7 @@ nr_rlc_entity_buffer_status_t nr_rlc_entity_um_buffer_status(
nr_rlc_entity_buffer_status_t ret; nr_rlc_entity_buffer_status_t ret;
ret.status_size = 0; ret.status_size = 0;
ret.tx_size = tx_list_size(entity, entity->tx_list, maxsize); ret.tx_size = entity->common.bstatus.tx_size;
ret.retx_size = 0; ret.retx_size = 0;
return ret; return ret;
...@@ -555,6 +544,10 @@ void nr_rlc_entity_um_recv_sdu(nr_rlc_entity_t *_entity, ...@@ -555,6 +544,10 @@ void nr_rlc_entity_um_recv_sdu(nr_rlc_entity_t *_entity,
sdu = nr_rlc_new_sdu(buffer, size, sdu_id); sdu = nr_rlc_new_sdu(buffer, size, sdu_id);
nr_rlc_sdu_segment_list_append(&entity->tx_list, &entity->tx_end, sdu); nr_rlc_sdu_segment_list_append(&entity->tx_list, &entity->tx_end, sdu);
/* update buffer status */
entity->common.bstatus.tx_size += compute_pdu_header_size(entity, sdu)
+ sdu->size;
} }
/*************************************************************************/ /*************************************************************************/
...@@ -650,6 +643,10 @@ void nr_rlc_entity_um_discard_sdu(nr_rlc_entity_t *_entity, int sdu_id) ...@@ -650,6 +643,10 @@ void nr_rlc_entity_um_discard_sdu(nr_rlc_entity_t *_entity, int sdu_id)
entity->tx_end = NULL; entity->tx_end = NULL;
} }
/* update buffer status */
entity->common.bstatus.tx_size -= compute_pdu_header_size(entity, cur)
+ cur->size;
nr_rlc_free_sdu_segment(cur); nr_rlc_free_sdu_segment(cur);
} }
...@@ -682,6 +679,8 @@ static void clear_entity(nr_rlc_entity_um_t *entity) ...@@ -682,6 +679,8 @@ static void clear_entity(nr_rlc_entity_um_t *entity)
entity->tx_list = NULL; entity->tx_list = NULL;
entity->tx_end = NULL; entity->tx_end = NULL;
entity->tx_size = 0; entity->tx_size = 0;
entity->common.bstatus.tx_size = 0;
} }
void nr_rlc_entity_um_reestablishment(nr_rlc_entity_t *_entity) void nr_rlc_entity_um_reestablishment(nr_rlc_entity_t *_entity)
......
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