Files
openairinterface5g/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_segment.c
T
Robert Schmidt cc8da80fbc Remove EXMIMO leftover
- Remove all files referencing EXMIMO
- Remove all targets/variables/defines that seem to be related to EXMIMO
2022-10-14 09:14:18 +02:00

809 lines
32 KiB
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
*/
#define RLC_UM_MODULE 1
#define RLC_UM_SEGMENT_C 1
//-----------------------------------------------------------------------------
#include "platform_types.h"
#include "platform_constants.h"
//-----------------------------------------------------------------------------
#include <assert.h>
#include "assertions.h"
#include "list.h"
#include "rlc_um.h"
#include "rlc_primitives.h"
#include "common/utils/LOG/log.h"
//-----------------------------------------------------------------------------
void
rlc_um_segment_10 (const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t *rlc_pP)
{
list_t pdus;
signed int pdu_remaining_size;
signed int test_pdu_remaining_size;
int nb_bytes_to_transmit = rlc_pP->nb_bytes_requested_by_mac;
rlc_um_pdu_sn_10_t *pdu_p;
struct mac_tb_req *pdu_tb_req_p;
mem_block_t *pdu_mem_p;
char *data;
char *data_sdu_p;
rlc_um_e_li_t *e_li_p;
struct rlc_um_tx_sdu_management *sdu_mngt_p;
unsigned int li_length_in_bytes;
unsigned int test_li_length_in_bytes;
unsigned int test_remaining_size_to_substract;
unsigned int test_remaining_num_li_to_substract;
unsigned int continue_fill_pdu_with_sdu;
unsigned int num_fill_sdu;
unsigned int test_num_li;
unsigned int fill_num_li;
mem_block_t *sdu_in_buffer = NULL;
unsigned int data_pdu_size;
unsigned int fi_first_byte_pdu_is_first_byte_sdu;
unsigned int fi_last_byte_pdu_is_last_byte_sdu;
unsigned int fi;
unsigned int max_li_overhead;
if (nb_bytes_to_transmit < 3) {
#if TRACE_RLC_UM_SEGMENT
LOG_D(RLC, PROTOCOL_RLC_UM_CTXT_FMT" NO SEGMENTATION nb_bytes to transmit = %d\n",
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_pP),
nb_bytes_to_transmit);
#endif
return;
}
list_init (&pdus, NULL); // param string identifying the list is NULL
pdu_mem_p = NULL;
// not fine locking
RLC_UM_MUTEX_LOCK(&rlc_pP->lock_input_sdus, ctxt_pP, rlc_pP);
while ((list_get_head(&rlc_pP->input_sdus)) && (nb_bytes_to_transmit > 0)) {
#if TRACE_RLC_UM_SEGMENT
LOG_D(RLC, PROTOCOL_RLC_UM_CTXT_FMT" nb_bytes_to_transmit %d BO %d\n",
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_pP),
nb_bytes_to_transmit,
rlc_pP->buffer_occupancy);
#endif
// pdu_p management
if (!pdu_mem_p) {
if (rlc_pP->input_sdus.nb_elements <= 1) {
max_li_overhead = 0;
} else {
max_li_overhead = (((rlc_pP->input_sdus.nb_elements - 1) * 3) / 2) + ((rlc_pP->input_sdus.nb_elements - 1) % 2);
}
if (nb_bytes_to_transmit >= (rlc_pP->buffer_occupancy + rlc_pP->tx_header_min_length_in_bytes + max_li_overhead)) {
data_pdu_size = rlc_pP->buffer_occupancy + rlc_pP->tx_header_min_length_in_bytes + max_li_overhead;
#if TRACE_RLC_UM_SEGMENT
LOG_D(RLC, PROTOCOL_RLC_UM_CTXT_FMT" alloc PDU size %d bytes to contain not all bytes requested by MAC but all BO of RLC@1\n",
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_pP),
data_pdu_size);
#endif
} else {
data_pdu_size = nb_bytes_to_transmit;
#if TRACE_RLC_UM_SEGMENT
LOG_D(RLC, PROTOCOL_RLC_UM_CTXT_FMT" alloc PDU size %d bytes to contain all bytes requested by MAC@1\n",
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_pP),
data_pdu_size);
#endif
}
if (!(pdu_mem_p = get_free_mem_block (data_pdu_size + sizeof(struct mac_tb_req), __func__))) {
#if TRACE_RLC_UM_SEGMENT
LOG_E(RLC, PROTOCOL_RLC_UM_CTXT_FMT" ERROR COULD NOT GET NEW PDU, EXIT\n",
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_pP));
#endif
RLC_UM_MUTEX_UNLOCK(&rlc_pP->lock_input_sdus);
return;
}
#if TRACE_RLC_UM_SEGMENT
LOG_D(RLC, PROTOCOL_RLC_UM_CTXT_FMT" get new PDU %d bytes\n",
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_pP),
data_pdu_size);
#endif
pdu_remaining_size = data_pdu_size - 2;
pdu_p = (rlc_um_pdu_sn_10_t*) (&pdu_mem_p->data[sizeof(struct mac_tb_req)]);
pdu_tb_req_p = (struct mac_tb_req*) (pdu_mem_p->data);
memset (pdu_mem_p->data, 0, sizeof (rlc_um_pdu_sn_10_t)+sizeof(struct mac_tb_req));
li_length_in_bytes = 1;
}
//----------------------------------------
// compute how many SDUS can fill the PDU
//----------------------------------------
continue_fill_pdu_with_sdu = 1;
num_fill_sdu = 0;
test_num_li = 0;
sdu_in_buffer = list_get_head(&rlc_pP->input_sdus);
test_pdu_remaining_size = pdu_remaining_size;
test_li_length_in_bytes = 1;
test_remaining_size_to_substract = 0;
test_remaining_num_li_to_substract = 0;
while ((sdu_in_buffer) && (continue_fill_pdu_with_sdu > 0)) {
sdu_mngt_p = ((struct rlc_um_tx_sdu_management *) (sdu_in_buffer->data));
if (sdu_mngt_p->sdu_remaining_size > test_pdu_remaining_size) {
// no LI
continue_fill_pdu_with_sdu = 0;
num_fill_sdu += 1;
test_pdu_remaining_size = 0;
test_remaining_size_to_substract = 0;
test_remaining_num_li_to_substract = 0;
} else if (sdu_mngt_p->sdu_remaining_size == test_pdu_remaining_size) {
// fi will indicate end of PDU is end of SDU, no need for LI
continue_fill_pdu_with_sdu = 0;
num_fill_sdu += 1;
test_pdu_remaining_size = 0;
test_remaining_size_to_substract = 0;
test_remaining_num_li_to_substract = 0;
} else if ((sdu_mngt_p->sdu_remaining_size + (test_li_length_in_bytes ^ 3)) == test_pdu_remaining_size ) {
// no LI
continue_fill_pdu_with_sdu = 0;
num_fill_sdu += 1;
test_pdu_remaining_size = 0;
test_remaining_size_to_substract = 0;
test_remaining_num_li_to_substract = 0;
//pdu_remaining_size = pdu_remaining_size - (test_li_length_in_bytes ^ 3);
} else if ((sdu_mngt_p->sdu_remaining_size + (test_li_length_in_bytes ^ 3)) < test_pdu_remaining_size ) {
test_num_li += 1;
num_fill_sdu += 1;
test_pdu_remaining_size = test_pdu_remaining_size - (sdu_mngt_p->sdu_remaining_size + (test_li_length_in_bytes ^ 3));
test_remaining_size_to_substract = test_li_length_in_bytes ^ 3;
test_remaining_num_li_to_substract = 1;
test_li_length_in_bytes = test_li_length_in_bytes ^ 3;
} else {
#if TRACE_RLC_UM_SEGMENT
LOG_D(RLC, PROTOCOL_RLC_UM_CTXT_FMT" sdu_mngt_p->sdu_remaining_size=%d test_pdu_remaining_size=%d test_li_length_in_bytes=%d\n",
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_pP),
sdu_mngt_p->sdu_remaining_size,
test_pdu_remaining_size,
test_li_length_in_bytes ^ 3);
#endif
// reduce the size of the PDU
continue_fill_pdu_with_sdu = 0;
num_fill_sdu += 1;
test_pdu_remaining_size = 0;
test_remaining_size_to_substract = 0;
test_remaining_num_li_to_substract = 0;
pdu_remaining_size = pdu_remaining_size - 1;
}
sdu_in_buffer = sdu_in_buffer->next;
}
if (test_remaining_num_li_to_substract > 0) {
// there is a LI that is not necessary
test_num_li = test_num_li - 1;
pdu_remaining_size = pdu_remaining_size - test_remaining_size_to_substract;
}
//----------------------------------------
// Do the real filling of the pdu_p
//----------------------------------------
#if TRACE_RLC_UM_SEGMENT
LOG_D(RLC, PROTOCOL_RLC_UM_CTXT_FMT" data shift %d Bytes num_li %d\n",
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_pP),
((test_num_li*3) +1) >> 1,
test_num_li);
#endif
data = ((char*)(&pdu_p->data[((test_num_li*3) +1) >> 1]));
e_li_p = (rlc_um_e_li_t*)(pdu_p->data);
continue_fill_pdu_with_sdu = 1;
li_length_in_bytes = 1;
fill_num_li = 0;
fi_first_byte_pdu_is_first_byte_sdu = 0;
fi_last_byte_pdu_is_last_byte_sdu = 0;
sdu_in_buffer = list_get_head(&rlc_pP->input_sdus);
if (
((struct rlc_um_tx_sdu_management *) (sdu_in_buffer->data))->sdu_remaining_size ==
((struct rlc_um_tx_sdu_management *) (sdu_in_buffer->data))->sdu_size) {
fi_first_byte_pdu_is_first_byte_sdu = 1;
}
while ((sdu_in_buffer) && (continue_fill_pdu_with_sdu > 0)) {
sdu_mngt_p = ((struct rlc_um_tx_sdu_management *) (sdu_in_buffer->data));
if (sdu_mngt_p->sdu_segmented_size == 0) {
#if TRACE_RLC_UM_SEGMENT
LOG_D(RLC, PROTOCOL_RLC_UM_CTXT_FMT" GET NEW SDU %p AVAILABLE SIZE %d Bytes\n",
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_pP),
sdu_mngt_p,
sdu_mngt_p->sdu_remaining_size);
#endif
} else {
#if TRACE_RLC_UM_SEGMENT
LOG_D(RLC, PROTOCOL_RLC_UM_CTXT_FMT" GET AGAIN SDU %p REMAINING AVAILABLE SIZE %d Bytes / %d Bytes \n",
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_pP),
sdu_mngt_p,
sdu_mngt_p->sdu_remaining_size,
sdu_mngt_p->sdu_size);
#endif
}
data_sdu_p = (char *) &(sdu_in_buffer->data[sizeof (struct rlc_um_tx_sdu_management) + sdu_mngt_p->sdu_segmented_size]);
if (sdu_mngt_p->sdu_remaining_size > pdu_remaining_size) {
#if TRACE_RLC_UM_SEGMENT
LOG_D(RLC, PROTOCOL_RLC_UM_CTXT_FMT" Filling all remaining PDU with %d bytes\n",
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_pP),
pdu_remaining_size);
LOG_D(RLC, PROTOCOL_RLC_UM_CTXT_FMT" pdu_mem_p %p pdu_mem_p->data %p pdu_p %p pdu_p->data %p data %p data_sdu_p %p pdu_remaining_size %d\n",
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_pP),
pdu_mem_p,
pdu_mem_p->data,
pdu_p,
pdu_p->data,
data,
data_sdu_p,
pdu_remaining_size);
#endif
memcpy(data, data_sdu_p, pdu_remaining_size);
sdu_mngt_p->sdu_remaining_size = sdu_mngt_p->sdu_remaining_size - pdu_remaining_size;
sdu_mngt_p->sdu_segmented_size = sdu_mngt_p->sdu_segmented_size + pdu_remaining_size;
fi_last_byte_pdu_is_last_byte_sdu = 0;
// no LI
rlc_pP->buffer_occupancy -= pdu_remaining_size;
continue_fill_pdu_with_sdu = 0;
pdu_remaining_size = 0;
} else if (sdu_mngt_p->sdu_remaining_size == pdu_remaining_size) {
#if TRACE_RLC_UM_SEGMENT
LOG_D(RLC, PROTOCOL_RLC_UM_CTXT_FMT" Exactly Filling remaining PDU with %d remaining bytes of SDU\n",
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_pP),
pdu_remaining_size);
#endif
memcpy(data, data_sdu_p, pdu_remaining_size);
// free SDU
rlc_pP->buffer_occupancy -= sdu_mngt_p->sdu_remaining_size;
sdu_in_buffer = list_remove_head(&rlc_pP->input_sdus);
free_mem_block (sdu_in_buffer, __func__);
sdu_in_buffer = list_get_head(&rlc_pP->input_sdus);
sdu_mngt_p = NULL;
fi_last_byte_pdu_is_last_byte_sdu = 1;
// fi will indicate end of PDU is end of SDU, no need for LI
continue_fill_pdu_with_sdu = 0;
pdu_remaining_size = 0;
} else if ((sdu_mngt_p->sdu_remaining_size + (li_length_in_bytes ^ 3)) < pdu_remaining_size ) {
#if TRACE_RLC_UM_SEGMENT
LOG_D(RLC, PROTOCOL_RLC_UM_CTXT_FMT" Filling PDU with %d all remaining bytes of SDU\n",
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_pP),
sdu_mngt_p->sdu_remaining_size);
#endif
memcpy(data, data_sdu_p, sdu_mngt_p->sdu_remaining_size);
data = &data[sdu_mngt_p->sdu_remaining_size];
li_length_in_bytes = li_length_in_bytes ^ 3;
fill_num_li += 1;
if (li_length_in_bytes == 2) {
if (fill_num_li == test_num_li) {
//e_li_p->e1 = 0;
e_li_p->b1 = 0;
} else {
//e_li_p->e1 = 1;
e_li_p->b1 = 0x80;
}
//e_li_p->li1 = sdu_mngt_p->sdu_remaining_size;
e_li_p->b1 = e_li_p->b1 | (sdu_mngt_p->sdu_remaining_size >> 4);
e_li_p->b2 = sdu_mngt_p->sdu_remaining_size << 4;
#if TRACE_RLC_UM_SEGMENT
LOG_D(RLC, PROTOCOL_RLC_UM_CTXT_FMT" set e_li_p->b1=%02X set e_li_p->b2=%02X fill_num_li=%d test_num_li=%d\n",
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_pP),
e_li_p->b1,
e_li_p->b2,
fill_num_li,
test_num_li);
#endif
} else {
if (fill_num_li != test_num_li) {
//e_li_p->e2 = 1;
e_li_p->b2 = e_li_p->b2 | 0x08;
}
//e_li_p->li2 = sdu_mngt_p->sdu_remaining_size;
e_li_p->b2 = e_li_p->b2 | (sdu_mngt_p->sdu_remaining_size >> 8);
e_li_p->b3 = sdu_mngt_p->sdu_remaining_size & 0xFF;
#if TRACE_RLC_UM_SEGMENT
LOG_D(RLC, PROTOCOL_RLC_UM_CTXT_FMT" set e_li_p->b2=%02X set e_li_p->b3=%02X fill_num_li=%d test_num_li=%d\n",
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_pP),
e_li_p->b2,
e_li_p->b3,
fill_num_li,
test_num_li);
#endif
e_li_p++;
}
pdu_remaining_size = pdu_remaining_size - (sdu_mngt_p->sdu_remaining_size + li_length_in_bytes);
// free SDU
rlc_pP->buffer_occupancy -= sdu_mngt_p->sdu_remaining_size;
sdu_in_buffer = list_remove_head(&rlc_pP->input_sdus);
free_mem_block (sdu_in_buffer, __func__);
sdu_in_buffer = list_get_head(&rlc_pP->input_sdus);
sdu_mngt_p = NULL;
} else {
#if TRACE_RLC_UM_SEGMENT
LOG_D(RLC, PROTOCOL_RLC_UM_CTXT_FMT" Filling PDU with %d all remaining bytes of SDU and reduce TB size by %d bytes\n",
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_pP),
sdu_mngt_p->sdu_remaining_size,
pdu_remaining_size - sdu_mngt_p->sdu_remaining_size);
#endif
memcpy(data, data_sdu_p, sdu_mngt_p->sdu_remaining_size);
// reduce the size of the PDU
continue_fill_pdu_with_sdu = 0;
fi_last_byte_pdu_is_last_byte_sdu = 1;
pdu_remaining_size = pdu_remaining_size - sdu_mngt_p->sdu_remaining_size;
// free SDU
rlc_pP->buffer_occupancy -= sdu_mngt_p->sdu_remaining_size;
sdu_in_buffer = list_remove_head(&rlc_pP->input_sdus);
free_mem_block (sdu_in_buffer, __func__);
sdu_in_buffer = list_get_head(&rlc_pP->input_sdus);
sdu_mngt_p = NULL;
}
}
// set framing info
if (fi_first_byte_pdu_is_first_byte_sdu) {
fi = 0;
} else {
fi = 2;
}
if (!fi_last_byte_pdu_is_last_byte_sdu) {
fi = fi + 1;
}
pdu_p->b1 = (fi << 3); //pdu_p->b1 |
// set fist e bit
if (fill_num_li > 0) {
pdu_p->b1 = pdu_p->b1 | 0x04;
}
pdu_p->b1 = pdu_p->b1 | ((rlc_pP->vt_us >> 8) & 0x03);
pdu_p->b2 = rlc_pP->vt_us & 0xFF;
rlc_pP->vt_us = rlc_pP->vt_us+1;
pdu_tb_req_p->data_ptr = (unsigned char*)pdu_p;
pdu_tb_req_p->tb_size = data_pdu_size - pdu_remaining_size;
list_add_tail_eurecom (pdu_mem_p, &rlc_pP->pdus_to_mac_layer);
#if TRACE_RLC_PAYLOAD
rlc_util_print_hex_octets(RLC, pdu_mem_p->data, data_pdu_size);
#endif
//AssertFatal( pdu_tb_req_p->tb_size > 0 , "SEGMENT10: FINAL RLC UM PDU LENGTH %d", pdu_tb_req_p->tb_size);
if(pdu_tb_req_p->tb_size <= 0) {
LOG_E(RLC, "SEGMENT10: FINAL RLC UM PDU LENGTH %d\n", pdu_tb_req_p->tb_size);
break;
}
pdu_p = NULL;
pdu_mem_p = NULL;
//nb_bytes_to_transmit = nb_bytes_to_transmit - data_pdu_size;
nb_bytes_to_transmit = 0; // 1 PDU only
}
RLC_UM_MUTEX_UNLOCK(&rlc_pP->lock_input_sdus);
}
//-----------------------------------------------------------------------------
void
rlc_um_segment_5 (const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t *rlc_pP)
{
list_t pdus;
signed int pdu_remaining_size = 0;
signed int test_pdu_remaining_size = 0;
int nb_bytes_to_transmit = rlc_pP->nb_bytes_requested_by_mac;
rlc_um_pdu_sn_5_t *pdu_p = NULL;
struct mac_tb_req *pdu_tb_req_p = NULL;
mem_block_t *pdu_mem_p = NULL;
char *data = NULL;
char *data_sdu_p = NULL;
rlc_um_e_li_t *e_li_p = NULL;
struct rlc_um_tx_sdu_management *sdu_mngt_p = NULL;
unsigned int li_length_in_bytes = 0;
unsigned int test_li_length_in_bytes = 0;
unsigned int test_remaining_size_to_substract = 0;
unsigned int test_remaining_num_li_to_substract = 0;
unsigned int continue_fill_pdu_with_sdu = 0;
unsigned int num_fill_sdu = 0;
unsigned int test_num_li = 0;
unsigned int fill_num_li = 0;
mem_block_t *sdu_in_buffer = NULL;
unsigned int data_pdu_size = 0;
unsigned int fi_first_byte_pdu_is_first_byte_sdu = 0;
unsigned int fi_last_byte_pdu_is_last_byte_sdu = 0;
unsigned int fi = 0;
unsigned int max_li_overhead = 0;
if (nb_bytes_to_transmit < 2) {
#if TRACE_RLC_UM_SEGMENT
LOG_D(RLC, PROTOCOL_RLC_UM_CTXT_FMT" NO SEGMENTATION5 nb_bytes to transmit = %d\n",
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_pP),
nb_bytes_to_transmit);
#endif
return;
}
list_init (&pdus, NULL); // param string identifying the list is NULL
pdu_mem_p = NULL;
RLC_UM_MUTEX_LOCK(&rlc_pP->lock_input_sdus, ctxt_pP, rlc_pP);
while ((list_get_head(&rlc_pP->input_sdus)) && (nb_bytes_to_transmit > 0)) {
#if TRACE_RLC_UM_SEGMENT
LOG_D(RLC, PROTOCOL_RLC_UM_CTXT_FMT"nb_bytes_to_transmit %d BO %d\n",
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_pP),
nb_bytes_to_transmit,
rlc_pP->buffer_occupancy);
#endif
// pdu_p management
if (!pdu_mem_p) {
if (rlc_pP->input_sdus.nb_elements <= 1) {
max_li_overhead = 0;
} else {
max_li_overhead = (((rlc_pP->input_sdus.nb_elements - 1) * 3) / 2) + ((rlc_pP->input_sdus.nb_elements - 1) % 2);
}
if (nb_bytes_to_transmit >= (rlc_pP->buffer_occupancy + rlc_pP->tx_header_min_length_in_bytes + max_li_overhead)) {
data_pdu_size = rlc_pP->buffer_occupancy + rlc_pP->tx_header_min_length_in_bytes + max_li_overhead;
#if TRACE_RLC_UM_SEGMENT
LOG_D(RLC, PROTOCOL_RLC_UM_CTXT_FMT" alloc PDU size %d bytes to contain not all bytes requested by MAC but all BO of RLC@1\n",
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_pP),
data_pdu_size);
#endif
} else {
data_pdu_size = nb_bytes_to_transmit;
#if TRACE_RLC_UM_SEGMENT
LOG_D(RLC, PROTOCOL_RLC_UM_CTXT_FMT" alloc PDU size %d bytes to contain all bytes requested by MAC@1\n",
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_pP),
data_pdu_size);
#endif
}
if (!(pdu_mem_p = get_free_mem_block (data_pdu_size + sizeof(struct mac_tb_req), __func__))) {
#if TRACE_RLC_UM_SEGMENT
LOG_E(RLC, PROTOCOL_RLC_UM_CTXT_FMT" ERROR COULD NOT GET NEW PDU, EXIT\n",
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_pP));
#endif
RLC_UM_MUTEX_UNLOCK(&rlc_pP->lock_input_sdus);
return;
}
#if TRACE_RLC_UM_SEGMENT
LOG_D(RLC, PROTOCOL_RLC_UM_CTXT_FMT" get new PDU %d bytes\n",
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_pP),
data_pdu_size);
#endif
pdu_remaining_size = data_pdu_size - 1;
pdu_p = (rlc_um_pdu_sn_5_t*) (&pdu_mem_p->data[sizeof(struct mac_tb_req)]);
pdu_tb_req_p = (struct mac_tb_req*) (pdu_mem_p->data);
memset (pdu_mem_p->data, 0, sizeof (rlc_um_pdu_sn_5_t)+sizeof(struct mac_tb_req));
li_length_in_bytes = 1;
}
//----------------------------------------
// compute how many SDUS can fill the PDU
//----------------------------------------
continue_fill_pdu_with_sdu = 1;
num_fill_sdu = 0;
test_num_li = 0;
sdu_in_buffer = list_get_head(&rlc_pP->input_sdus);
test_pdu_remaining_size = pdu_remaining_size;
test_li_length_in_bytes = 1;
test_remaining_size_to_substract = 0;
test_remaining_num_li_to_substract = 0;
while ((sdu_in_buffer) && (continue_fill_pdu_with_sdu > 0)) {
sdu_mngt_p = ((struct rlc_um_tx_sdu_management *) (sdu_in_buffer->data));
if (sdu_mngt_p->sdu_remaining_size > test_pdu_remaining_size) {
// no LI
continue_fill_pdu_with_sdu = 0;
num_fill_sdu += 1;
test_pdu_remaining_size = 0;
test_remaining_size_to_substract = 0;
test_remaining_num_li_to_substract = 0;
} else if (sdu_mngt_p->sdu_remaining_size == test_pdu_remaining_size) {
// fi will indicate end of PDU is end of SDU, no need for LI
continue_fill_pdu_with_sdu = 0;
num_fill_sdu += 1;
test_pdu_remaining_size = 0;
test_remaining_size_to_substract = 0;
test_remaining_num_li_to_substract = 0;
} else if ((sdu_mngt_p->sdu_remaining_size + (test_li_length_in_bytes ^ 3)) == test_pdu_remaining_size ) {
// no LI
continue_fill_pdu_with_sdu = 0;
num_fill_sdu += 1;
test_pdu_remaining_size = 0;
test_remaining_size_to_substract = 0;
test_remaining_num_li_to_substract = 0;
pdu_remaining_size = pdu_remaining_size - (test_li_length_in_bytes ^ 3);
data_pdu_size -= (test_li_length_in_bytes ^ 3);//modifier pour duy
} else if ((sdu_mngt_p->sdu_remaining_size + (test_li_length_in_bytes ^ 3)) < test_pdu_remaining_size ) {
test_num_li += 1;
num_fill_sdu += 1;
test_pdu_remaining_size = test_pdu_remaining_size - (sdu_mngt_p->sdu_remaining_size + (test_li_length_in_bytes ^ 3));
test_remaining_size_to_substract = test_li_length_in_bytes ^ 3;
test_remaining_num_li_to_substract = 1;
test_li_length_in_bytes = test_li_length_in_bytes ^ 3;
} else {
#if TRACE_RLC_UM_SEGMENT
LOG_D(RLC, PROTOCOL_RLC_UM_CTXT_FMT" sdu_mngt_p->sdu_remaining_size=%d test_pdu_remaining_size=%d test_li_length_in_bytes=%d\n",
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_pP),
sdu_mngt_p->sdu_remaining_size,
test_pdu_remaining_size,
test_li_length_in_bytes ^ 3);
#endif
// reduce the size of the PDU
continue_fill_pdu_with_sdu = 0;
num_fill_sdu += 1;
test_pdu_remaining_size = 0;
test_remaining_size_to_substract = 0;
test_remaining_num_li_to_substract = 0;
pdu_remaining_size = pdu_remaining_size - 1;
data_pdu_size -= 1;//modifier pour duy
}
sdu_in_buffer = sdu_in_buffer->next;
}
if (test_remaining_num_li_to_substract > 0) {
// there is a LI that is not necessary
test_num_li = test_num_li - 1;
pdu_remaining_size = pdu_remaining_size - test_remaining_size_to_substract;
}
//----------------------------------------
// Do the real filling of the pdu_p
//----------------------------------------
#if TRACE_RLC_UM_SEGMENT
LOG_D(RLC, PROTOCOL_RLC_UM_CTXT_FMT" data shift %d Bytes num_li %d\n",
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_pP),
((test_num_li*3) +1) >> 1,
test_num_li);
#endif
data = ((char*)(&pdu_p->data[((test_num_li*3) +1) >> 1]));
e_li_p = (rlc_um_e_li_t*)(pdu_p->data);
continue_fill_pdu_with_sdu = 1;
li_length_in_bytes = 1;
fill_num_li = 0;
fi_first_byte_pdu_is_first_byte_sdu = 0;
fi_last_byte_pdu_is_last_byte_sdu = 0;
sdu_in_buffer = list_get_head(&rlc_pP->input_sdus);
if (
((struct rlc_um_tx_sdu_management *) (sdu_in_buffer->data))->sdu_remaining_size ==
((struct rlc_um_tx_sdu_management *) (sdu_in_buffer->data))->sdu_size) {
fi_first_byte_pdu_is_first_byte_sdu = 1;
}
while ((sdu_in_buffer) && (continue_fill_pdu_with_sdu > 0)) {
sdu_mngt_p = ((struct rlc_um_tx_sdu_management *) (sdu_in_buffer->data));
if (sdu_mngt_p->sdu_segmented_size == 0) {
#if TRACE_RLC_UM_SEGMENT
LOG_D(RLC, PROTOCOL_RLC_UM_CTXT_FMT" GET NEW SDU %p AVAILABLE SIZE %d Bytes\n",
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_pP),
sdu_mngt_p,
sdu_mngt_p->sdu_remaining_size);
#endif
} else {
#if TRACE_RLC_UM_SEGMENT
LOG_D(RLC, PROTOCOL_RLC_UM_CTXT_FMT" GET AGAIN SDU %p REMAINING AVAILABLE SIZE %d Bytes / %d Bytes \n",
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_pP),
sdu_mngt_p,
sdu_mngt_p->sdu_remaining_size,
sdu_mngt_p->sdu_size);
#endif
}
data_sdu_p = (char*) &(sdu_in_buffer->data[sizeof (struct rlc_um_tx_sdu_management) + sdu_mngt_p->sdu_segmented_size]);
if (sdu_mngt_p->sdu_remaining_size > pdu_remaining_size) {
#if TRACE_RLC_UM_SEGMENT
LOG_D(RLC, PROTOCOL_RLC_UM_CTXT_FMT" Filling all remaining PDU with %d bytes\n",
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_pP),
pdu_remaining_size);
LOG_D(RLC, PROTOCOL_RLC_UM_CTXT_FMT" pdu_mem_p %p pdu_p %p pdu_p->data %p data %p data_sdu_p %p pdu_remaining_size %d\n",
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_pP),
pdu_mem_p,
pdu_p,
pdu_p->data,
data,
data_sdu_p,
pdu_remaining_size);
#endif
memcpy(data, data_sdu_p, pdu_remaining_size);
sdu_mngt_p->sdu_remaining_size = sdu_mngt_p->sdu_remaining_size - pdu_remaining_size;
sdu_mngt_p->sdu_segmented_size = sdu_mngt_p->sdu_segmented_size + pdu_remaining_size;
fi_last_byte_pdu_is_last_byte_sdu = 0;
// no LI
rlc_pP->buffer_occupancy -= pdu_remaining_size;
continue_fill_pdu_with_sdu = 0;
pdu_remaining_size = 0;
} else if (sdu_mngt_p->sdu_remaining_size == pdu_remaining_size) {
#if TRACE_RLC_UM_SEGMENT
LOG_D(RLC, PROTOCOL_RLC_UM_CTXT_FMT" Exactly Filling remaining PDU with %d remaining bytes of SDU\n",
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_pP),
pdu_remaining_size);
#endif
memcpy(data, data_sdu_p, pdu_remaining_size);
// free SDU
rlc_pP->buffer_occupancy -= sdu_mngt_p->sdu_remaining_size;
sdu_in_buffer = list_remove_head(&rlc_pP->input_sdus);
free_mem_block (sdu_in_buffer, __func__);
sdu_in_buffer = list_get_head(&rlc_pP->input_sdus);
sdu_mngt_p = NULL;
fi_last_byte_pdu_is_last_byte_sdu = 1;
// fi will indicate end of PDU is end of SDU, no need for LI
continue_fill_pdu_with_sdu = 0;
pdu_remaining_size = 0;
} else if ((sdu_mngt_p->sdu_remaining_size + (li_length_in_bytes ^ 3)) < pdu_remaining_size ) {
#if TRACE_RLC_UM_SEGMENT
LOG_D(RLC, PROTOCOL_RLC_UM_CTXT_FMT" Filling PDU with %d all remaining bytes of SDU\n",
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_pP),
sdu_mngt_p->sdu_remaining_size);
#endif
memcpy(data, data_sdu_p, sdu_mngt_p->sdu_remaining_size);
data = &data[sdu_mngt_p->sdu_remaining_size];
li_length_in_bytes = li_length_in_bytes ^ 3;
fill_num_li += 1;
if (li_length_in_bytes == 2) {
if (fill_num_li == test_num_li) {
//e_li_p->e1 = 0;
e_li_p->b1 = 0;
} else {
//e_li_p->e1 = 1;
e_li_p->b1 = 0x80;
}
//e_li_p->li1 = sdu_mngt_p->sdu_remaining_size;
e_li_p->b1 = e_li_p->b1 | (sdu_mngt_p->sdu_remaining_size >> 4);
e_li_p->b2 = sdu_mngt_p->sdu_remaining_size << 4;
#if TRACE_RLC_UM_SEGMENT
LOG_D(RLC, PROTOCOL_RLC_UM_CTXT_FMT" set e_li_p->b1=%02X set e_li_p->b2=%02X fill_num_li=%d test_num_li=%d\n",
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_pP),
e_li_p->b1,
e_li_p->b2,
fill_num_li,
test_num_li);
#endif
} else {
if (fill_num_li != test_num_li) {
//e_li_p->e2 = 1;
e_li_p->b2 = e_li_p->b2 | 0x08;
}
//e_li_p->li2 = sdu_mngt_p->sdu_remaining_size;
e_li_p->b2 = e_li_p->b2 | (sdu_mngt_p->sdu_remaining_size >> 8);
e_li_p->b3 = sdu_mngt_p->sdu_remaining_size & 0xFF;
#if TRACE_RLC_UM_SEGMENT
LOG_D(RLC, PROTOCOL_RLC_UM_CTXT_FMT" set e_li_p->b2=%02X set e_li_p->b3=%02X fill_num_li=%d test_num_li=%d\n",
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_pP),
e_li_p->b2,
e_li_p->b3,
fill_num_li,
test_num_li);
#endif
e_li_p++;
}
pdu_remaining_size = pdu_remaining_size - (sdu_mngt_p->sdu_remaining_size + li_length_in_bytes);
// free SDU
rlc_pP->buffer_occupancy -= sdu_mngt_p->sdu_remaining_size;
sdu_in_buffer = list_remove_head(&rlc_pP->input_sdus);
free_mem_block (sdu_in_buffer, __func__);
sdu_in_buffer = list_get_head(&rlc_pP->input_sdus);
sdu_mngt_p = NULL;
} else {
LOG_E(RLC, PROTOCOL_RLC_UM_CTXT_FMT" Filling PDU with %d all remaining bytes of SDU and reduce TB size by %d bytes\n",
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_pP),
sdu_mngt_p->sdu_remaining_size,
pdu_remaining_size - sdu_mngt_p->sdu_remaining_size);
//assert(1!=1);
memcpy(data, data_sdu_p, sdu_mngt_p->sdu_remaining_size);
// reduce the size of the PDU
continue_fill_pdu_with_sdu = 0;
fi_last_byte_pdu_is_last_byte_sdu = 1;
pdu_remaining_size = pdu_remaining_size - sdu_mngt_p->sdu_remaining_size;
// free SDU
rlc_pP->buffer_occupancy -= sdu_mngt_p->sdu_remaining_size;
sdu_in_buffer = list_remove_head(&rlc_pP->input_sdus);
free_mem_block (sdu_in_buffer, __func__);
sdu_in_buffer = list_get_head(&rlc_pP->input_sdus);
sdu_mngt_p = NULL;
}
}
// set framing info
if (fi_first_byte_pdu_is_first_byte_sdu) {
fi = 0;
} else {
fi = 2;
}
if (!fi_last_byte_pdu_is_last_byte_sdu) {
fi = fi + 1;
}
pdu_p->b1 = (fi << 6); //pdu_p->b1 |
// set fist e bit
if (fill_num_li > 0) {
pdu_p->b1 = pdu_p->b1 | 0x20;
}
pdu_p->b1 = pdu_p->b1 | (rlc_pP->vt_us & 0x1F);
rlc_pP->vt_us = rlc_pP->vt_us+1;
pdu_tb_req_p->data_ptr = (unsigned char*)pdu_p;
pdu_tb_req_p->tb_size = data_pdu_size - pdu_remaining_size;
list_add_tail_eurecom (pdu_mem_p, &rlc_pP->pdus_to_mac_layer);
#if TRACE_RLC_PAYLOAD
rlc_util_print_hex_octets(RLC, (unsigned char*)pdu_mem_p->data, data_pdu_size);
#endif
//AssertFatal( pdu_tb_req_p->tb_size > 0 , "SEGMENT5: FINAL RLC UM PDU LENGTH %d", pdu_tb_req_p->tb_size);
if(pdu_tb_req_p->tb_size <= 0) {
LOG_E(RLC, "SEGMENT5: FINAL RLC UM PDU LENGTH %d\n", pdu_tb_req_p->tb_size);
break;
}
pdu_p = NULL;
pdu_mem_p = NULL;
//nb_bytes_to_transmit = nb_bytes_to_transmit - data_pdu_size;
nb_bytes_to_transmit = 0; // 1 PDU only
}
RLC_UM_MUTEX_UNLOCK(&rlc_pP->lock_input_sdus);
}