Add pack/unpack for CONFIG.request Precoding Matrix table

Adds the packing and unpacking functions needed for the PM Table in CONFIG.request
This table tag is specified in SCF222.10.06(0x104B), previous versions didn't have a tag for this table, and this version of the spec introduces the parameter `num_pm_idx`, previously not present.
A struct nfapi_nr_pm_tlv_ve_t is added to represent this TLV in order to be able to use the pack_nr_tlv function.
The necessary additions to the utility functions are done to account for this table.
The unitary test is changed to fill this table with randomized data to test transport and copy.
This commit is contained in:
Rúben Soares Silva
2025-06-17 10:09:31 +01:00
parent 8519c748d1
commit 018d456a2a
4 changed files with 131 additions and 2 deletions
+64 -1
View File
@@ -746,6 +746,31 @@ static uint8_t pack_dbt_table_tlv_value(void *tlv, uint8_t **ppWritePackedMsg, u
return 1;
}
static uint8_t pack_pm_table_tlv_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
{
nfapi_nr_pm_tlv_ve_t *pm_ve = (nfapi_nr_pm_tlv_ve_t *)tlv;
nfapi_nr_pm_list_t *pmi_list = &pm_ve->value;
if (!( push16(pmi_list->num_pm_idx, ppWritePackedMsg, end) )) {
return 0;
}
for (int i = 0; i< pmi_list->num_pm_idx; i++) {
const nfapi_nr_pm_pdu_t *pm_pdu = &pmi_list->pmi_pdu[i];
if (!(push16(pm_pdu->pm_idx, ppWritePackedMsg, end) && push16(pm_pdu->numLayers, ppWritePackedMsg, end)
&& push16(pm_pdu->num_ant_ports, ppWritePackedMsg, end))) {
return 0;
}
for (int k = 0; k < pm_pdu->numLayers; k++) {
for (int j = 0; j < pm_pdu->num_ant_ports; j++) {
const nfapi_nr_pm_weights_t *pm_weight = &pm_pdu->weights[k][j];
if (!(push16(pm_weight->precoder_weight_Re, ppWritePackedMsg, end) && push16(pm_weight->precoder_weight_Im, ppWritePackedMsg, end))) {
return 0;
}
}
}
}
return 1;
}
uint8_t pack_nr_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config)
{
uint8_t *pNumTLVFields = (uint8_t *)*ppWritePackedMsg;
@@ -1074,7 +1099,11 @@ uint8_t pack_nr_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *e
// END Digital Beam Table (DBT) PDU
// START Precoding Matrix (PM) PDU
// Struct in nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h nfapi_nr_pm_pdu_t, currently unused, tag to use for AERIAL
if (pNfapiMsg->pmi_list.num_pm_idx != 0) {
nfapi_nr_pm_tlv_ve_t pm_tlv = {.tl.tag = NFAPI_NR_CONFIG_PRECODING_TABLE_V6_TAG, .value = pNfapiMsg->pmi_list};
pack_nr_tlv(NFAPI_NR_CONFIG_PRECODING_TABLE_V6_TAG, &pm_tlv, ppWritePackedMsg, end, &pack_pm_table_tlv_value);
numTLVs++;
}
// is 0xA011 END Precoding Matrix (PM) PDU
#ifndef ENABLE_AERIAL
// START nFAPI TLVs included in CONFIG.request for IDLE and CONFIGURED states
@@ -1209,6 +1238,35 @@ static uint8_t unpack_dbt_table_tlv_value(void *tlv, uint8_t **ppReadPackedMsg,
return 1;
}
static uint8_t unpack_pm_table_tlv_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
{
nfapi_nr_pm_list_t *pm_list = (nfapi_nr_pm_list_t *)tlv;
if (!(pull16(ppReadPackedMsg, &pm_list->num_pm_idx, end))) {
return 0;
}
if (pm_list->num_pm_idx > 0) {
pm_list->pmi_pdu = calloc(pm_list->num_pm_idx, sizeof(*pm_list->pmi_pdu));
}
for (int i = 0; i < pm_list->num_pm_idx; i++) {
nfapi_nr_pm_pdu_t *pm_pdu = &pm_list->pmi_pdu[i];
if (!(pull16(ppReadPackedMsg, &pm_pdu->pm_idx, end) && pull16(ppReadPackedMsg, &pm_pdu->numLayers, end)
&& pull16(ppReadPackedMsg, &pm_pdu->num_ant_ports, end))) {
return 0;
}
AssertFatal(pm_pdu->numLayers <= 4 && pm_pdu->num_ant_ports <= 4, "Precoding matrix size limited to 4X4 for the time being\n");
for (int k = 0; k < pm_pdu->numLayers; k++) {
for (int j = 0; j < pm_pdu->num_ant_ports; j++) {
nfapi_nr_pm_weights_t *pm_weight = &pm_pdu->weights[k][j];
if (!(pulls16(ppReadPackedMsg, &pm_weight->precoder_weight_Re, end)
&& pulls16(ppReadPackedMsg, &pm_weight->precoder_weight_Im, end))) {
return 0;
}
}
}
}
return 1;
}
uint8_t unpack_nr_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config)
{
// Helper vars for indexed TLVs
@@ -1275,6 +1333,7 @@ uint8_t unpack_nr_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *
{NFAPI_NR_FAPI_ANALOG_BEAM_VENDOR_EXTENSION_TAG, NULL, &unpack_uint8_tlv_value},
{NFAPI_NR_CONFIG_RSSI_MEASUREMENT_TAG, &(pNfapiMsg->measurement_config.rssi_measurement), &unpack_uint8_tlv_value},
{NFAPI_NR_CONFIG_BEAMFORMING_TABLE_TAG, NULL, &unpack_dbt_table_tlv_value},
{NFAPI_NR_CONFIG_PRECODING_TABLE_V6_TAG, NULL, &unpack_pm_table_tlv_value},
{NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV4_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv4), &unpack_ipv4_address_value},
{NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV6_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv6), &unpack_ipv6_address_value},
{NFAPI_NR_NFAPI_P7_VNF_PORT_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_port), &unpack_uint16_tlv_value},
@@ -1326,6 +1385,10 @@ uint8_t unpack_nr_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *
unpack_fns[idx].tlv = &generic_tl;
result = (*unpack_fns[idx].unpack_func)(&pNfapiMsg->dbt_config, ppReadPackedMsg, end);
break;
case NFAPI_NR_CONFIG_PRECODING_TABLE_V6_TAG:
unpack_fns[idx].tlv = &generic_tl;
result = (*unpack_fns[idx].unpack_func)(&pNfapiMsg->pmi_list, ppReadPackedMsg, end);
break;
case NFAPI_NR_CONFIG_NUM_PRACH_FD_OCCASIONS_TAG:
pNfapiMsg->prach_config.num_prach_fd_occasions.tl.tag = generic_tl.tag;
pNfapiMsg->prach_config.num_prach_fd_occasions.tl.length = generic_tl.length;
@@ -275,6 +275,24 @@ bool eq_config_request(const nfapi_nr_config_request_scf_t *unpacked_req, const
}
}
EQ(unpacked_req->pmi_list.num_pm_idx, req->pmi_list.num_pm_idx);
for (int i = 0; i < req->pmi_list.num_pm_idx; i++) {
const nfapi_nr_pm_pdu_t *req_pmi_pdu = &req->pmi_list.pmi_pdu[i];
const nfapi_nr_pm_pdu_t *unpacked_pmi_pdu = &unpacked_req->pmi_list.pmi_pdu[i];
EQ(unpacked_pmi_pdu->pm_idx, req_pmi_pdu->pm_idx);
EQ(unpacked_pmi_pdu->numLayers, req_pmi_pdu->numLayers);
EQ(unpacked_pmi_pdu->num_ant_ports, req_pmi_pdu->num_ant_ports);
for (int j = 0; j < req_pmi_pdu->num_ant_ports; ++j) {
for (int k = 0; k < req_pmi_pdu->num_ant_ports; ++k) {
const nfapi_nr_pm_weights_t* req_pm_weight = &req_pmi_pdu->weights[j][k];
const nfapi_nr_pm_weights_t* unpacked_pm_weight = &unpacked_pmi_pdu->weights[j][k];
EQ(unpacked_pm_weight->precoder_weight_Re, req_pm_weight->precoder_weight_Re);
EQ(unpacked_pm_weight->precoder_weight_Im, req_pm_weight->precoder_weight_Im);
}
}
}
EQ(unpacked_req->nfapi_config.p7_vnf_address_ipv4.tl.tag, req->nfapi_config.p7_vnf_address_ipv4.tl.tag);
for (int i = 0; i < NFAPI_IPV4_ADDRESS_LENGTH; ++i) {
EQ(unpacked_req->nfapi_config.p7_vnf_address_ipv4.address[i], req->nfapi_config.p7_vnf_address_ipv4.address[i]);
@@ -841,6 +859,26 @@ void copy_config_request(const nfapi_nr_config_request_scf_t *src, nfapi_nr_conf
}
}
dst->pmi_list.num_pm_idx = src->pmi_list.num_pm_idx;
if (dst->pmi_list.num_pm_idx > 0) {
dst->pmi_list.pmi_pdu = calloc(dst->pmi_list.num_pm_idx , sizeof(*dst->pmi_list.pmi_pdu));
for (int i = 0; i < dst->pmi_list.num_pm_idx; i++) {
nfapi_nr_pm_pdu_t * dst_pmi_pdu = &dst->pmi_list.pmi_pdu[i];
const nfapi_nr_pm_pdu_t * src_pmi_pdu = &src->pmi_list.pmi_pdu[i];
dst_pmi_pdu->pm_idx = src_pmi_pdu->pm_idx;
dst_pmi_pdu->numLayers = src_pmi_pdu->numLayers;
dst_pmi_pdu->num_ant_ports = src_pmi_pdu->num_ant_ports;
for (int j = 0; j < dst_pmi_pdu->numLayers; ++j) {
for (int k = 0; k < dst_pmi_pdu->num_ant_ports; ++k) {
nfapi_nr_pm_weights_t* dst_pm_weight = &dst_pmi_pdu->weights[j][k];
const nfapi_nr_pm_weights_t* src_pm_weight = &src_pmi_pdu->weights[j][k];
dst_pm_weight->precoder_weight_Re = src_pm_weight->precoder_weight_Re;
dst_pm_weight->precoder_weight_Im = src_pm_weight->precoder_weight_Im;
}
}
}
}
COPY_TL(dst->nfapi_config.p7_vnf_address_ipv4.tl, src->nfapi_config.p7_vnf_address_ipv4.tl);
memcpy(dst->nfapi_config.p7_vnf_address_ipv4.address,
src->nfapi_config.p7_vnf_address_ipv4.address,
@@ -329,6 +329,7 @@ typedef struct
#define NFAPI_NR_CONFIG_RSSI_MEASUREMENT_TAG 0x1028
#define NFAPI_NR_CONFIG_TDD_TABLE 0x1035
#define NFAPI_NR_CONFIG_BEAMFORMING_TABLE_TAG 0x1043 // This tag was added in version 5 of the SCF222 standard ( Table 3-50 of SCF222.10.05 )
#define NFAPI_NR_CONFIG_PRECODING_TABLE_V6_TAG 0x104B // This tag was added in version 6 of the SCF222 standard ( Table 3-52 of SCF222.10.06 )
//table 3-21
typedef struct
@@ -497,7 +498,12 @@ typedef struct {
typedef struct {
uint16_t num_pm_idx;
nfapi_nr_pm_pdu_t *pmi_pdu;
} nfapi_nr_pm_list_t;
} nfapi_nr_pm_list_t; // This corresponds to Table 3-69 of SCF222.10.06, which introduces the num_pm_idx parameter
typedef struct {
nfapi_tl_t tl;
nfapi_nr_pm_list_t value;
} nfapi_nr_pm_tlv_ve_t;
typedef struct {
nfapi_uint8_tlv_t num_beams_period_vendor_ext;
@@ -225,6 +225,28 @@ static void fill_config_request_tlv_tdd_rand(nfapi_nr_config_request_scf_t *nfap
nfapi_resp->num_tlv++;
}
nfapi_nr_pm_list_t *pm_list = &nfapi_resp->pmi_list;
const uint16_t num_layers = rand16_range(1, 4);
const uint16_t num_ant_ports = rand16_range(1, 4);
pm_list->num_pm_idx = rand16_range(1, 4);
if (nfapi_resp->pmi_list.num_pm_idx > 0) {
pm_list->pmi_pdu = calloc(pm_list->num_pm_idx, sizeof(*pm_list->pmi_pdu));
for (int i = 0; i < pm_list->num_pm_idx; i++) {
nfapi_nr_pm_pdu_t *pmi_pdu = &pm_list->pmi_pdu[i];
pmi_pdu->pm_idx = i+1;
pmi_pdu->numLayers = num_layers;
pmi_pdu->num_ant_ports = num_ant_ports;
for (int j = 0; j < num_layers; j++) {
for (int k = 0; k < num_ant_ports; k++) {
nfapi_nr_pm_weights_t* pm_weight = &pmi_pdu->weights[j][k];
pm_weight->precoder_weight_Re = (int16_t)rand16_range(1, 0xffff);
pm_weight->precoder_weight_Im = (int16_t)rand16_range(1, 0xffff);
}
}
}
nfapi_resp->num_tlv++;
}
nfapi_resp->nfapi_config.p7_vnf_address_ipv4.tl.tag = NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV4_TAG;
for (int i = 0; i < NFAPI_IPV4_ADDRESS_LENGTH; ++i) {
nfapi_resp->nfapi_config.p7_vnf_address_ipv4.address[i] = rand8();