From 1495a6b01fc03b0d21f2e56fba23f249273be9b6 Mon Sep 17 00:00:00 2001 From: Cedric Roux <cedric.roux@eurecom.fr> Date: Tue, 16 Nov 2021 13:22:49 +0100 Subject: [PATCH] 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.) --- openair2/LAYER2/nr_rlc/nr_rlc_entity.h | 2 + openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c | 84 +++++++++++++---------- openair2/LAYER2/nr_rlc/nr_rlc_entity_tm.c | 23 +++---- openair2/LAYER2/nr_rlc/nr_rlc_entity_um.c | 67 +++++++++--------- 4 files changed, 93 insertions(+), 83 deletions(-) diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_entity.h b/openair2/LAYER2/nr_rlc/nr_rlc_entity.h index 5b12a90cfd..b9b638fe07 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_entity.h +++ b/openair2/LAYER2/nr_rlc/nr_rlc_entity.h @@ -63,6 +63,8 @@ typedef struct nr_rlc_entity_t { void (*max_retx_reached)(void *max_retx_reached_data, struct nr_rlc_entity_t *entity); void *max_retx_reached_data; + /* buffer status computation */ + nr_rlc_entity_buffer_status_t bstatus; } nr_rlc_entity_t; nr_rlc_entity_t *new_nr_rlc_entity_am( diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c b/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c index 8db5ce31ad..aaf5492241 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c @@ -28,6 +28,19 @@ #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 */ /*************************************************************************/ @@ -114,6 +127,10 @@ static void consider_retransmission(nr_rlc_entity_am_t *entity, nr_rlc_sdu_segment_list_append(&entity->retransmit_list, &entity->retransmit_end, 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 @@ -351,6 +368,9 @@ static void process_received_ack(nr_rlc_entity_am_t *entity, int ack_sn) } /* remove from retransmit list */ 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 */ entity->ack_list = nr_rlc_sdu_segment_list_add(sn_compare_tx, entity, entity->ack_list, cur); @@ -840,19 +860,6 @@ static int serialize_sdu(nr_rlc_entity_am_t *entity, 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' * bytes * - 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, sdu->next = NULL; - /* segment if necessary */ pdu_size = pdu_header_size + sdu->size; + + /* update buffer status */ + entity->common.bstatus.retx_size -= pdu_size; + + /* segment if necessary */ if (pdu_size > size) { nr_rlc_sdu_segment_t *next_sdu; next_sdu = resegment(sdu, entity, size); @@ -1436,6 +1447,9 @@ static int generate_retx_pdu(nr_rlc_entity_am_t *entity, char *buffer, entity->retransmit_list = next_sdu; if (entity->retransmit_end == NULL) 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 */ @@ -1479,11 +1493,15 @@ static int generate_tx_pdu(nr_rlc_entity_am_t *entity, char *buffer, int size) sdu->next = NULL; + pdu_size = pdu_header_size + sdu->size; + + /* update buffer status */ + entity->common.bstatus.tx_size -= pdu_size; + /* assign SN to SDU */ sdu->sdu->sn = entity->tx_next; /* segment if necessary */ - pdu_size = pdu_header_size + sdu->size; if (pdu_size > size) { nr_rlc_sdu_segment_t *next_sdu; 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) entity->tx_list = next_sdu; if (entity->tx_end == NULL) 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 */ @@ -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); } -/* 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_t *_entity, int maxsize) { @@ -1549,8 +1552,8 @@ nr_rlc_entity_buffer_status_t nr_rlc_entity_am_buffer_status( else ret.status_size = 0; - ret.tx_size = tx_list_size(entity, entity->tx_list, maxsize); - ret.retx_size = tx_list_size(entity, entity->retransmit_list, maxsize); + ret.tx_size = entity->common.bstatus.tx_size; + ret.retx_size = entity->common.bstatus.retx_size; return ret; } @@ -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"); 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) 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); } @@ -1845,6 +1856,9 @@ static void clear_entity(nr_rlc_entity_am_t *entity) entity->retransmit_end = 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) diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_entity_tm.c b/openair2/LAYER2/nr_rlc/nr_rlc_entity_tm.c index 26ae481889..75408276d1 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_entity_tm.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_entity_tm.c @@ -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); entity->tx_size -= sdu->size; - nr_rlc_free_sdu_segment(sdu); - return ret; -} - -static int tx_list_size(nr_rlc_entity_tm_t *entity, - nr_rlc_sdu_segment_t *l, int maxsize) -{ - int ret = 0; + /* update buffer status */ + entity->common.bstatus.tx_size -= sdu->size; - while (l != NULL && ret < maxsize) { - ret += l->size; - l = l->next; - } + nr_rlc_free_sdu_segment(sdu); - if (ret > maxsize) ret = maxsize; return ret; } @@ -94,7 +84,7 @@ nr_rlc_entity_buffer_status_t nr_rlc_entity_tm_buffer_status( nr_rlc_entity_buffer_status_t ret; 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; return ret; @@ -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); 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) entity->tx_list = NULL; entity->tx_end = NULL; entity->tx_size = 0; + + entity->common.bstatus.tx_size = 0; } void nr_rlc_entity_tm_reestablishment(nr_rlc_entity_t *_entity) diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_entity_um.c b/openair2/LAYER2/nr_rlc/nr_rlc_entity_um.c index 71173eee5a..7336e8f9da 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_entity_um.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_entity_um.c @@ -28,6 +28,20 @@ #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 */ /*************************************************************************/ @@ -375,20 +389,6 @@ static int serialize_sdu(nr_rlc_entity_um_t *entity, 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' * bytes * - 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) /* assign SN to SDU */ sdu->sdu->sn = entity->tx_next; - /* segment if necessary */ pdu_size = pdu_header_size + sdu->size; + + /* update buffer status */ + entity->common.bstatus.tx_size -= pdu_size; + + /* segment if necessary */ if (pdu_size > size) { nr_rlc_sdu_segment_t *next_sdu; 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) entity->tx_list = next_sdu; if (entity->tx_end == NULL) 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 */ @@ -488,24 +495,6 @@ static int generate_tx_pdu(nr_rlc_entity_um_t *entity, char *buffer, int size) 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_t *_entity, int maxsize) { @@ -513,7 +502,7 @@ nr_rlc_entity_buffer_status_t nr_rlc_entity_um_buffer_status( nr_rlc_entity_buffer_status_t ret; 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; return ret; @@ -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); 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) 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); } @@ -682,6 +679,8 @@ static void clear_entity(nr_rlc_entity_um_t *entity) entity->tx_list = NULL; entity->tx_end = NULL; entity->tx_size = 0; + + entity->common.bstatus.tx_size = 0; } void nr_rlc_entity_um_reestablishment(nr_rlc_entity_t *_entity) -- 2.26.2