Commit 1fc4bb6f authored by Robert Schmidt's avatar Robert Schmidt

Merge remote-tracking branch 'gabri94/aerial-64l-srs' into integration_2026_w29

nfapi: support SRS channel reports for 64 gNB antenna elements (#268)

This MR is part of the reciprocity-based dynamic BF series and goes
together with #156 and #267.  Additional MRs will follow with the FAPI
changes to support Dynamic Beamforming, as well as adaptations to the
scheduler.

SRS-reciprocity workflows with Aerial mMIMO (Cat-B, 64-element arrays)
return the normalized channel IQ matrix over FAPI, but the
SRS.indication structs and codec were dimensioned for 8 gNB antenna
elements. A 64-element report needs up to 272 PRGs × 4 UE ports × 64
elements × 4 B ≈ 272 KiB, which the current code truncates or silently
drops.

Changes:

- Buffer dimensioning (nfapi_nr_interface_scf.h): new NFAPI_NR_SRS_MAX_*
  macros size channel_matrix and the SRS report TLV value[] for 64
  antenna elements / 4 UE SRS ports / 272 PRGs. The two buffers are now
  sized consistently (previously the report TLV allowed more UE ports
  than channel_matrix could hold).
- Integer overflow fixes on the SRS report path, which become fatal at
  these report sizes:
  * unpack_nr_srs_report_tlv_value(): last_idx was int16_t, overflowing
    for reports >= 128 KiB so the copy loop never ran and the report was
      dropped.  Widened to int32_t, and oversized reports are now
      rejected instead of overrunning the value buffer.
  * pack/unpack_nr_srs_normalized_channel_iq_matrix():
    channel_matrix_size was uint16_t (wraps at 64 KiB). Widened to
    uint32_t and bounded by sizeof(channel_matrix).
  * handle_nr_srs_measurements(): the SRS_IND_DEBUG print indexed the
    matrix with a uint16_t, which wraps for Nu·Ng·Np > 65535.
Reviewed-by: default avatarRobert Schmidt <robert.schmidt@openairinterface.org>
Reviewed-By: default avatarRúben Soares Silva <rsilva@allbesmart.pt>
parents de6d57f5 5fb8973d
...@@ -2405,6 +2405,14 @@ uint8_t pack_nr_srs_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *e ...@@ -2405,6 +2405,14 @@ uint8_t pack_nr_srs_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *e
uint8_t unpack_nr_srs_report_tlv_value(nfapi_srs_report_tlv_t *report_tlv, uint8_t **ppReadPackedMsg, uint8_t *end) uint8_t unpack_nr_srs_report_tlv_value(nfapi_srs_report_tlv_t *report_tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
{ {
if ((report_tlv->length + 3) / 4 > sizeof(report_tlv->value) / sizeof(report_tlv->value[0])) {
NFAPI_TRACE(NFAPI_TRACE_ERROR,
"%s: SRS report TLV too large to unpack (length %u bytes, max %zu), dropping report\n",
__FUNCTION__,
report_tlv->length,
sizeof(report_tlv->value));
return 0;
}
#ifndef ENABLE_AERIAL #ifndef ENABLE_AERIAL
for (int i = 0; i < (report_tlv->length + 3) / 4; i++) { for (int i = 0; i < (report_tlv->length + 3) / 4; i++) {
if (!pull32(ppReadPackedMsg, &report_tlv->value[i], end)) { if (!pull32(ppReadPackedMsg, &report_tlv->value[i], end)) {
...@@ -2412,7 +2420,7 @@ uint8_t unpack_nr_srs_report_tlv_value(nfapi_srs_report_tlv_t *report_tlv, uint8 ...@@ -2412,7 +2420,7 @@ uint8_t unpack_nr_srs_report_tlv_value(nfapi_srs_report_tlv_t *report_tlv, uint8
} }
} }
#else #else
const int16_t last_idx = ((report_tlv->length + 3) / 4) - 1; const int32_t last_idx = ((report_tlv->length + 3) / 4) - 1;
for (int i = 0; i < last_idx; i++) { for (int i = 0; i < last_idx; i++) {
if (!pull32(ppReadPackedMsg, &report_tlv->value[i], end)) { if (!pull32(ppReadPackedMsg, &report_tlv->value[i], end)) {
return 0; return 0;
......
...@@ -1924,13 +1924,23 @@ typedef struct { ...@@ -1924,13 +1924,23 @@ typedef struct {
// Normalized channel I/Q matrix // Normalized channel I/Q matrix
// Dimensioning of the SRS channel-estimate buffers: up to 64 gNB antenna
// elements (Ng), 4 sampled UE SRS ports (Nu), 272 PRGs and 4-byte complex
// samples (iqSize).
#define NFAPI_NR_SRS_MAX_PRGS 272
#define NFAPI_NR_SRS_MAX_GNB_ANTENNA_ELEMENTS 64
#define NFAPI_NR_SRS_MAX_UE_SRS_PORTS 4
#define NFAPI_NR_SRS_MAX_IQ_SAMPLE_SIZE 4
#define NFAPI_NR_SRS_CHANNEL_MATRIX_SIZE \
(NFAPI_NR_SRS_MAX_PRGS * NFAPI_NR_SRS_MAX_UE_SRS_PORTS * NFAPI_NR_SRS_MAX_GNB_ANTENNA_ELEMENTS * NFAPI_NR_SRS_MAX_IQ_SAMPLE_SIZE)
typedef struct { typedef struct {
uint8_t normalized_iq_representation; // 0: 16-bit normalized complex number (iqSize = 2); 1: 32-bit normalized complex number (iqSize = 4) uint8_t normalized_iq_representation; // 0: 16-bit normalized complex number (iqSize = 2); 1: 32-bit normalized complex number (iqSize = 4)
uint16_t num_gnb_antenna_elements; // Ng: Number of gNB antenna elements. Value: 0511 uint16_t num_gnb_antenna_elements; // Ng: Number of gNB antenna elements. Value: 0511
uint16_t num_ue_srs_ports; // Nu: Number of sampled UE SRS ports. Value: 07 uint16_t num_ue_srs_ports; // Nu: Number of sampled UE SRS ports. Value: 07
uint16_t prg_size; // Size in RBs of a precoding resource block group (PRG) – to which the same digital beamforming gets applied. Value: 1->272 uint16_t prg_size; // Size in RBs of a precoding resource block group (PRG) – to which the same digital beamforming gets applied. Value: 1->272
uint16_t num_prgs; // Number of PRGs Np to be reported for this SRS PDU. Value: 0-> 272 uint16_t num_prgs; // Number of PRGs Np to be reported for this SRS PDU. Value: 0-> 272
uint8_t channel_matrix[272*2*8*4]; // Array of (numPRGs*Nu*Ng) entries of the type denoted by iqRepresentation H{PRG pI} [ueAntenna uI, gNB antenna gI] = array[uI*Ng*Np + gI*Np + pI]; uI: 0…Nu-1 (UE antenna index); gI: 0…Ng-1 (gNB antenna index); pI: 0…Np-1 (PRG index) uint8_t channel_matrix[NFAPI_NR_SRS_CHANNEL_MATRIX_SIZE]; // Array of (numPRGs*Nu*Ng) entries of the type denoted by iqRepresentation H{PRG pI} [ueAntenna uI, gNB antenna gI] = array[uI*Ng*Np + gI*Np + pI]; uI: 0…Nu-1 (UE antenna index); gI: 0…Ng-1 (gNB antenna index); pI: 0…Np-1 (PRG index)
} nfapi_nr_srs_normalized_channel_iq_matrix_t; } nfapi_nr_srs_normalized_channel_iq_matrix_t;
// Beamforming report // Beamforming report
...@@ -1957,7 +1967,7 @@ typedef struct { ...@@ -1957,7 +1967,7 @@ typedef struct {
typedef struct { typedef struct {
uint16_t tag; // 0: Report is carried directly in the value field; 3: The offset from the end of the control portion of the message to the beginning of the report. Other values are reserved. uint16_t tag; // 0: Report is carried directly in the value field; 3: The offset from the end of the control portion of the message to the beginning of the report. Other values are reserved.
uint32_t length; // Length of the actual report in bytes, without the padding bytes. uint32_t length; // Length of the actual report in bytes, without the padding bytes.
uint32_t value[16384]; // tag=0: Only the most significant bytes of the size indicated by ‘length’ field are valid. Remaining bytes are zero padded to the nearest 32-bit bit boundary; Tag=2 Offset from the end of the control portion of the message to the payload is in the value field. Occupies 32-bits. uint32_t value[NFAPI_NR_SRS_CHANNEL_MATRIX_SIZE / 4]; // tag=0: Only the most significant bytes of the size indicated by ‘length’ field are valid. Remaining bytes are zero padded to the nearest 32-bit bit boundary; Tag=2 Offset from the end of the control portion of the message to the payload is in the value field. Occupies 32-bits.
} nfapi_srs_report_tlv_t; } nfapi_srs_report_tlv_t;
typedef struct { typedef struct {
......
...@@ -147,7 +147,7 @@ int pack_nr_srs_normalized_channel_iq_matrix(void *pMessageBuf, void *pPackedBuf ...@@ -147,7 +147,7 @@ int pack_nr_srs_normalized_channel_iq_matrix(void *pMessageBuf, void *pPackedBuf
return 0; return 0;
} }
uint16_t channel_matrix_size = nr_srs_normalized_channel_iq_matrix->num_prgs uint32_t channel_matrix_size = (uint32_t)nr_srs_normalized_channel_iq_matrix->num_prgs
* nr_srs_normalized_channel_iq_matrix->num_ue_srs_ports * nr_srs_normalized_channel_iq_matrix->num_ue_srs_ports
* nr_srs_normalized_channel_iq_matrix->num_gnb_antenna_elements; * nr_srs_normalized_channel_iq_matrix->num_gnb_antenna_elements;
if (nr_srs_normalized_channel_iq_matrix->normalized_iq_representation == 0) { if (nr_srs_normalized_channel_iq_matrix->normalized_iq_representation == 0) {
...@@ -157,8 +157,11 @@ int pack_nr_srs_normalized_channel_iq_matrix(void *pMessageBuf, void *pPackedBuf ...@@ -157,8 +157,11 @@ int pack_nr_srs_normalized_channel_iq_matrix(void *pMessageBuf, void *pPackedBuf
// 1: 32-bit normalized complex number (iqSize = 4) // 1: 32-bit normalized complex number (iqSize = 4)
channel_matrix_size <<= 2; channel_matrix_size <<= 2;
} }
if (channel_matrix_size > sizeof(nr_srs_normalized_channel_iq_matrix->channel_matrix)) {
return 0;
}
for (int i = 0; i < channel_matrix_size; i++) { for (uint32_t i = 0; i < channel_matrix_size; i++) {
if (!push8(nr_srs_normalized_channel_iq_matrix->channel_matrix[i], &pWritePackedMessage, end)) { if (!push8(nr_srs_normalized_channel_iq_matrix->channel_matrix[i], &pWritePackedMessage, end)) {
return 0; return 0;
} }
...@@ -409,7 +412,7 @@ int unpack_nr_srs_normalized_channel_iq_matrix(void *pMessageBuf, ...@@ -409,7 +412,7 @@ int unpack_nr_srs_normalized_channel_iq_matrix(void *pMessageBuf,
return -1; return -1;
} }
uint16_t channel_matrix_size = nr_srs_normalized_channel_iq_matrix->num_prgs uint32_t channel_matrix_size = (uint32_t)nr_srs_normalized_channel_iq_matrix->num_prgs
* nr_srs_normalized_channel_iq_matrix->num_ue_srs_ports * nr_srs_normalized_channel_iq_matrix->num_ue_srs_ports
* nr_srs_normalized_channel_iq_matrix->num_gnb_antenna_elements; * nr_srs_normalized_channel_iq_matrix->num_gnb_antenna_elements;
if (nr_srs_normalized_channel_iq_matrix->normalized_iq_representation == 0) { if (nr_srs_normalized_channel_iq_matrix->normalized_iq_representation == 0) {
...@@ -419,8 +422,11 @@ int unpack_nr_srs_normalized_channel_iq_matrix(void *pMessageBuf, ...@@ -419,8 +422,11 @@ int unpack_nr_srs_normalized_channel_iq_matrix(void *pMessageBuf,
// 1: 32-bit normalized complex number (iqSize = 4) // 1: 32-bit normalized complex number (iqSize = 4)
channel_matrix_size <<= 2; channel_matrix_size <<= 2;
} }
if (channel_matrix_size > sizeof(nr_srs_normalized_channel_iq_matrix->channel_matrix)) {
return -1;
}
for (int i = 0; i < channel_matrix_size; i++) { for (uint32_t i = 0; i < channel_matrix_size; i++) {
if (!pull8(&pReadPackedMessage, &nr_srs_normalized_channel_iq_matrix->channel_matrix[i], end)) { if (!pull8(&pReadPackedMessage, &nr_srs_normalized_channel_iq_matrix->channel_matrix[i], end)) {
return 0; return 0;
} }
......
...@@ -1587,7 +1587,7 @@ void handle_nr_srs_measurements(const module_id_t module_id, ...@@ -1587,7 +1587,7 @@ void handle_nr_srs_measurements(const module_id_t module_id,
for (int uI = 0; uI < nr_srs_channel_iq_matrix.num_ue_srs_ports; uI++) { for (int uI = 0; uI < nr_srs_channel_iq_matrix.num_ue_srs_ports; uI++) {
for (int gI = 0; gI < nr_srs_channel_iq_matrix.num_gnb_antenna_elements; gI++) { for (int gI = 0; gI < nr_srs_channel_iq_matrix.num_gnb_antenna_elements; gI++) {
for (int pI = 0; pI < nr_srs_channel_iq_matrix.num_prgs; pI++) { for (int pI = 0; pI < nr_srs_channel_iq_matrix.num_prgs; pI++) {
uint16_t index = uI * nr_srs_channel_iq_matrix.num_gnb_antenna_elements * nr_srs_channel_iq_matrix.num_prgs + gI * nr_srs_channel_iq_matrix.num_prgs + pI; uint32_t index = (uint32_t)uI * nr_srs_channel_iq_matrix.num_gnb_antenna_elements * nr_srs_channel_iq_matrix.num_prgs + gI * nr_srs_channel_iq_matrix.num_prgs + pI;
LOG_I(NR_MAC, LOG_I(NR_MAC,
"(uI %i, gI %i, pI %i) channel_matrix --> real %i, imag %i\n", "(uI %i, gI %i, pI %i) channel_matrix --> real %i, imag %i\n",
uI, uI,
......
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