mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-13 04:30:28 +00:00
Resolves the missing DL symbols
Previously, in F, only the following (subframe, slot, symbol) combinations were sent every frame: (0, 0, 0) (2, 1, 0) (5, 0, 0) (7, 1, 0) Now, all the DL symbols are sent. Notes: In both E and F, the radio-transport fragmentation is not supported, and all the "fragmented" (not seen as fragments in the xran, only as sections) packets contain "E-bit" equal to 1. Per spec, the value 1 for "E-bit" signifies the last fragment of one symbol. For more info, please see "ecpriSeqid" section in the spec. In E: - nRBStart and nRBSize is updated according to the sent/received packet; - max sections = 1. In F: - nRBStart and nRBSize is only used for C-plane messages; - nPrbElm represents the number of sections for DL only; - based on the nPrbElm, each section contains UP_nRBStart and UP_nRBSize parameters which represent the start and number of PRBs in one section or one fragment. Co-authored-by: Mario Joa-Ng <mario.joa-ng@openairinterface.com>
This commit is contained in:
@@ -521,7 +521,6 @@ int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp)
|
||||
|
||||
const struct xran_fh_init *fh_init = get_xran_fh_init();
|
||||
const struct xran_fh_config *fh_cfg = get_xran_fh_config(0);
|
||||
int nPRBs = fh_cfg->nDLRBs;
|
||||
int fftsize = 1 << fh_cfg->nDLFftSize;
|
||||
int nb_tx_per_ru = ru->nb_tx / fh_init->xran_ports;
|
||||
int nb_rx_per_ru = ru->nb_rx / fh_init->xran_ports;
|
||||
@@ -583,9 +582,8 @@ int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp)
|
||||
}
|
||||
// This loop would better be more inner to avoid confusion and maybe also errors.
|
||||
for (int32_t sym_idx = 0; sym_idx < XRAN_NUM_OF_SYMBOL_PER_SLOT; sym_idx++) {
|
||||
/* the callback is for mixed and UL slots. In mixed, we have to
|
||||
* skip UL and guard symbols. */
|
||||
if (is_tdd_ul_symbol(frame_conf, slot, sym_idx)) {
|
||||
/* skip UL and guard symbols. */
|
||||
if (!is_tdd_dl_symbol(frame_conf, slot, sym_idx)) {
|
||||
continue;
|
||||
}
|
||||
uint8_t *pData =
|
||||
@@ -596,20 +594,36 @@ int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp)
|
||||
pos = &ru->txdataF_BF[ant_id][sym_idx * fftsize];
|
||||
|
||||
uint8_t *u8dptr;
|
||||
struct xran_prb_map *pRbMap = pPrbMap;
|
||||
int32_t sym_id = sym_idx % XRAN_NUM_OF_SYMBOL_PER_SLOT;
|
||||
// even when the fragmentation occurs, nRBSize & nRBStart carry the same values in each prbMap
|
||||
// therefore, I took the liberty to just extract these values from the first prbMap
|
||||
struct xran_prb_elm *p_prbMapElm = &pPrbMap->prbMap[0];
|
||||
int num_totalRB = p_prbMapElm->nRBSize;
|
||||
int start_totalRB = p_prbMapElm->nRBStart;
|
||||
|
||||
int pos_len = 0;
|
||||
int neg_len = 0;
|
||||
|
||||
if (start_totalRB < (num_totalRB >> 1)) // there are PRBs left of DC
|
||||
neg_len = min((num_totalRB * 6) - (start_totalRB * 12), num_totalRB * N_SC_PER_PRB);
|
||||
pos_len = (num_totalRB * N_SC_PER_PRB) - neg_len;
|
||||
// Calculation of the pointer for the section in the buffer.
|
||||
// start of positive frequency component
|
||||
uint16_t *src1 = (uint16_t *)&pos[(neg_len == 0) ? ((start_totalRB * N_SC_PER_PRB) - (num_totalRB * 6)) : 0];
|
||||
// start of negative frequency component
|
||||
uint16_t *src2 = (uint16_t *)&pos[(start_totalRB * N_SC_PER_PRB) + fftsize - (num_totalRB * 6)];
|
||||
|
||||
uint32_t local_src[num_totalRB * N_SC_PER_PRB] __attribute__((aligned(64)));
|
||||
memcpy((void *)local_src, (void *)src2, neg_len * 4);
|
||||
memcpy((void *)&local_src[neg_len], (void *)src1, pos_len * 4);
|
||||
if (ptr && pos) {
|
||||
uint32_t idxElm = 0;
|
||||
u8dptr = (uint8_t *)ptr;
|
||||
int16_t payload_len = 0;
|
||||
|
||||
uint8_t *dst = (uint8_t *)u8dptr;
|
||||
|
||||
struct xran_prb_elm *p_prbMapElm = &pRbMap->prbMap[idxElm];
|
||||
|
||||
for (idxElm = 0; idxElm < pRbMap->nPrbElm; idxElm++) {
|
||||
for (uint32_t idxElm = 0; idxElm < pPrbMap->nPrbElm; idxElm++) {
|
||||
struct xran_section_desc *p_sec_desc = NULL;
|
||||
p_prbMapElm = &pRbMap->prbMap[idxElm];
|
||||
struct xran_prb_elm *p_prbMapElm = &pPrbMap->prbMap[idxElm];
|
||||
if (sym_idx == 0) {
|
||||
// ant_id / no of antenna per beam gives the beam_nb
|
||||
p_prbMapElm->nBeamIndex = ru->beam_id[ant_id / (ru->nb_tx / ru->num_beams_period)][slot * XRAN_NUM_OF_SYMBOL_PER_SLOT];
|
||||
@@ -618,11 +632,18 @@ int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp)
|
||||
p_prbMapElm->nBeamIndex = 0;
|
||||
}
|
||||
|
||||
// assumes one fragment per symbol
|
||||
// radio-transport fragmentation is not supported in both E and F releases;
|
||||
// E-bit = 1 => each ethernet frame is considered as the last fragment;
|
||||
// a group of PRBs per each symbol is encapsulated in one ethernet frame.
|
||||
// => seems that the RUs don't check for E-bit
|
||||
#ifdef E_RELEASE
|
||||
p_sec_desc = p_prbMapElm->p_sec_desc[sym_id][0];
|
||||
p_sec_desc = p_prbMapElm->p_sec_desc[sym_idx][0];
|
||||
int16_t startRB = p_prbMapElm->nRBStart;
|
||||
int16_t numRB = p_prbMapElm->nRBSize;
|
||||
#elif F_RELEASE
|
||||
p_sec_desc = &p_prbMapElm->sec_desc[sym_id][0];
|
||||
p_sec_desc = &p_prbMapElm->sec_desc[sym_idx][0];
|
||||
int16_t startRB = p_prbMapElm->UP_nRBStart;
|
||||
int16_t numRB = p_prbMapElm->UP_nRBSize;
|
||||
#endif
|
||||
|
||||
dst = xran_add_hdr_offset(dst, p_prbMapElm->compMethod);
|
||||
@@ -633,36 +654,28 @@ int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp)
|
||||
}
|
||||
uint16_t *dst16 = (uint16_t *)dst;
|
||||
|
||||
int pos_len = 0;
|
||||
int neg_len = 0;
|
||||
|
||||
if (p_prbMapElm->nRBStart < (nPRBs >> 1)) // there are PRBs left of DC
|
||||
neg_len = min((nPRBs * 6) - (p_prbMapElm->nRBStart * 12), p_prbMapElm->nRBSize * N_SC_PER_PRB);
|
||||
pos_len = (p_prbMapElm->nRBSize * N_SC_PER_PRB) - neg_len;
|
||||
// Calculation of the pointer for the section in the buffer.
|
||||
// start of positive frequency component
|
||||
uint16_t *src1 = (uint16_t *)&pos[(neg_len == 0) ? ((p_prbMapElm->nRBStart * N_SC_PER_PRB) - (nPRBs * 6)) : 0];
|
||||
// start of negative frequency component
|
||||
uint16_t *src2 = (uint16_t *)&pos[(p_prbMapElm->nRBStart * N_SC_PER_PRB) + fftsize - (nPRBs * 6)];
|
||||
|
||||
uint32_t local_src[p_prbMapElm->nRBSize * N_SC_PER_PRB] __attribute__((aligned(64)));
|
||||
memcpy((void *)local_src, (void *)src2, neg_len * 4);
|
||||
memcpy((void *)&local_src[neg_len], (void *)src1, pos_len * 4);
|
||||
if (p_prbMapElm->compMethod == XRAN_COMPMETHOD_NONE) {
|
||||
payload_len = p_prbMapElm->nRBSize * N_SC_PER_PRB * 4L;
|
||||
payload_len = numRB * N_SC_PER_PRB * 4L;
|
||||
/* convert to Network order */
|
||||
// NOTE: ggc 11 knows how to generate AVX2 for this!
|
||||
for (idx = 0; idx < (pos_len + neg_len) * 2; idx++)
|
||||
((uint16_t *)dst16)[idx] = htons(((uint16_t *)local_src)[idx]);
|
||||
for (idx = 0; idx < (numRB * N_SC_PER_PRB) * 2; idx++)
|
||||
((uint16_t *)dst16)[idx] = htons(((uint16_t *)local_src)[idx + startRB * N_SC_PER_PRB * 2]);
|
||||
} else if (p_prbMapElm->compMethod == XRAN_COMPMETHOD_BLKFLOAT) {
|
||||
payload_len = (3 * p_prbMapElm->iqWidth + 1) * p_prbMapElm->nRBSize;
|
||||
payload_len = (3 * p_prbMapElm->iqWidth + 1) * numRB;
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
struct xranlib_compress_request bfp_com_req = {};
|
||||
struct xranlib_compress_response bfp_com_rsp = {};
|
||||
|
||||
bfp_com_req.data_in = (int16_t *)local_src;
|
||||
bfp_com_req.numRBs = p_prbMapElm->nRBSize;
|
||||
uint32_t src_compr[num_totalRB * N_SC_PER_PRB] __attribute__((aligned(64)));
|
||||
if (numRB == num_totalRB) {
|
||||
bfp_com_req.data_in = (int16_t *)local_src;
|
||||
} else {
|
||||
memcpy(src_compr, local_src + (startRB * N_SC_PER_PRB), (numRB * N_SC_PER_PRB) * sizeof(*local_src));
|
||||
bfp_com_req.data_in = (int16_t *)src_compr;
|
||||
}
|
||||
|
||||
bfp_com_req.numRBs = numRB;
|
||||
bfp_com_req.len = payload_len;
|
||||
bfp_com_req.compMethod = p_prbMapElm->compMethod;
|
||||
bfp_com_req.iqWidth = p_prbMapElm->iqWidth;
|
||||
@@ -672,11 +685,10 @@ int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp)
|
||||
|
||||
xranlib_compress_avx512(&bfp_com_req, &bfp_com_rsp);
|
||||
#elif defined(__arm__) || defined(__aarch64__)
|
||||
armral_bfp_compression(p_prbMapElm->iqWidth, p_prbMapElm->nRBSize, (int16_t *)local_src, (int8_t *)dst);
|
||||
armral_bfp_compression(p_prbMapElm->iqWidth, numRB, (int16_t *)local_src, (int8_t *)dst);
|
||||
#else
|
||||
AssertFatal(1 == 0, "BFP compression not supported on this architecture");
|
||||
#endif
|
||||
|
||||
} else {
|
||||
printf("p_prbMapElm->compMethod == %d is not supported\n", p_prbMapElm->compMethod);
|
||||
exit(-1);
|
||||
@@ -690,7 +702,7 @@ int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp)
|
||||
}
|
||||
|
||||
// The tti should be updated as it increased.
|
||||
pRbMap->tti_id = tti;
|
||||
pPrbMap->tti_id = tti;
|
||||
|
||||
} else {
|
||||
printf("ptr ==NULL\n");
|
||||
|
||||
@@ -92,7 +92,7 @@ static struct xran_prb_map get_xran_prb_map(const struct xran_fh_config *f, cons
|
||||
.cc_id = 0,
|
||||
.ru_port_id = 0,
|
||||
.tti_id = 0,
|
||||
.nPrbElm = 1,
|
||||
.nPrbElm = 1, // represents the number of fragments on DL only; calculated in xran_init_PrbMap_from_cfg()/xran_init_PrbMap_by_symbol_from_cfg()
|
||||
};
|
||||
struct xran_prb_elm *e = &prbmap.prbMap[0];
|
||||
e->nStartSymb = start_sym;
|
||||
|
||||
Reference in New Issue
Block a user