Commit e1869e38 authored by laurent's avatar laurent

fix CI warnings

parent 4a86d53c
This source diff could not be displayed because it is too large. You can view the blob instead.
/* /*
* Copyright 2017 Cisco Systems, Inc. * Copyright 2017 Cisco Systems, Inc.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
...@@ -20,413 +20,323 @@ ...@@ -20,413 +20,323 @@
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
nfapi_pnf_config_t* nfapi_pnf_config_create() nfapi_pnf_config_t *nfapi_pnf_config_create() {
{ static pnf_t *_this==NULL;
pnf_t* _this = (pnf_t*)malloc(sizeof(pnf_t));
if(_this == 0) if (_this)
return 0; NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: called twice\n", __FUNCTION__);
memset(_this, 0, sizeof(pnf_t)); _this = (pnf_t *)malloc(sizeof(pnf_t));
_this->sctp = 1; // enable sctp if(_this == 0)
return 0;
_this->_public.vnf_p5_port = NFAPI_P5_SCTP_PORT;
_this->_public.malloc = &malloc;
_this->_public.free = &free;
_this->_public.codec_config.allocate = &malloc; memset(_this, 0, sizeof(pnf_t));
_this->_public.codec_config.deallocate = &free; _this->sctp = 1; // enable sctp
_this->_public.vnf_p5_port = NFAPI_P5_SCTP_PORT;
return &(_this->_public); _this->_public.malloc = &malloc;
_this->_public.free = &free;
_this->_public.codec_config.allocate = &malloc;
_this->_public.codec_config.deallocate = &free;
return &(_this->_public);
} }
void nfapi_pnf_config_destory(nfapi_pnf_config_t* config) void nfapi_pnf_config_destory(nfapi_pnf_config_t *config) {
{ free(config);
free(config);
} }
int nfapi_pnf_start(nfapi_pnf_config_t* config) int nfapi_pnf_start(nfapi_pnf_config_t *config) {
{ // Verify that config is not null
// Verify that config is not null if(config == 0)
if(config == 0) return -1;
return -1;
// Make sure to set the defined trace function before using NFAPI_TRACE
if(config->trace)
nfapi_trace_g = config->trace;
NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__); // Make sure to set the defined trace function before using NFAPI_TRACE
if(config->trace)
nfapi_trace_g = config->trace;
pnf_t* _this = (pnf_t*)(config); NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__);
pnf_t *_this = (pnf_t *)(config);
while (_this->terminate == 0) while (_this->terminate == 0) {
{ int connect_result = pnf_connect(_this);
int connect_result = pnf_connect(_this);
if(connect_result > 0) if(connect_result > 0) {
{ pnf_message_pump(_this);
pnf_message_pump(_this); } else if(connect_result < 0) {
} return connect_result;
else if(connect_result < 0) }
{
return connect_result;
}
sleep(1); sleep(1);
} }
NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() terminate=1 - EXITTING............\n", __FUNCTION__);
return 0; NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() terminate=1 - EXITTING............\n", __FUNCTION__);
return 0;
} }
int nfapi_pnf_stop(nfapi_pnf_config_t* config) int nfapi_pnf_stop(nfapi_pnf_config_t *config) {
{ // Verify that config is not null
// Verify that config is not null if(config == 0)
if(config == 0) return -1;
return -1;
pnf_t* _this = (pnf_t*)(config);
_this->terminate = 1;
// todo wait for the pnf to stop before returning pnf_t *_this = (pnf_t *)(config);
_this->terminate = 1;
return 0; // todo wait for the pnf to stop before returning
return 0;
} }
int nfapi_pnf_pnf_param_resp(nfapi_pnf_config_t* config, nfapi_pnf_param_response_t* resp) int nfapi_pnf_pnf_param_resp(nfapi_pnf_config_t *config, nfapi_pnf_param_response_t *resp) {
{ // ensure it's valid
// ensure it's valid if (config == NULL || resp == NULL) {
if (config == NULL || resp == NULL) NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
{ return -1;
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); }
return -1;
}
pnf_t* _this = (pnf_t*)(config);
return pnf_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_pnf_param_response_t)); pnf_t *_this = (pnf_t *)(config);
return pnf_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_pnf_param_response_t));
} }
int nfapi_pnf_pnf_config_resp(nfapi_pnf_config_t* config, nfapi_pnf_config_response_t* resp) int nfapi_pnf_pnf_config_resp(nfapi_pnf_config_t *config, nfapi_pnf_config_response_t *resp) {
{ // ensure it's valid
// ensure it's valid if (config == NULL || resp == NULL) {
if (config == NULL || resp == NULL) NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
{ return -1;
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); }
return -1;
}
if(resp->error_code == NFAPI_MSG_OK) if(resp->error_code == NFAPI_MSG_OK) {
{ config->state = NFAPI_PNF_CONFIGURED;
config->state = NFAPI_PNF_CONFIGURED; }
}
pnf_t* _this = (pnf_t*)(config); pnf_t *_this = (pnf_t *)(config);
return pnf_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_pnf_config_response_t));
return pnf_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_pnf_config_response_t));
} }
int nfapi_pnf_pnf_start_resp(nfapi_pnf_config_t* config, nfapi_pnf_start_response_t* resp) int nfapi_pnf_pnf_start_resp(nfapi_pnf_config_t *config, nfapi_pnf_start_response_t *resp) {
{ // ensure it's valid
// ensure it's valid if (config == NULL || resp == NULL) {
if (config == NULL || resp == NULL) NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
{ return -1;
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); }
return -1;
}
if(resp->error_code == NFAPI_MSG_OK)
{
config->state = NFAPI_PNF_RUNNING;
}
pnf_t* _this = (pnf_t*)(config); if(resp->error_code == NFAPI_MSG_OK) {
config->state = NFAPI_PNF_RUNNING;
}
return pnf_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_pnf_start_response_t)); pnf_t *_this = (pnf_t *)(config);
return pnf_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_pnf_start_response_t));
} }
int nfapi_pnf_pnf_stop_resp(nfapi_pnf_config_t* config, nfapi_pnf_stop_response_t* resp) int nfapi_pnf_pnf_stop_resp(nfapi_pnf_config_t *config, nfapi_pnf_stop_response_t *resp) {
{ // ensure it's valid
// ensure it's valid if (config == NULL || resp == NULL) {
if (config == NULL || resp == NULL) NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
{ return -1;
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); }
return -1;
}
if(resp->error_code == NFAPI_MSG_OK) if(resp->error_code == NFAPI_MSG_OK) {
{ config->state = NFAPI_PNF_CONFIGURED;
config->state = NFAPI_PNF_CONFIGURED; }
}
pnf_t* _this = (pnf_t*)(config); pnf_t *_this = (pnf_t *)(config);
return pnf_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_pnf_stop_response_t));
return pnf_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_pnf_stop_response_t));
} }
int nfapi_pnf_param_resp(nfapi_pnf_config_t* config, nfapi_param_response_t* resp) int nfapi_pnf_param_resp(nfapi_pnf_config_t *config, nfapi_param_response_t *resp) {
{ if (config == NULL || resp == NULL) {
if (config == NULL || resp == NULL) NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
{ return -1;
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); }
return -1;
}
pnf_t* _this = (pnf_t*)(config);
return pnf_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_param_response_t));
}
int nfapi_pnf_config_resp(nfapi_pnf_config_t* config, nfapi_config_response_t* resp) pnf_t *_this = (pnf_t *)(config);
{ return pnf_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_param_response_t));
if (config == NULL || resp == NULL)
{
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
return -1;
}
pnf_t* _this = (pnf_t*)(config);
nfapi_pnf_phy_config_t* phy = nfapi_pnf_phy_config_find(config, resp->header.phy_id);
if(phy)
{
if(resp->error_code == NFAPI_MSG_OK)
{
phy->state = NFAPI_PNF_PHY_CONFIGURED;
}
}
else
{
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: unknow phy id %d\n", __FUNCTION__, resp->header.phy_id);
return -1;
}
return pnf_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_config_response_t));
} }
int nfapi_pnf_start_resp(nfapi_pnf_config_t* config, nfapi_start_response_t* resp) int nfapi_pnf_config_resp(nfapi_pnf_config_t *config, nfapi_config_response_t *resp) {
{ if (config == NULL || resp == NULL) {
if (config == NULL || resp == NULL) NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
{ return -1;
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); }
return -1;
} pnf_t *_this = (pnf_t *)(config);
nfapi_pnf_phy_config_t *phy = nfapi_pnf_phy_config_find(config, resp->header.phy_id);
pnf_t* _this = (pnf_t*)(config);
if(phy) {
nfapi_pnf_phy_config_t* phy = nfapi_pnf_phy_config_find(config, resp->header.phy_id); if(resp->error_code == NFAPI_MSG_OK) {
if(phy) phy->state = NFAPI_PNF_PHY_CONFIGURED;
{ }
if(resp->error_code == NFAPI_MSG_OK) } else {
{ NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: unknow phy id %d\n", __FUNCTION__, resp->header.phy_id);
phy->state = NFAPI_PNF_PHY_RUNNING; return -1;
} }
}
else return pnf_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_config_response_t));
{
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: unknown phy id %d\n", __FUNCTION__, resp->header.phy_id);
return -1;
}
return pnf_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_start_response_t));
} }
int nfapi_pnf_stop_resp(nfapi_pnf_config_t* config, nfapi_stop_response_t* resp) int nfapi_pnf_start_resp(nfapi_pnf_config_t *config, nfapi_start_response_t *resp) {
{ if (config == NULL || resp == NULL) {
if (config == NULL || resp == NULL) NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
{ return -1;
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); }
return -1;
} pnf_t *_this = (pnf_t *)(config);
nfapi_pnf_phy_config_t *phy = nfapi_pnf_phy_config_find(config, resp->header.phy_id);
pnf_t* _this = (pnf_t*)(config);
if(phy) {
nfapi_pnf_phy_config_t* phy = nfapi_pnf_phy_config_find(config, resp->header.phy_id); if(resp->error_code == NFAPI_MSG_OK) {
if(phy) phy->state = NFAPI_PNF_PHY_RUNNING;
{ }
if(resp->error_code == NFAPI_MSG_OK) } else {
{ NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: unknown phy id %d\n", __FUNCTION__, resp->header.phy_id);
phy->state = NFAPI_PNF_PHY_CONFIGURED; return -1;
} }
}
else return pnf_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_start_response_t));
{
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: unknow phy id %d\n", __FUNCTION__, resp->header.phy_id);
return -1;
}
return pnf_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_stop_response_t));
} }
int nfapi_pnf_measurement_resp(nfapi_pnf_config_t* config, nfapi_measurement_response_t* resp) int nfapi_pnf_stop_resp(nfapi_pnf_config_t *config, nfapi_stop_response_t *resp) {
{ if (config == NULL || resp == NULL) {
if (config == NULL || resp == NULL) NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
{ return -1;
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); }
return -1;
} pnf_t *_this = (pnf_t *)(config);
nfapi_pnf_phy_config_t *phy = nfapi_pnf_phy_config_find(config, resp->header.phy_id);
pnf_t* _this = (pnf_t*)(config);
if(phy) {
return pnf_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_measurement_response_t)); if(resp->error_code == NFAPI_MSG_OK) {
phy->state = NFAPI_PNF_PHY_CONFIGURED;
}
} else {
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: unknow phy id %d\n", __FUNCTION__, resp->header.phy_id);
return -1;
}
return pnf_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_stop_response_t));
} }
int nfapi_pnf_measurement_resp(nfapi_pnf_config_t *config, nfapi_measurement_response_t *resp) {
if (config == NULL || resp == NULL) {
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
return -1;
}
int nfapi_pnf_rssi_resp(nfapi_pnf_config_t* config, nfapi_rssi_response_t* resp) pnf_t *_this = (pnf_t *)(config);
{ return pnf_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_measurement_response_t));
if (config == NULL || resp == NULL)
{
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
return -1;
}
pnf_t* _this = (pnf_t*)(config);
return pnf_pack_and_send_p4_message(_this, &(resp->header), sizeof(nfapi_rssi_response_t));
} }
int nfapi_pnf_rssi_ind(nfapi_pnf_config_t* config, nfapi_rssi_indication_t* ind)
{
if (config == NULL || ind == NULL)
{
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
return -1;
}
pnf_t* _this = (pnf_t*)(config); int nfapi_pnf_rssi_resp(nfapi_pnf_config_t *config, nfapi_rssi_response_t *resp) {
if (config == NULL || resp == NULL) {
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
return -1;
}
return pnf_pack_and_send_p4_message(_this, &(ind->header), sizeof(nfapi_rssi_indication_t)); pnf_t *_this = (pnf_t *)(config);
return pnf_pack_and_send_p4_message(_this, &(resp->header), sizeof(nfapi_rssi_response_t));
} }
int nfapi_pnf_cell_search_resp(nfapi_pnf_config_t* config, nfapi_cell_search_response_t* resp)
{
if (config == NULL || resp == NULL)
{
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
return -1;
}
NFAPI_TRACE(NFAPI_TRACE_INFO, "Send CELL_SEARCH.response\n");
pnf_t* _this = (pnf_t*)(config); int nfapi_pnf_rssi_ind(nfapi_pnf_config_t *config, nfapi_rssi_indication_t *ind) {
if (config == NULL || ind == NULL) {
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
return -1;
}
return pnf_pack_and_send_p4_message(_this, &(resp->header), sizeof(nfapi_cell_search_response_t)); pnf_t *_this = (pnf_t *)(config);
return pnf_pack_and_send_p4_message(_this, &(ind->header), sizeof(nfapi_rssi_indication_t));
} }
int nfapi_pnf_cell_search_ind(nfapi_pnf_config_t* config, nfapi_cell_search_indication_t* ind) int nfapi_pnf_cell_search_resp(nfapi_pnf_config_t *config, nfapi_cell_search_response_t *resp) {
{ if (config == NULL || resp == NULL) {
if (config == NULL || ind == NULL) NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
{ return -1;
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); }
return -1;
} NFAPI_TRACE(NFAPI_TRACE_INFO, "Send CELL_SEARCH.response\n");
pnf_t *_this = (pnf_t *)(config);
pnf_t* _this = (pnf_t*)(config); return pnf_pack_and_send_p4_message(_this, &(resp->header), sizeof(nfapi_cell_search_response_t));
return pnf_pack_and_send_p4_message(_this, &(ind->header), sizeof(nfapi_cell_search_indication_t));
} }
int nfapi_pnf_broadcast_detect_resp(nfapi_pnf_config_t* config, nfapi_broadcast_detect_response_t* resp) int nfapi_pnf_cell_search_ind(nfapi_pnf_config_t *config, nfapi_cell_search_indication_t *ind) {
{ if (config == NULL || ind == NULL) {
if (config == NULL || resp == NULL) NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
{ return -1;
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); }
return -1;
} pnf_t *_this = (pnf_t *)(config);
return pnf_pack_and_send_p4_message(_this, &(ind->header), sizeof(nfapi_cell_search_indication_t));
pnf_t* _this = (pnf_t*)(config);
return pnf_pack_and_send_p4_message(_this, &(resp->header), sizeof(nfapi_broadcast_detect_response_t));
} }
int nfapi_pnf_broadcast_detect_ind(nfapi_pnf_config_t* config, nfapi_broadcast_detect_indication_t* ind) int nfapi_pnf_broadcast_detect_resp(nfapi_pnf_config_t *config, nfapi_broadcast_detect_response_t *resp) {
{ if (config == NULL || resp == NULL) {
if (config == NULL || ind == NULL) NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
{ return -1;
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); }
return -1;
} pnf_t *_this = (pnf_t *)(config);
return pnf_pack_and_send_p4_message(_this, &(resp->header), sizeof(nfapi_broadcast_detect_response_t));
pnf_t* _this = (pnf_t*)(config);
return pnf_pack_and_send_p4_message(_this, &(ind->header), sizeof(nfapi_broadcast_detect_indication_t));
} }
int nfapi_pnf_system_information_schedule_resp(nfapi_pnf_config_t* config, nfapi_system_information_schedule_response_t* resp) int nfapi_pnf_broadcast_detect_ind(nfapi_pnf_config_t *config, nfapi_broadcast_detect_indication_t *ind) {
{ if (config == NULL || ind == NULL) {
if (config == NULL || resp == NULL) NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
{ return -1;
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); }
return -1;;
} pnf_t *_this = (pnf_t *)(config);
return pnf_pack_and_send_p4_message(_this, &(ind->header), sizeof(nfapi_broadcast_detect_indication_t));
pnf_t* _this = (pnf_t*)(config);
return pnf_pack_and_send_p4_message(_this, &(resp->header), sizeof(nfapi_system_information_schedule_response_t));
} }
int nfapi_pnf_system_information_schedule_resp(nfapi_pnf_config_t *config, nfapi_system_information_schedule_response_t *resp) {
int nfapi_pnf_system_information_schedule_ind(nfapi_pnf_config_t* config, nfapi_system_information_schedule_indication_t* ind) if (config == NULL || resp == NULL) {
{ NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
if (config == NULL || ind == NULL) return -1;;
{ }
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
return -1; pnf_t *_this = (pnf_t *)(config);
} return pnf_pack_and_send_p4_message(_this, &(resp->header), sizeof(nfapi_system_information_schedule_response_t));
pnf_t* _this = (pnf_t*)(config);
return pnf_pack_and_send_p4_message(_this, &(ind->header), sizeof(nfapi_system_information_schedule_indication_t));
} }
int nfapi_pnf_system_information_resp(nfapi_pnf_config_t* config, nfapi_system_information_response_t* resp)
{
if (config == NULL || resp == NULL)
{
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
return -1;
}
pnf_t* _this = (pnf_t*)(config); int nfapi_pnf_system_information_schedule_ind(nfapi_pnf_config_t *config, nfapi_system_information_schedule_indication_t *ind) {
if (config == NULL || ind == NULL) {
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
return -1;
}
return pnf_pack_and_send_p4_message(_this, &(resp->header), sizeof(nfapi_system_information_response_t)); pnf_t *_this = (pnf_t *)(config);
return pnf_pack_and_send_p4_message(_this, &(ind->header), sizeof(nfapi_system_information_schedule_indication_t));
}
int nfapi_pnf_system_information_resp(nfapi_pnf_config_t *config, nfapi_system_information_response_t *resp) {
if (config == NULL || resp == NULL) {
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
return -1;
}
pnf_t *_this = (pnf_t *)(config);
return pnf_pack_and_send_p4_message(_this, &(resp->header), sizeof(nfapi_system_information_response_t));
} }
int nfapi_pnf_system_information_ind(nfapi_pnf_config_t* config, nfapi_system_information_indication_t* ind) int nfapi_pnf_system_information_ind(nfapi_pnf_config_t *config, nfapi_system_information_indication_t *ind) {
{ if (config == NULL || ind == NULL) {
if (config == NULL || ind == NULL) NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
{ return -1;
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); }
return -1;
}
pnf_t* _this = (pnf_t*)(config);
return pnf_pack_and_send_p4_message(_this, &(ind->header), sizeof(nfapi_system_information_indication_t)); pnf_t *_this = (pnf_t *)(config);
return pnf_pack_and_send_p4_message(_this, &(ind->header), sizeof(nfapi_system_information_indication_t));
} }
int nfapi_pnf_nmm_stop_resp(nfapi_pnf_config_t* config, nfapi_nmm_stop_response_t* resp) int nfapi_pnf_nmm_stop_resp(nfapi_pnf_config_t *config, nfapi_nmm_stop_response_t *resp) {
{ // ensure it's valid
// ensure it's valid if (config == NULL || resp == NULL) {
if (config == NULL || resp == NULL) NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
{ return -1;
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); }
return -1;
} pnf_t *_this = (pnf_t *)(config);
return pnf_pack_and_send_p4_message(_this, &(resp->header), sizeof(nfapi_nmm_stop_request_t));
pnf_t* _this = (pnf_t*)(config);
return pnf_pack_and_send_p4_message(_this, &(resp->header), sizeof(nfapi_nmm_stop_request_t));
} }
int nfapi_pnf_vendor_extension(nfapi_pnf_config_t* config, nfapi_p4_p5_message_header_t* msg, uint32_t msg_len) int nfapi_pnf_vendor_extension(nfapi_pnf_config_t *config, nfapi_p4_p5_message_header_t *msg, uint32_t msg_len) {
{ // ensure it's valid
// ensure it's valid if (config == NULL || msg == NULL) {
if (config == NULL || msg == NULL) NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
{ return -1;
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); }
return -1;
}
pnf_t* _this = (pnf_t*)(config);
return pnf_pack_and_send_p5_message(_this, msg, msg_len); pnf_t *_this = (pnf_t *)(config);
return pnf_pack_and_send_p5_message(_this, msg, msg_len);
} }
/* /*
* Copyright 2017 Cisco Systems, Inc. * Copyright 2017 Cisco Systems, Inc.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
...@@ -19,219 +19,182 @@ ...@@ -19,219 +19,182 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
nfapi_pnf_p7_config_t* nfapi_pnf_p7_config_create() nfapi_pnf_p7_config_t *nfapi_pnf_p7_config_create() {
{ static pnf_p7_t *_this = NULL;
pnf_p7_t* _this = (pnf_p7_t*)calloc(1, sizeof(pnf_p7_t));
if(_this == 0) if (_this)
return 0; NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: called twice\n", __FUNCTION__);
_this=(pnf_p7_t *)calloc(1, sizeof(pnf_p7_t));
// set the default parameters if(_this == 0)
_this->_public.segment_size = 1400; return 0;
_this->max_num_segments = 8;
_this->_public.subframe_buffer_size = 8;
_this->_public.timing_info_mode_periodic = 1;
_this->_public.timing_info_period = 32;
_this->_public.timing_info_mode_aperiodic = 1;
_this->_public.checksum_enabled = 1;
_this->_public.malloc = &malloc;
_this->_public.free = &free;
_this->_public.codec_config.allocate = &malloc; // set the default parameters
_this->_public.codec_config.deallocate = &free; _this->_public.segment_size = 1400;
_this->max_num_segments = 8;
return &(_this->_public); _this->_public.subframe_buffer_size = 8;
_this->_public.timing_info_mode_periodic = 1;
_this->_public.timing_info_period = 32;
_this->_public.timing_info_mode_aperiodic = 1;
_this->_public.checksum_enabled = 1;
_this->_public.malloc = &malloc;
_this->_public.free = &free;
_this->_public.codec_config.allocate = &malloc;
_this->_public.codec_config.deallocate = &free;
return &(_this->_public);
} }
void nfapi_pnf_p7_config_destory(nfapi_pnf_p7_config_t* config) void nfapi_pnf_p7_config_destory(nfapi_pnf_p7_config_t *config) {
{ if(config == 0)
if(config == 0) return ;
return ;
free(config); free(config);
} }
int nfapi_pnf_p7_start(nfapi_pnf_p7_config_t* config) int nfapi_pnf_p7_start(nfapi_pnf_p7_config_t *config) {
{ // Verify that config is not null
// Verify that config is not null if(config == 0)
if(config == 0) return -1;
return -1;
// Make sure to set the defined trace function before using NFAPI_TRACE
if(config->trace)
nfapi_trace_g = config->trace;
pnf_p7_t* _this = (pnf_p7_t*)(config); // Make sure to set the defined trace function before using NFAPI_TRACE
if(config->trace)
nfapi_trace_g = config->trace;
NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__); pnf_p7_t *_this = (pnf_p7_t *)(config);
NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__);
pnf_p7_message_pump(_this);
return 0;
}
pnf_p7_message_pump(_this); int nfapi_pnf_p7_stop(nfapi_pnf_p7_config_t *config) {
// Verify that config is not null
if(config == 0)
return -1;
return 0; pnf_p7_t *_this = (pnf_p7_t *)(config);
_this->terminate = 1;
return 0;
} }
int nfapi_pnf_p7_stop(nfapi_pnf_p7_config_t* config)
{
// Verify that config is not null
if(config == 0)
return -1;
pnf_p7_t* _this = (pnf_p7_t*)(config); int nfapi_pnf_p7_subframe_ind(nfapi_pnf_p7_config_t *config, uint16_t phy_id, uint16_t sfn_sf) {
_this->terminate = 1; // Verify that config is not null
if(config == 0)
return -1;
return 0; pnf_p7_t *_this = (pnf_p7_t *)(config);
return pnf_p7_subframe_ind(_this, phy_id, sfn_sf);
} }
int nfapi_pnf_p7_harq_ind(nfapi_pnf_p7_config_t *config, nfapi_harq_indication_t *ind) {
if(config == NULL || ind == NULL) {
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__);
return -1;
}
int nfapi_pnf_p7_subframe_ind(nfapi_pnf_p7_config_t* config, uint16_t phy_id, uint16_t sfn_sf) pnf_p7_t *_this = (pnf_p7_t *)(config);
{ return pnf_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t *)ind, sizeof(nfapi_harq_indication_t));
// Verify that config is not null }
if(config == 0) int nfapi_pnf_p7_crc_ind(nfapi_pnf_p7_config_t *config, nfapi_crc_indication_t *ind) {
return -1; if(config == NULL || ind == NULL) {
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__);
pnf_p7_t* _this = (pnf_p7_t*)(config); return -1;
}
return pnf_p7_subframe_ind(_this, phy_id, sfn_sf); pnf_p7_t *_this = (pnf_p7_t *)(config);
return pnf_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t *)ind, sizeof(nfapi_crc_indication_t));
} }
int nfapi_pnf_p7_rx_ind(nfapi_pnf_p7_config_t *config, nfapi_rx_indication_t *ind) {
if(config == NULL || ind == NULL) {
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__);
return -1;
}
int nfapi_pnf_p7_harq_ind(nfapi_pnf_p7_config_t* config, nfapi_harq_indication_t* ind) pnf_p7_t *_this = (pnf_p7_t *)(config);
{ return pnf_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t *)ind, sizeof(nfapi_rx_indication_t));
if(config == NULL || ind == NULL) }
{ int nfapi_pnf_p7_rach_ind(nfapi_pnf_p7_config_t *config, nfapi_rach_indication_t *ind) {
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__); if(config == NULL || ind == NULL) {
return -1; NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__);
} return -1;
}
pnf_p7_t* _this = (pnf_p7_t*)(config); pnf_p7_t *_this = (pnf_p7_t *)(config);
return pnf_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t *)ind, sizeof(nfapi_rach_indication_t));
}
int nfapi_pnf_p7_srs_ind(nfapi_pnf_p7_config_t *config, nfapi_srs_indication_t *ind) {
if(config == NULL || ind == NULL) {
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__);
return -1;
}
return pnf_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_harq_indication_t)); pnf_p7_t *_this = (pnf_p7_t *)(config);
return pnf_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t *)ind, sizeof(nfapi_srs_indication_t));
} }
int nfapi_pnf_p7_crc_ind(nfapi_pnf_p7_config_t* config, nfapi_crc_indication_t* ind) int nfapi_pnf_p7_sr_ind(nfapi_pnf_p7_config_t *config, nfapi_sr_indication_t *ind) {
{ if(config == NULL || ind == NULL) {
if(config == NULL || ind == NULL) NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__);
{ return -1;
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__); }
return -1;
} pnf_p7_t *_this = (pnf_p7_t *)(config);
return pnf_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t *)ind, sizeof(nfapi_sr_indication_t));
pnf_p7_t* _this = (pnf_p7_t*)(config);
return pnf_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_crc_indication_t));
} }
int nfapi_pnf_p7_rx_ind(nfapi_pnf_p7_config_t* config, nfapi_rx_indication_t* ind) int nfapi_pnf_p7_cqi_ind(nfapi_pnf_p7_config_t *config, nfapi_cqi_indication_t *ind) {
{ if(config == NULL || ind == NULL) {
if(config == NULL || ind == NULL) NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__);
{ return -1;
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__); }
return -1;
} pnf_p7_t *_this = (pnf_p7_t *)(config);
return pnf_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t *)ind, sizeof(nfapi_cqi_indication_t));
pnf_p7_t* _this = (pnf_p7_t*)(config);
return pnf_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_rx_indication_t));
} }
int nfapi_pnf_p7_rach_ind(nfapi_pnf_p7_config_t* config, nfapi_rach_indication_t* ind) int nfapi_pnf_p7_lbt_dl_ind(nfapi_pnf_p7_config_t *config, nfapi_lbt_dl_indication_t *ind) {
{ if(config == NULL || ind == NULL) {
if(config == NULL || ind == NULL) NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__);
{ return -1;
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__); }
return -1;
}
pnf_p7_t* _this = (pnf_p7_t*)(config); pnf_p7_t *_this = (pnf_p7_t *)(config);
return pnf_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_rach_indication_t)); return pnf_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t *)ind, sizeof(nfapi_lbt_dl_indication_t));
} }
int nfapi_pnf_p7_srs_ind(nfapi_pnf_p7_config_t* config, nfapi_srs_indication_t* ind) int nfapi_pnf_p7_nb_harq_ind(nfapi_pnf_p7_config_t *config, nfapi_nb_harq_indication_t *ind) {
{ if(config == NULL || ind == NULL) {
if(config == NULL || ind == NULL) NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__);
{ return -1;
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__); }
return -1;
}
pnf_p7_t* _this = (pnf_p7_t*)(config); pnf_p7_t *_this = (pnf_p7_t *)(config);
return pnf_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_srs_indication_t)); return pnf_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t *)ind, sizeof(nfapi_nb_harq_indication_t));
} }
int nfapi_pnf_p7_sr_ind(nfapi_pnf_p7_config_t* config, nfapi_sr_indication_t* ind) int nfapi_pnf_p7_nrach_ind(nfapi_pnf_p7_config_t *config, nfapi_nrach_indication_t *ind) {
{ if(config == NULL || ind == NULL) {
if(config == NULL || ind == NULL) NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__);
{ return -1;
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__); }
return -1;
} pnf_p7_t *_this = (pnf_p7_t *)(config);
return pnf_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t *)ind, sizeof(nfapi_nrach_indication_t));
pnf_p7_t* _this = (pnf_p7_t*)(config); }
return pnf_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_sr_indication_t)); int nfapi_pnf_p7_vendor_extension(nfapi_pnf_p7_config_t *config, nfapi_p7_message_header_t *msg) {
} if(config == NULL || msg == NULL) {
int nfapi_pnf_p7_cqi_ind(nfapi_pnf_p7_config_t* config, nfapi_cqi_indication_t* ind) NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__);
{ return -1;
if(config == NULL || ind == NULL) }
{
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__); pnf_p7_t *_this = (pnf_p7_t *)(config);
return -1; return pnf_p7_pack_and_send_p7_message(_this, msg, 0);
} }
pnf_p7_t* _this = (pnf_p7_t*)(config); int nfapi_pnf_ue_release_resp(nfapi_pnf_p7_config_t *config, nfapi_ue_release_response_t *resp) {
return pnf_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_cqi_indication_t)); if (config == NULL || resp == NULL) {
} NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
int nfapi_pnf_p7_lbt_dl_ind(nfapi_pnf_p7_config_t* config, nfapi_lbt_dl_indication_t* ind) return -1;
{ }
if(config == NULL || ind == NULL)
{ pnf_p7_t *_this = (pnf_p7_t *)(config);
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__); return pnf_p7_pack_and_send_p7_message(_this, &(resp->header), sizeof(nfapi_ue_release_response_t));
return -1;
}
pnf_p7_t* _this = (pnf_p7_t*)(config);
return pnf_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_lbt_dl_indication_t));
}
int nfapi_pnf_p7_nb_harq_ind(nfapi_pnf_p7_config_t* config, nfapi_nb_harq_indication_t* ind)
{
if(config == NULL || ind == NULL)
{
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__);
return -1;
}
pnf_p7_t* _this = (pnf_p7_t*)(config);
return pnf_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_nb_harq_indication_t));
}
int nfapi_pnf_p7_nrach_ind(nfapi_pnf_p7_config_t* config, nfapi_nrach_indication_t* ind)
{
if(config == NULL || ind == NULL)
{
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__);
return -1;
}
pnf_p7_t* _this = (pnf_p7_t*)(config);
return pnf_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_nrach_indication_t));
}
int nfapi_pnf_p7_vendor_extension(nfapi_pnf_p7_config_t* config, nfapi_p7_message_header_t* msg)
{
if(config == NULL || msg == NULL)
{
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__);
return -1;
}
pnf_p7_t* _this = (pnf_p7_t*)(config);
return pnf_p7_pack_and_send_p7_message(_this, msg, 0);
}
int nfapi_pnf_ue_release_resp(nfapi_pnf_p7_config_t* config, nfapi_ue_release_response_t* resp)
{
if (config == NULL || resp == NULL)
{
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
return -1;
}
pnf_p7_t* _this = (pnf_p7_t*)(config);
return pnf_p7_pack_and_send_p7_message(_this, &(resp->header), sizeof(nfapi_ue_release_response_t));
} }
/* /*
* Copyright 2017 Cisco Systems, Inc. * Copyright 2017 Cisco Systems, Inc.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
...@@ -32,645 +32,535 @@ ...@@ -32,645 +32,535 @@
nfapi_vnf_config_t* nfapi_vnf_config_create() nfapi_vnf_config_t *nfapi_vnf_config_create() {
{ static vnf_t *_this = NULL;
vnf_t* _this = (vnf_t*)calloc(1, sizeof(vnf_t));
if(_this == 0) if (_this)
return 0; NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: called twice\n", __FUNCTION__);
_this->sctp = 1; _this= (vnf_t *)calloc(1, sizeof(vnf_t));
_this->next_phy_id = 1; if(_this == 0)
return 0;
// Set the default P5 port
_this->_public.vnf_p5_port = NFAPI_P5_SCTP_PORT;
// set the default memory allocation
_this->_public.malloc = &malloc;
_this->_public.free = &free;
// set the default memory allocation
_this->_public.codec_config.allocate = &malloc;
_this->_public.codec_config.deallocate = &free;
return &(_this->_public); _this->sctp = 1;
_this->next_phy_id = 1;
// Set the default P5 port
_this->_public.vnf_p5_port = NFAPI_P5_SCTP_PORT;
// set the default memory allocation
_this->_public.malloc = &malloc;
_this->_public.free = &free;
// set the default memory allocation
_this->_public.codec_config.allocate = &malloc;
_this->_public.codec_config.deallocate = &free;
return &(_this->_public);
} }
void nfapi_vnf_config_destory(nfapi_vnf_config_t* config) void nfapi_vnf_config_destory(nfapi_vnf_config_t *config) {
{ free(config);
free(config);
} }
int nfapi_vnf_start(nfapi_vnf_config_t* config) int nfapi_vnf_start(nfapi_vnf_config_t *config) {
{ // Verify that config is not null
// Verify that config is not null if(config == 0)
if(config == 0) return -1;
return -1;
// Make sure to set the defined trace function before using NFAPI_TRACE
// Make sure to set the defined trace function before using NFAPI_TRACE if(config->trace)
if(config->trace) nfapi_trace_g = (nfapi_trace_fn_t)config->trace;
nfapi_trace_g = (nfapi_trace_fn_t)config->trace;
NFAPI_TRACE(NFAPI_TRACE_INFO, "%s()\n", __FUNCTION__);
NFAPI_TRACE(NFAPI_TRACE_INFO, "%s()\n", __FUNCTION__); int p5ListenSock, p5Sock;
struct sockaddr_in addr;
int p5ListenSock, p5Sock; socklen_t addrSize;
struct sockaddr_in6 addr6;
struct sockaddr_in addr; struct sctp_event_subscribe events;
socklen_t addrSize; struct sctp_initmsg initMsg;
int noDelay;
struct sockaddr_in6 addr6; (void)memset(&addr, 0, sizeof(struct sockaddr_in));
(void)memset(&addr6, 0, sizeof(struct sockaddr_in6));
struct sctp_event_subscribe events; (void)memset(&events, 0, sizeof(struct sctp_event_subscribe));
struct sctp_initmsg initMsg; (void)memset(&initMsg, 0, sizeof(struct sctp_initmsg));
int noDelay; vnf_t *vnf = (vnf_t *)(config);
NFAPI_TRACE(NFAPI_TRACE_INFO, "Starting P5 VNF connection on port %u\n", config->vnf_p5_port);
(void)memset(&addr, 0, sizeof(struct sockaddr_in)); /*
(void)memset(&addr6, 0, sizeof(struct sockaddr_in6)); char * host = 0;
(void)memset(&events, 0, sizeof(struct sctp_event_subscribe)); char * port = "4242";
(void)memset(&initMsg, 0, sizeof(struct sctp_initmsg)); struct addrinfo hints;
bzero(&hints, sizeof(struct addrinfo));
vnf_t* vnf = (vnf_t*)(config); //hints.ai_flags=AI_PASSIVE;
//hints.ai_flags=AI_DEFAULT;
NFAPI_TRACE(NFAPI_TRACE_INFO, "Starting P5 VNF connection on port %u\n", config->vnf_p5_port); hints.ai_family=AF_UNSPEC;
//hints.ai_family=AF_INET6;
/* hints.ai_socktype=SOCK_STREAM;
char * host = 0; //hints.ai_protocol=IPPROTO_SCTP
char * port = "4242";
struct addrinfo hints; struct addrinfo *aiHead = 0;
bzero(&hints, sizeof(struct addrinfo));
//hints.ai_flags=AI_PASSIVE;
//hints.ai_flags=AI_DEFAULT;
hints.ai_family=AF_UNSPEC; int result = getaddrinfo(host, port, &hints, &aiHead);
//hints.ai_family=AF_INET6; NFAPI_TRACE(NFAPI_TRACE_INFO, "getaddrinfo return %d %d\n", result, errno);
hints.ai_socktype=SOCK_STREAM;
//hints.ai_protocol=IPPROTO_SCTP while(aiHead->ai_next != NULL)
{
struct addrinfo *aiHead = 0; NFAPI_TRACE(NFAPI_TRACE_INFO, "addr info %d (IP %d UDP %d SCTP %d)\n %d (%d)\n",
aiHead->ai_protocol, IPPROTO_IP, IPPROTO_UDP, IPPROTO_SCTP,
aiHead->ai_flags, AI_PASSIVE);
int result = getaddrinfo(host, port, &hints, &aiHead); char hostBfr[ NI_MAXHOST ];
NFAPI_TRACE(NFAPI_TRACE_INFO, "getaddrinfo return %d %d\n", result, errno); char servBfr[ NI_MAXSERV ];
while(aiHead->ai_next != NULL) getnameinfo(aiHead->ai_addr,
{ aiHead->ai_addrlen,
NFAPI_TRACE(NFAPI_TRACE_INFO, "addr info %d (IP %d UDP %d SCTP %d)\n %d (%d)\n", hostBfr,
aiHead->ai_protocol, IPPROTO_IP, IPPROTO_UDP, IPPROTO_SCTP, sizeof( hostBfr ),
aiHead->ai_flags, AI_PASSIVE); servBfr,
sizeof( servBfr ),
char hostBfr[ NI_MAXHOST ]; NI_NUMERICHOST | NI_NUMERICSERV );
char servBfr[ NI_MAXSERV ];
switch(aiHead->ai_family)
getnameinfo(aiHead->ai_addr, {
aiHead->ai_addrlen, case PF_INET:
hostBfr, {
sizeof( hostBfr ), struct sockaddr_in *pSadrIn = (struct sockaddr_in*) aiHead->ai_addr;
servBfr, printf(
sizeof( servBfr ), " ai_addr = sin_family: %d (AF_INET = %d, "
NI_NUMERICHOST | NI_NUMERICSERV ); "AF_INET6 = %d)\n"
" sin_addr: %s\n"
switch(aiHead->ai_family) " sin_port: %s\n",
{ pSadrIn->sin_family,
case PF_INET: AF_INET,
{ AF_INET6,
struct sockaddr_in *pSadrIn = (struct sockaddr_in*) aiHead->ai_addr; hostBfr,
printf( servBfr );
" ai_addr = sin_family: %d (AF_INET = %d, " }
"AF_INET6 = %d)\n" break;
" sin_addr: %s\n" case PF_INET6:
" sin_port: %s\n", {
pSadrIn->sin_family, struct sockaddr_in6 *pSadrIn6 = (struct sockaddr_in6*) aiHead->ai_addr;
AF_INET, fprintf( stderr,
AF_INET6, " ai_addr = sin6_family: %d (AF_INET = %d, "
hostBfr, "AF_INET6 = %d) \n"
servBfr ); " sin6_addr: %s\n"
} " sin6_port: %s\n"
break; " sin6_flowinfo: %d\n"
case PF_INET6: " sin6_scope_id: %d\n",
{ pSadrIn6->sin6_family,
struct sockaddr_in6 *pSadrIn6 = (struct sockaddr_in6*) aiHead->ai_addr; AF_INET,
fprintf( stderr, AF_INET6,
" ai_addr = sin6_family: %d (AF_INET = %d, " hostBfr,
"AF_INET6 = %d) \n" servBfr,
" sin6_addr: %s\n" pSadrIn6->sin6_flowinfo,
" sin6_port: %s\n" pSadrIn6->sin6_scope_id);
" sin6_flowinfo: %d\n" }
" sin6_scope_id: %d\n", break;
pSadrIn6->sin6_family, default:
AF_INET, NFAPI_TRACE(NFAPI_TRACE_INFO, "Not ment to be here\n");
AF_INET6, break;
hostBfr, }
servBfr,
pSadrIn6->sin6_flowinfo, aiHead = aiHead->ai_next;
pSadrIn6->sin6_scope_id); }
} */
break; {
default: int protocol;
NFAPI_TRACE(NFAPI_TRACE_INFO, "Not ment to be here\n"); int domain;
break;
} if (vnf->sctp)
protocol = IPPROTO_SCTP;
aiHead = aiHead->ai_next; else
} protocol = IPPROTO_IP;
*/
if(config->vnf_ipv6) {
{ domain = PF_INET6;
int protocol; } else {
int domain; domain = AF_INET;
}
if (vnf->sctp)
protocol = IPPROTO_SCTP; // open the SCTP socket
else if ((p5ListenSock = socket(domain, SOCK_STREAM, protocol)) < 0) {
protocol = IPPROTO_IP; NFAPI_TRACE(NFAPI_TRACE_ERROR, "After P5 socket errno: %d\n", errno);
return 0;
if(config->vnf_ipv6) }
{
domain = PF_INET6; NFAPI_TRACE(NFAPI_TRACE_INFO, "P5 socket created... %d\n", p5ListenSock);
} }
else
{ if (vnf->sctp) {
domain = AF_INET; // configure for MSG_NOTIFICATION
} if (setsockopt(p5ListenSock, IPPROTO_SCTP, SCTP_EVENTS, &events, sizeof(struct sctp_event_subscribe)) < 0) {
NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt (SCTP_EVENTS) errno: %d\n", errno);
// open the SCTP socket close(p5ListenSock);
if ((p5ListenSock = socket(domain, SOCK_STREAM, protocol)) < 0) return 0;
{ }
NFAPI_TRACE(NFAPI_TRACE_ERROR, "After P5 socket errno: %d\n", errno);
return 0; NFAPI_TRACE(NFAPI_TRACE_NOTE, "VNF Setting the SCTP_INITMSG\n");
} // configure the SCTP socket options
NFAPI_TRACE(NFAPI_TRACE_INFO, "P5 socket created... %d\n", p5ListenSock); initMsg.sinit_num_ostreams = 5; //MAX_SCTP_STREAMS; // number of output streams can be greater
} initMsg.sinit_max_instreams = 5; //MAX_SCTP_STREAMS; // number of output streams can be greater
if (vnf->sctp) if (setsockopt(p5ListenSock, IPPROTO_SCTP, SCTP_INITMSG, &initMsg, sizeof(initMsg)) < 0) {
{ NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt (SCTP_INITMSG) errno: %d\n", errno)
// configure for MSG_NOTIFICATION close(p5ListenSock);
if (setsockopt(p5ListenSock, IPPROTO_SCTP, SCTP_EVENTS, &events, sizeof(struct sctp_event_subscribe)) < 0) return 0;
{ }
NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt (SCTP_EVENTS) errno: %d\n", errno);
close(p5ListenSock); noDelay = 1;
return 0;
} if (setsockopt(p5ListenSock, IPPROTO_SCTP, SCTP_NODELAY, &noDelay, sizeof(noDelay)) < 0) {
NFAPI_TRACE(NFAPI_TRACE_NOTE, "VNF Setting the SCTP_INITMSG\n"); NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt (STCP_NODELAY) errno: %d\n", errno);
// configure the SCTP socket options close(p5ListenSock);
initMsg.sinit_num_ostreams = 5; //MAX_SCTP_STREAMS; // number of output streams can be greater return 0;
initMsg.sinit_max_instreams = 5; //MAX_SCTP_STREAMS; // number of output streams can be greater }
if (setsockopt(p5ListenSock, IPPROTO_SCTP, SCTP_INITMSG, &initMsg, sizeof(initMsg)) < 0)
{ struct sctp_event_subscribe events;
NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt (SCTP_INITMSG) errno: %d\n", errno)
close(p5ListenSock); memset( (void *)&events, 0, sizeof(events) );
return 0;
} events.sctp_data_io_event = 1;
noDelay = 1;
if (setsockopt(p5ListenSock, IPPROTO_SCTP, SCTP_NODELAY, &noDelay, sizeof(noDelay)) < 0) if(setsockopt(p5ListenSock, SOL_SCTP, SCTP_EVENTS, (const void *)&events, sizeof(events)) < 0) {
{ NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt errno: %d\n", errno);
NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt (STCP_NODELAY) errno: %d\n", errno); close(p5ListenSock);
close(p5ListenSock); return -1;
return 0; }
} }
struct sctp_event_subscribe events;
memset( (void *)&events, 0, sizeof(events) ); if(config->vnf_ipv6) {
events.sctp_data_io_event = 1; NFAPI_TRACE(NFAPI_TRACE_INFO, "IPV6 binding to port %d %d\n", config->vnf_p5_port, p5ListenSock);
addr6.sin6_family = AF_INET6;
if(setsockopt(p5ListenSock, SOL_SCTP, SCTP_EVENTS, (const void *)&events, sizeof(events)) < 0) addr6.sin6_port = htons(config->vnf_p5_port);
{ addr6.sin6_addr = in6addr_any;
NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt errno: %d\n", errno);
close(p5ListenSock); // bind to the configured address and port
return -1; if (bind(p5ListenSock, (struct sockaddr *)&addr6, sizeof(struct sockaddr_in6)) < 0) {
} NFAPI_TRACE(NFAPI_TRACE_ERROR, "After bind errno: %d\n", errno);
close(p5ListenSock);
} return 0;
}
} else if(config->vnf_ipv4) {
if(config->vnf_ipv6) NFAPI_TRACE(NFAPI_TRACE_INFO, "IPV4 binding to port %d\n", config->vnf_p5_port);
{ addr.sin_family = AF_INET;
NFAPI_TRACE(NFAPI_TRACE_INFO, "IPV6 binding to port %d %d\n", config->vnf_p5_port, p5ListenSock); addr.sin_port = htons(config->vnf_p5_port);
addr6.sin6_family = AF_INET6; addr.sin_addr.s_addr = INADDR_ANY;
addr6.sin6_port = htons(config->vnf_p5_port);
addr6.sin6_addr = in6addr_any; // bind to the configured address and port
if (bind(p5ListenSock, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0)
// bind to the configured address and port //if (sctp_bindx(p5ListenSock, (struct sockaddr *)&addr, sizeof(struct sockaddr_in), SCTP_BINDX_ADD_ADDR) < 0)
if (bind(p5ListenSock, (struct sockaddr *)&addr6, sizeof(struct sockaddr_in6)) < 0) {
{ NFAPI_TRACE(NFAPI_TRACE_ERROR, "After bind errno: %d\n", errno);
NFAPI_TRACE(NFAPI_TRACE_ERROR, "After bind errno: %d\n", errno); close(p5ListenSock);
close(p5ListenSock); return 0;
return 0; }
} }
}
else if(config->vnf_ipv4) NFAPI_TRACE(NFAPI_TRACE_INFO, "bind succeeded..%d.\n", p5ListenSock);
{
NFAPI_TRACE(NFAPI_TRACE_INFO, "IPV4 binding to port %d\n", config->vnf_p5_port); // put the socket into listen mode
addr.sin_family = AF_INET; if (listen(p5ListenSock, 2) < 0) {
addr.sin_port = htons(config->vnf_p5_port); NFAPI_TRACE(NFAPI_TRACE_ERROR, "After listen errno: %d\n", errno);
addr.sin_addr.s_addr = INADDR_ANY; close(p5ListenSock);
return 0;
// bind to the configured address and port }
if (bind(p5ListenSock, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0)
//if (sctp_bindx(p5ListenSock, (struct sockaddr *)&addr, sizeof(struct sockaddr_in), SCTP_BINDX_ADD_ADDR) < 0) NFAPI_TRACE(NFAPI_TRACE_INFO, "listen succeeded...\n");
{ struct timeval tv;
NFAPI_TRACE(NFAPI_TRACE_ERROR, "After bind errno: %d\n", errno); fd_set read_fd_set;
close(p5ListenSock); int p5_idx = 0;
return 0;
} while(vnf->terminate == 0) {
} FD_ZERO(&read_fd_set);
FD_SET(p5ListenSock, &read_fd_set);
NFAPI_TRACE(NFAPI_TRACE_INFO, "bind succeeded..%d.\n", p5ListenSock); int max_fd = p5ListenSock;
tv.tv_sec = 5;
// put the socket into listen mode tv.tv_usec = 0;
if (listen(p5ListenSock, 2) < 0) nfapi_vnf_pnf_info_t *pnf = config->pnf_list;
{
NFAPI_TRACE(NFAPI_TRACE_ERROR, "After listen errno: %d\n", errno); while(pnf != 0) {
close(p5ListenSock); if(pnf->connected) {
return 0; FD_SET(pnf->p5_sock, &read_fd_set);
}
if (pnf->p5_sock > max_fd) {
NFAPI_TRACE(NFAPI_TRACE_INFO, "listen succeeded...\n"); max_fd = pnf->p5_sock;
}
struct timeval tv; }
fd_set read_fd_set;
pnf = pnf->next;
}
int p5_idx = 0;
while(vnf->terminate == 0) int select_result = select(max_fd + 1, &read_fd_set, 0, 0, &tv);
{
FD_ZERO(&read_fd_set); if(select_result == -1) {
NFAPI_TRACE(NFAPI_TRACE_INFO, "select result %d errno %d\n", select_result, errno);
FD_SET(p5ListenSock, &read_fd_set); close(p5ListenSock);
int max_fd = p5ListenSock; return 0;
} else if(select_result) {
tv.tv_sec = 5; if(FD_ISSET(p5ListenSock, &read_fd_set)) {
tv.tv_usec = 0; addrSize = sizeof(struct sockaddr_in);
NFAPI_TRACE(NFAPI_TRACE_INFO, "Accepting connection from PNF...\n");
nfapi_vnf_pnf_info_t* pnf = config->pnf_list; p5Sock = accept(p5ListenSock, (struct sockaddr *)&addr, &addrSize);
while(pnf != 0)
{ if (p5Sock < 0) {
if(pnf->connected) NFAPI_TRACE(NFAPI_TRACE_ERROR, "Failed to accept PNF connection reason:%d\n", errno);
{ } else {
FD_SET(pnf->p5_sock, &read_fd_set); NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF connection (fd:%d) accepted from %s:%d \n", p5Sock, inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
if (pnf->p5_sock > max_fd) nfapi_vnf_pnf_info_t *pnf = (nfapi_vnf_pnf_info_t *)malloc(sizeof(nfapi_vnf_pnf_info_t));
{ NFAPI_TRACE(NFAPI_TRACE_INFO, "MALLOC nfapi_vnf_pnf_info_t for pnf_list pnf:%p\n", pnf);
max_fd = pnf->p5_sock; memset(pnf, 0, sizeof(nfapi_vnf_pnf_info_t));
} pnf->p5_sock = p5Sock;
} pnf->p5_idx = p5_idx++;
pnf->p5_pnf_sockaddr = addr;
pnf = pnf->next; pnf->connected = 1;
} nfapi_vnf_pnf_list_add(config, pnf);
int select_result = select(max_fd + 1, &read_fd_set, 0, 0, &tv); // Inform mac that a pnf connection has been established
// todo : allow mac to 'accept' the connection. i.e. to
if(select_result == -1) // reject it.
{ if(config->pnf_connection_indication != 0) {
NFAPI_TRACE(NFAPI_TRACE_INFO, "select result %d errno %d\n", select_result, errno); (config->pnf_connection_indication)(config, pnf->p5_idx);
close(p5ListenSock); }
return 0;
} // check the connection status
else if(select_result) {
{ struct sctp_status status;
if(FD_ISSET(p5ListenSock, &read_fd_set)) (void)memset(&status, 0, sizeof(struct sctp_status));
{ socklen_t optLen = (socklen_t) sizeof(struct sctp_status);
addrSize = sizeof(struct sockaddr_in);
NFAPI_TRACE(NFAPI_TRACE_INFO, "Accepting connection from PNF...\n"); if (getsockopt(p5Sock, IPPROTO_SCTP, SCTP_STATUS, &status, &optLen) < 0) {
NFAPI_TRACE(NFAPI_TRACE_ERROR, "After getsockopt errno: %d\n", errno);
p5Sock = accept(p5ListenSock, (struct sockaddr *)&addr, &addrSize); return -1;
} else {
if (p5Sock < 0) NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF Association ID = %d\n", status.sstat_assoc_id);
{ NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF Receiver window size = %d\n", status.sstat_rwnd);
NFAPI_TRACE(NFAPI_TRACE_ERROR, "Failed to accept PNF connection reason:%d\n", errno); NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF In Streams = %d\n", status.sstat_instrms);
} NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF Out Streams = %d\n", status.sstat_outstrms);
else }
{ }
NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF connection (fd:%d) accepted from %s:%d \n", p5Sock, inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); }
nfapi_vnf_pnf_info_t* pnf = (nfapi_vnf_pnf_info_t*)malloc(sizeof(nfapi_vnf_pnf_info_t)); } else {
NFAPI_TRACE(NFAPI_TRACE_INFO, "MALLOC nfapi_vnf_pnf_info_t for pnf_list pnf:%p\n", pnf); uint8_t delete_pnfs = 0;
memset(pnf, 0, sizeof(nfapi_vnf_pnf_info_t)); nfapi_vnf_pnf_info_t *pnf = config->pnf_list;
pnf->p5_sock = p5Sock;
pnf->p5_idx = p5_idx++; while(pnf != 0) {
pnf->p5_pnf_sockaddr = addr; if(FD_ISSET(pnf->p5_sock, &read_fd_set)) {
pnf->connected = 1; if(vnf_read_dispatch_message(config, pnf) == 0) {
if(config->pnf_disconnect_indication != 0) {
nfapi_vnf_pnf_list_add(config, pnf); (config->pnf_disconnect_indication)(config, pnf->p5_idx);
}
// Inform mac that a pnf connection has been established
// todo : allow mac to 'accept' the connection. i.e. to close(pnf->p5_sock);
// reject it. pnf->to_delete = 1;
if(config->pnf_connection_indication != 0) delete_pnfs = 1;
{ }
(config->pnf_connection_indication)(config, pnf->p5_idx); }
}
pnf = pnf->next;
}
// check the connection status
{ if(delete_pnfs) {
struct sctp_status status; nfapi_vnf_pnf_info_t *pnf = config->pnf_list;
(void)memset(&status, 0, sizeof(struct sctp_status)); nfapi_vnf_pnf_info_t *prev = 0;
socklen_t optLen = (socklen_t) sizeof(struct sctp_status);
if (getsockopt(p5Sock, IPPROTO_SCTP, SCTP_STATUS, &status, &optLen) < 0) while(pnf != 0) {
{ nfapi_vnf_pnf_info_t *curr = pnf;
NFAPI_TRACE(NFAPI_TRACE_ERROR, "After getsockopt errno: %d\n", errno);
return -1; if(pnf->to_delete == 1) {
} if(prev == 0) {
else config->pnf_list = pnf->next;
{ } else {
NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF Association ID = %d\n", status.sstat_assoc_id); prev->next = pnf->next;
NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF Receiver window size = %d\n", status.sstat_rwnd); }
NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF In Streams = %d\n", status.sstat_instrms);
NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF Out Streams = %d\n", status.sstat_outstrms); pnf = pnf->next;
free(curr);
} } else {
} prev = pnf;
} pnf = pnf->next;
} }
else }
{ }
uint8_t delete_pnfs = 0; }
nfapi_vnf_pnf_info_t* pnf = config->pnf_list; continue;
while(pnf != 0) } else {
{ // timeout
if(FD_ISSET(pnf->p5_sock, &read_fd_set)) // Should we test for socket closure here every second?
{ continue;
if(vnf_read_dispatch_message(config, pnf) == 0) }
{ }
if(config->pnf_disconnect_indication != 0)
{ NFAPI_TRACE(NFAPI_TRACE_INFO, "Closing p5Sock socket's\n");
(config->pnf_disconnect_indication)(config, pnf->p5_idx); {
} nfapi_vnf_pnf_info_t *curr = config->pnf_list;
close(pnf->p5_sock); while(curr != NULL) {
if(config->pnf_disconnect_indication) {
pnf->to_delete = 1; (config->pnf_disconnect_indication)(config, curr->p5_idx);
delete_pnfs = 1; }
}
} close(curr->p5_sock);
curr = curr->next;
pnf = pnf->next; }
} }
NFAPI_TRACE(NFAPI_TRACE_INFO, "Closing p5Listen socket\n");
if(delete_pnfs) close(p5ListenSock);
{ return 0;
nfapi_vnf_pnf_info_t* pnf = config->pnf_list;
nfapi_vnf_pnf_info_t* prev = 0;
while(pnf != 0)
{
nfapi_vnf_pnf_info_t* curr = pnf;
if(pnf->to_delete == 1)
{
if(prev == 0)
{
config->pnf_list = pnf->next;
}
else
{
prev->next = pnf->next;
}
pnf = pnf->next;
free(curr);
}
else
{
prev = pnf;
pnf = pnf->next;
}
}
}
}
continue;
}
else
{
// timeout
// Should we test for socket closure here every second?
continue;
}
}
NFAPI_TRACE(NFAPI_TRACE_INFO, "Closing p5Sock socket's\n");
{
nfapi_vnf_pnf_info_t* curr = config->pnf_list;
while(curr != NULL)
{
if(config->pnf_disconnect_indication)
{
(config->pnf_disconnect_indication)(config, curr->p5_idx);
}
close(curr->p5_sock);
curr = curr->next;
}
}
NFAPI_TRACE(NFAPI_TRACE_INFO, "Closing p5Listen socket\n");
close(p5ListenSock);
return 0;
} }
int nfapi_vnf_stop(nfapi_vnf_config_t* config) int nfapi_vnf_stop(nfapi_vnf_config_t *config) {
{ // Verify that config is not null
// Verify that config is not null if(config == 0)
if(config == 0) return -1;
return -1;
vnf_t* _this = (vnf_t*)(config); vnf_t *_this = (vnf_t *)(config);
_this->terminate = 1; _this->terminate = 1;
return 0; return 0;
} }
int nfapi_vnf_pnf_param_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_param_request_t* req) int nfapi_vnf_pnf_param_req(nfapi_vnf_config_t *config, int p5_idx, nfapi_pnf_param_request_t *req) {
{ if(config == 0 || req == 0)
if(config == 0 || req == 0) return -1;
return -1;
vnf_t* _this = (vnf_t*)(config);
return vnf_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_pnf_param_request_t)); vnf_t *_this = (vnf_t *)(config);
return vnf_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_pnf_param_request_t));
} }
int nfapi_vnf_pnf_config_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_config_request_t* req) int nfapi_vnf_pnf_config_req(nfapi_vnf_config_t *config, int p5_idx, nfapi_pnf_config_request_t *req) {
{ if(config == 0 || req == 0)
if(config == 0 || req == 0) return -1;
return -1;
vnf_t* _this = (vnf_t*)(config); vnf_t *_this = (vnf_t *)(config);
return vnf_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_pnf_config_request_t));
return vnf_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_pnf_config_request_t));
} }
int nfapi_vnf_pnf_start_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_start_request_t* req) int nfapi_vnf_pnf_start_req(nfapi_vnf_config_t *config, int p5_idx, nfapi_pnf_start_request_t *req) {
{ if(config == 0 || req == 0)
if(config == 0 || req == 0) return -1;
return -1;
vnf_t* _this = (vnf_t*)(config);
return vnf_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_pnf_start_request_t)); vnf_t *_this = (vnf_t *)(config);
return vnf_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_pnf_start_request_t));
} }
int nfapi_vnf_pnf_stop_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_stop_request_t* req) int nfapi_vnf_pnf_stop_req(nfapi_vnf_config_t *config, int p5_idx, nfapi_pnf_stop_request_t *req) {
{ if(config == 0 || req == 0)
if(config == 0 || req == 0) return -1;
return -1;
vnf_t* _this = (vnf_t*)(config); vnf_t *_this = (vnf_t *)(config);
return vnf_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_pnf_stop_request_t));
return vnf_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_pnf_stop_request_t));
} }
int nfapi_vnf_param_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_param_request_t* req) int nfapi_vnf_param_req(nfapi_vnf_config_t *config, int p5_idx, nfapi_param_request_t *req) {
{ if(config == 0 || req == 0)
if(config == 0 || req == 0) return -1;
return -1;
vnf_t* _this = (vnf_t*)(config);
return vnf_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_param_request_t)); vnf_t *_this = (vnf_t *)(config);
return vnf_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_param_request_t));
} }
int nfapi_vnf_config_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_config_request_t* req) int nfapi_vnf_config_req(nfapi_vnf_config_t *config, int p5_idx, nfapi_config_request_t *req) {
{ if(config == 0 || req == 0)
if(config == 0 || req == 0) return -1;
return -1;
vnf_t *_this = (vnf_t *)(config);
vnf_t* _this = (vnf_t*)(config); nfapi_vnf_phy_info_t *phy = nfapi_vnf_phy_info_list_find(config, req->header.phy_id);
nfapi_vnf_phy_info_t* phy = nfapi_vnf_phy_info_list_find(config, req->header.phy_id); if(phy == NULL) {
NFAPI_TRACE(NFAPI_TRACE_WARN, "%s failed to find phy inforation phy_id:%d\n", __FUNCTION__, req->header.phy_id);
if(phy == NULL) return -1;
{ }
NFAPI_TRACE(NFAPI_TRACE_WARN, "%s failed to find phy inforation phy_id:%d\n", __FUNCTION__, req->header.phy_id);
return -1; // set the timing parameters
} req->nfapi_config.timing_window.tl.tag = NFAPI_NFAPI_TIMING_WINDOW_TAG;
req->nfapi_config.timing_window.value = phy->timing_window;
// set the timing parameters req->num_tlv++;
req->nfapi_config.timing_window.tl.tag = NFAPI_NFAPI_TIMING_WINDOW_TAG; req->nfapi_config.timing_info_mode.tl.tag = NFAPI_NFAPI_TIMING_INFO_MODE_TAG;
req->nfapi_config.timing_window.value = phy->timing_window; req->nfapi_config.timing_info_mode.value = phy->timing_info_mode;
req->num_tlv++; req->num_tlv++;
req->nfapi_config.timing_info_period.tl.tag = NFAPI_NFAPI_TIMING_INFO_PERIOD_TAG;
req->nfapi_config.timing_info_mode.tl.tag = NFAPI_NFAPI_TIMING_INFO_MODE_TAG; req->nfapi_config.timing_info_period.value = phy->timing_info_period;
req->nfapi_config.timing_info_mode.value = phy->timing_info_mode; req->num_tlv++;
req->num_tlv++; return vnf_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_config_request_t));
req->nfapi_config.timing_info_period.tl.tag = NFAPI_NFAPI_TIMING_INFO_PERIOD_TAG;
req->nfapi_config.timing_info_period.value = phy->timing_info_period;
req->num_tlv++;
return vnf_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_config_request_t));
} }
int nfapi_vnf_start_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_start_request_t* req) int nfapi_vnf_start_req(nfapi_vnf_config_t *config, int p5_idx, nfapi_start_request_t *req) {
{ if(config == 0 || req == 0)
if(config == 0 || req == 0) return -1;
return -1;
vnf_t* _this = (vnf_t*)(config);
return vnf_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_start_request_t)); vnf_t *_this = (vnf_t *)(config);
return vnf_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_start_request_t));
} }
int nfapi_vnf_stop_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_stop_request_t* req) int nfapi_vnf_stop_req(nfapi_vnf_config_t *config, int p5_idx, nfapi_stop_request_t *req) {
{ if(config == 0 || req == 0)
if(config == 0 || req == 0) return -1;
return -1;
vnf_t* _this = (vnf_t*)(config); vnf_t *_this = (vnf_t *)(config);
return vnf_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_stop_request_t));
return vnf_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_stop_request_t));
} }
int nfapi_vnf_measurement_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_measurement_request_t* req) int nfapi_vnf_measurement_req(nfapi_vnf_config_t *config, int p5_idx, nfapi_measurement_request_t *req) {
{ if(config == 0 || req == 0)
if(config == 0 || req == 0) return -1;
return -1;
vnf_t* _this = (vnf_t*)(config);
return vnf_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_measurement_request_t)); vnf_t *_this = (vnf_t *)(config);
return vnf_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_measurement_request_t));
} }
int nfapi_vnf_rssi_request(nfapi_vnf_config_t* config, int p5_idx, nfapi_rssi_request_t* req) int nfapi_vnf_rssi_request(nfapi_vnf_config_t *config, int p5_idx, nfapi_rssi_request_t *req) {
{ if(config == 0 || req == 0)
if(config == 0 || req == 0) return -1;
return -1;
vnf_t* _this = (vnf_t*)(config); vnf_t *_this = (vnf_t *)(config);
return vnf_pack_and_send_p4_message(_this, p5_idx, &req->header, sizeof(nfapi_rssi_request_t));
return vnf_pack_and_send_p4_message(_this, p5_idx, &req->header, sizeof(nfapi_rssi_request_t));
} }
int nfapi_vnf_cell_search_request(nfapi_vnf_config_t* config, int p5_idx, nfapi_cell_search_request_t* req) int nfapi_vnf_cell_search_request(nfapi_vnf_config_t *config, int p5_idx, nfapi_cell_search_request_t *req) {
{ if(config == 0 || req == 0)
if(config == 0 || req == 0) return -1;
return -1;
vnf_t* _this = (vnf_t*)(config);
return vnf_pack_and_send_p4_message(_this, p5_idx, &req->header, sizeof(nfapi_cell_search_request_t)); vnf_t *_this = (vnf_t *)(config);
return vnf_pack_and_send_p4_message(_this, p5_idx, &req->header, sizeof(nfapi_cell_search_request_t));
} }
int nfapi_vnf_broadcast_detect_request(nfapi_vnf_config_t* config, int p5_idx, nfapi_broadcast_detect_request_t* req) int nfapi_vnf_broadcast_detect_request(nfapi_vnf_config_t *config, int p5_idx, nfapi_broadcast_detect_request_t *req) {
{ if(config == 0 || req == 0)
if(config == 0 || req == 0) return -1;
return -1;
vnf_t* _this = (vnf_t*)(config); vnf_t *_this = (vnf_t *)(config);
return vnf_pack_and_send_p4_message(_this, p5_idx, &req->header, sizeof(nfapi_broadcast_detect_request_t));
return vnf_pack_and_send_p4_message(_this, p5_idx, &req->header, sizeof(nfapi_broadcast_detect_request_t));
} }
int nfapi_vnf_system_information_schedule_request(nfapi_vnf_config_t* config, int p5_idx, nfapi_system_information_schedule_request_t* req) int nfapi_vnf_system_information_schedule_request(nfapi_vnf_config_t *config, int p5_idx, nfapi_system_information_schedule_request_t *req) {
{ if(config == 0 || req == 0)
if(config == 0 || req == 0) return -1;
return -1;
vnf_t* _this = (vnf_t*)(config);
return vnf_pack_and_send_p4_message(_this, p5_idx, &req->header, sizeof(nfapi_system_information_schedule_request_t)); vnf_t *_this = (vnf_t *)(config);
return vnf_pack_and_send_p4_message(_this, p5_idx, &req->header, sizeof(nfapi_system_information_schedule_request_t));
} }
int nfapi_vnf_system_information_request(nfapi_vnf_config_t* config, int p5_idx, nfapi_system_information_request_t* req) int nfapi_vnf_system_information_request(nfapi_vnf_config_t *config, int p5_idx, nfapi_system_information_request_t *req) {
{ if(config == 0 || req == 0)
if(config == 0 || req == 0) return -1;
return -1;
vnf_t* _this = (vnf_t*)(config);
return vnf_pack_and_send_p4_message(_this, p5_idx, &req->header, sizeof(nfapi_system_information_request_t)); vnf_t *_this = (vnf_t *)(config);
return vnf_pack_and_send_p4_message(_this, p5_idx, &req->header, sizeof(nfapi_system_information_request_t));
} }
int nfapi_vnf_nmm_stop_request(nfapi_vnf_config_t* config, int p5_idx, nfapi_nmm_stop_request_t* req) int nfapi_vnf_nmm_stop_request(nfapi_vnf_config_t *config, int p5_idx, nfapi_nmm_stop_request_t *req) {
{ if(config == 0 || req == 0)
if(config == 0 || req == 0) return -1;
return -1;
vnf_t* _this = (vnf_t*)(config); vnf_t *_this = (vnf_t *)(config);
return vnf_pack_and_send_p4_message(_this, p5_idx, &req->header, sizeof(nfapi_nmm_stop_request_t));
return vnf_pack_and_send_p4_message(_this, p5_idx, &req->header, sizeof(nfapi_nmm_stop_request_t));
} }
int nfapi_vnf_vendor_extension(nfapi_vnf_config_t* config, int p5_idx, nfapi_p4_p5_message_header_t* msg) int nfapi_vnf_vendor_extension(nfapi_vnf_config_t *config, int p5_idx, nfapi_p4_p5_message_header_t *msg) {
{ if(config == 0 || msg == 0)
if(config == 0 || msg == 0) return -1;
return -1;
vnf_t* _this = (vnf_t*)(config);
return vnf_pack_and_send_p5_message(_this, p5_idx, msg, sizeof(nfapi_p4_p5_message_header_t)); vnf_t *_this = (vnf_t *)(config);
return vnf_pack_and_send_p5_message(_this, p5_idx, msg, sizeof(nfapi_p4_p5_message_header_t));
} }
int nfapi_vnf_allocate_phy(nfapi_vnf_config_t* config, int p5_idx, uint16_t* phy_id) int nfapi_vnf_allocate_phy(nfapi_vnf_config_t *config, int p5_idx, uint16_t *phy_id) {
{ vnf_t *vnf = (vnf_t *)config;
vnf_t* vnf = (vnf_t*)config; nfapi_vnf_phy_info_t *info = (nfapi_vnf_phy_info_t *)calloc(1, sizeof(nfapi_vnf_phy_info_t));
info->p5_idx = p5_idx;
nfapi_vnf_phy_info_t* info = (nfapi_vnf_phy_info_t*)calloc(1, sizeof(nfapi_vnf_phy_info_t)); info->phy_id = vnf->next_phy_id++;
info->p5_idx = p5_idx; info->timing_window = 30; // This seems to override what gets set by the user - why???
info->phy_id = vnf->next_phy_id++; info->timing_info_mode = 0x03;
info->timing_info_period = 128;
info->timing_window = 30; // This seems to override what gets set by the user - why??? nfapi_vnf_phy_info_list_add(config, info);
info->timing_info_mode = 0x03; (*phy_id) = info->phy_id;
info->timing_info_period = 128; return 0;
nfapi_vnf_phy_info_list_add(config, info);
(*phy_id) = info->phy_id;
return 0;
} }
/* /*
* Copyright 2017 Cisco Systems, Inc. * Copyright 2017 Cisco Systems, Inc.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
...@@ -26,531 +26,434 @@ ...@@ -26,531 +26,434 @@
#include "vnf_p7.h" #include "vnf_p7.h"
#define FAPI2_IP_DSCP 0 #define FAPI2_IP_DSCP 0
nfapi_vnf_p7_config_t* nfapi_vnf_p7_config_create() nfapi_vnf_p7_config_t *nfapi_vnf_p7_config_create() {
{ static vnf_p7_t *_this==NULL;
vnf_p7_t* _this = (vnf_p7_t*)calloc(1, sizeof(vnf_p7_t));
if(_this == 0) if (_this)
return 0; NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: called twice\n", __FUNCTION__);
// todo : initialize _this = (vnf_p7_t *)calloc(1, sizeof(vnf_p7_t));
_this->_public.segment_size = 1400;
_this->_public.max_num_segments = 8;
_this->_public.checksum_enabled = 1;
_this->_public.malloc = &malloc;
_this->_public.free = &free;
_this->_public.codec_config.allocate = &malloc; if(_this == 0)
_this->_public.codec_config.deallocate = &free; return 0;
return &(_this->_public); // todo : initialize
_this->_public.segment_size = 1400;
_this->_public.max_num_segments = 8;
_this->_public.checksum_enabled = 1;
_this->_public.malloc = &malloc;
_this->_public.free = &free;
_this->_public.codec_config.allocate = &malloc;
_this->_public.codec_config.deallocate = &free;
return &(_this->_public);
} }
void nfapi_vnf_p7_config_destory(nfapi_vnf_p7_config_t* config) void nfapi_vnf_p7_config_destory(nfapi_vnf_p7_config_t *config) {
{ free(config);
free(config);
} }
struct timespec timespec_add(struct timespec lhs, struct timespec rhs) struct timespec timespec_add(struct timespec lhs, struct timespec rhs) {
{ struct timespec result;
struct timespec result; result.tv_sec = lhs.tv_sec + rhs.tv_sec;
result.tv_nsec = lhs.tv_nsec + rhs.tv_nsec;
result.tv_sec = lhs.tv_sec + rhs.tv_sec; if(result.tv_nsec > 1e9) {
result.tv_nsec = lhs.tv_nsec + rhs.tv_nsec; result.tv_sec++;
result.tv_nsec-= 1e9;
}
if(result.tv_nsec > 1e9) return result;
{
result.tv_sec++;
result.tv_nsec-= 1e9;
}
return result;
}
struct timespec timespec_sub(struct timespec lhs, struct timespec rhs)
{
struct timespec result;
if ((lhs.tv_nsec-rhs.tv_nsec)<0)
{
result.tv_sec = lhs.tv_sec-rhs.tv_sec-1;
result.tv_nsec = 1000000000+lhs.tv_nsec-rhs.tv_nsec;
}
else
{
result.tv_sec = lhs.tv_sec-rhs.tv_sec;
result.tv_nsec = lhs.tv_nsec-rhs.tv_nsec;
}
return result;
}
// monitor the p7 endpoints and the timing loop and
// send indications to mac
int nfapi_vnf_p7_start(nfapi_vnf_p7_config_t* config)
{
if(config == 0)
return -1;
NFAPI_TRACE(NFAPI_TRACE_INFO, "%s()\n", __FUNCTION__);
vnf_p7_t* vnf_p7 = (vnf_p7_t*)config;
// Create p7 receive udp port
// todo : this needs updating for Ipv6
NFAPI_TRACE(NFAPI_TRACE_INFO, "Initialising VNF P7 port:%u\n", config->port);
// open the UDP socket
if ((vnf_p7->socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
NFAPI_TRACE(NFAPI_TRACE_ERROR, "After P7 socket errno: %d\n", errno);
return -1;
}
NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF P7 socket created...\n");
// configure the UDP socket options
int iptos_value = FAPI2_IP_DSCP << 2;
if (setsockopt(vnf_p7->socket, IPPROTO_IP, IP_TOS, &iptos_value, sizeof(iptos_value)) < 0)
{
NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt (IP_TOS) errno: %d\n", errno);
return -1;
}
NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF P7 setsockopt succeeded...\n");
// Create the address structure
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(config->port);
addr.sin_addr.s_addr = INADDR_ANY;
// bind to the configured port
NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF P7 binding too %s:%d\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
if (bind(vnf_p7->socket, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0)
//if (sctp_bindx(config->socket, (struct sockaddr *)&addr, sizeof(struct sockaddr_in), 0) < 0)
{
NFAPI_TRACE(NFAPI_TRACE_ERROR, "After bind errno: %d\n", errno);
return -1;
}
NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF P7 bind succeeded...\n");
//struct timespec original_pselect_timeout;
struct timespec pselect_timeout;
pselect_timeout.tv_sec = 0;
pselect_timeout.tv_nsec = 1000000; // ns in a 1 us
struct timespec pselect_start;
struct timespec pselect_stop;
//struct timespec sf_end;
long last_millisecond = -1;
struct timespec sf_duration;
sf_duration.tv_sec = 0;
sf_duration.tv_nsec = 1e6; // We want 1ms pause
struct timespec sf_start;
clock_gettime(CLOCK_MONOTONIC, &sf_start);
long millisecond = sf_start.tv_nsec / 1e6;
sf_start = timespec_add(sf_start, sf_duration);
NFAPI_TRACE(NFAPI_TRACE_INFO, "next subframe will start at %d.%d\n", sf_start.tv_sec, sf_start.tv_nsec);
while(vnf_p7->terminate == 0)
{
fd_set rfds;
int maxSock = 0;
FD_ZERO(&rfds);
int selectRetval = 0;
// Add the p7 socket
FD_SET(vnf_p7->socket, &rfds);
maxSock = vnf_p7->socket;
clock_gettime(CLOCK_MONOTONIC, &pselect_start);
//long millisecond = pselect_start.tv_nsec / 1e6;
if((last_millisecond == -1) || (millisecond == last_millisecond) || (millisecond == (last_millisecond + 1) % 1000) )
{
//NFAPI_TRACE(NFAPI_TRACE_INFO, "pselect_start:%d.%d sf_start:%d.%d\n", pselect_start.tv_sec, pselect_start.tv_nsec, sf_start.tv_sec, sf_start.tv_nsec);
if((pselect_start.tv_sec > sf_start.tv_sec) ||
((pselect_start.tv_sec == sf_start.tv_sec) && (pselect_start.tv_nsec > sf_start.tv_nsec)))
{
// overran the end of the subframe we do not want to wait
pselect_timeout.tv_sec = 0;
pselect_timeout.tv_nsec = 0;
//struct timespec overrun = timespec_sub(pselect_start, sf_start);
//NFAPI_TRACE(NFAPI_TRACE_INFO, "Subframe overrun detected of %d.%d running to catchup\n", overrun.tv_sec, overrun.tv_nsec);
}
else
{
// still time before the end of the subframe wait
pselect_timeout = timespec_sub(sf_start, pselect_start);
}
//original_pselect_timeout = pselect_timeout;
// detemine how long to sleep in ns before the start of the next 1ms
//pselect_timeout.tv_nsec = 1e6 - (pselect_start.tv_nsec % 1000000);
//uint8_t underrun_possible =0;
// if we are not sleeping until the next milisecond due to the
// insycn minor adjment flag it so we don't consider it an error
//uint8_t underrun_possible =0;
/*
{
nfapi_vnf_p7_connection_info_t* phy = vnf_p7->p7_connections;
if(phy && phy->in_sync && phy->insync_minor_adjustment != 0 && phy->insync_minor_adjustment_duration > 0 && pselect_start.tv_nsec != 0)
{
NFAPI_TRACE(NFAPI_TRACE_NOTE, "[VNF] Subframe minor adjustment %d (%d->%d)\n", phy->insync_minor_adjustment,
pselect_timeout.tv_nsec, pselect_timeout.tv_nsec - (phy->insync_minor_adjustment * 1000))
if(phy->insync_minor_adjustment > 0)
{
// todo check we don't go below 0
if((phy->insync_minor_adjustment * 1000) > pselect_timeout.tv_nsec)
pselect_timeout.tv_nsec = 0;
else
pselect_timeout.tv_nsec = pselect_timeout.tv_nsec - (phy->insync_minor_adjustment * 1000);
//underrun_possible = 1;
}
else if(phy->insync_minor_adjustment < 0)
{
// todo check we don't go below 0
pselect_timeout.tv_nsec = pselect_timeout.tv_nsec - (phy->insync_minor_adjustment * 1000);
}
//phy->insync_minor_adjustment = 0;
phy->insync_minor_adjustment_duration--;
}
}
*/
//long wraps = pselect_timeout.tv_nsec % 1e9;
selectRetval = pselect(maxSock+1, &rfds, NULL, NULL, &pselect_timeout, NULL);
clock_gettime(CLOCK_MONOTONIC, &pselect_stop);
nfapi_vnf_p7_connection_info_t* phy = vnf_p7->p7_connections;
if (selectRetval==-1 && errno == 22)
{
NFAPI_TRACE(NFAPI_TRACE_ERROR, "INVAL: pselect_timeout:%d.%ld adj[dur:%d adj:%d], sf_dur:%d.%ld\n",
pselect_timeout.tv_sec, pselect_timeout.tv_nsec,
phy->insync_minor_adjustment_duration, phy->insync_minor_adjustment,
sf_duration.tv_sec, sf_duration.tv_nsec);
} }
if(selectRetval == 0)
{
// calculate the start of the next subframe
sf_start = timespec_add(sf_start, sf_duration);
//NFAPI_TRACE(NFAPI_TRACE_INFO, "next subframe will start at %d.%d\n", sf_start.tv_sec, sf_start.tv_nsec);
if(phy && phy->in_sync && phy->insync_minor_adjustment != 0 && phy->insync_minor_adjustment_duration > 0) struct timespec timespec_sub(struct timespec lhs, struct timespec rhs) {
{ struct timespec result;
long insync_minor_adjustment_ns = (phy->insync_minor_adjustment * 1000);
sf_start.tv_nsec -= insync_minor_adjustment_ns; if ((lhs.tv_nsec-rhs.tv_nsec)<0) {
result.tv_sec = lhs.tv_sec-rhs.tv_sec-1;
result.tv_nsec = 1000000000+lhs.tv_nsec-rhs.tv_nsec;
} else {
result.tv_sec = lhs.tv_sec-rhs.tv_sec;
result.tv_nsec = lhs.tv_nsec-rhs.tv_nsec;
}
#if 1 return result;
if (sf_start.tv_nsec > 1e9)
{
sf_start.tv_sec++;
sf_start.tv_nsec-=1e9;
}
else if (sf_start.tv_nsec < 0)
{
sf_start.tv_sec--;
sf_start.tv_nsec+=1e9;
}
#else
//NFAPI_TRACE(NFAPI_TRACE_NOTE, "[VNF] BEFORE adjustment - Subframe minor adjustment %dus sf_start.tv_nsec:%d\n", phy->insync_minor_adjustment, sf_start.tv_nsec);
if(phy->insync_minor_adjustment > 0)
{
// decrease the subframe duration a little
if (sf_start.tv_nsec > insync_minor_adjustment_ns)
sf_start.tv_nsec -= insync_minor_adjustment_ns;
else
{
NFAPI_TRACE(NFAPI_TRACE_ERROR, "[VNF] Adjustment would make it negative sf:%d.%ld adjust:%ld\n\n\n", sf_start.tv_sec, sf_start.tv_nsec, insync_minor_adjustment_ns);
sf_start.tv_sec--;
sf_start.tv_nsec += 1e9 - insync_minor_adjustment_ns;
}
}
else if(phy->insync_minor_adjustment < 0)
{
// todo check we don't go below 0
// increase the subframe duration a little
sf_start.tv_nsec += insync_minor_adjustment_ns;
if (sf_start.tv_nsec < 0)
{
NFAPI_TRACE(NFAPI_TRACE_ERROR, "[VNF] OVERFLOW %d.%ld\n\n\n\n", sf_start.tv_sec, sf_start.tv_nsec);
sf_start.tv_sec++;
sf_start.tv_nsec += 1e9;
}
}
#endif
//phy->insync_minor_adjustment = 0;
phy->insync_minor_adjustment_duration--;
NFAPI_TRACE(NFAPI_TRACE_NOTE, "[VNF] AFTER adjustment - Subframe minor adjustment %dus sf_start.tv_nsec:%d duration:%u\n",
phy->insync_minor_adjustment, sf_start.tv_nsec, phy->insync_minor_adjustment_duration);
if (phy->insync_minor_adjustment_duration==0)
{
phy->insync_minor_adjustment = 0;
}
}
/*
long pselect_stop_millisecond = pselect_stop.tv_nsec / 1e6;
if(millisecond == pselect_stop_millisecond)
{
// we have woke up in the same subframe
if(underrun_possible == 0)
NFAPI_TRACE(NFAPI_TRACE_WARN, "subframe pselect underrun %ld (%d.%d)\n", millisecond, pselect_stop.tv_sec, pselect_stop.tv_nsec);
}
else if(((millisecond + 1) % 1000) != pselect_stop_millisecond)
{
// we have overrun the subframe
NFAPI_TRACE(NFAPI_TRACE_WARN, "subframe pselect overrun %ld %ld\n", millisecond, pselect_stop_millisecond);
NFAPI_TRACE(NFAPI_TRACE_WARN, "subframe underrun %ld\n", millisecond);
}
last_millisecond = millisecond;
*/
millisecond ++;
}
}
else
{
// we have overrun the subframe advance to go and collect $200
if((millisecond - last_millisecond) > 3)
NFAPI_TRACE(NFAPI_TRACE_WARN, "subframe overrun %ld %ld (%ld)\n", millisecond, last_millisecond, millisecond - last_millisecond + 1);
last_millisecond = ( last_millisecond + 1 ) % 1000;
selectRetval = 0;
}
if(selectRetval == 0)
{
vnf_p7->sf_start_time_hr = vnf_get_current_time_hr();
// pselect timed out
nfapi_vnf_p7_connection_info_t* curr = vnf_p7->p7_connections;
while(curr != 0)
{
curr->sfn_sf = increment_sfn_sf(curr->sfn_sf);
vnf_sync(vnf_p7, curr);
curr = curr->next;
}
send_mac_subframe_indications(vnf_p7);
}
else if(selectRetval > 0)
{
// have a p7 message
if(FD_ISSET(vnf_p7->socket, &rfds))
{
vnf_p7_read_dispatch_message(vnf_p7);
}
}
else
{
// pselect error
if(selectRetval == -1 && errno == EINTR)
{
// a sigal was received.
}
else
{
NFAPI_TRACE(NFAPI_TRACE_INFO, "P7 select failed result %d errno %d timeout:%d.%d orginal:%d.%d last_ms:%ld ms:%ld\n", selectRetval, errno, pselect_timeout.tv_sec, pselect_timeout.tv_nsec, pselect_timeout.tv_sec, pselect_timeout.tv_nsec, last_millisecond, millisecond);
// should we exit now?
if (selectRetval == -1 && errno == 22) // invalid argument??? not sure about timeout duration
{
usleep(100000);
}
}
}
}
NFAPI_TRACE(NFAPI_TRACE_INFO, "Closing p7 socket\n");
close(vnf_p7->socket);
NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() returning\n", __FUNCTION__);
return 0;
} }
int nfapi_vnf_p7_stop(nfapi_vnf_p7_config_t* config) // monitor the p7 endpoints and the timing loop and
{ // send indications to mac
if(config == 0) int nfapi_vnf_p7_start(nfapi_vnf_p7_config_t *config) {
return -1; if(config == 0)
return -1;
vnf_p7_t* vnf_p7 = (vnf_p7_t*)config;
vnf_p7->terminate =1; NFAPI_TRACE(NFAPI_TRACE_INFO, "%s()\n", __FUNCTION__);
return 0; vnf_p7_t *vnf_p7 = (vnf_p7_t *)config;
} // Create p7 receive udp port
// todo : this needs updating for Ipv6
int nfapi_vnf_p7_add_pnf(nfapi_vnf_p7_config_t* config, const char* pnf_p7_addr, int pnf_p7_port, int phy_id) NFAPI_TRACE(NFAPI_TRACE_INFO, "Initialising VNF P7 port:%u\n", config->port);
{
NFAPI_TRACE(NFAPI_TRACE_INFO, "%s(config:%p phy_id:%d pnf_addr:%s pnf_p7_port:%d)\n", __FUNCTION__, config, phy_id, pnf_p7_addr, pnf_p7_port); // open the UDP socket
if ((vnf_p7->socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
if(config == 0) NFAPI_TRACE(NFAPI_TRACE_ERROR, "After P7 socket errno: %d\n", errno);
return -1;
}
NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF P7 socket created...\n");
// configure the UDP socket options
int iptos_value = FAPI2_IP_DSCP << 2;
if (setsockopt(vnf_p7->socket, IPPROTO_IP, IP_TOS, &iptos_value, sizeof(iptos_value)) < 0) {
NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt (IP_TOS) errno: %d\n", errno);
return -1;
}
NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF P7 setsockopt succeeded...\n");
// Create the address structure
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(config->port);
addr.sin_addr.s_addr = INADDR_ANY;
// bind to the configured port
NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF P7 binding too %s:%d\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
if (bind(vnf_p7->socket, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0)
//if (sctp_bindx(config->socket, (struct sockaddr *)&addr, sizeof(struct sockaddr_in), 0) < 0)
{
NFAPI_TRACE(NFAPI_TRACE_ERROR, "After bind errno: %d\n", errno);
return -1;
}
NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF P7 bind succeeded...\n");
//struct timespec original_pselect_timeout;
struct timespec pselect_timeout;
pselect_timeout.tv_sec = 0;
pselect_timeout.tv_nsec = 1000000; // ns in a 1 us
struct timespec pselect_start;
struct timespec pselect_stop;
//struct timespec sf_end;
long last_millisecond = -1;
struct timespec sf_duration;
sf_duration.tv_sec = 0;
sf_duration.tv_nsec = 1e6; // We want 1ms pause
struct timespec sf_start;
clock_gettime(CLOCK_MONOTONIC, &sf_start);
long millisecond = sf_start.tv_nsec / 1e6;
sf_start = timespec_add(sf_start, sf_duration);
NFAPI_TRACE(NFAPI_TRACE_INFO, "next subframe will start at %d.%d\n", sf_start.tv_sec, sf_start.tv_nsec);
while(vnf_p7->terminate == 0) {
fd_set rfds;
int maxSock = 0;
FD_ZERO(&rfds);
int selectRetval = 0;
// Add the p7 socket
FD_SET(vnf_p7->socket, &rfds);
maxSock = vnf_p7->socket;
clock_gettime(CLOCK_MONOTONIC, &pselect_start);
//long millisecond = pselect_start.tv_nsec / 1e6;
if((last_millisecond == -1) || (millisecond == last_millisecond) || (millisecond == (last_millisecond + 1) % 1000) ) {
//NFAPI_TRACE(NFAPI_TRACE_INFO, "pselect_start:%d.%d sf_start:%d.%d\n", pselect_start.tv_sec, pselect_start.tv_nsec, sf_start.tv_sec, sf_start.tv_nsec);
if((pselect_start.tv_sec > sf_start.tv_sec) ||
((pselect_start.tv_sec == sf_start.tv_sec) && (pselect_start.tv_nsec > sf_start.tv_nsec))) {
// overran the end of the subframe we do not want to wait
pselect_timeout.tv_sec = 0;
pselect_timeout.tv_nsec = 0;
//struct timespec overrun = timespec_sub(pselect_start, sf_start);
//NFAPI_TRACE(NFAPI_TRACE_INFO, "Subframe overrun detected of %d.%d running to catchup\n", overrun.tv_sec, overrun.tv_nsec);
} else {
// still time before the end of the subframe wait
pselect_timeout = timespec_sub(sf_start, pselect_start);
}
//original_pselect_timeout = pselect_timeout;
// detemine how long to sleep in ns before the start of the next 1ms
//pselect_timeout.tv_nsec = 1e6 - (pselect_start.tv_nsec % 1000000);
//uint8_t underrun_possible =0;
// if we are not sleeping until the next milisecond due to the
// insycn minor adjment flag it so we don't consider it an error
//uint8_t underrun_possible =0;
/*
{
nfapi_vnf_p7_connection_info_t* phy = vnf_p7->p7_connections;
if(phy && phy->in_sync && phy->insync_minor_adjustment != 0 && phy->insync_minor_adjustment_duration > 0 && pselect_start.tv_nsec != 0)
{ {
return -1; NFAPI_TRACE(NFAPI_TRACE_NOTE, "[VNF] Subframe minor adjustment %d (%d->%d)\n", phy->insync_minor_adjustment,
pselect_timeout.tv_nsec, pselect_timeout.tv_nsec - (phy->insync_minor_adjustment * 1000))
if(phy->insync_minor_adjustment > 0)
{
// todo check we don't go below 0
if((phy->insync_minor_adjustment * 1000) > pselect_timeout.tv_nsec)
pselect_timeout.tv_nsec = 0;
else
pselect_timeout.tv_nsec = pselect_timeout.tv_nsec - (phy->insync_minor_adjustment * 1000);
//underrun_possible = 1;
}
else if(phy->insync_minor_adjustment < 0)
{
// todo check we don't go below 0
pselect_timeout.tv_nsec = pselect_timeout.tv_nsec - (phy->insync_minor_adjustment * 1000);
}
//phy->insync_minor_adjustment = 0;
phy->insync_minor_adjustment_duration--;
} }
}
*/
//long wraps = pselect_timeout.tv_nsec % 1e9;
selectRetval = pselect(maxSock+1, &rfds, NULL, NULL, &pselect_timeout, NULL);
clock_gettime(CLOCK_MONOTONIC, &pselect_stop);
nfapi_vnf_p7_connection_info_t *phy = vnf_p7->p7_connections;
if (selectRetval==-1 && errno == 22) {
NFAPI_TRACE(NFAPI_TRACE_ERROR, "INVAL: pselect_timeout:%d.%ld adj[dur:%d adj:%d], sf_dur:%d.%ld\n",
pselect_timeout.tv_sec, pselect_timeout.tv_nsec,
phy->insync_minor_adjustment_duration, phy->insync_minor_adjustment,
sf_duration.tv_sec, sf_duration.tv_nsec);
}
if(selectRetval == 0) {
// calculate the start of the next subframe
sf_start = timespec_add(sf_start, sf_duration);
//NFAPI_TRACE(NFAPI_TRACE_INFO, "next subframe will start at %d.%d\n", sf_start.tv_sec, sf_start.tv_nsec);
if(phy && phy->in_sync && phy->insync_minor_adjustment != 0 && phy->insync_minor_adjustment_duration > 0) {
long insync_minor_adjustment_ns = (phy->insync_minor_adjustment * 1000);
sf_start.tv_nsec -= insync_minor_adjustment_ns;
#if 1
vnf_p7_t* vnf_p7 = (vnf_p7_t*)config; if (sf_start.tv_nsec > 1e9) {
sf_start.tv_sec++;
sf_start.tv_nsec-=1e9;
} else if (sf_start.tv_nsec < 0) {
sf_start.tv_sec--;
sf_start.tv_nsec+=1e9;
}
nfapi_vnf_p7_connection_info_t* node = (nfapi_vnf_p7_connection_info_t*)malloc(sizeof(nfapi_vnf_p7_connection_info_t)); #else
memset(node, 0, sizeof(nfapi_vnf_p7_connection_info_t)); //NFAPI_TRACE(NFAPI_TRACE_NOTE, "[VNF] BEFORE adjustment - Subframe minor adjustment %dus sf_start.tv_nsec:%d\n", phy->insync_minor_adjustment, sf_start.tv_nsec);
node->phy_id = phy_id; if(phy->insync_minor_adjustment > 0) {
node->in_sync = 0; // decrease the subframe duration a little
node->dl_out_sync_offset = 30; if (sf_start.tv_nsec > insync_minor_adjustment_ns)
node->dl_out_sync_period = 10; sf_start.tv_nsec -= insync_minor_adjustment_ns;
node->dl_in_sync_offset = 30; else {
node->dl_in_sync_period = 512; NFAPI_TRACE(NFAPI_TRACE_ERROR, "[VNF] Adjustment would make it negative sf:%d.%ld adjust:%ld\n\n\n", sf_start.tv_sec, sf_start.tv_nsec, insync_minor_adjustment_ns);
node->sfn_sf = 0; sf_start.tv_sec--;
sf_start.tv_nsec += 1e9 - insync_minor_adjustment_ns;
}
} else if(phy->insync_minor_adjustment < 0) {
// todo check we don't go below 0
// increase the subframe duration a little
sf_start.tv_nsec += insync_minor_adjustment_ns;
if (sf_start.tv_nsec < 0) {
NFAPI_TRACE(NFAPI_TRACE_ERROR, "[VNF] OVERFLOW %d.%ld\n\n\n\n", sf_start.tv_sec, sf_start.tv_nsec);
sf_start.tv_sec++;
sf_start.tv_nsec += 1e9;
}
}
node->min_sync_cycle_count = 8; #endif
//phy->insync_minor_adjustment = 0;
phy->insync_minor_adjustment_duration--;
NFAPI_TRACE(NFAPI_TRACE_NOTE, "[VNF] AFTER adjustment - Subframe minor adjustment %dus sf_start.tv_nsec:%d duration:%u\n",
phy->insync_minor_adjustment, sf_start.tv_nsec, phy->insync_minor_adjustment_duration);
if (phy->insync_minor_adjustment_duration==0) {
phy->insync_minor_adjustment = 0;
}
}
// save the remote endpoint information /*
node->remote_addr.sin_family = AF_INET; long pselect_stop_millisecond = pselect_stop.tv_nsec / 1e6;
node->remote_addr.sin_port = htons(pnf_p7_port); if(millisecond == pselect_stop_millisecond)
node->remote_addr.sin_addr.s_addr = inet_addr(pnf_p7_addr); {
// we have woke up in the same subframe
if(underrun_possible == 0)
NFAPI_TRACE(NFAPI_TRACE_WARN, "subframe pselect underrun %ld (%d.%d)\n", millisecond, pselect_stop.tv_sec, pselect_stop.tv_nsec);
}
else if(((millisecond + 1) % 1000) != pselect_stop_millisecond)
{
// we have overrun the subframe
NFAPI_TRACE(NFAPI_TRACE_WARN, "subframe pselect overrun %ld %ld\n", millisecond, pselect_stop_millisecond);
NFAPI_TRACE(NFAPI_TRACE_WARN, "subframe underrun %ld\n", millisecond);
}
last_millisecond = millisecond;
*/
millisecond ++;
}
} else {
// we have overrun the subframe advance to go and collect $200
if((millisecond - last_millisecond) > 3)
NFAPI_TRACE(NFAPI_TRACE_WARN, "subframe overrun %ld %ld (%ld)\n", millisecond, last_millisecond, millisecond - last_millisecond + 1);
last_millisecond = ( last_millisecond + 1 ) % 1000;
selectRetval = 0;
}
if(selectRetval == 0) {
vnf_p7->sf_start_time_hr = vnf_get_current_time_hr();
// pselect timed out
nfapi_vnf_p7_connection_info_t *curr = vnf_p7->p7_connections;
while(curr != 0) {
curr->sfn_sf = increment_sfn_sf(curr->sfn_sf);
vnf_sync(vnf_p7, curr);
curr = curr->next;
}
send_mac_subframe_indications(vnf_p7);
} else if(selectRetval > 0) {
// have a p7 message
if(FD_ISSET(vnf_p7->socket, &rfds)) {
vnf_p7_read_dispatch_message(vnf_p7);
}
} else {
// pselect error
if(selectRetval == -1 && errno == EINTR) {
// a sigal was received.
} else {
NFAPI_TRACE(NFAPI_TRACE_INFO, "P7 select failed result %d errno %d timeout:%d.%d orginal:%d.%d last_ms:%ld ms:%ld\n", selectRetval, errno, pselect_timeout.tv_sec, pselect_timeout.tv_nsec,
pselect_timeout.tv_sec, pselect_timeout.tv_nsec, last_millisecond, millisecond);
// should we exit now?
if (selectRetval == -1 && errno == 22) { // invalid argument??? not sure about timeout duration
usleep(100000);
}
}
}
}
NFAPI_TRACE(NFAPI_TRACE_INFO, "Closing p7 socket\n");
close(vnf_p7->socket);
NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() returning\n", __FUNCTION__);
return 0;
}
vnf_p7_connection_info_list_add(vnf_p7, node); int nfapi_vnf_p7_stop(nfapi_vnf_p7_config_t *config) {
if(config == 0)
return -1;
return 0; vnf_p7_t *vnf_p7 = (vnf_p7_t *)config;
vnf_p7->terminate =1;
return 0;
} }
int nfapi_vnf_p7_del_pnf(nfapi_vnf_p7_config_t* config, int phy_id) int nfapi_vnf_p7_add_pnf(nfapi_vnf_p7_config_t *config, const char *pnf_p7_addr, int pnf_p7_port, int phy_id) {
{ NFAPI_TRACE(NFAPI_TRACE_INFO, "%s(config:%p phy_id:%d pnf_addr:%s pnf_p7_port:%d)\n", __FUNCTION__, config, phy_id, pnf_p7_addr, pnf_p7_port);
NFAPI_TRACE(NFAPI_TRACE_INFO, "%s(phy_id:%d)\n", __FUNCTION__, phy_id);
if(config == 0) {
return -1;
}
vnf_p7_t *vnf_p7 = (vnf_p7_t *)config;
nfapi_vnf_p7_connection_info_t *node = (nfapi_vnf_p7_connection_info_t *)malloc(sizeof(nfapi_vnf_p7_connection_info_t));
memset(node, 0, sizeof(nfapi_vnf_p7_connection_info_t));
node->phy_id = phy_id;
node->in_sync = 0;
node->dl_out_sync_offset = 30;
node->dl_out_sync_period = 10;
node->dl_in_sync_offset = 30;
node->dl_in_sync_period = 512;
node->sfn_sf = 0;
node->min_sync_cycle_count = 8;
// save the remote endpoint information
node->remote_addr.sin_family = AF_INET;
node->remote_addr.sin_port = htons(pnf_p7_port);
node->remote_addr.sin_addr.s_addr = inet_addr(pnf_p7_addr);
vnf_p7_connection_info_list_add(vnf_p7, node);
return 0;
}
if(config == 0) int nfapi_vnf_p7_del_pnf(nfapi_vnf_p7_config_t *config, int phy_id) {
return -1; NFAPI_TRACE(NFAPI_TRACE_INFO, "%s(phy_id:%d)\n", __FUNCTION__, phy_id);
vnf_p7_t* vnf_p7 = (vnf_p7_t*)config; if(config == 0)
return -1;
nfapi_vnf_p7_connection_info_t* to_delete = vnf_p7_connection_info_list_delete(vnf_p7, phy_id); vnf_p7_t *vnf_p7 = (vnf_p7_t *)config;
nfapi_vnf_p7_connection_info_t *to_delete = vnf_p7_connection_info_list_delete(vnf_p7, phy_id);
if(to_delete) if(to_delete) {
{ NFAPI_TRACE(NFAPI_TRACE_INFO, "%s(phy_id:%d) deleting connection info\n", __FUNCTION__, phy_id);
NFAPI_TRACE(NFAPI_TRACE_INFO, "%s(phy_id:%d) deleting connection info\n", __FUNCTION__, phy_id); free(to_delete);
free(to_delete); }
}
return 0; return 0;
} }
int nfapi_vnf_p7_dl_config_req(nfapi_vnf_p7_config_t* config, nfapi_dl_config_request_t* req) int nfapi_vnf_p7_dl_config_req(nfapi_vnf_p7_config_t *config, nfapi_dl_config_request_t *req) {
{ //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s(config:%p req:%p)\n", __FUNCTION__, config, req);
//NFAPI_TRACE(NFAPI_TRACE_INFO, "%s(config:%p req:%p)\n", __FUNCTION__, config, req); if(config == 0 || req == 0)
return -1;
if(config == 0 || req == 0)
return -1;
vnf_p7_t* vnf_p7 = (vnf_p7_t*)config; vnf_p7_t *vnf_p7 = (vnf_p7_t *)config;
return vnf_p7_pack_and_send_p7_msg(vnf_p7, &req->header); return vnf_p7_pack_and_send_p7_msg(vnf_p7, &req->header);
} }
int nfapi_vnf_p7_ul_config_req(nfapi_vnf_p7_config_t* config, nfapi_ul_config_request_t* req) int nfapi_vnf_p7_ul_config_req(nfapi_vnf_p7_config_t *config, nfapi_ul_config_request_t *req) {
{ if(config == 0 || req == 0)
if(config == 0 || req == 0) return -1;
return -1;
vnf_p7_t* vnf_p7 = (vnf_p7_t*)config; vnf_p7_t *vnf_p7 = (vnf_p7_t *)config;
return vnf_p7_pack_and_send_p7_msg(vnf_p7, &req->header); return vnf_p7_pack_and_send_p7_msg(vnf_p7, &req->header);
} }
int nfapi_vnf_p7_hi_dci0_req(nfapi_vnf_p7_config_t* config, nfapi_hi_dci0_request_t* req) int nfapi_vnf_p7_hi_dci0_req(nfapi_vnf_p7_config_t *config, nfapi_hi_dci0_request_t *req) {
{ if(config == 0 || req == 0)
if(config == 0 || req == 0) return -1;
return -1;
vnf_p7_t* vnf_p7 = (vnf_p7_t*)config; vnf_p7_t *vnf_p7 = (vnf_p7_t *)config;
return vnf_p7_pack_and_send_p7_msg(vnf_p7, &req->header); return vnf_p7_pack_and_send_p7_msg(vnf_p7, &req->header);
} }
int nfapi_vnf_p7_tx_req(nfapi_vnf_p7_config_t* config, nfapi_tx_request_t* req) int nfapi_vnf_p7_tx_req(nfapi_vnf_p7_config_t *config, nfapi_tx_request_t *req) {
{ if(config == 0 || req == 0)
if(config == 0 || req == 0) return -1;
return -1;
vnf_p7_t* vnf_p7 = (vnf_p7_t*)config; vnf_p7_t *vnf_p7 = (vnf_p7_t *)config;
return vnf_p7_pack_and_send_p7_msg(vnf_p7, &req->header); return vnf_p7_pack_and_send_p7_msg(vnf_p7, &req->header);
} }
int nfapi_vnf_p7_lbt_dl_config_req(nfapi_vnf_p7_config_t* config, nfapi_lbt_dl_config_request_t* req) int nfapi_vnf_p7_lbt_dl_config_req(nfapi_vnf_p7_config_t *config, nfapi_lbt_dl_config_request_t *req) {
{ if(config == 0 || req == 0)
if(config == 0 || req == 0) return -1;
return -1;
vnf_p7_t* vnf_p7 = (vnf_p7_t*)config; vnf_p7_t *vnf_p7 = (vnf_p7_t *)config;
return vnf_p7_pack_and_send_p7_msg(vnf_p7, &req->header); return vnf_p7_pack_and_send_p7_msg(vnf_p7, &req->header);
} }
int nfapi_vnf_p7_vendor_extension(nfapi_vnf_p7_config_t* config, nfapi_p7_message_header_t* header) int nfapi_vnf_p7_vendor_extension(nfapi_vnf_p7_config_t *config, nfapi_p7_message_header_t *header) {
{ if(config == 0 || header == 0)
if(config == 0 || header == 0) return -1;
return -1;
vnf_p7_t* vnf_p7 = (vnf_p7_t*)config; vnf_p7_t *vnf_p7 = (vnf_p7_t *)config;
return vnf_p7_pack_and_send_p7_msg(vnf_p7, header); return vnf_p7_pack_and_send_p7_msg(vnf_p7, header);
} }
int nfapi_vnf_p7_ue_release_req(nfapi_vnf_p7_config_t* config, nfapi_ue_release_request_t* req) int nfapi_vnf_p7_ue_release_req(nfapi_vnf_p7_config_t *config, nfapi_ue_release_request_t *req) {
{ if(config == 0 || req == 0)
if(config == 0 || req == 0) return -1;
return -1;
vnf_p7_t* vnf_p7 = (vnf_p7_t*)config; vnf_p7_t *vnf_p7 = (vnf_p7_t *)config;
return vnf_p7_pack_and_send_p7_msg(vnf_p7, &req->header); return vnf_p7_pack_and_send_p7_msg(vnf_p7, &req->header);
} }
int nfapi_vnf_p7_release_msg(nfapi_vnf_p7_config_t* config, nfapi_p7_message_header_t* header) int nfapi_vnf_p7_release_msg(nfapi_vnf_p7_config_t *config, nfapi_p7_message_header_t *header) {
{ if(config == 0 || header == 0)
if(config == 0 || header == 0) return -1;
return -1;
vnf_p7_t* vnf_p7 = (vnf_p7_t*)config;
vnf_p7_release_msg(vnf_p7, header);
return 0;
vnf_p7_t *vnf_p7 = (vnf_p7_t *)config;
vnf_p7_release_msg(vnf_p7, header);
return 0;
} }
int nfapi_vnf_p7_release_pdu(nfapi_vnf_p7_config_t* config, void* pdu) int nfapi_vnf_p7_release_pdu(nfapi_vnf_p7_config_t *config, void *pdu) {
{ if(config == 0 || pdu == 0)
if(config == 0 || pdu == 0) return -1;
return -1;
vnf_p7_t* vnf_p7 = (vnf_p7_t*)config;
vnf_p7_release_pdu(vnf_p7, pdu);
return 0; vnf_p7_t *vnf_p7 = (vnf_p7_t *)config;
vnf_p7_release_pdu(vnf_p7, pdu);
return 0;
} }
...@@ -35,7 +35,7 @@ static int16_t ru_90c[2*128] = {32767, 0,32766, -402,32758, -804,32746, -1206,32 ...@@ -35,7 +35,7 @@ static int16_t ru_90c[2*128] = {32767, 0,32766, -402,32758, -804,32746, -1206,32
#define SCALE 0x3FFF #define SCALE 0x3FFF
int32_t lte_ul_channel_estimation(PHY_VARS_eNB *eNB, int32_t lte_ul_channel_estimation(PHY_VARS_eNB *eNB,
L1_rxtx_proc_t *proc, L1_rxtx_proc_t *proc,
module_id_t UE_id, module_id_t UE_id,
unsigned char l, unsigned char l,
unsigned char Ns) { unsigned char Ns) {
...@@ -45,46 +45,32 @@ int32_t lte_ul_channel_estimation(PHY_VARS_eNB *eNB, ...@@ -45,46 +45,32 @@ int32_t lte_ul_channel_estimation(PHY_VARS_eNB *eNB,
LTE_eNB_PUSCH *pusch_vars = (eNB!=NULL) ? eNB->pusch_vars[UE_id] : NULL; LTE_eNB_PUSCH *pusch_vars = (eNB!=NULL) ? eNB->pusch_vars[UE_id] : NULL;
RU_CALIBRATION *calibration = &ru->calibration; RU_CALIBRATION *calibration = &ru->calibration;
int32_t **ul_ch_estimates = (eNB!=NULL) ? pusch_vars->drs_ch_estimates : calibration->drs_ch_estimates; int32_t **ul_ch_estimates = (eNB!=NULL) ? pusch_vars->drs_ch_estimates : calibration->drs_ch_estimates;
AssertFatal(ul_ch_estimates != NULL, "ul_ch_estimates is null (eNB %p, pusch %p, pusch->drs_ch_estimates %p, pusch->drs_ch_estimates[0] %p ul_ch_estimates %p UE_id %d)\n",eNB,pusch_vars,
AssertFatal(ul_ch_estimates != NULL, "ul_ch_estimates is null (eNB %p, pusch %p, pusch->drs_ch_estimates %p, pusch->drs_ch_estimates[0] %p ul_ch_estimates %p UE_id %d)\n",eNB,pusch_vars,pusch_vars->drs_ch_estimates,pusch_vars->drs_ch_estimates[0],ul_ch_estimates,UE_id); pusch_vars->drs_ch_estimates,pusch_vars->drs_ch_estimates[0],ul_ch_estimates,UE_id);
int32_t **ul_ch_estimates_time = (eNB!=NULL) ? pusch_vars->drs_ch_estimates_time : calibration->drs_ch_estimates_time; int32_t **ul_ch_estimates_time = (eNB!=NULL) ? pusch_vars->drs_ch_estimates_time : calibration->drs_ch_estimates_time;
AssertFatal(ul_ch_estimates_time != NULL, "ul_ch_estimates_time is null\n"); AssertFatal(ul_ch_estimates_time != NULL, "ul_ch_estimates_time is null\n");
int32_t **rxdataF_ext = (eNB!=NULL) ? pusch_vars->rxdataF_ext : calibration->rxdataF_ext; int32_t **rxdataF_ext = (eNB!=NULL) ? pusch_vars->rxdataF_ext : calibration->rxdataF_ext;
int subframe = (eNB!=NULL) ? proc->subframe_rx : ru->proc.subframe_rx; int subframe = (eNB!=NULL) ? proc->subframe_rx : ru->proc.subframe_rx;
uint8_t harq_pid;
uint8_t harq_pid;
int16_t delta_phase = 0; int16_t delta_phase = 0;
int16_t *ru1 = ru_90; int16_t *ru1 = ru_90;
int16_t *ru2 = ru_90; int16_t *ru2 = ru_90;
int16_t current_phase1,current_phase2; int16_t current_phase1,current_phase2;
uint16_t aa,Msc_RS,Msc_RS_idx; uint16_t aa,Msc_RS,Msc_RS_idx;
uint16_t * Msc_idx_ptr; uint16_t *Msc_idx_ptr;
int k,pilot_pos1 = 3 - frame_parms->Ncp, pilot_pos2 = 10 - 2*frame_parms->Ncp; int k,pilot_pos1 = 3 - frame_parms->Ncp, pilot_pos2 = 10 - 2*frame_parms->Ncp;
int32_t *ul_ch1=NULL, *ul_ch2=NULL; int32_t *ul_ch1=NULL, *ul_ch2=NULL;
int16_t ul_ch_estimates_re,ul_ch_estimates_im; int16_t ul_ch_estimates_re,ul_ch_estimates_im;
//uint8_t nb_antennas_rx = frame_parms->nb_antenna_ports_eNB; //uint8_t nb_antennas_rx = frame_parms->nb_antenna_ports_eNB;
uint8_t nb_antennas_rx = frame_parms->nb_antennas_rx; uint8_t nb_antennas_rx = frame_parms->nb_antennas_rx;
uint8_t cyclic_shift; uint8_t cyclic_shift;
uint32_t alpha_ind; uint32_t alpha_ind;
uint32_t u=frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.grouphop[Ns+(subframe<<1)]; uint32_t u=frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.grouphop[Ns+(subframe<<1)];
uint32_t v=frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[Ns+(subframe<<1)]; uint32_t v=frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[Ns+(subframe<<1)];
int symbol_offset,i; int symbol_offset,i;
//debug_msg("lte_ul_channel_estimation: cyclic shift %d\n",cyclicShift); //debug_msg("lte_ul_channel_estimation: cyclic shift %d\n",cyclicShift);
int16_t alpha_re[12] = {32767, 28377, 16383, 0,-16384, -28378,-32768,-28378,-16384, -1, 16383, 28377}; int16_t alpha_re[12] = {32767, 28377, 16383, 0,-16384, -28378,-32768,-28378,-16384, -1, 16383, 28377};
int16_t alpha_im[12] = {0, 16383, 28377, 32767, 28377, 16383, 0,-16384,-28378,-32768,-28378,-16384}; int16_t alpha_im[12] = {0, 16383, 28377, 32767, 28377, 16383, 0,-16384,-28378,-32768,-28378,-16384};
#if defined(__x86_64__) || defined(__i386__) #if defined(__x86_64__) || defined(__i386__)
__m128i *rxdataF128,*ul_ref128,*ul_ch128; __m128i *rxdataF128,*ul_ref128,*ul_ch128;
__m128i mmtmpU0,mmtmpU1,mmtmpU2,mmtmpU3; __m128i mmtmpU0,mmtmpU1,mmtmpU2,mmtmpU3;
...@@ -92,28 +78,23 @@ int32_t lte_ul_channel_estimation(PHY_VARS_eNB *eNB, ...@@ -92,28 +78,23 @@ int32_t lte_ul_channel_estimation(PHY_VARS_eNB *eNB,
int16x8_t *rxdataF128,*ul_ref128,*ul_ch128; int16x8_t *rxdataF128,*ul_ref128,*ul_ch128;
int32x4_t mmtmp0,mmtmp1,mmtmp_re,mmtmp_im; int32x4_t mmtmp0,mmtmp1,mmtmp_re,mmtmp_im;
#endif #endif
int32_t temp_in_ifft_0[2048*2] __attribute__((aligned(32))); int32_t temp_in_ifft_0[2048*2] __attribute__((aligned(32)));
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) #if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
if (eNB->ulsch[UE_id]->ue_type > NOCE) harq_pid = 0; if (eNB->ulsch[UE_id]->ue_type > NOCE) harq_pid = 0;
else else
#endif #endif
{ {
harq_pid = subframe2harq_pid(frame_parms,proc->frame_rx,subframe); harq_pid = subframe2harq_pid(frame_parms,proc->frame_rx,subframe);
} }
uint16_t N_rb_alloc = eNB->ulsch[UE_id]->harq_processes[harq_pid]->nb_rb; uint16_t N_rb_alloc = eNB->ulsch[UE_id]->harq_processes[harq_pid]->nb_rb;
int32_t tmp_estimates[N_rb_alloc*12] __attribute__((aligned(16))); int32_t tmp_estimates[N_rb_alloc*12] __attribute__((aligned(16)));
Msc_RS = N_rb_alloc*12; Msc_RS = N_rb_alloc*12;
cyclic_shift = (frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift + cyclic_shift = (frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift +
eNB->ulsch[UE_id]->harq_processes[harq_pid]->n_DMRS2 + eNB->ulsch[UE_id]->harq_processes[harq_pid]->n_DMRS2 +
frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[(subframe<<1)+Ns]) % 12; frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[(subframe<<1)+Ns]) % 12;
Msc_idx_ptr = (uint16_t *) bsearch(&Msc_RS, dftsizes, 34, sizeof(uint16_t), compareints);
Msc_idx_ptr = (uint16_t*) bsearch(&Msc_RS, dftsizes, 34, sizeof(uint16_t), compareints);
if (Msc_idx_ptr) if (Msc_idx_ptr)
Msc_RS_idx = Msc_idx_ptr - dftsizes; Msc_RS_idx = Msc_idx_ptr - dftsizes;
...@@ -133,7 +114,6 @@ int32_t lte_ul_channel_estimation(PHY_VARS_eNB *eNB, ...@@ -133,7 +114,6 @@ int32_t lte_ul_channel_estimation(PHY_VARS_eNB *eNB,
#endif #endif
if (l == (3 - frame_parms->Ncp)) { if (l == (3 - frame_parms->Ncp)) {
symbol_offset = frame_parms->N_RB_UL*12*(l+((7-frame_parms->Ncp)*(Ns&1))); symbol_offset = frame_parms->N_RB_UL*12*(l+((7-frame_parms->Ncp)*(Ns&1)));
for (aa=0; aa<nb_antennas_rx; aa++) { for (aa=0; aa<nb_antennas_rx; aa++) {
...@@ -154,14 +134,13 @@ int32_t lte_ul_channel_estimation(PHY_VARS_eNB *eNB, ...@@ -154,14 +134,13 @@ int32_t lte_ul_channel_estimation(PHY_VARS_eNB *eNB,
// mmtmpU0 contains real part of 4 consecutive outputs (32-bit) // mmtmpU0 contains real part of 4 consecutive outputs (32-bit)
mmtmpU1 = _mm_shufflelo_epi16(ul_ref128[0],_MM_SHUFFLE(2,3,0,1)); mmtmpU1 = _mm_shufflelo_epi16(ul_ref128[0],_MM_SHUFFLE(2,3,0,1));
mmtmpU1 = _mm_shufflehi_epi16(mmtmpU1,_MM_SHUFFLE(2,3,0,1)); mmtmpU1 = _mm_shufflehi_epi16(mmtmpU1,_MM_SHUFFLE(2,3,0,1));
mmtmpU1 = _mm_sign_epi16(mmtmpU1,*(__m128i*)&conjugate[0]); mmtmpU1 = _mm_sign_epi16(mmtmpU1,*(__m128i *)&conjugate[0]);
mmtmpU1 = _mm_madd_epi16(mmtmpU1,rxdataF128[0]); mmtmpU1 = _mm_madd_epi16(mmtmpU1,rxdataF128[0]);
// mmtmpU1 contains imag part of 4 consecutive outputs (32-bit) // mmtmpU1 contains imag part of 4 consecutive outputs (32-bit)
mmtmpU0 = _mm_srai_epi32(mmtmpU0,15); mmtmpU0 = _mm_srai_epi32(mmtmpU0,15);
mmtmpU1 = _mm_srai_epi32(mmtmpU1,15); mmtmpU1 = _mm_srai_epi32(mmtmpU1,15);
mmtmpU2 = _mm_unpacklo_epi32(mmtmpU0,mmtmpU1); mmtmpU2 = _mm_unpacklo_epi32(mmtmpU0,mmtmpU1);
mmtmpU3 = _mm_unpackhi_epi32(mmtmpU0,mmtmpU1); mmtmpU3 = _mm_unpackhi_epi32(mmtmpU0,mmtmpU1);
ul_ch128[0] = _mm_packs_epi32(mmtmpU2,mmtmpU3); ul_ch128[0] = _mm_packs_epi32(mmtmpU2,mmtmpU3);
// printf("rb %d ch: %d %d\n",i,((int16_t*)ul_ch128)[0],((int16_t*)ul_ch128)[1]); // printf("rb %d ch: %d %d\n",i,((int16_t*)ul_ch128)[0],((int16_t*)ul_ch128)[1]);
// multiply by conjugated channel // multiply by conjugated channel
...@@ -169,72 +148,63 @@ int32_t lte_ul_channel_estimation(PHY_VARS_eNB *eNB, ...@@ -169,72 +148,63 @@ int32_t lte_ul_channel_estimation(PHY_VARS_eNB *eNB,
// mmtmpU0 contains real part of 4 consecutive outputs (32-bit) // mmtmpU0 contains real part of 4 consecutive outputs (32-bit)
mmtmpU1 = _mm_shufflelo_epi16(ul_ref128[1],_MM_SHUFFLE(2,3,0,1)); mmtmpU1 = _mm_shufflelo_epi16(ul_ref128[1],_MM_SHUFFLE(2,3,0,1));
mmtmpU1 = _mm_shufflehi_epi16(mmtmpU1,_MM_SHUFFLE(2,3,0,1)); mmtmpU1 = _mm_shufflehi_epi16(mmtmpU1,_MM_SHUFFLE(2,3,0,1));
mmtmpU1 = _mm_sign_epi16(mmtmpU1,*(__m128i*)conjugate); mmtmpU1 = _mm_sign_epi16(mmtmpU1,*(__m128i *)conjugate);
mmtmpU1 = _mm_madd_epi16(mmtmpU1,rxdataF128[1]); mmtmpU1 = _mm_madd_epi16(mmtmpU1,rxdataF128[1]);
// mmtmpU1 contains imag part of 4 consecutive outputs (32-bit) // mmtmpU1 contains imag part of 4 consecutive outputs (32-bit)
mmtmpU0 = _mm_srai_epi32(mmtmpU0,15); mmtmpU0 = _mm_srai_epi32(mmtmpU0,15);
mmtmpU1 = _mm_srai_epi32(mmtmpU1,15); mmtmpU1 = _mm_srai_epi32(mmtmpU1,15);
mmtmpU2 = _mm_unpacklo_epi32(mmtmpU0,mmtmpU1); mmtmpU2 = _mm_unpacklo_epi32(mmtmpU0,mmtmpU1);
mmtmpU3 = _mm_unpackhi_epi32(mmtmpU0,mmtmpU1); mmtmpU3 = _mm_unpackhi_epi32(mmtmpU0,mmtmpU1);
ul_ch128[1] = _mm_packs_epi32(mmtmpU2,mmtmpU3); ul_ch128[1] = _mm_packs_epi32(mmtmpU2,mmtmpU3);
mmtmpU0 = _mm_madd_epi16(ul_ref128[2],rxdataF128[2]); mmtmpU0 = _mm_madd_epi16(ul_ref128[2],rxdataF128[2]);
// mmtmpU0 contains real part of 4 consecutive outputs (32-bit) // mmtmpU0 contains real part of 4 consecutive outputs (32-bit)
mmtmpU1 = _mm_shufflelo_epi16(ul_ref128[2],_MM_SHUFFLE(2,3,0,1)); mmtmpU1 = _mm_shufflelo_epi16(ul_ref128[2],_MM_SHUFFLE(2,3,0,1));
mmtmpU1 = _mm_shufflehi_epi16(mmtmpU1,_MM_SHUFFLE(2,3,0,1)); mmtmpU1 = _mm_shufflehi_epi16(mmtmpU1,_MM_SHUFFLE(2,3,0,1));
mmtmpU1 = _mm_sign_epi16(mmtmpU1,*(__m128i*)conjugate); mmtmpU1 = _mm_sign_epi16(mmtmpU1,*(__m128i *)conjugate);
mmtmpU1 = _mm_madd_epi16(mmtmpU1,rxdataF128[2]); mmtmpU1 = _mm_madd_epi16(mmtmpU1,rxdataF128[2]);
// mmtmpU1 contains imag part of 4 consecutive outputs (32-bit) // mmtmpU1 contains imag part of 4 consecutive outputs (32-bit)
mmtmpU0 = _mm_srai_epi32(mmtmpU0,15); mmtmpU0 = _mm_srai_epi32(mmtmpU0,15);
mmtmpU1 = _mm_srai_epi32(mmtmpU1,15); mmtmpU1 = _mm_srai_epi32(mmtmpU1,15);
mmtmpU2 = _mm_unpacklo_epi32(mmtmpU0,mmtmpU1); mmtmpU2 = _mm_unpacklo_epi32(mmtmpU0,mmtmpU1);
mmtmpU3 = _mm_unpackhi_epi32(mmtmpU0,mmtmpU1); mmtmpU3 = _mm_unpackhi_epi32(mmtmpU0,mmtmpU1);
ul_ch128[2] = _mm_packs_epi32(mmtmpU2,mmtmpU3); ul_ch128[2] = _mm_packs_epi32(mmtmpU2,mmtmpU3);
#elif defined(__arm__) #elif defined(__arm__)
mmtmp0 = vmull_s16(((int16x4_t*)ul_ref128)[0],((int16x4_t*)rxdataF128)[0]); mmtmp0 = vmull_s16(((int16x4_t *)ul_ref128)[0],((int16x4_t *)rxdataF128)[0]);
mmtmp1 = vmull_s16(((int16x4_t*)ul_ref128)[1],((int16x4_t*)rxdataF128)[1]); mmtmp1 = vmull_s16(((int16x4_t *)ul_ref128)[1],((int16x4_t *)rxdataF128)[1]);
mmtmp_re = vcombine_s32(vpadd_s32(vget_low_s32(mmtmp0),vget_high_s32(mmtmp0)), mmtmp_re = vcombine_s32(vpadd_s32(vget_low_s32(mmtmp0),vget_high_s32(mmtmp0)),
vpadd_s32(vget_low_s32(mmtmp1),vget_high_s32(mmtmp1))); vpadd_s32(vget_low_s32(mmtmp1),vget_high_s32(mmtmp1)));
mmtmp0 = vmull_s16(vrev32_s16(vmul_s16(((int16x4_t*)ul_ref128)[0],*(int16x4_t*)conjugate)), ((int16x4_t*)rxdataF128)[0]); mmtmp0 = vmull_s16(vrev32_s16(vmul_s16(((int16x4_t *)ul_ref128)[0],*(int16x4_t *)conjugate)), ((int16x4_t *)rxdataF128)[0]);
mmtmp1 = vmull_s16(vrev32_s16(vmul_s16(((int16x4_t*)ul_ref128)[1],*(int16x4_t*)conjugate)), ((int16x4_t*)rxdataF128)[1]); mmtmp1 = vmull_s16(vrev32_s16(vmul_s16(((int16x4_t *)ul_ref128)[1],*(int16x4_t *)conjugate)), ((int16x4_t *)rxdataF128)[1]);
mmtmp_im = vcombine_s32(vpadd_s32(vget_low_s32(mmtmp0),vget_high_s32(mmtmp0)), mmtmp_im = vcombine_s32(vpadd_s32(vget_low_s32(mmtmp0),vget_high_s32(mmtmp0)),
vpadd_s32(vget_low_s32(mmtmp1),vget_high_s32(mmtmp1))); vpadd_s32(vget_low_s32(mmtmp1),vget_high_s32(mmtmp1)));
ul_ch128[0] = vcombine_s16(vmovn_s32(mmtmp_re),vmovn_s32(mmtmp_im));
ul_ch128[0] = vcombine_s16(vmovn_s32(mmtmp_re),vmovn_s32(mmtmp_im)); ul_ch128++;
ul_ch128++; ul_ref128++;
ul_ref128++; rxdataF128++;
rxdataF128++; mmtmp0 = vmull_s16(((int16x4_t *)ul_ref128)[0],((int16x4_t *)rxdataF128)[0]);
mmtmp0 = vmull_s16(((int16x4_t*)ul_ref128)[0],((int16x4_t*)rxdataF128)[0]); mmtmp1 = vmull_s16(((int16x4_t *)ul_ref128)[1],((int16x4_t *)rxdataF128)[1]);
mmtmp1 = vmull_s16(((int16x4_t*)ul_ref128)[1],((int16x4_t*)rxdataF128)[1]); mmtmp_re = vcombine_s32(vpadd_s32(vget_low_s32(mmtmp0),vget_high_s32(mmtmp0)),
mmtmp_re = vcombine_s32(vpadd_s32(vget_low_s32(mmtmp0),vget_high_s32(mmtmp0)), vpadd_s32(vget_low_s32(mmtmp1),vget_high_s32(mmtmp1)));
vpadd_s32(vget_low_s32(mmtmp1),vget_high_s32(mmtmp1))); mmtmp0 = vmull_s16(vrev32_s16(vmul_s16(((int16x4_t *)ul_ref128)[0],*(int16x4_t *)conjugate)), ((int16x4_t *)rxdataF128)[0]);
mmtmp0 = vmull_s16(vrev32_s16(vmul_s16(((int16x4_t*)ul_ref128)[0],*(int16x4_t*)conjugate)), ((int16x4_t*)rxdataF128)[0]); mmtmp1 = vmull_s16(vrev32_s16(vmul_s16(((int16x4_t *)ul_ref128)[1],*(int16x4_t *)conjugate)), ((int16x4_t *)rxdataF128)[1]);
mmtmp1 = vmull_s16(vrev32_s16(vmul_s16(((int16x4_t*)ul_ref128)[1],*(int16x4_t*)conjugate)), ((int16x4_t*)rxdataF128)[1]); mmtmp_im = vcombine_s32(vpadd_s32(vget_low_s32(mmtmp0),vget_high_s32(mmtmp0)),
mmtmp_im = vcombine_s32(vpadd_s32(vget_low_s32(mmtmp0),vget_high_s32(mmtmp0)), vpadd_s32(vget_low_s32(mmtmp1),vget_high_s32(mmtmp1)));
vpadd_s32(vget_low_s32(mmtmp1),vget_high_s32(mmtmp1))); ul_ch128[0] = vcombine_s16(vmovn_s32(mmtmp_re),vmovn_s32(mmtmp_im));
ul_ch128++;
ul_ch128[0] = vcombine_s16(vmovn_s32(mmtmp_re),vmovn_s32(mmtmp_im)); ul_ref128++;
ul_ch128++; rxdataF128++;
ul_ref128++; mmtmp0 = vmull_s16(((int16x4_t *)ul_ref128)[0],((int16x4_t *)rxdataF128)[0]);
rxdataF128++; mmtmp1 = vmull_s16(((int16x4_t *)ul_ref128)[1],((int16x4_t *)rxdataF128)[1]);
mmtmp_re = vcombine_s32(vpadd_s32(vget_low_s32(mmtmp0),vget_high_s32(mmtmp0)),
mmtmp0 = vmull_s16(((int16x4_t*)ul_ref128)[0],((int16x4_t*)rxdataF128)[0]); vpadd_s32(vget_low_s32(mmtmp1),vget_high_s32(mmtmp1)));
mmtmp1 = vmull_s16(((int16x4_t*)ul_ref128)[1],((int16x4_t*)rxdataF128)[1]); mmtmp0 = vmull_s16(vrev32_s16(vmul_s16(((int16x4_t *)ul_ref128)[0],*(int16x4_t *)conjugate)), ((int16x4_t *)rxdataF128)[0]);
mmtmp_re = vcombine_s32(vpadd_s32(vget_low_s32(mmtmp0),vget_high_s32(mmtmp0)), mmtmp1 = vmull_s16(vrev32_s16(vmul_s16(((int16x4_t *)ul_ref128)[1],*(int16x4_t *)conjugate)), ((int16x4_t *)rxdataF128)[1]);
vpadd_s32(vget_low_s32(mmtmp1),vget_high_s32(mmtmp1))); mmtmp_im = vcombine_s32(vpadd_s32(vget_low_s32(mmtmp0),vget_high_s32(mmtmp0)),
mmtmp0 = vmull_s16(vrev32_s16(vmul_s16(((int16x4_t*)ul_ref128)[0],*(int16x4_t*)conjugate)), ((int16x4_t*)rxdataF128)[0]); vpadd_s32(vget_low_s32(mmtmp1),vget_high_s32(mmtmp1)));
mmtmp1 = vmull_s16(vrev32_s16(vmul_s16(((int16x4_t*)ul_ref128)[1],*(int16x4_t*)conjugate)), ((int16x4_t*)rxdataF128)[1]); ul_ch128[0] = vcombine_s16(vmovn_s32(mmtmp_re),vmovn_s32(mmtmp_im));
mmtmp_im = vcombine_s32(vpadd_s32(vget_low_s32(mmtmp0),vget_high_s32(mmtmp0)), ul_ch128++;
vpadd_s32(vget_low_s32(mmtmp1),vget_high_s32(mmtmp1))); ul_ref128++;
rxdataF128++;
ul_ch128[0] = vcombine_s16(vmovn_s32(mmtmp_re),vmovn_s32(mmtmp_im));
ul_ch128++;
ul_ref128++;
rxdataF128++;
#endif #endif
ul_ch128+=3; ul_ch128+=3;
ul_ref128+=3; ul_ref128+=3;
...@@ -250,18 +220,16 @@ int32_t lte_ul_channel_estimation(PHY_VARS_eNB *eNB, ...@@ -250,18 +220,16 @@ int32_t lte_ul_channel_estimation(PHY_VARS_eNB *eNB,
#endif #endif
for(i=symbol_offset; i<symbol_offset+Msc_RS; i++) { for(i=symbol_offset; i<symbol_offset+Msc_RS; i++) {
ul_ch_estimates_re = ((int16_t*) ul_ch_estimates[aa])[i<<1]; ul_ch_estimates_re = ((int16_t *) ul_ch_estimates[aa])[i<<1];
ul_ch_estimates_im = ((int16_t*) ul_ch_estimates[aa])[(i<<1)+1]; ul_ch_estimates_im = ((int16_t *) ul_ch_estimates[aa])[(i<<1)+1];
// ((int16_t*) ul_ch_estimates[aa])[i<<1] = (i%2 == 1? 1:-1) * ul_ch_estimates_re; // ((int16_t*) ul_ch_estimates[aa])[i<<1] = (i%2 == 1? 1:-1) * ul_ch_estimates_re;
((int16_t*) ul_ch_estimates[aa])[i<<1] = ((int16_t *) ul_ch_estimates[aa])[i<<1] =
(int16_t) (((int32_t) (alpha_re[alpha_ind]) * (int32_t) (ul_ch_estimates_re) + (int16_t) (((int32_t) (alpha_re[alpha_ind]) * (int32_t) (ul_ch_estimates_re) +
(int32_t) (alpha_im[alpha_ind]) * (int32_t) (ul_ch_estimates_im))>>15); (int32_t) (alpha_im[alpha_ind]) * (int32_t) (ul_ch_estimates_im))>>15);
//((int16_t*) ul_ch_estimates[aa])[(i<<1)+1] = (i%2 == 1? 1:-1) * ul_ch_estimates_im; //((int16_t*) ul_ch_estimates[aa])[(i<<1)+1] = (i%2 == 1? 1:-1) * ul_ch_estimates_im;
((int16_t*) ul_ch_estimates[aa])[(i<<1)+1] = ((int16_t *) ul_ch_estimates[aa])[(i<<1)+1] =
(int16_t) (((int32_t) (alpha_re[alpha_ind]) * (int32_t) (ul_ch_estimates_im) - (int16_t) (((int32_t) (alpha_re[alpha_ind]) * (int32_t) (ul_ch_estimates_im) -
(int32_t) (alpha_im[alpha_ind]) * (int32_t) (ul_ch_estimates_re))>>15); (int32_t) (alpha_im[alpha_ind]) * (int32_t) (ul_ch_estimates_re))>>15);
alpha_ind+=cyclic_shift; alpha_ind+=cyclic_shift;
if (alpha_ind>11) if (alpha_ind>11)
...@@ -275,39 +243,44 @@ int32_t lte_ul_channel_estimation(PHY_VARS_eNB *eNB, ...@@ -275,39 +243,44 @@ int32_t lte_ul_channel_estimation(PHY_VARS_eNB *eNB,
// Convert to time domain for visualization // Convert to time domain for visualization
memset(temp_in_ifft_0,0,frame_parms->ofdm_symbol_size*sizeof(int32_t)); memset(temp_in_ifft_0,0,frame_parms->ofdm_symbol_size*sizeof(int32_t));
for(i=0; i<Msc_RS; i++) for(i=0; i<Msc_RS; i++)
((int32_t*)temp_in_ifft_0)[i] = ul_ch_estimates[aa][symbol_offset+i]; ((int32_t *)temp_in_ifft_0)[i] = ul_ch_estimates[aa][symbol_offset+i];
switch(frame_parms->N_RB_DL) { switch(frame_parms->N_RB_DL) {
case 6: case 6:
idft128((int16_t*) temp_in_ifft_0, idft128((int16_t *) temp_in_ifft_0,
(int16_t*) ul_ch_estimates_time[aa], (int16_t *) ul_ch_estimates_time[aa],
1); 1);
break; break;
case 25:
idft512((int16_t*) temp_in_ifft_0, case 25:
(int16_t*) ul_ch_estimates_time[aa], idft512((int16_t *) temp_in_ifft_0,
1); (int16_t *) ul_ch_estimates_time[aa],
break; 1);
case 50: break;
idft1024((int16_t*) temp_in_ifft_0,
(int16_t*) ul_ch_estimates_time[aa], case 50:
1); idft1024((int16_t *) temp_in_ifft_0,
break; (int16_t *) ul_ch_estimates_time[aa],
case 100: 1);
idft2048((int16_t*) temp_in_ifft_0, break;
(int16_t*) ul_ch_estimates_time[aa],
1); case 100:
break; idft2048((int16_t *) temp_in_ifft_0,
(int16_t *) ul_ch_estimates_time[aa],
1);
break;
} }
#if T_TRACER #if T_TRACER
if (aa == 0) if (aa == 0)
T(T_ENB_PHY_UL_CHANNEL_ESTIMATE, T_INT(0), T_INT(eNB->ulsch[UE_id]->rnti), T(T_ENB_PHY_UL_CHANNEL_ESTIMATE, T_INT(0), T_INT(eNB->ulsch[UE_id]->rnti),
T_INT(proc->frame_rx), T_INT(subframe), T_INT(proc->frame_rx), T_INT(subframe),
T_INT(0), T_BUFFER(ul_ch_estimates_time[0], 512 * 4)); T_INT(0), T_BUFFER(ul_ch_estimates_time[0], 512 * 4));
#endif
#endif
#ifdef DEBUG_CH #ifdef DEBUG_CH
if (aa==1) { if (aa==1) {
...@@ -321,151 +294,122 @@ int32_t lte_ul_channel_estimation(PHY_VARS_eNB *eNB, ...@@ -321,151 +294,122 @@ int32_t lte_ul_channel_estimation(PHY_VARS_eNB *eNB,
#endif #endif
if (Ns&1) {//we are in the second slot of the sub-frame, so do the interpolation
ul_ch1 = &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*pilot_pos1];
ul_ch2 = &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*pilot_pos2];
if (Ns&1) {//we are in the second slot of the sub-frame, so do the interpolation // Estimation of phase difference between the 2 channel estimates
delta_phase = lte_ul_freq_offset_estimation(frame_parms,
ul_ch1 = &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*pilot_pos1]; ul_ch_estimates[aa],
ul_ch2 = &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*pilot_pos2]; N_rb_alloc);
// negative phase index indicates negative Im of ru
// msg("delta_phase: %d\n",delta_phase);
// Estimation of phase difference between the 2 channel estimates
delta_phase = lte_ul_freq_offset_estimation(frame_parms,
ul_ch_estimates[aa],
N_rb_alloc);
// negative phase index indicates negative Im of ru
// msg("delta_phase: %d\n",delta_phase);
#ifdef DEBUG_CH #ifdef DEBUG_CH
LOG_D(PHY,"lte_ul_channel_estimation: ul_ch1 = %p, ul_ch2 = %p, pilot_pos1=%d, pilot_pos2=%d\n",ul_ch1, ul_ch2, pilot_pos1,pilot_pos2); LOG_D(PHY,"lte_ul_channel_estimation: ul_ch1 = %p, ul_ch2 = %p, pilot_pos1=%d, pilot_pos2=%d\n",ul_ch1, ul_ch2, pilot_pos1,pilot_pos2);
#endif #endif
for (k=0; k<frame_parms->symbols_per_tti; k++) { for (k=0; k<frame_parms->symbols_per_tti; k++) {
// we scale alpha and beta by SCALE (instead of 0x7FFF) to avoid overflows
// we scale alpha and beta by SCALE (instead of 0x7FFF) to avoid overflows // alpha = (int16_t) (((int32_t) SCALE * (int32_t) (pilot_pos2-k))/(pilot_pos2-pilot_pos1));
// alpha = (int16_t) (((int32_t) SCALE * (int32_t) (pilot_pos2-k))/(pilot_pos2-pilot_pos1)); // beta = (int16_t) (((int32_t) SCALE * (int32_t) (k-pilot_pos1))/(pilot_pos2-pilot_pos1));
// beta = (int16_t) (((int32_t) SCALE * (int32_t) (k-pilot_pos1))/(pilot_pos2-pilot_pos1));
#ifdef DEBUG_CH #ifdef DEBUG_CH
LOG_D(PHY,"lte_ul_channel_estimation: k=%d, alpha = %d, beta = %d\n",k,alpha,beta); LOG_D(PHY,"lte_ul_channel_estimation: k=%d, alpha = %d, beta = %d\n",k,alpha,beta);
#endif #endif
//symbol_offset_subframe = frame_parms->N_RB_UL*12*k; //symbol_offset_subframe = frame_parms->N_RB_UL*12*k;
// interpolate between estimates
if ((k != pilot_pos1) && (k != pilot_pos2)) {
// multadd_complex_vector_real_scalar((int16_t*) ul_ch1,alpha,(int16_t*) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],1,Msc_RS);
// multadd_complex_vector_real_scalar((int16_t*) ul_ch2,beta ,(int16_t*) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],0,Msc_RS);
// multadd_complex_vector_real_scalar((int16_t*) ul_ch1,SCALE,(int16_t*) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],1,Msc_RS);
// multadd_complex_vector_real_scalar((int16_t*) ul_ch2,SCALE,(int16_t*) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],0,Msc_RS);
// msg("phase = %d\n",ru[2*cmax(((delta_phase/7)*(k-3)),0)]);
// the phase is linearly interpolated
current_phase1 = (delta_phase/7)*(k-pilot_pos1);
current_phase2 = (delta_phase/7)*(k-pilot_pos2);
// msg("sym: %d, current_phase1: %d, current_phase2: %d\n",k,current_phase1,current_phase2);
// set the right quadrant
(current_phase1 > 0) ? (ru1 = ru_90) : (ru1 = ru_90c);
(current_phase2 > 0) ? (ru2 = ru_90) : (ru2 = ru_90c);
// take absolute value and clip
current_phase1 = cmin(abs(current_phase1),127);
current_phase2 = cmin(abs(current_phase2),127);
// msg("sym: %d, current_phase1: %d, ru: %d + j%d, current_phase2: %d, ru: %d + j%d\n",k,current_phase1,ru1[2*current_phase1],ru1[2*current_phase1+1],current_phase2,ru2[2*current_phase2],ru2[2*current_phase2+1]);
// rotate channel estimates by estimated phase
rotate_cpx_vector((int16_t*) ul_ch1,
&ru1[2*current_phase1],
(int16_t*) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],
Msc_RS,
15);
rotate_cpx_vector((int16_t*) ul_ch2,
&ru2[2*current_phase2],
(int16_t*) &tmp_estimates[0],
Msc_RS,
15);
// Combine the two rotated estimates
multadd_complex_vector_real_scalar((int16_t*) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],SCALE,(int16_t*) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],1,Msc_RS);
multadd_complex_vector_real_scalar((int16_t*) &tmp_estimates[0],SCALE,(int16_t*) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],0,Msc_RS);
/*
if ((k<pilot_pos1) || ((k>pilot_pos2))) {
multadd_complex_vector_real_scalar((int16_t*) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],SCALE>>1,(int16_t*) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],1,Msc_RS);
multadd_complex_vector_real_scalar((int16_t*) &tmp_estimates[0],SCALE>>1,(int16_t*) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],0,Msc_RS);
} else {
multadd_complex_vector_real_scalar((int16_t*) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],SCALE>>1,(int16_t*) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],1,Msc_RS);
multadd_complex_vector_real_scalar((int16_t*) &tmp_estimates[0],SCALE>>1,(int16_t*) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],0,Msc_RS);
// multadd_complex_vector_real_scalar((int16_t*) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],alpha,(int16_t*) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],1,Msc_RS);
// multadd_complex_vector_real_scalar((int16_t*) &tmp_estimates[0],beta ,(int16_t*) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],0,Msc_RS);
}
*/
// memcpy(&ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],ul_ch1,Msc_RS*sizeof(int32_t));
}
} //for(k=...
// because of the scaling of alpha and beta we also need to scale the final channel estimate at the pilot positions
// multadd_complex_vector_real_scalar((int16_t*) ul_ch1,SCALE,(int16_t*) ul_ch1,1,Msc_RS);
// multadd_complex_vector_real_scalar((int16_t*) ul_ch2,SCALE,(int16_t*) ul_ch2,1,Msc_RS);
} //if (Ns&1)
// interpolate between estimates
if ((k != pilot_pos1) && (k != pilot_pos2)) {
// multadd_complex_vector_real_scalar((int16_t*) ul_ch1,alpha,(int16_t*) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],1,Msc_RS);
// multadd_complex_vector_real_scalar((int16_t*) ul_ch2,beta ,(int16_t*) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],0,Msc_RS);
// multadd_complex_vector_real_scalar((int16_t*) ul_ch1,SCALE,(int16_t*) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],1,Msc_RS);
// multadd_complex_vector_real_scalar((int16_t*) ul_ch2,SCALE,(int16_t*) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],0,Msc_RS);
// msg("phase = %d\n",ru[2*cmax(((delta_phase/7)*(k-3)),0)]);
// the phase is linearly interpolated
current_phase1 = (delta_phase/7)*(k-pilot_pos1);
current_phase2 = (delta_phase/7)*(k-pilot_pos2);
// msg("sym: %d, current_phase1: %d, current_phase2: %d\n",k,current_phase1,current_phase2);
// set the right quadrant
(current_phase1 > 0) ? (ru1 = ru_90) : (ru1 = ru_90c);
(current_phase2 > 0) ? (ru2 = ru_90) : (ru2 = ru_90c);
// take absolute value and clip
current_phase1 = cmin(abs(current_phase1),127);
current_phase2 = cmin(abs(current_phase2),127);
// msg("sym: %d, current_phase1: %d, ru: %d + j%d, current_phase2: %d, ru: %d + j%d\n",k,current_phase1,ru1[2*current_phase1],ru1[2*current_phase1+1],current_phase2,ru2[2*current_phase2],ru2[2*current_phase2+1]);
// rotate channel estimates by estimated phase
rotate_cpx_vector((int16_t *) ul_ch1,
&ru1[2*current_phase1],
(int16_t *) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],
Msc_RS,
15);
rotate_cpx_vector((int16_t *) ul_ch2,
&ru2[2*current_phase2],
(int16_t *) &tmp_estimates[0],
Msc_RS,
15);
// Combine the two rotated estimates
multadd_complex_vector_real_scalar((int16_t *) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],SCALE,(int16_t *) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],1,Msc_RS);
multadd_complex_vector_real_scalar((int16_t *) &tmp_estimates[0],SCALE,(int16_t *) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],0,Msc_RS);
/*
if ((k<pilot_pos1) || ((k>pilot_pos2))) {
multadd_complex_vector_real_scalar((int16_t*) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],SCALE>>1,(int16_t*) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],1,Msc_RS);
multadd_complex_vector_real_scalar((int16_t*) &tmp_estimates[0],SCALE>>1,(int16_t*) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],0,Msc_RS);
} else {
multadd_complex_vector_real_scalar((int16_t*) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],SCALE>>1,(int16_t*) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],1,Msc_RS);
multadd_complex_vector_real_scalar((int16_t*) &tmp_estimates[0],SCALE>>1,(int16_t*) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],0,Msc_RS);
// multadd_complex_vector_real_scalar((int16_t*) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],alpha,(int16_t*) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],1,Msc_RS);
// multadd_complex_vector_real_scalar((int16_t*) &tmp_estimates[0],beta ,(int16_t*) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],0,Msc_RS);
}
*/
// memcpy(&ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],ul_ch1,Msc_RS*sizeof(int32_t));
}
} //for(k=...
// because of the scaling of alpha and beta we also need to scale the final channel estimate at the pilot positions
// multadd_complex_vector_real_scalar((int16_t*) ul_ch1,SCALE,(int16_t*) ul_ch1,1,Msc_RS);
// multadd_complex_vector_real_scalar((int16_t*) ul_ch2,SCALE,(int16_t*) ul_ch2,1,Msc_RS);
} //if (Ns&1)
} //for(aa=... } //for(aa=...
} //if(l==... } //if(l==...
return(0); return(0);
} }
int32_t lte_ul_channel_estimation_RRU(LTE_DL_FRAME_PARMS *frame_parms, int32_t lte_ul_channel_estimation_RRU(LTE_DL_FRAME_PARMS *frame_parms,
int32_t **ul_ch_estimates, int32_t **ul_ch_estimates,
int32_t **ul_ch_estimates_time, int32_t **ul_ch_estimates_time,
int32_t **rxdataF_ext, int32_t **rxdataF_ext,
int N_rb_alloc, int N_rb_alloc,
int frame_rx, int frame_rx,
int subframe_rx, int subframe_rx,
uint32_t u, uint32_t u,
uint32_t v, uint32_t v,
uint32_t cyclic_shift, uint32_t cyclic_shift,
unsigned char l, unsigned char l,
int interpolate, int interpolate,
uint16_t rnti) { uint16_t rnti) {
int16_t delta_phase = 0; int16_t delta_phase = 0;
int16_t *ru1 = ru_90; int16_t *ru1 = ru_90;
int16_t *ru2 = ru_90; int16_t *ru2 = ru_90;
int16_t current_phase1,current_phase2; int16_t current_phase1,current_phase2;
uint16_t aa,Msc_RS,Msc_RS_idx; uint16_t aa,Msc_RS,Msc_RS_idx;
uint16_t * Msc_idx_ptr; uint16_t *Msc_idx_ptr;
int k,pilot_pos1 = 3 - frame_parms->Ncp, pilot_pos2 = 10 - 2*frame_parms->Ncp; int k,pilot_pos1 = 3 - frame_parms->Ncp, pilot_pos2 = 10 - 2*frame_parms->Ncp;
int32_t *ul_ch1=NULL, *ul_ch2=NULL; int32_t *ul_ch1=NULL, *ul_ch2=NULL;
int16_t ul_ch_estimates_re,ul_ch_estimates_im; int16_t ul_ch_estimates_re,ul_ch_estimates_im;
uint8_t nb_antennas_rx = frame_parms->nb_antennas_rx; uint8_t nb_antennas_rx = frame_parms->nb_antennas_rx;
uint32_t alpha_ind; uint32_t alpha_ind;
int32_t tmp_estimates[N_rb_alloc*12] __attribute__((aligned(16))); int32_t tmp_estimates[N_rb_alloc*12] __attribute__((aligned(16)));
int symbol_offset,i; int symbol_offset,i;
//debug_msg("lte_ul_channel_estimation_RRU: cyclic shift %d\n",cyclicShift); //debug_msg("lte_ul_channel_estimation_RRU: cyclic shift %d\n",cyclicShift);
int16_t alpha_re[12] = {32767, 28377, 16383, 0,-16384, -28378,-32768,-28378,-16384, -1, 16383, 28377}; int16_t alpha_re[12] = {32767, 28377, 16383, 0,-16384, -28378,-32768,-28378,-16384, -1, 16383, 28377};
int16_t alpha_im[12] = {0, 16383, 28377, 32767, 28377, 16383, 0,-16384,-28378,-32768,-28378,-16384}; int16_t alpha_im[12] = {0, 16383, 28377, 32767, 28377, 16383, 0,-16384,-28378,-32768,-28378,-16384};
#if defined(__x86_64__) || defined(__i386__) #if defined(__x86_64__) || defined(__i386__)
__m128i *rxdataF128,*ul_ref128,*ul_ch128; __m128i *rxdataF128,*ul_ref128,*ul_ch128;
__m128i mmtmpU0,mmtmpU1,mmtmpU2,mmtmpU3; __m128i mmtmpU0,mmtmpU1,mmtmpU2,mmtmpU3;
...@@ -473,18 +417,14 @@ int32_t lte_ul_channel_estimation_RRU(LTE_DL_FRAME_PARMS *frame_parms, ...@@ -473,18 +417,14 @@ int32_t lte_ul_channel_estimation_RRU(LTE_DL_FRAME_PARMS *frame_parms,
int16x8_t *rxdataF128,*ul_ref128,*ul_ch128; int16x8_t *rxdataF128,*ul_ref128,*ul_ch128;
int32x4_t mmtmp0,mmtmp1,mmtmp_re,mmtmp_im; int32x4_t mmtmp0,mmtmp1,mmtmp_re,mmtmp_im;
#endif #endif
int32_t temp_in_ifft_0[2048*2] __attribute__((aligned(32))); int32_t temp_in_ifft_0[2048*2] __attribute__((aligned(32)));
AssertFatal(l==pilot_pos1 || l==pilot_pos2,"%d is not a valid symbol for DMRS, should be %d or %d\n", AssertFatal(l==pilot_pos1 || l==pilot_pos2,"%d is not a valid symbol for DMRS, should be %d or %d\n",
l,pilot_pos1,pilot_pos2); l,pilot_pos1,pilot_pos2);
Msc_RS = N_rb_alloc*12; Msc_RS = N_rb_alloc*12;
/* /*
*/ */
Msc_idx_ptr = (uint16_t *) bsearch(&Msc_RS, dftsizes, 33, sizeof(uint16_t), compareints);
Msc_idx_ptr = (uint16_t*) bsearch(&Msc_RS, dftsizes, 33, sizeof(uint16_t), compareints);
if (Msc_idx_ptr) if (Msc_idx_ptr)
Msc_RS_idx = Msc_idx_ptr - dftsizes; Msc_RS_idx = Msc_idx_ptr - dftsizes;
...@@ -492,19 +432,19 @@ int32_t lte_ul_channel_estimation_RRU(LTE_DL_FRAME_PARMS *frame_parms, ...@@ -492,19 +432,19 @@ int32_t lte_ul_channel_estimation_RRU(LTE_DL_FRAME_PARMS *frame_parms,
LOG_E(PHY,"lte_ul_channel_estimation_RRU: index for Msc_RS=%d not found\n",Msc_RS); LOG_E(PHY,"lte_ul_channel_estimation_RRU: index for Msc_RS=%d not found\n",Msc_RS);
return(-1); return(-1);
} }
LOG_D(PHY,"subframe %d, l %d, Msc_RS = %d, Msc_RS_idx = %d, u %d, v %d, cyclic_shift %d\n",subframe_rx,l,Msc_RS, Msc_RS_idx,u,v,cyclic_shift); LOG_D(PHY,"subframe %d, l %d, Msc_RS = %d, Msc_RS_idx = %d, u %d, v %d, cyclic_shift %d\n",subframe_rx,l,Msc_RS, Msc_RS_idx,u,v,cyclic_shift);
#ifdef DEBUG_CH #ifdef DEBUG_CH
if (l==pilot_pos1) if (l==pilot_pos1)
write_output("drs_seq0.m","drsseq0",ul_ref_sigs_rx[u][v][Msc_RS_idx],Msc_RS,1,1); write_output("drs_seq0.m","drsseq0",ul_ref_sigs_rx[u][v][Msc_RS_idx],Msc_RS,1,1);
else else
write_output("drs_seq1.m","drsseq1",ul_ref_sigs_rx[u][v][Msc_RS_idx],Msc_RS,1,1); write_output("drs_seq1.m","drsseq1",ul_ref_sigs_rx[u][v][Msc_RS_idx],Msc_RS,1,1);
#endif #endif
symbol_offset = frame_parms->N_RB_UL*12*l; symbol_offset = frame_parms->N_RB_UL*12*l;
for (aa=0; aa<nb_antennas_rx; aa++) { for (aa=0; aa<nb_antennas_rx; aa++) {
#if defined(__x86_64__) || defined(__i386__) #if defined(__x86_64__) || defined(__i386__)
rxdataF128 = (__m128i *)&rxdataF_ext[aa][symbol_offset]; rxdataF128 = (__m128i *)&rxdataF_ext[aa][symbol_offset];
ul_ch128 = (__m128i *)&ul_ch_estimates[aa][symbol_offset]; ul_ch128 = (__m128i *)&ul_ch_estimates[aa][symbol_offset];
...@@ -514,7 +454,7 @@ int32_t lte_ul_channel_estimation_RRU(LTE_DL_FRAME_PARMS *frame_parms, ...@@ -514,7 +454,7 @@ int32_t lte_ul_channel_estimation_RRU(LTE_DL_FRAME_PARMS *frame_parms,
ul_ch128 = (int16x8_t *)&ul_ch_estimates[aa][symbol_offset]; ul_ch128 = (int16x8_t *)&ul_ch_estimates[aa][symbol_offset];
ul_ref128 = (int16x8_t *)ul_ref_sigs_rx[u][v][Msc_RS_idx]; ul_ref128 = (int16x8_t *)ul_ref_sigs_rx[u][v][Msc_RS_idx];
#endif #endif
for (i=0; i<Msc_RS/12; i++) { for (i=0; i<Msc_RS/12; i++) {
#if defined(__x86_64__) || defined(__i386__) #if defined(__x86_64__) || defined(__i386__)
// multiply by conjugated channel // multiply by conjugated channel
...@@ -522,14 +462,13 @@ int32_t lte_ul_channel_estimation_RRU(LTE_DL_FRAME_PARMS *frame_parms, ...@@ -522,14 +462,13 @@ int32_t lte_ul_channel_estimation_RRU(LTE_DL_FRAME_PARMS *frame_parms,
// mmtmpU0 contains real part of 4 consecutive outputs (32-bit) // mmtmpU0 contains real part of 4 consecutive outputs (32-bit)
mmtmpU1 = _mm_shufflelo_epi16(ul_ref128[0],_MM_SHUFFLE(2,3,0,1)); mmtmpU1 = _mm_shufflelo_epi16(ul_ref128[0],_MM_SHUFFLE(2,3,0,1));
mmtmpU1 = _mm_shufflehi_epi16(mmtmpU1,_MM_SHUFFLE(2,3,0,1)); mmtmpU1 = _mm_shufflehi_epi16(mmtmpU1,_MM_SHUFFLE(2,3,0,1));
mmtmpU1 = _mm_sign_epi16(mmtmpU1,*(__m128i*)&conjugate[0]); mmtmpU1 = _mm_sign_epi16(mmtmpU1,*(__m128i *)&conjugate[0]);
mmtmpU1 = _mm_madd_epi16(mmtmpU1,rxdataF128[0]); mmtmpU1 = _mm_madd_epi16(mmtmpU1,rxdataF128[0]);
// mmtmpU1 contains imag part of 4 consecutive outputs (32-bit) // mmtmpU1 contains imag part of 4 consecutive outputs (32-bit)
mmtmpU0 = _mm_srai_epi32(mmtmpU0,15); mmtmpU0 = _mm_srai_epi32(mmtmpU0,15);
mmtmpU1 = _mm_srai_epi32(mmtmpU1,15); mmtmpU1 = _mm_srai_epi32(mmtmpU1,15);
mmtmpU2 = _mm_unpacklo_epi32(mmtmpU0,mmtmpU1); mmtmpU2 = _mm_unpacklo_epi32(mmtmpU0,mmtmpU1);
mmtmpU3 = _mm_unpackhi_epi32(mmtmpU0,mmtmpU1); mmtmpU3 = _mm_unpackhi_epi32(mmtmpU0,mmtmpU1);
ul_ch128[0] = _mm_packs_epi32(mmtmpU2,mmtmpU3); ul_ch128[0] = _mm_packs_epi32(mmtmpU2,mmtmpU3);
// printf("rb %d ch: %d %d\n",i,((int16_t*)ul_ch128)[0],((int16_t*)ul_ch128)[1]); // printf("rb %d ch: %d %d\n",i,((int16_t*)ul_ch128)[0],((int16_t*)ul_ch128)[1]);
// multiply by conjugated channel // multiply by conjugated channel
...@@ -537,248 +476,231 @@ int32_t lte_ul_channel_estimation_RRU(LTE_DL_FRAME_PARMS *frame_parms, ...@@ -537,248 +476,231 @@ int32_t lte_ul_channel_estimation_RRU(LTE_DL_FRAME_PARMS *frame_parms,
// mmtmpU0 contains real part of 4 consecutive outputs (32-bit) // mmtmpU0 contains real part of 4 consecutive outputs (32-bit)
mmtmpU1 = _mm_shufflelo_epi16(ul_ref128[1],_MM_SHUFFLE(2,3,0,1)); mmtmpU1 = _mm_shufflelo_epi16(ul_ref128[1],_MM_SHUFFLE(2,3,0,1));
mmtmpU1 = _mm_shufflehi_epi16(mmtmpU1,_MM_SHUFFLE(2,3,0,1)); mmtmpU1 = _mm_shufflehi_epi16(mmtmpU1,_MM_SHUFFLE(2,3,0,1));
mmtmpU1 = _mm_sign_epi16(mmtmpU1,*(__m128i*)conjugate); mmtmpU1 = _mm_sign_epi16(mmtmpU1,*(__m128i *)conjugate);
mmtmpU1 = _mm_madd_epi16(mmtmpU1,rxdataF128[1]); mmtmpU1 = _mm_madd_epi16(mmtmpU1,rxdataF128[1]);
// mmtmpU1 contains imag part of 4 consecutive outputs (32-bit) // mmtmpU1 contains imag part of 4 consecutive outputs (32-bit)
mmtmpU0 = _mm_srai_epi32(mmtmpU0,15); mmtmpU0 = _mm_srai_epi32(mmtmpU0,15);
mmtmpU1 = _mm_srai_epi32(mmtmpU1,15); mmtmpU1 = _mm_srai_epi32(mmtmpU1,15);
mmtmpU2 = _mm_unpacklo_epi32(mmtmpU0,mmtmpU1); mmtmpU2 = _mm_unpacklo_epi32(mmtmpU0,mmtmpU1);
mmtmpU3 = _mm_unpackhi_epi32(mmtmpU0,mmtmpU1); mmtmpU3 = _mm_unpackhi_epi32(mmtmpU0,mmtmpU1);
ul_ch128[1] = _mm_packs_epi32(mmtmpU2,mmtmpU3); ul_ch128[1] = _mm_packs_epi32(mmtmpU2,mmtmpU3);
mmtmpU0 = _mm_madd_epi16(ul_ref128[2],rxdataF128[2]); mmtmpU0 = _mm_madd_epi16(ul_ref128[2],rxdataF128[2]);
// mmtmpU0 contains real part of 4 consecutive outputs (32-bit) // mmtmpU0 contains real part of 4 consecutive outputs (32-bit)
mmtmpU1 = _mm_shufflelo_epi16(ul_ref128[2],_MM_SHUFFLE(2,3,0,1)); mmtmpU1 = _mm_shufflelo_epi16(ul_ref128[2],_MM_SHUFFLE(2,3,0,1));
mmtmpU1 = _mm_shufflehi_epi16(mmtmpU1,_MM_SHUFFLE(2,3,0,1)); mmtmpU1 = _mm_shufflehi_epi16(mmtmpU1,_MM_SHUFFLE(2,3,0,1));
mmtmpU1 = _mm_sign_epi16(mmtmpU1,*(__m128i*)conjugate); mmtmpU1 = _mm_sign_epi16(mmtmpU1,*(__m128i *)conjugate);
mmtmpU1 = _mm_madd_epi16(mmtmpU1,rxdataF128[2]); mmtmpU1 = _mm_madd_epi16(mmtmpU1,rxdataF128[2]);
// mmtmpU1 contains imag part of 4 consecutive outputs (32-bit) // mmtmpU1 contains imag part of 4 consecutive outputs (32-bit)
mmtmpU0 = _mm_srai_epi32(mmtmpU0,15); mmtmpU0 = _mm_srai_epi32(mmtmpU0,15);
mmtmpU1 = _mm_srai_epi32(mmtmpU1,15); mmtmpU1 = _mm_srai_epi32(mmtmpU1,15);
mmtmpU2 = _mm_unpacklo_epi32(mmtmpU0,mmtmpU1); mmtmpU2 = _mm_unpacklo_epi32(mmtmpU0,mmtmpU1);
mmtmpU3 = _mm_unpackhi_epi32(mmtmpU0,mmtmpU1); mmtmpU3 = _mm_unpackhi_epi32(mmtmpU0,mmtmpU1);
ul_ch128[2] = _mm_packs_epi32(mmtmpU2,mmtmpU3); ul_ch128[2] = _mm_packs_epi32(mmtmpU2,mmtmpU3);
#elif defined(__arm__) #elif defined(__arm__)
mmtmp0 = vmull_s16(((int16x4_t*)ul_ref128)[0],((int16x4_t*)rxdataF128)[0]); mmtmp0 = vmull_s16(((int16x4_t *)ul_ref128)[0],((int16x4_t *)rxdataF128)[0]);
mmtmp1 = vmull_s16(((int16x4_t*)ul_ref128)[1],((int16x4_t*)rxdataF128)[1]); mmtmp1 = vmull_s16(((int16x4_t *)ul_ref128)[1],((int16x4_t *)rxdataF128)[1]);
mmtmp_re = vcombine_s32(vpadd_s32(vget_low_s32(mmtmp0),vget_high_s32(mmtmp0)), mmtmp_re = vcombine_s32(vpadd_s32(vget_low_s32(mmtmp0),vget_high_s32(mmtmp0)),
vpadd_s32(vget_low_s32(mmtmp1),vget_high_s32(mmtmp1))); vpadd_s32(vget_low_s32(mmtmp1),vget_high_s32(mmtmp1)));
mmtmp0 = vmull_s16(vrev32_s16(vmul_s16(((int16x4_t*)ul_ref128)[0],*(int16x4_t*)conjugate)), ((int16x4_t*)rxdataF128)[0]); mmtmp0 = vmull_s16(vrev32_s16(vmul_s16(((int16x4_t *)ul_ref128)[0],*(int16x4_t *)conjugate)), ((int16x4_t *)rxdataF128)[0]);
mmtmp1 = vmull_s16(vrev32_s16(vmul_s16(((int16x4_t*)ul_ref128)[1],*(int16x4_t*)conjugate)), ((int16x4_t*)rxdataF128)[1]); mmtmp1 = vmull_s16(vrev32_s16(vmul_s16(((int16x4_t *)ul_ref128)[1],*(int16x4_t *)conjugate)), ((int16x4_t *)rxdataF128)[1]);
mmtmp_im = vcombine_s32(vpadd_s32(vget_low_s32(mmtmp0),vget_high_s32(mmtmp0)), mmtmp_im = vcombine_s32(vpadd_s32(vget_low_s32(mmtmp0),vget_high_s32(mmtmp0)),
vpadd_s32(vget_low_s32(mmtmp1),vget_high_s32(mmtmp1))); vpadd_s32(vget_low_s32(mmtmp1),vget_high_s32(mmtmp1)));
ul_ch128[0] = vcombine_s16(vmovn_s32(mmtmp_re),vmovn_s32(mmtmp_im)); ul_ch128[0] = vcombine_s16(vmovn_s32(mmtmp_re),vmovn_s32(mmtmp_im));
ul_ch128++; ul_ch128++;
ul_ref128++; ul_ref128++;
rxdataF128++; rxdataF128++;
mmtmp0 = vmull_s16(((int16x4_t*)ul_ref128)[0],((int16x4_t*)rxdataF128)[0]); mmtmp0 = vmull_s16(((int16x4_t *)ul_ref128)[0],((int16x4_t *)rxdataF128)[0]);
mmtmp1 = vmull_s16(((int16x4_t*)ul_ref128)[1],((int16x4_t*)rxdataF128)[1]); mmtmp1 = vmull_s16(((int16x4_t *)ul_ref128)[1],((int16x4_t *)rxdataF128)[1]);
mmtmp_re = vcombine_s32(vpadd_s32(vget_low_s32(mmtmp0),vget_high_s32(mmtmp0)), mmtmp_re = vcombine_s32(vpadd_s32(vget_low_s32(mmtmp0),vget_high_s32(mmtmp0)),
vpadd_s32(vget_low_s32(mmtmp1),vget_high_s32(mmtmp1))); vpadd_s32(vget_low_s32(mmtmp1),vget_high_s32(mmtmp1)));
mmtmp0 = vmull_s16(vrev32_s16(vmul_s16(((int16x4_t*)ul_ref128)[0],*(int16x4_t*)conjugate)), ((int16x4_t*)rxdataF128)[0]); mmtmp0 = vmull_s16(vrev32_s16(vmul_s16(((int16x4_t *)ul_ref128)[0],*(int16x4_t *)conjugate)), ((int16x4_t *)rxdataF128)[0]);
mmtmp1 = vmull_s16(vrev32_s16(vmul_s16(((int16x4_t*)ul_ref128)[1],*(int16x4_t*)conjugate)), ((int16x4_t*)rxdataF128)[1]); mmtmp1 = vmull_s16(vrev32_s16(vmul_s16(((int16x4_t *)ul_ref128)[1],*(int16x4_t *)conjugate)), ((int16x4_t *)rxdataF128)[1]);
mmtmp_im = vcombine_s32(vpadd_s32(vget_low_s32(mmtmp0),vget_high_s32(mmtmp0)), mmtmp_im = vcombine_s32(vpadd_s32(vget_low_s32(mmtmp0),vget_high_s32(mmtmp0)),
vpadd_s32(vget_low_s32(mmtmp1),vget_high_s32(mmtmp1))); vpadd_s32(vget_low_s32(mmtmp1),vget_high_s32(mmtmp1)));
ul_ch128[0] = vcombine_s16(vmovn_s32(mmtmp_re),vmovn_s32(mmtmp_im)); ul_ch128[0] = vcombine_s16(vmovn_s32(mmtmp_re),vmovn_s32(mmtmp_im));
ul_ch128++; ul_ch128++;
ul_ref128++; ul_ref128++;
rxdataF128++; rxdataF128++;
mmtmp0 = vmull_s16(((int16x4_t *)ul_ref128)[0],((int16x4_t *)rxdataF128)[0]);
mmtmp0 = vmull_s16(((int16x4_t*)ul_ref128)[0],((int16x4_t*)rxdataF128)[0]); mmtmp1 = vmull_s16(((int16x4_t *)ul_ref128)[1],((int16x4_t *)rxdataF128)[1]);
mmtmp1 = vmull_s16(((int16x4_t*)ul_ref128)[1],((int16x4_t*)rxdataF128)[1]);
mmtmp_re = vcombine_s32(vpadd_s32(vget_low_s32(mmtmp0),vget_high_s32(mmtmp0)), mmtmp_re = vcombine_s32(vpadd_s32(vget_low_s32(mmtmp0),vget_high_s32(mmtmp0)),
vpadd_s32(vget_low_s32(mmtmp1),vget_high_s32(mmtmp1))); vpadd_s32(vget_low_s32(mmtmp1),vget_high_s32(mmtmp1)));
mmtmp0 = vmull_s16(vrev32_s16(vmul_s16(((int16x4_t*)ul_ref128)[0],*(int16x4_t*)conjugate)), ((int16x4_t*)rxdataF128)[0]); mmtmp0 = vmull_s16(vrev32_s16(vmul_s16(((int16x4_t *)ul_ref128)[0],*(int16x4_t *)conjugate)), ((int16x4_t *)rxdataF128)[0]);
mmtmp1 = vmull_s16(vrev32_s16(vmul_s16(((int16x4_t*)ul_ref128)[1],*(int16x4_t*)conjugate)), ((int16x4_t*)rxdataF128)[1]); mmtmp1 = vmull_s16(vrev32_s16(vmul_s16(((int16x4_t *)ul_ref128)[1],*(int16x4_t *)conjugate)), ((int16x4_t *)rxdataF128)[1]);
mmtmp_im = vcombine_s32(vpadd_s32(vget_low_s32(mmtmp0),vget_high_s32(mmtmp0)), mmtmp_im = vcombine_s32(vpadd_s32(vget_low_s32(mmtmp0),vget_high_s32(mmtmp0)),
vpadd_s32(vget_low_s32(mmtmp1),vget_high_s32(mmtmp1))); vpadd_s32(vget_low_s32(mmtmp1),vget_high_s32(mmtmp1)));
ul_ch128[0] = vcombine_s16(vmovn_s32(mmtmp_re),vmovn_s32(mmtmp_im)); ul_ch128[0] = vcombine_s16(vmovn_s32(mmtmp_re),vmovn_s32(mmtmp_im));
ul_ch128++; ul_ch128++;
ul_ref128++; ul_ref128++;
rxdataF128++; rxdataF128++;
#endif #endif
ul_ch128+=3; ul_ch128+=3;
ul_ref128+=3; ul_ref128+=3;
rxdataF128+=3; rxdataF128+=3;
} }
alpha_ind = 0; alpha_ind = 0;
if((cyclic_shift != 0)) { if((cyclic_shift != 0)) {
// Compensating for the phase shift introduced at the transmitte // Compensating for the phase shift introduced at the transmitte
#ifdef DEBUG_CH #ifdef DEBUG_CH
write_output("drs_est_pre.m","drsest_pre",ul_ch_estimates[0],300*12,1,1); write_output("drs_est_pre.m","drsest_pre",ul_ch_estimates[0],300*12,1,1);
#endif #endif
for(i=symbol_offset; i<symbol_offset+Msc_RS; i++) { for(i=symbol_offset; i<symbol_offset+Msc_RS; i++) {
ul_ch_estimates_re = ((int16_t*) ul_ch_estimates[aa])[i<<1]; ul_ch_estimates_re = ((int16_t *) ul_ch_estimates[aa])[i<<1];
ul_ch_estimates_im = ((int16_t*) ul_ch_estimates[aa])[(i<<1)+1]; ul_ch_estimates_im = ((int16_t *) ul_ch_estimates[aa])[(i<<1)+1];
// ((int16_t*) ul_ch_estimates[aa])[i<<1] = (i%2 == 1? 1:-1) * ul_ch_estimates_re; // ((int16_t*) ul_ch_estimates[aa])[i<<1] = (i%2 == 1? 1:-1) * ul_ch_estimates_re;
((int16_t*) ul_ch_estimates[aa])[i<<1] = ((int16_t *) ul_ch_estimates[aa])[i<<1] =
(int16_t) (((int32_t) (alpha_re[alpha_ind]) * (int32_t) (ul_ch_estimates_re) + (int16_t) (((int32_t) (alpha_re[alpha_ind]) * (int32_t) (ul_ch_estimates_re) +
(int32_t) (alpha_im[alpha_ind]) * (int32_t) (ul_ch_estimates_im))>>15); (int32_t) (alpha_im[alpha_ind]) * (int32_t) (ul_ch_estimates_im))>>15);
//((int16_t*) ul_ch_estimates[aa])[(i<<1)+1] = (i%2 == 1? 1:-1) * ul_ch_estimates_im;
//((int16_t*) ul_ch_estimates[aa])[(i<<1)+1] = (i%2 == 1? 1:-1) * ul_ch_estimates_im; ((int16_t *) ul_ch_estimates[aa])[(i<<1)+1] =
((int16_t*) ul_ch_estimates[aa])[(i<<1)+1] = (int16_t) (((int32_t) (alpha_re[alpha_ind]) * (int32_t) (ul_ch_estimates_im) -
(int16_t) (((int32_t) (alpha_re[alpha_ind]) * (int32_t) (ul_ch_estimates_im) - (int32_t) (alpha_im[alpha_ind]) * (int32_t) (ul_ch_estimates_re))>>15);
(int32_t) (alpha_im[alpha_ind]) * (int32_t) (ul_ch_estimates_re))>>15); alpha_ind+=cyclic_shift;
alpha_ind+=cyclic_shift; if (alpha_ind>11)
alpha_ind-=12;
if (alpha_ind>11)
alpha_ind-=12;
} }
#ifdef DEBUG_CH #ifdef DEBUG_CH
write_output("drs_est_post.m","drsest_post",ul_ch_estimates[0],300*12,1,1); write_output("drs_est_post.m","drsest_post",ul_ch_estimates[0],300*12,1,1);
#endif #endif
} }
if (ul_ch_estimates_time && ul_ch_estimates_time[aa]) { if (ul_ch_estimates_time && ul_ch_estimates_time[aa]) {
// Convert to time domain for visualization // Convert to time domain for visualization
memset(temp_in_ifft_0,0,frame_parms->ofdm_symbol_size*sizeof(int32_t)); memset(temp_in_ifft_0,0,frame_parms->ofdm_symbol_size*sizeof(int32_t));
for(i=0; i<Msc_RS; i++) for(i=0; i<Msc_RS; i++)
((int32_t*)temp_in_ifft_0)[i] = ul_ch_estimates[aa][symbol_offset+i]; ((int32_t *)temp_in_ifft_0)[i] = ul_ch_estimates[aa][symbol_offset+i];
switch(frame_parms->N_RB_DL) { switch(frame_parms->N_RB_DL) {
case 6: case 6:
idft128((int16_t*) temp_in_ifft_0, idft128((int16_t *) temp_in_ifft_0,
(int16_t*) ul_ch_estimates_time[aa], (int16_t *) ul_ch_estimates_time[aa],
1); 1);
break; break;
case 25:
idft512((int16_t*) temp_in_ifft_0, case 25:
(int16_t*) ul_ch_estimates_time[aa], idft512((int16_t *) temp_in_ifft_0,
1); (int16_t *) ul_ch_estimates_time[aa],
break; 1);
case 50: break;
idft1024((int16_t*) temp_in_ifft_0,
(int16_t*) ul_ch_estimates_time[aa], case 50:
1); idft1024((int16_t *) temp_in_ifft_0,
break; (int16_t *) ul_ch_estimates_time[aa],
case 100: 1);
idft2048((int16_t*) temp_in_ifft_0, break;
(int16_t*) ul_ch_estimates_time[aa],
1); case 100:
break; idft2048((int16_t *) temp_in_ifft_0,
(int16_t *) ul_ch_estimates_time[aa],
1);
break;
} }
#if T_TRACER #if T_TRACER
if (aa == 0) if (aa == 0)
T(T_ENB_PHY_UL_CHANNEL_ESTIMATE, T_INT(0), T_INT(rnti), T(T_ENB_PHY_UL_CHANNEL_ESTIMATE, T_INT(0), T_INT(rnti),
T_INT(frame_rx), T_INT(subframe_rx), T_INT(frame_rx), T_INT(subframe_rx),
T_INT(0), T_BUFFER(ul_ch_estimates_time[0], 512 * 4)); T_INT(0), T_BUFFER(ul_ch_estimates_time[0], 512 * 4));
#endif #endif
} }
#ifdef DEBUG_CH #ifdef DEBUG_CH
if (aa==1) { if (aa==1) {
if (l == pilot_pos1) { if (l == pilot_pos1) {
write_output("rxdataF_ext.m","rxF_ext",&rxdataF_ext[aa][symbol_offset],512*2,2,1); write_output("rxdataF_ext.m","rxF_ext",&rxdataF_ext[aa][symbol_offset],512*2,2,1);
write_output("tmpin_ifft.m","drs_in",temp_in_ifft_0,512,1,1); write_output("tmpin_ifft.m","drs_in",temp_in_ifft_0,512,1,1);
if (ul_ch_estimates_time[aa]) write_output("drs_est0.m","drs0",ul_ch_estimates_time[aa],512,1,1);
} else if (ul_ch_estimates_time[aa]) write_output("drs_est0.m","drs0",ul_ch_estimates_time[aa],512,1,1);
if (ul_ch_estimates_time[aa]) write_output("drs_est1.m","drs1",ul_ch_estimates_time[aa],512,1,1); } else if (ul_ch_estimates_time[aa]) write_output("drs_est1.m","drs1",ul_ch_estimates_time[aa],512,1,1);
} }
#endif #endif
if (l==pilot_pos2 && interpolate==1) {//we are in the second slot of the sub-frame, so do the interpolation if (l==pilot_pos2 && interpolate==1) {//we are in the second slot of the sub-frame, so do the interpolation
ul_ch1 = &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*pilot_pos1]; ul_ch1 = &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*pilot_pos1];
ul_ch2 = &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*pilot_pos2]; ul_ch2 = &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*pilot_pos2];
// Estimation of phase difference between the 2 channel estimates // Estimation of phase difference between the 2 channel estimates
delta_phase = lte_ul_freq_offset_estimation(frame_parms, delta_phase = lte_ul_freq_offset_estimation(frame_parms,
ul_ch_estimates[aa], ul_ch_estimates[aa],
N_rb_alloc); N_rb_alloc);
// negative phase index indicates negative Im of ru // negative phase index indicates negative Im of ru
// msg("delta_phase: %d\n",delta_phase); // msg("delta_phase: %d\n",delta_phase);
#ifdef DEBUG_CH #ifdef DEBUG_CH
LOG_D(PHY,"lte_ul_channel_estimation_RRU: ul_ch1 = %p, ul_ch2 = %p, pilot_pos1=%d, pilot_pos2=%d\n",ul_ch1, ul_ch2, pilot_pos1,pilot_pos2); LOG_D(PHY,"lte_ul_channel_estimation_RRU: ul_ch1 = %p, ul_ch2 = %p, pilot_pos1=%d, pilot_pos2=%d\n",ul_ch1, ul_ch2, pilot_pos1,pilot_pos2);
#endif #endif
for (k=0; k<frame_parms->symbols_per_tti; k++) { for (k=0; k<frame_parms->symbols_per_tti; k++) {
#ifdef DEBUG_CH #ifdef DEBUG_CH
// LOG_D(PHY,"lte_ul_channel_estimation: k=%d, alpha = %d, beta = %d\n",k,alpha,beta); // LOG_D(PHY,"lte_ul_channel_estimation: k=%d, alpha = %d, beta = %d\n",k,alpha,beta);
#endif #endif
//symbol_offset_subframe = frame_parms->N_RB_UL*12*k; //symbol_offset_subframe = frame_parms->N_RB_UL*12*k;
// interpolate between estimates // interpolate between estimates
if ((k != pilot_pos1) && (k != pilot_pos2)) { if ((k != pilot_pos1) && (k != pilot_pos2)) {
// the phase is linearly interpolated
// the phase is linearly interpolated current_phase1 = (delta_phase/7)*(k-pilot_pos1);
current_phase1 = (delta_phase/7)*(k-pilot_pos1); current_phase2 = (delta_phase/7)*(k-pilot_pos2);
current_phase2 = (delta_phase/7)*(k-pilot_pos2); // msg("sym: %d, current_phase1: %d, current_phase2: %d\n",k,current_phase1,current_phase2);
// msg("sym: %d, current_phase1: %d, current_phase2: %d\n",k,current_phase1,current_phase2); // set the right quadrant
// set the right quadrant (current_phase1 > 0) ? (ru1 = ru_90) : (ru1 = ru_90c);
(current_phase1 > 0) ? (ru1 = ru_90) : (ru1 = ru_90c); (current_phase2 > 0) ? (ru2 = ru_90) : (ru2 = ru_90c);
(current_phase2 > 0) ? (ru2 = ru_90) : (ru2 = ru_90c); // take absolute value and clip
// take absolute value and clip current_phase1 = cmin(abs(current_phase1),127);
current_phase1 = cmin(abs(current_phase1),127); current_phase2 = cmin(abs(current_phase2),127);
current_phase2 = cmin(abs(current_phase2),127); // msg("sym: %d, current_phase1: %d, ru: %d + j%d, current_phase2: %d, ru: %d + j%d\n",k,current_phase1,ru1[2*current_phase1],ru1[2*current_phase1+1],current_phase2,ru2[2*current_phase2],ru2[2*current_phase2+1]);
// rotate channel estimates by estimated phase
// msg("sym: %d, current_phase1: %d, ru: %d + j%d, current_phase2: %d, ru: %d + j%d\n",k,current_phase1,ru1[2*current_phase1],ru1[2*current_phase1+1],current_phase2,ru2[2*current_phase2],ru2[2*current_phase2+1]); rotate_cpx_vector((int16_t *) ul_ch1,
&ru1[2*current_phase1],
// rotate channel estimates by estimated phase (int16_t *) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],
rotate_cpx_vector((int16_t*) ul_ch1, Msc_RS,
&ru1[2*current_phase1], 15);
(int16_t*) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k], rotate_cpx_vector((int16_t *) ul_ch2,
Msc_RS, &ru2[2*current_phase2],
15); (int16_t *) &tmp_estimates[0],
Msc_RS,
rotate_cpx_vector((int16_t*) ul_ch2, 15);
&ru2[2*current_phase2], // Combine the two rotated estimates
(int16_t*) &tmp_estimates[0], multadd_complex_vector_real_scalar((int16_t *) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],SCALE,(int16_t *) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],1,Msc_RS);
Msc_RS, multadd_complex_vector_real_scalar((int16_t *) &tmp_estimates[0],SCALE,(int16_t *) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],0,Msc_RS);
15); }
// Combine the two rotated estimates
multadd_complex_vector_real_scalar((int16_t*) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],SCALE,(int16_t*) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],1,Msc_RS);
multadd_complex_vector_real_scalar((int16_t*) &tmp_estimates[0],SCALE,(int16_t*) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],0,Msc_RS);
}
} //for(k=... } //for(k=...
// because of the scaling of alpha and beta we also need to scale the final channel estimate at the pilot positions // because of the scaling of alpha and beta we also need to scale the final channel estimate at the pilot positions
// multadd_complex_vector_real_scalar((int16_t*) ul_ch1,SCALE,(int16_t*) ul_ch1,1,Msc_RS); // multadd_complex_vector_real_scalar((int16_t*) ul_ch1,SCALE,(int16_t*) ul_ch1,1,Msc_RS);
// multadd_complex_vector_real_scalar((int16_t*) ul_ch2,SCALE,(int16_t*) ul_ch2,1,Msc_RS); // multadd_complex_vector_real_scalar((int16_t*) ul_ch2,SCALE,(int16_t*) ul_ch2,1,Msc_RS);
} //if (Ns&1 && interpolate==1) } //if (Ns&1 && interpolate==1)
else if (interpolate == 0 && l == pilot_pos1) else if (interpolate == 0 && l == pilot_pos1)
for (k=0;k<frame_parms->symbols_per_tti>>1;k++) { for (k=0; k<frame_parms->symbols_per_tti>>1; k++) {
if (k==pilot_pos1) k++; if (k==pilot_pos1) k++;
memcpy((void*)&ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],
(void*)&ul_ch_estimates[aa][frame_parms->N_RB_UL*12*pilot_pos1], memcpy((void *)&ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],
frame_parms->N_RB_UL*12*sizeof(int)); (void *)&ul_ch_estimates[aa][frame_parms->N_RB_UL*12*pilot_pos1],
frame_parms->N_RB_UL*12*sizeof(int));
} else if (interpolate == 0 && l == pilot_pos2) {
for (k=0; k<frame_parms->symbols_per_tti>>1; k++) {
if (k==pilot_pos2) k++;
memcpy((void *)&ul_ch_estimates[aa][frame_parms->N_RB_UL*12*(k+(frame_parms->symbols_per_tti>>1))],
(void *)&ul_ch_estimates[aa][frame_parms->N_RB_UL*12*pilot_pos2],
frame_parms->N_RB_UL*12*sizeof(int));
} }
else if (interpolate == 0 && l == pilot_pos2) {
for (k=0;k<frame_parms->symbols_per_tti>>1;k++) {
if (k==pilot_pos2) k++;
memcpy((void*)&ul_ch_estimates[aa][frame_parms->N_RB_UL*12*(k+(frame_parms->symbols_per_tti>>1))],
(void*)&ul_ch_estimates[aa][frame_parms->N_RB_UL*12*pilot_pos2],
frame_parms->N_RB_UL*12*sizeof(int));
}
delta_phase = lte_ul_freq_offset_estimation(frame_parms, delta_phase = lte_ul_freq_offset_estimation(frame_parms,
ul_ch_estimates[aa], ul_ch_estimates[aa],
N_rb_alloc); N_rb_alloc);
LOG_D(PHY,"delta_phase = %d\n",delta_phase); LOG_D(PHY,"delta_phase = %d\n",delta_phase);
} }
} //for(aa=... } //for(aa=...
return(0); return(0);
} }
...@@ -790,19 +712,15 @@ int32_t lte_srs_channel_estimation(LTE_DL_FRAME_PARMS *frame_parms, ...@@ -790,19 +712,15 @@ int32_t lte_srs_channel_estimation(LTE_DL_FRAME_PARMS *frame_parms,
LTE_eNB_SRS *srs_vars, LTE_eNB_SRS *srs_vars,
SOUNDINGRS_UL_CONFIG_DEDICATED *soundingrs_ul_config_dedicated, SOUNDINGRS_UL_CONFIG_DEDICATED *soundingrs_ul_config_dedicated,
unsigned char subframe, unsigned char subframe,
unsigned char eNB_id) unsigned char eNB_id) {
{
int aa; int aa;
int N_symb,symbol; int N_symb,symbol;
uint8_t nb_antennas_rx = frame_parms->nb_antennas_rx; uint8_t nb_antennas_rx = frame_parms->nb_antennas_rx;
#ifdef DEBUG_SRS #ifdef DEBUG_SRS
char fname[40], vname[40]; char fname[40], vname[40];
#endif #endif
//uint8_t Ssrs = frame_parms->soundingrs_ul_config_common.srs_SubframeConfig; //uint8_t Ssrs = frame_parms->soundingrs_ul_config_common.srs_SubframeConfig;
//uint8_t T_SFC = (Ssrs<=7 ? 5 : 10); //uint8_t T_SFC = (Ssrs<=7 ? 5 : 10);
N_symb = 2*7-frame_parms->Ncp; N_symb = 2*7-frame_parms->Ncp;
symbol = N_symb-1; //SRS is always in last symbol of subframe symbol = N_symb-1; //SRS is always in last symbol of subframe
...@@ -818,39 +736,35 @@ int32_t lte_srs_channel_estimation(LTE_DL_FRAME_PARMS *frame_parms, ...@@ -818,39 +736,35 @@ int32_t lte_srs_channel_estimation(LTE_DL_FRAME_PARMS *frame_parms,
//if ((1<<(sub_frame_number%T_SFC))&transmission_offset_tdd[Ssrs]) { //if ((1<<(sub_frame_number%T_SFC))&transmission_offset_tdd[Ssrs]) {
if (generate_srs(frame_parms, if (generate_srs(frame_parms,
soundingrs_ul_config_dedicated, soundingrs_ul_config_dedicated,
&srs_vars->srs[eNB_id], &srs_vars->srs[eNB_id],
0x7FFF, 0x7FFF,
subframe)==-1) { subframe)==-1) {
LOG_E(PHY,"lte_srs_channel_estimation: Error in generate_srs\n"); LOG_E(PHY,"lte_srs_channel_estimation: Error in generate_srs\n");
return(-1); return(-1);
} }
for (aa=0; aa<nb_antennas_rx; aa++) { for (aa=0; aa<nb_antennas_rx; aa++) {
#ifdef DEBUG_SRS #ifdef DEBUG_SRS
LOG_E(PHY,"SRS channel estimation eNB %d, subframs %d, aarx %d, %p, %p, %p\n",eNB_id,sub_frame_number,aa, LOG_E(PHY,"SRS channel estimation eNB %d, subframs %d, aarx %d, %p, %p, %p\n",eNB_id,sub_frame_number,aa,
&common_vars->rxdataF[aa][frame_parms->ofdm_symbol_size*symbol], &common_vars->rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],
srs_vars->srs, srs_vars->srs,
srs_vars->srs_ch_estimates[aa]); srs_vars->srs_ch_estimates[aa]);
#endif #endif
//LOG_M("eNB_rxF.m","rxF",&common_vars->rxdataF[0][aa][2*frame_parms->ofdm_symbol_size*symbol],2*(frame_parms->ofdm_symbol_size),2,1);
//LOG_M("eNB_rxF.m","rxF",&common_vars->rxdataF[0][aa][2*frame_parms->ofdm_symbol_size*symbol],2*(frame_parms->ofdm_symbol_size),2,1); //LOG_M("eNB_srs.m","srs_eNB",common_vars->srs,(frame_parms->ofdm_symbol_size),1,1);
//LOG_M("eNB_srs.m","srs_eNB",common_vars->srs,(frame_parms->ofdm_symbol_size),1,1); mult_cpx_conj_vector((int16_t *) &common_vars->rxdataF[aa][2*frame_parms->ofdm_symbol_size*symbol],
(int16_t *) srs_vars->srs,
(int16_t *) srs_vars->srs_ch_estimates[aa],
mult_cpx_conj_vector((int16_t*) &common_vars->rxdataF[aa][2*frame_parms->ofdm_symbol_size*symbol], frame_parms->ofdm_symbol_size,
(int16_t*) srs_vars->srs, 15,
(int16_t*) srs_vars->srs_ch_estimates[aa], 0);
frame_parms->ofdm_symbol_size,
15,
0);
#ifdef DEBUG_SRS #ifdef DEBUG_SRS
sprintf(fname,"srs_ch_est%d.m",aa); sprintf(fname,"srs_ch_est%d.m",aa);
sprintf(vname,"srs_est%d",aa); sprintf(vname,"srs_est%d",aa);
LOG_M(fname,vname,srs_vars->srs_ch_estimates[aa],frame_parms->ofdm_symbol_size,1,1); LOG_M(fname,vname,srs_vars->srs_ch_estimates[aa],frame_parms->ofdm_symbol_size,1,1);
#endif #endif
} }
/* /*
else { else {
...@@ -863,9 +777,7 @@ int32_t lte_srs_channel_estimation(LTE_DL_FRAME_PARMS *frame_parms, ...@@ -863,9 +777,7 @@ int32_t lte_srs_channel_estimation(LTE_DL_FRAME_PARMS *frame_parms,
int16_t lte_ul_freq_offset_estimation(LTE_DL_FRAME_PARMS *frame_parms, int16_t lte_ul_freq_offset_estimation(LTE_DL_FRAME_PARMS *frame_parms,
int32_t *ul_ch_estimates, int32_t *ul_ch_estimates,
uint16_t nb_rb) uint16_t nb_rb) {
{
#if defined(__x86_64__) || defined(__i386__) #if defined(__x86_64__) || defined(__i386__)
int k, rb; int k, rb;
int a_idx = 64; int a_idx = 64;
...@@ -873,18 +785,16 @@ int16_t lte_ul_freq_offset_estimation(LTE_DL_FRAME_PARMS *frame_parms, ...@@ -873,18 +785,16 @@ int16_t lte_ul_freq_offset_estimation(LTE_DL_FRAME_PARMS *frame_parms,
uint8_t output_shift; uint8_t output_shift;
int pilot_pos1 = 3 - frame_parms->Ncp; int pilot_pos1 = 3 - frame_parms->Ncp;
int pilot_pos2 = 10 - 2*frame_parms->Ncp; int pilot_pos2 = 10 - 2*frame_parms->Ncp;
__m128i *ul_ch1 = (__m128i*)&ul_ch_estimates[pilot_pos1*frame_parms->N_RB_UL*12]; __m128i *ul_ch1 = (__m128i *)&ul_ch_estimates[pilot_pos1*frame_parms->N_RB_UL*12];
__m128i *ul_ch2 = (__m128i*)&ul_ch_estimates[pilot_pos2*frame_parms->N_RB_UL*12]; __m128i *ul_ch2 = (__m128i *)&ul_ch_estimates[pilot_pos2*frame_parms->N_RB_UL*12];
int32_t avg[2]; int32_t avg[2];
int16_t Ravg[2]; int16_t Ravg[2];
Ravg[0]=0; Ravg[0]=0;
Ravg[1]=0; Ravg[1]=0;
int16_t iv, rv, phase_idx; int16_t iv, rv, phase_idx;
__m128i avg128U1, avg128U2, R[3], mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3; __m128i avg128U1, avg128U2, R[3], mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3;
// round(tan((pi/4)*[1:1:N]/N)*pow2(15)) // round(tan((pi/4)*[1:1:N]/N)*pow2(15))
int16_t alpha[128] = {201, 402, 603, 804, 1006, 1207, 1408, 1610, 1811, 2013, 2215, 2417, 2619, 2822, 3024, 3227, 3431, 3634, 3838, 4042, 4246, 4450, 4655, 4861, 5066, 5272, 5479, 5686, 5893, 6101, 6309, 6518, 6727, 6937, 7147, 7358, 7570, 7782, 7995, 8208, 8422, 8637, 8852, 9068, 9285, 9503, 9721, 9940, 10160, 10381, 10603, 10825, 11049, 11273, 11498, 11725, 11952, 12180, 12410, 12640, 12872, 13104, 13338, 13573, 13809, 14046, 14285, 14525, 14766, 15009, 15253, 15498, 15745, 15993, 16243, 16494, 16747, 17001, 17257, 17515, 17774, 18035, 18298, 18563, 18829, 19098, 19368, 19640, 19915, 20191, 20470, 20750, 21033, 21318, 21605, 21895, 22187, 22481, 22778, 23078, 23380, 23685, 23992, 24302, 24615, 24931, 25250, 25572, 25897, 26226, 26557, 26892, 27230, 27572, 27917, 28266, 28618, 28975, 29335, 29699, 30067, 30440, 30817, 31198, 31583, 31973, 32368, 32767}; int16_t alpha[128] = {201, 402, 603, 804, 1006, 1207, 1408, 1610, 1811, 2013, 2215, 2417, 2619, 2822, 3024, 3227, 3431, 3634, 3838, 4042, 4246, 4450, 4655, 4861, 5066, 5272, 5479, 5686, 5893, 6101, 6309, 6518, 6727, 6937, 7147, 7358, 7570, 7782, 7995, 8208, 8422, 8637, 8852, 9068, 9285, 9503, 9721, 9940, 10160, 10381, 10603, 10825, 11049, 11273, 11498, 11725, 11952, 12180, 12410, 12640, 12872, 13104, 13338, 13573, 13809, 14046, 14285, 14525, 14766, 15009, 15253, 15498, 15745, 15993, 16243, 16494, 16747, 17001, 17257, 17515, 17774, 18035, 18298, 18563, 18829, 19098, 19368, 19640, 19915, 20191, 20470, 20750, 21033, 21318, 21605, 21895, 22187, 22481, 22778, 23078, 23380, 23685, 23992, 24302, 24615, 24931, 25250, 25572, 25897, 26226, 26557, 26892, 27230, 27572, 27917, 28266, 28618, 28975, 29335, 29699, 30067, 30440, 30817, 31198, 31583, 31973, 32368, 32767};
// compute log2_maxh (output_shift) // compute log2_maxh (output_shift)
avg128U1 = _mm_setzero_si128(); avg128U1 = _mm_setzero_si128();
avg128U2 = _mm_setzero_si128(); avg128U2 = _mm_setzero_si128();
...@@ -893,83 +803,72 @@ int16_t lte_ul_freq_offset_estimation(LTE_DL_FRAME_PARMS *frame_parms, ...@@ -893,83 +803,72 @@ int16_t lte_ul_freq_offset_estimation(LTE_DL_FRAME_PARMS *frame_parms,
avg128U1 = _mm_add_epi32(avg128U1,_mm_madd_epi16(ul_ch1[0],ul_ch1[0])); avg128U1 = _mm_add_epi32(avg128U1,_mm_madd_epi16(ul_ch1[0],ul_ch1[0]));
avg128U1 = _mm_add_epi32(avg128U1,_mm_madd_epi16(ul_ch1[1],ul_ch1[1])); avg128U1 = _mm_add_epi32(avg128U1,_mm_madd_epi16(ul_ch1[1],ul_ch1[1]));
avg128U1 = _mm_add_epi32(avg128U1,_mm_madd_epi16(ul_ch1[2],ul_ch1[2])); avg128U1 = _mm_add_epi32(avg128U1,_mm_madd_epi16(ul_ch1[2],ul_ch1[2]));
avg128U2 = _mm_add_epi32(avg128U2,_mm_madd_epi16(ul_ch2[0],ul_ch2[0])); avg128U2 = _mm_add_epi32(avg128U2,_mm_madd_epi16(ul_ch2[0],ul_ch2[0]));
avg128U2 = _mm_add_epi32(avg128U2,_mm_madd_epi16(ul_ch2[1],ul_ch2[1])); avg128U2 = _mm_add_epi32(avg128U2,_mm_madd_epi16(ul_ch2[1],ul_ch2[1]));
avg128U2 = _mm_add_epi32(avg128U2,_mm_madd_epi16(ul_ch2[2],ul_ch2[2])); avg128U2 = _mm_add_epi32(avg128U2,_mm_madd_epi16(ul_ch2[2],ul_ch2[2]));
ul_ch1+=3; ul_ch1+=3;
ul_ch2+=3; ul_ch2+=3;
} }
avg[0] = (((int*)&avg128U1)[0] + avg[0] = (((int *)&avg128U1)[0] +
((int*)&avg128U1)[1] + ((int *)&avg128U1)[1] +
((int*)&avg128U1)[2] + ((int *)&avg128U1)[2] +
((int*)&avg128U1)[3])/(nb_rb*12); ((int *)&avg128U1)[3])/(nb_rb*12);
avg[1] = (((int *)&avg128U2)[0] +
avg[1] = (((int*)&avg128U2)[0] + ((int *)&avg128U2)[1] +
((int*)&avg128U2)[1] + ((int *)&avg128U2)[2] +
((int*)&avg128U2)[2] + ((int *)&avg128U2)[3])/(nb_rb*12);
((int*)&avg128U2)[3])/(nb_rb*12);
// msg("avg0 = %d, avg1 = %d\n",avg[0],avg[1]); // msg("avg0 = %d, avg1 = %d\n",avg[0],avg[1]);
avg[0] = cmax(avg[0],avg[1]); avg[0] = cmax(avg[0],avg[1]);
avg[1] = log2_approx(avg[0]); avg[1] = log2_approx(avg[0]);
output_shift = cmax(0,avg[1]-10); output_shift = cmax(0,avg[1]-10);
//output_shift = (log2_approx(avg[0])/2)+ log2_approx(frame_parms->nb_antennas_rx-1)+1; //output_shift = (log2_approx(avg[0])/2)+ log2_approx(frame_parms->nb_antennas_rx-1)+1;
// msg("avg= %d, shift = %d\n",avg[0],output_shift); // msg("avg= %d, shift = %d\n",avg[0],output_shift);
ul_ch1 = (__m128i *)&ul_ch_estimates[pilot_pos1*frame_parms->N_RB_UL*12];
ul_ch1 = (__m128i*)&ul_ch_estimates[pilot_pos1*frame_parms->N_RB_UL*12]; ul_ch2 = (__m128i *)&ul_ch_estimates[pilot_pos2*frame_parms->N_RB_UL*12];
ul_ch2 = (__m128i*)&ul_ch_estimates[pilot_pos2*frame_parms->N_RB_UL*12];
// correlate and average the 2 channel estimates ul_ch1*ul_ch2 // correlate and average the 2 channel estimates ul_ch1*ul_ch2
for (rb=0; rb<nb_rb; rb++) { for (rb=0; rb<nb_rb; rb++) {
mmtmpD0 = _mm_madd_epi16(ul_ch1[0],ul_ch2[0]); mmtmpD0 = _mm_madd_epi16(ul_ch1[0],ul_ch2[0]);
mmtmpD1 = _mm_shufflelo_epi16(ul_ch1[0],_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_shufflelo_epi16(ul_ch1[0],_MM_SHUFFLE(2,3,0,1));
mmtmpD1 = _mm_shufflehi_epi16(mmtmpD1,_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_shufflehi_epi16(mmtmpD1,_MM_SHUFFLE(2,3,0,1));
mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i*)&conjugate); mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i *)&conjugate);
mmtmpD1 = _mm_madd_epi16(mmtmpD1,ul_ch2[0]); mmtmpD1 = _mm_madd_epi16(mmtmpD1,ul_ch2[0]);
mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift); mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift);
mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift); mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift);
mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1); mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1);
mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1); mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1);
R[0] = _mm_packs_epi32(mmtmpD2,mmtmpD3); R[0] = _mm_packs_epi32(mmtmpD2,mmtmpD3);
mmtmpD0 = _mm_madd_epi16(ul_ch1[1],ul_ch2[1]); mmtmpD0 = _mm_madd_epi16(ul_ch1[1],ul_ch2[1]);
mmtmpD1 = _mm_shufflelo_epi16(ul_ch1[1],_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_shufflelo_epi16(ul_ch1[1],_MM_SHUFFLE(2,3,0,1));
mmtmpD1 = _mm_shufflehi_epi16(mmtmpD1,_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_shufflehi_epi16(mmtmpD1,_MM_SHUFFLE(2,3,0,1));
mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i*)&conjugate); mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i *)&conjugate);
mmtmpD1 = _mm_madd_epi16(mmtmpD1,ul_ch2[1]); mmtmpD1 = _mm_madd_epi16(mmtmpD1,ul_ch2[1]);
mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift); mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift);
mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift); mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift);
mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1); mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1);
mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1); mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1);
R[1] = _mm_packs_epi32(mmtmpD2,mmtmpD3); R[1] = _mm_packs_epi32(mmtmpD2,mmtmpD3);
mmtmpD0 = _mm_madd_epi16(ul_ch1[2],ul_ch2[2]); mmtmpD0 = _mm_madd_epi16(ul_ch1[2],ul_ch2[2]);
mmtmpD1 = _mm_shufflelo_epi16(ul_ch1[2],_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_shufflelo_epi16(ul_ch1[2],_MM_SHUFFLE(2,3,0,1));
mmtmpD1 = _mm_shufflehi_epi16(mmtmpD1,_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_shufflehi_epi16(mmtmpD1,_MM_SHUFFLE(2,3,0,1));
mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i*)&conjugate); mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i *)&conjugate);
mmtmpD1 = _mm_madd_epi16(mmtmpD1,ul_ch2[2]); mmtmpD1 = _mm_madd_epi16(mmtmpD1,ul_ch2[2]);
mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift); mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift);
mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift); mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift);
mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1); mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1);
mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1); mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1);
R[2] = _mm_packs_epi32(mmtmpD2,mmtmpD3); R[2] = _mm_packs_epi32(mmtmpD2,mmtmpD3);
R[0] = _mm_add_epi16(_mm_srai_epi16(R[0],1),_mm_srai_epi16(R[1],1)); R[0] = _mm_add_epi16(_mm_srai_epi16(R[0],1),_mm_srai_epi16(R[1],1));
R[0] = _mm_add_epi16(_mm_srai_epi16(R[0],1),_mm_srai_epi16(R[2],1)); R[0] = _mm_add_epi16(_mm_srai_epi16(R[0],1),_mm_srai_epi16(R[2],1));
Ravg[0] += (((short *)&R)[0] +
Ravg[0] += (((short*)&R)[0] + ((short *)&R)[2] +
((short*)&R)[2] + ((short *)&R)[4] +
((short*)&R)[4] + ((short *)&R)[6])/(nb_rb*4);
((short*)&R)[6])/(nb_rb*4); Ravg[1] += (((short *)&R)[1] +
((short *)&R)[3] +
Ravg[1] += (((short*)&R)[1] + ((short *)&R)[5] +
((short*)&R)[3] + ((short *)&R)[7])/(nb_rb*4);
((short*)&R)[5] +
((short*)&R)[7])/(nb_rb*4);
ul_ch1+=3; ul_ch1+=3;
ul_ch2+=3; ul_ch2+=3;
} }
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -125,7 +125,7 @@ void dlsch_scrambling(LTE_DL_FRAME_PARMS *frame_parms, ...@@ -125,7 +125,7 @@ void dlsch_scrambling(LTE_DL_FRAME_PARMS *frame_parms,
for (n=0; n<(1+(G>>5)); n++) { for (n=0; n<(1+(G>>5)); n++) {
#ifdef DEBUG_SCRAMBLING #ifdef DEBUG_SCRAMBLING
for (int k=0;k<32;k++) printf("scrambling %d : %d xor %d = %d\n",k+(n<<5),e[k],(s>>k)&1,e[k]^((s>>k)&1)); for (int k=0;k<32;k++) printf("scrambling %d : %u xor %d = %u\n",k+(n<<5),e[k],(s>>k)&1,e[k]^((s>>k)&1));
#endif #endif
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
#include "mdci.h" #include "mdci.h"
//#include "uci.h" //#include "uci.h"
#ifndef STANDALONE_COMPILE #ifndef STANDALONE_COMPILE
#include "UTIL/LISTS/list.h" #include "UTIL/LISTS/list.h"
#endif #endif
#include <nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h> #include <nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h>
...@@ -68,19 +68,19 @@ ...@@ -68,19 +68,19 @@
#define MAX_NUM_RE (14*1200) #define MAX_NUM_RE (14*1200)
#if !defined(SI_RNTI) #if !defined(SI_RNTI)
#define SI_RNTI (rnti_t)0xffff #define SI_RNTI (rnti_t)0xffff
#endif #endif
#if !defined(M_RNTI) #if !defined(M_RNTI)
#define M_RNTI (rnti_t)0xfffd #define M_RNTI (rnti_t)0xfffd
#endif #endif
#if !defined(P_RNTI) #if !defined(P_RNTI)
#define P_RNTI (rnti_t)0xfffe #define P_RNTI (rnti_t)0xfffe
#endif #endif
#if !defined(CBA_RNTI) #if !defined(CBA_RNTI)
#define CBA_RNTI (rnti_t)0xfff4 #define CBA_RNTI (rnti_t)0xfff4
#endif #endif
#if !defined(C_RNTI) #if !defined(C_RNTI)
#define C_RNTI (rnti_t)0x1234 #define C_RNTI (rnti_t)0x1234
#endif #endif
// These are the codebook indexes according to Table 6.3.4.2.3-1 of 36.211 // These are the codebook indexes according to Table 6.3.4.2.3-1 of 36.211
//1 layer //1 layer
...@@ -94,7 +94,8 @@ ...@@ -94,7 +94,8 @@
#define PMI_2A_R1_1j 2 #define PMI_2A_R1_1j 2
typedef enum { SEARCH_EXIST=0, typedef enum { SEARCH_EXIST=0,
SEARCH_EXIST_OR_FREE} find_type_t; SEARCH_EXIST_OR_FREE
} find_type_t;
typedef enum { typedef enum {
SCH_IDLE=0, SCH_IDLE=0,
...@@ -136,7 +137,7 @@ typedef enum { ...@@ -136,7 +137,7 @@ typedef enum {
HARQ_SR, HARQ_SR,
HARQ_CQI, HARQ_CQI,
SR_CQI, SR_CQI,
HARQ_SR_CQI HARQ_SR_CQI
} UCI_type_t; } UCI_type_t;
typedef enum { typedef enum {
...@@ -242,7 +243,7 @@ typedef struct { ...@@ -242,7 +243,7 @@ typedef struct {
typedef struct { typedef struct {
/// payload length /// payload length
int payload_length; int payload_length;
uint8_t payload[100]; uint8_t payload[100];
} SLDCH_t; } SLDCH_t;
#define TTI_SYNC 0 #define TTI_SYNC 0
......
...@@ -38,7 +38,7 @@ ...@@ -38,7 +38,7 @@
#include "mdci.h" #include "mdci.h"
#include "uci_common.h" #include "uci_common.h"
#ifndef STANDALONE_COMPILE #ifndef STANDALONE_COMPILE
#include "UTIL/LISTS/list.h" #include "UTIL/LISTS/list.h"
#endif #endif
...@@ -343,7 +343,7 @@ typedef struct { ...@@ -343,7 +343,7 @@ typedef struct {
uint16_t n_pucch_1[4][2]; uint16_t n_pucch_1[4][2];
/// two antenna n1_pucch 1_0 for SR /// two antenna n1_pucch 1_0 for SR
uint16_t n_pucch_1_0_sr[2]; uint16_t n_pucch_1_0_sr[2];
/// two antenna n2_pucch /// two antenna n2_pucch
uint16_t n_pucch_2[2]; uint16_t n_pucch_2[2];
/// two antenna n3_pucch /// two antenna n3_pucch
uint16_t n_pucch_3[2]; uint16_t n_pucch_3[2];
......
...@@ -174,7 +174,7 @@ int rx_pdsch(PHY_VARS_UE *ue, ...@@ -174,7 +174,7 @@ int rx_pdsch(PHY_VARS_UE *ue,
dlsch1_harq = NULL; dlsch1_harq = NULL;
codeword_TB0 = -1; codeword_TB0 = -1;
#ifdef DEBUG_HARQ #ifdef DEBUG_HARQ
printf("[DEMOD] I am assuming only TB1 is active, it is in cw %d\n", dlsch0_harq->codeword); printf("[DEMOD] I am assuming only TB1 is active, it is in cw %u\n", dlsch0_harq->codeword);
#endif #endif
} else { } else {
LOG_E(PHY,"[UE][FATAL] Frame %d subframe %d: no active DLSCH\n",ue->proc.proc_rxtx[0].frame_rx,subframe); LOG_E(PHY,"[UE][FATAL] Frame %d subframe %d: no active DLSCH\n",ue->proc.proc_rxtx[0].frame_rx,subframe);
...@@ -251,7 +251,7 @@ int rx_pdsch(PHY_VARS_UE *ue, ...@@ -251,7 +251,7 @@ int rx_pdsch(PHY_VARS_UE *ue,
#endif #endif
#ifdef DEBUG_HARQ #ifdef DEBUG_HARQ
printf("Demod dlsch0_harq->pmi_alloc %d\n", dlsch0_harq->pmi_alloc); printf("Demod dlsch0_harq->pmi_alloc %u\n", dlsch0_harq->pmi_alloc);
#endif #endif
if (frame_parms->nb_antenna_ports_eNB>1 && beamforming_mode==0) { if (frame_parms->nb_antenna_ports_eNB>1 && beamforming_mode==0) {
...@@ -2204,7 +2204,7 @@ void dlsch_channel_compensation_TM56(int **rxdataF_ext, ...@@ -2204,7 +2204,7 @@ void dlsch_channel_compensation_TM56(int **rxdataF_ext,
for (rb=0; rb<nb_rb; rb++) { for (rb=0; rb<nb_rb; rb++) {
#ifdef DEBUG_DLSCH_DEMOD #ifdef DEBUG_DLSCH_DEMOD
printf("mode 6 prec: rb %d, pmi->%u\n",rb,pmi_ext[rb]); printf("mode 6 prec: rb %u, pmi->%u\n",rb,pmi_ext[rb]);
#endif #endif
prec2A_TM56_128(pmi_ext[rb],&dl_ch0_128b[0],&dl_ch1_128b[0]); prec2A_TM56_128(pmi_ext[rb],&dl_ch0_128b[0],&dl_ch1_128b[0]);
prec2A_TM56_128(pmi_ext[rb],&dl_ch0_128b[1],&dl_ch1_128b[1]); prec2A_TM56_128(pmi_ext[rb],&dl_ch0_128b[1],&dl_ch1_128b[1]);
......
...@@ -240,8 +240,8 @@ bool dlsch_procedures(PHY_VARS_eNB *eNB, ...@@ -240,8 +240,8 @@ bool dlsch_procedures(PHY_VARS_eNB *eNB,
LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
if (dlsch->rnti != 0xffff) {//frame < 200) { if (dlsch->rnti != 0xffff) {//frame < 200) {
LOG_D(PHY, LOG_D(PHY,
"[eNB %"PRIu8"][PDSCH %"PRIx16"/%"PRIu8"] Frame %d, subframe %d: Generating PDSCH/DLSCH (type %d) with input size = %"PRIu16", pdsch_start %d, G %d, nb_rb %"PRIu16", rb0 %x, rb1 %x, TBS %"PRIu16", pmi_alloc %"PRIx64", rv %"PRIu8" (round %"PRIu8")\n", "[eNB %"PRIu8"][PDSCH %"PRIx16"/%"PRIu8"] Frame %d, subframe %d: Generating PDSCH/DLSCH (type %d) with input size = %"PRIu16", pdsch_start %d, G %d, nb_rb %"PRIu16", rb0 %x, rb1 %x, TBS %"PRIu16", pmi_alloc %"PRIx64", rv %"PRIu8" (round %"PRIu8")\n",
eNB->Mod_id, dlsch->rnti,harq_pid, eNB->Mod_id, dlsch->rnti,harq_pid,
frame, subframe, dlsch->ue_type,dlsch_harq->TBS/8, dlsch_harq->pdsch_start, frame, subframe, dlsch->ue_type,dlsch_harq->TBS/8, dlsch_harq->pdsch_start,
get_G(fp, get_G(fp,
...@@ -278,8 +278,8 @@ bool dlsch_procedures(PHY_VARS_eNB *eNB, ...@@ -278,8 +278,8 @@ bool dlsch_procedures(PHY_VARS_eNB *eNB,
if (dlsch->rnti!=0xffff) if (dlsch->rnti!=0xffff)
LOG_D(PHY,"Generating DLSCH/PDSCH pdu:%p pdsch_start:%d frame:%d subframe:%d nb_rb:%d rb_alloc:%d Qm:%d Nl:%d round:%d\n", LOG_D(PHY,"Generating DLSCH/PDSCH pdu:%p pdsch_start:%d frame:%d subframe:%d nb_rb:%d rb_alloc:%d Qm:%d Nl:%d round:%d\n",
dlsch_harq->pdu,dlsch_harq->pdsch_start,frame,subframe,dlsch_harq->nb_rb,dlsch_harq->rb_alloc[0], dlsch_harq->pdu,dlsch_harq->pdsch_start,frame,subframe,dlsch_harq->nb_rb,dlsch_harq->rb_alloc[0],
dlsch_harq->Qm,dlsch_harq->Nl,dlsch_harq->round); dlsch_harq->Qm,dlsch_harq->Nl,dlsch_harq->round);
// 36-212 // 36-212
if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { // monolthic OR PNF - do not need turbo encoding on VNF if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { // monolthic OR PNF - do not need turbo encoding on VNF
...@@ -308,6 +308,7 @@ bool dlsch_procedures(PHY_VARS_eNB *eNB, ...@@ -308,6 +308,7 @@ bool dlsch_procedures(PHY_VARS_eNB *eNB,
if(eNB->dlsch_encoding_stats.p_time>500*3000 && opp_enabled == 1) { if(eNB->dlsch_encoding_stats.p_time>500*3000 && opp_enabled == 1) {
print_meas_now(&eNB->dlsch_encoding_stats,"total coding",stderr); print_meas_now(&eNB->dlsch_encoding_stats,"total coding",stderr);
} }
#ifdef PHY_TX_THREAD #ifdef PHY_TX_THREAD
dlsch->active[subframe] = 0; dlsch->active[subframe] = 0;
#else #else
...@@ -317,6 +318,7 @@ bool dlsch_procedures(PHY_VARS_eNB *eNB, ...@@ -317,6 +318,7 @@ bool dlsch_procedures(PHY_VARS_eNB *eNB,
LOG_D(PHY,"Generated DLSCH dlsch_harq[round:%d]\n",dlsch_harq->round); LOG_D(PHY,"Generated DLSCH dlsch_harq[round:%d]\n",dlsch_harq->round);
return true; return true;
} }
return false; return false;
} }
...@@ -332,32 +334,31 @@ void pdsch_procedures(PHY_VARS_eNB *eNB, ...@@ -332,32 +334,31 @@ void pdsch_procedures(PHY_VARS_eNB *eNB,
// 36-211 // 36-211
start_meas(&eNB->dlsch_scrambling_stats); start_meas(&eNB->dlsch_scrambling_stats);
dlsch_scrambling(fp, dlsch_scrambling(fp,
0, 0,
dlsch, dlsch,
harq_pid, harq_pid,
get_G(fp, get_G(fp,
dlsch_harq->nb_rb, dlsch_harq->nb_rb,
dlsch_harq->rb_alloc, dlsch_harq->rb_alloc,
dlsch_harq->Qm, dlsch_harq->Qm,
dlsch_harq->Nl, dlsch_harq->Nl,
dlsch_harq->pdsch_start, dlsch_harq->pdsch_start,
frame,subframe, frame,subframe,
0), 0),
0, 0,
frame, frame,
subframe<<1); subframe<<1);
stop_meas(&eNB->dlsch_scrambling_stats); stop_meas(&eNB->dlsch_scrambling_stats);
start_meas(&eNB->dlsch_modulation_stats); start_meas(&eNB->dlsch_modulation_stats);
dlsch_modulation(eNB, dlsch_modulation(eNB,
eNB->common_vars.txdataF, eNB->common_vars.txdataF,
AMP, AMP,
frame, frame,
subframe, subframe,
dlsch_harq->pdsch_start, dlsch_harq->pdsch_start,
dlsch, dlsch,
dlsch->ue_type==NOCE ? dlsch1 : (LTE_eNB_DLSCH_t *)NULL); dlsch->ue_type==NOCE ? dlsch1 : (LTE_eNB_DLSCH_t *)NULL);
stop_meas(&eNB->dlsch_modulation_stats); stop_meas(&eNB->dlsch_modulation_stats);
LOG_D(PHY,"Generated PDSCH dlsch_harq[round:%d]\n",dlsch_harq->round); LOG_D(PHY,"Generated PDSCH dlsch_harq[round:%d]\n",dlsch_harq->round);
} }
...@@ -452,7 +453,7 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, ...@@ -452,7 +453,7 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DCI_INFO,num_pdcch_symbols); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DCI_INFO,num_pdcch_symbols);
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME (VCD_SIGNAL_DUMPER_VARIABLES_DCI_INFO, (frame * 10) + subframe); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME (VCD_SIGNAL_DUMPER_VARIABLES_DCI_INFO, (frame * 10) + subframe);
if (num_pdcch_symbols == 0){ if (num_pdcch_symbols == 0) {
LOG_E(PHY,"[eNB %"PRIu8"] Frame %d, subframe %d: Calling generate_dci_top (pdcch) (num_dci %"PRIu8") num_pdcch_symbols:%d\n",eNB->Mod_id,frame, subframe, num_dci, num_pdcch_symbols); LOG_E(PHY,"[eNB %"PRIu8"] Frame %d, subframe %d: Calling generate_dci_top (pdcch) (num_dci %"PRIu8") num_pdcch_symbols:%d\n",eNB->Mod_id,frame, subframe, num_dci, num_pdcch_symbols);
return; return;
} }
...@@ -504,9 +505,9 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, ...@@ -504,9 +505,9 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
) { ) {
// get harq_pid // get harq_pid
harq_pid = dlsch0->harq_ids[frame%2][subframe]; harq_pid = dlsch0->harq_ids[frame%2][subframe];
//AssertFatal(harq_pid>=0,"harq_pid is negative\n"); //AssertFatal(harq_pid>=0,"harq_pid is negative\n");
if((harq_pid < 0) || (harq_pid >= dlsch0->Mdlharq)) { if((harq_pid < 0) || (harq_pid >= dlsch0->Mdlharq)) {
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) #if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
if (dlsch0->ue_type==NOCE) if (dlsch0->ue_type==NOCE)
...@@ -521,18 +522,18 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, ...@@ -521,18 +522,18 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
dlsch0->harq_ids[frame%2][6], dlsch0->harq_ids[frame%2][6],
dlsch0->harq_ids[frame%2][7]); dlsch0->harq_ids[frame%2][7]);
} else { } else {
if (dlsch_procedures(eNB, if (dlsch_procedures(eNB,
proc, proc,
harq_pid, harq_pid,
dlsch0, dlsch0,
&eNB->UE_stats[(uint32_t)UE_id])) { &eNB->UE_stats[(uint32_t)UE_id])) {
// if we generate dlsch, we must generate pdsch // if we generate dlsch, we must generate pdsch
pdsch_procedures(eNB, pdsch_procedures(eNB,
proc, proc,
harq_pid, harq_pid,
dlsch0, dlsch0,
dlsch1); dlsch1);
} }
} }
} else if ((dlsch0)&&(dlsch0->rnti>0)&& } else if ((dlsch0)&&(dlsch0->rnti>0)&&
#ifdef PHY_TX_THREAD #ifdef PHY_TX_THREAD
...@@ -635,7 +636,6 @@ uci_procedures(PHY_VARS_eNB *eNB, ...@@ -635,7 +636,6 @@ uci_procedures(PHY_VARS_eNB *eNB,
subframe, subframe,
uci->type, uci->type,
i); i);
uci->active = 0; uci->active = 0;
// Null out PUCCH PRBs for noise measurement // Null out PUCCH PRBs for noise measurement
...@@ -643,24 +643,30 @@ uci_procedures(PHY_VARS_eNB *eNB, ...@@ -643,24 +643,30 @@ uci_procedures(PHY_VARS_eNB *eNB,
case 6: case 6:
eNB->rb_mask_ul[0] |= (0x1 | (1 << 5)); // position 5 eNB->rb_mask_ul[0] |= (0x1 | (1 << 5)); // position 5
break; break;
case 15: case 15:
eNB->rb_mask_ul[0] |= (0x1 | (1 << 14)); // position 14 eNB->rb_mask_ul[0] |= (0x1 | (1 << 14)); // position 14
break; break;
case 25: case 25:
eNB->rb_mask_ul[0] |= (0x1 | (1 << 24)); // position 24 eNB->rb_mask_ul[0] |= (0x1 | (1 << 24)); // position 24
break; break;
case 50: case 50:
eNB->rb_mask_ul[0] |= 0x1; eNB->rb_mask_ul[0] |= 0x1;
eNB->rb_mask_ul[1] |= (1 << 17); // position 49 (49-32) eNB->rb_mask_ul[1] |= (1 << 17); // position 49 (49-32)
break; break;
case 75: case 75:
eNB->rb_mask_ul[0] |= 0x1; eNB->rb_mask_ul[0] |= 0x1;
eNB->rb_mask_ul[2] |= (1 << 10); // position 74 (74-64) eNB->rb_mask_ul[2] |= (1 << 10); // position 74 (74-64)
break; break;
case 100: case 100:
eNB->rb_mask_ul[0] |= 0x1; eNB->rb_mask_ul[0] |= 0x1;
eNB->rb_mask_ul[3] |= (1 << 3); // position 99 (99-96) eNB->rb_mask_ul[3] |= (1 << 3); // position 99 (99-96)
break; break;
default: default:
LOG_E(PHY,"Unknown number for N_RB_UL %d\n", fp->N_RB_UL); LOG_E(PHY,"Unknown number for N_RB_UL %d\n", fp->N_RB_UL);
break; break;
...@@ -859,6 +865,7 @@ uci_procedures(PHY_VARS_eNB *eNB, ...@@ -859,6 +865,7 @@ uci_procedures(PHY_VARS_eNB *eNB,
uci->rnti,uci->type,SR_payload,frame,subframe,pucch_b0b1[0][0],pucch_b0b1[0][1],pucch_b0b1[1][0],pucch_b0b1[1][1]); uci->rnti,uci->type,SR_payload,frame,subframe,pucch_b0b1[0][0],pucch_b0b1[0][1],pucch_b0b1[1][0],pucch_b0b1[1][1]);
#endif #endif
#endif #endif
if (SR_payload == 1) { // this implements Table 7.3.1 from 36.213 if (SR_payload == 1) { // this implements Table 7.3.1 from 36.213
if (pucch_b0b1[0][0] == 4) { // there isn't a likely transmission if (pucch_b0b1[0][0] == 4) { // there isn't a likely transmission
harq_ack[0] = 4; // DTX harq_ack[0] = 4; // DTX
...@@ -1492,31 +1499,27 @@ static void do_release_harq(PHY_VARS_eNB *eNB, ...@@ -1492,31 +1499,27 @@ static void do_release_harq(PHY_VARS_eNB *eNB,
int harq_pid; int harq_pid;
int subframe_tx; int subframe_tx;
int frame_tx; int frame_tx;
AssertFatal(UE_id != -1, "No existing dlsch context\n"); AssertFatal(UE_id != -1, "No existing dlsch context\n");
AssertFatal(UE_id < NUMBER_OF_UE_MAX, "Returned UE_id %d >= %d (NUMBER_OF_UE_MAX)\n", UE_id, NUMBER_OF_UE_MAX); AssertFatal(UE_id < NUMBER_OF_UE_MAX, "Returned UE_id %d >= %d (NUMBER_OF_UE_MAX)\n", UE_id, NUMBER_OF_UE_MAX);
dlsch0 = eNB->dlsch[UE_id][0]; dlsch0 = eNB->dlsch[UE_id][0];
dlsch1 = eNB->dlsch[UE_id][1]; dlsch1 = eNB->dlsch[UE_id][1];
if (eNB->frame_parms.frame_type == FDD) { if (eNB->frame_parms.frame_type == FDD) {
subframe_tx = (subframe + 6) % 10; subframe_tx = (subframe + 6) % 10;
frame_tx = ul_ACK_subframe2_dl_frame(&eNB->frame_parms, frame_tx = ul_ACK_subframe2_dl_frame(&eNB->frame_parms,
frame, frame,
subframe, subframe,
subframe_tx); subframe_tx);
harq_pid = dlsch0->harq_ids[frame_tx%2][subframe_tx]; harq_pid = dlsch0->harq_ids[frame_tx%2][subframe_tx];
if((harq_pid < 0) || (harq_pid >= dlsch0->Mdlharq)) { if((harq_pid < 0) || (harq_pid >= dlsch0->Mdlharq)) {
LOG_E(PHY,"illegal harq_pid %d %s:%d\n", harq_pid, __FILE__, __LINE__); LOG_E(PHY,"illegal harq_pid %d %s:%d\n", harq_pid, __FILE__, __LINE__);
return; return;
} }
dlsch0_harq = dlsch0->harq_processes[harq_pid]; dlsch0_harq = dlsch0->harq_processes[harq_pid];
dlsch1_harq = dlsch1->harq_processes[harq_pid]; dlsch1_harq = dlsch1->harq_processes[harq_pid];
AssertFatal(dlsch0_harq != NULL, "dlsch0_harq is null\n"); AssertFatal(dlsch0_harq != NULL, "dlsch0_harq is null\n");
#if T_TRACER #if T_TRACER
if (after_rounds != -1) { if (after_rounds != -1) {
...@@ -1541,7 +1544,6 @@ static void do_release_harq(PHY_VARS_eNB *eNB, ...@@ -1541,7 +1544,6 @@ static void do_release_harq(PHY_VARS_eNB *eNB,
dlsch0_harq->status = SCH_IDLE; dlsch0_harq->status = SCH_IDLE;
dlsch0->harq_mask &= ~(1 << harq_pid); dlsch0->harq_mask &= ~(1 << harq_pid);
} }
} else { } else {
/* Release all processes in the bundle that was acked, based on mask */ /* Release all processes in the bundle that was acked, based on mask */
/* This is at most 4 for multiplexing and 9 for bundling/special bundling */ /* This is at most 4 for multiplexing and 9 for bundling/special bundling */
...@@ -1549,13 +1551,12 @@ static void do_release_harq(PHY_VARS_eNB *eNB, ...@@ -1549,13 +1551,12 @@ static void do_release_harq(PHY_VARS_eNB *eNB,
for (int m=0; m < M; m++) { for (int m=0; m < M; m++) {
subframe_tx = ul_ACK_subframe2_dl_subframe(&eNB->frame_parms, subframe_tx = ul_ACK_subframe2_dl_subframe(&eNB->frame_parms,
subframe, subframe,
m); m);
frame_tx = ul_ACK_subframe2_dl_frame(&eNB->frame_parms, frame_tx = ul_ACK_subframe2_dl_frame(&eNB->frame_parms,
frame, frame,
subframe, subframe,
subframe_tx); subframe_tx);
if (((1 << m) & mask) > 0) { if (((1 << m) & mask) > 0) {
harq_pid = dlsch0->harq_ids[frame_tx%2][subframe_tx]; harq_pid = dlsch0->harq_ids[frame_tx%2][subframe_tx];
...@@ -1564,12 +1565,12 @@ static void do_release_harq(PHY_VARS_eNB *eNB, ...@@ -1564,12 +1565,12 @@ static void do_release_harq(PHY_VARS_eNB *eNB,
LOG_E(PHY,"illegal harq_pid %d %s:%d\n", harq_pid, __FILE__, __LINE__); LOG_E(PHY,"illegal harq_pid %d %s:%d\n", harq_pid, __FILE__, __LINE__);
return; return;
} }
dlsch0_harq = dlsch0->harq_processes[harq_pid]; dlsch0_harq = dlsch0->harq_processes[harq_pid];
dlsch1_harq = dlsch1->harq_processes[harq_pid]; dlsch1_harq = dlsch1->harq_processes[harq_pid];
AssertFatal(dlsch0_harq != NULL, "Dlsch0_harq is null\n"); AssertFatal(dlsch0_harq != NULL, "Dlsch0_harq is null\n");
#if T_TRACER #if T_TRACER
if (after_rounds != -1) { if (after_rounds != -1) {
T(T_ENB_PHY_DLSCH_UE_NACK, T(T_ENB_PHY_DLSCH_UE_NACK,
T_INT(0), T_INT(0),
...@@ -1585,7 +1586,9 @@ static void do_release_harq(PHY_VARS_eNB *eNB, ...@@ -1585,7 +1586,9 @@ static void do_release_harq(PHY_VARS_eNB *eNB,
T_INT(dlsch0->rnti), T_INT(dlsch0->rnti),
T_INT(harq_pid)); T_INT(harq_pid));
} }
#endif #endif
if (dlsch0_harq->round >= after_rounds) { if (dlsch0_harq->round >= after_rounds) {
dlsch0_harq->status = SCH_IDLE; dlsch0_harq->status = SCH_IDLE;
...@@ -1599,7 +1602,7 @@ static void do_release_harq(PHY_VARS_eNB *eNB, ...@@ -1599,7 +1602,7 @@ static void do_release_harq(PHY_VARS_eNB *eNB,
} }
static void release_harq(PHY_VARS_eNB *eNB,int UE_id,int tb,uint16_t frame,uint8_t subframe,uint16_t mask, int is_ack) { static void release_harq(PHY_VARS_eNB *eNB,int UE_id,int tb,uint16_t frame,uint8_t subframe,uint16_t mask, int is_ack) {
/* /*
* Maximum number of DL transmissions = 4. * Maximum number of DL transmissions = 4.
* TODO: get the value from configuration. * TODO: get the value from configuration.
* If is_ack is true then we release immediately. The value -1 can be used for that. * If is_ack is true then we release immediately. The value -1 can be used for that.
...@@ -1997,43 +2000,50 @@ void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { ...@@ -1997,43 +2000,50 @@ void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) {
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC, 0 ); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC, 0 );
} }
void release_rnti_of_phy(module_id_t mod_id){ void release_rnti_of_phy(module_id_t mod_id) {
int i,j; int i,j;
int CC_id; int CC_id;
rnti_t rnti; rnti_t rnti;
PHY_VARS_eNB *eNB_PHY = NULL; PHY_VARS_eNB *eNB_PHY = NULL;
LTE_eNB_ULSCH_t *ulsch = NULL; LTE_eNB_ULSCH_t *ulsch = NULL;
LTE_eNB_DLSCH_t *dlsch = NULL; LTE_eNB_DLSCH_t *dlsch = NULL;
for(i = 0; i< release_rntis.number_of_TLVs;i++){
for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { for(i = 0; i< release_rntis.number_of_TLVs; i++) {
eNB_PHY = RC.eNB[mod_id][CC_id]; for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
rnti = release_rntis.ue_release_request_TLVs_list[i].rnti; eNB_PHY = RC.eNB[mod_id][CC_id];
for (j=0; j<NUMBER_OF_UE_MAX; j++) { rnti = release_rntis.ue_release_request_TLVs_list[i].rnti;
ulsch = eNB_PHY->ulsch[j];
if((ulsch != NULL) && (ulsch->rnti == rnti)){ for (j=0; j<NUMBER_OF_UE_MAX; j++) {
LOG_I(PHY, "clean_eNb_ulsch ulsch[%d] UE %x\n", j, rnti); ulsch = eNB_PHY->ulsch[j];
clean_eNb_ulsch(ulsch);
} if((ulsch != NULL) && (ulsch->rnti == rnti)) {
LOG_I(PHY, "clean_eNb_ulsch ulsch[%d] UE %x\n", j, rnti);
clean_eNb_ulsch(ulsch);
}
dlsch = eNB_PHY->dlsch[j][0]; dlsch = eNB_PHY->dlsch[j][0];
if((dlsch != NULL) && (dlsch->rnti == rnti)){
LOG_I(PHY, "clean_eNb_dlsch dlsch[%d] UE %x \n", j, rnti);
clean_eNb_dlsch(dlsch);
}
}
ulsch = eNB_PHY->ulsch[j];
if((ulsch != NULL) && (ulsch->rnti == rnti)){
LOG_I(PHY, "clean_eNb_ulsch ulsch[%d] UE %x\n", j, rnti);
clean_eNb_ulsch(ulsch);
}
for(j=0; j<NUMBER_OF_UCI_VARS_MAX; j++) {
if(eNB_PHY->uci_vars[j].rnti == rnti){
LOG_I(PHY, "clean eNb uci_vars[%d] UE %x \n",j, rnti);
memset(&eNB_PHY->uci_vars[i],0,sizeof(LTE_eNB_UCI));
}
} if((dlsch != NULL) && (dlsch->rnti == rnti)) {
LOG_I(PHY, "clean_eNb_dlsch dlsch[%d] UE %x \n", j, rnti);
clean_eNb_dlsch(dlsch);
}
}
ulsch = eNB_PHY->ulsch[j];
if((ulsch != NULL) && (ulsch->rnti == rnti)) {
LOG_I(PHY, "clean_eNb_ulsch ulsch[%d] UE %x\n", j, rnti);
clean_eNb_ulsch(ulsch);
}
for(j=0; j<NUMBER_OF_UCI_VARS_MAX; j++) {
if(eNB_PHY->uci_vars[j].rnti == rnti) {
LOG_I(PHY, "clean eNb uci_vars[%d] UE %x \n",j, rnti);
memset(&eNB_PHY->uci_vars[i],0,sizeof(LTE_eNB_UCI));
} }
}
} }
memset(&release_rntis, 0, sizeof(nfapi_ue_release_request_body_t)); }
memset(&release_rntis, 0, sizeof(nfapi_ue_release_request_body_t));
} }
...@@ -329,9 +329,7 @@ void generate_Msg2(module_id_t module_idP, ...@@ -329,9 +329,7 @@ void generate_Msg2(module_id_t module_idP,
dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.mpdcch_tansmission_type = 1; // imposed (9.1.5 in 213) for Type 2 Common search space dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.mpdcch_tansmission_type = 1; // imposed (9.1.5 in 213) for Type 2 Common search space
AssertFatal (cc[CC_idP].sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13 != NULL, "cc[CC_idP].sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13 is null\n"); AssertFatal (cc[CC_idP].sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13 != NULL, "cc[CC_idP].sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13 is null\n");
dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.start_symbol = cc[CC_idP].sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13->startSymbolBR_r13; dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.start_symbol = cc[CC_idP].sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13->startSymbolBR_r13;
LOG_E(MAC, "start_symbol = %d \n", dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.start_symbol); LOG_E(MAC, "start_symbol = %d \n", dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.start_symbol);
dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.ecce_index = 0; // Note: this should be dynamic dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.ecce_index = 0; // Note: this should be dynamic
dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.aggregation_level = 24; // OK for CEModeA r1-3 (9.1.5-1b) or CEModeB r1-4 dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.aggregation_level = 24; // OK for CEModeA r1-3 (9.1.5-1b) or CEModeB r1-4
dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.rnti_type = 2; // RA-RNTI dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.rnti_type = 2; // RA-RNTI
...@@ -959,12 +957,10 @@ generate_Msg4(module_id_t module_idP, ...@@ -959,12 +957,10 @@ generate_Msg4(module_id_t module_idP,
1, // tpc, none 1, // tpc, none
getRIV(N_RB_DL, first_rb, 4), // resource_block_coding getRIV(N_RB_DL, first_rb, 4), // resource_block_coding
ra->msg4_mcs, // mcs ra->msg4_mcs, // mcs
1 - UE_list->UE_template[CC_idP][UE_id].oldNDI[ra->harq_pid], 1 - UE_list->UE_template[CC_idP][UE_id].oldNDI[ra->harq_pid],
0, // rv 0, // rv
0); // vrb_flag 0); // vrb_flag
UE_list->UE_template[CC_idP][UE_id].oldNDI[ra->harq_pid] = 1 - UE_list->UE_template[CC_idP][UE_id].oldNDI[ra->harq_pid];
UE_list->UE_template[CC_idP][UE_id].oldNDI[ra->harq_pid] = 1 - UE_list->UE_template[CC_idP][UE_id].oldNDI[ra->harq_pid];
LOG_D(MAC, LOG_D(MAC,
"Frame %d, subframe %d: Msg4 DCI pdu_num %d (rnti %x,rnti_type %d,harq_pid %d, resource_block_coding (%p) %d\n", "Frame %d, subframe %d: Msg4 DCI pdu_num %d (rnti %x,rnti_type %d,harq_pid %d, resource_block_coding (%p) %d\n",
frameP, subframeP, dl_req_body->number_pdu, frameP, subframeP, dl_req_body->number_pdu,
...@@ -1054,7 +1050,7 @@ generate_Msg4(module_id_t module_idP, ...@@ -1054,7 +1050,7 @@ generate_Msg4(module_id_t module_idP,
mac->TX_req[CC_idP].sfn_sf = mac->TX_req[CC_idP].sfn_sf =
fill_nfapi_tx_req(&mac->TX_req[CC_idP].tx_request_body, fill_nfapi_tx_req(&mac->TX_req[CC_idP].tx_request_body,
(frameP * 10) + subframeP, (frameP * 10) + subframeP,
rrc_sdu_length+offset, rrc_sdu_length+offset,
mac->pdu_index[CC_idP], mac->pdu_index[CC_idP],
mac->UE_list. mac->UE_list.
DLSCH_pdu[CC_idP][0][(unsigned char)UE_id].payload[0]); DLSCH_pdu[CC_idP][0][(unsigned char)UE_id].payload[0]);
...@@ -1199,7 +1195,7 @@ check_Msg4_retransmission(module_id_t module_idP, int CC_idP, ...@@ -1199,7 +1195,7 @@ check_Msg4_retransmission(module_id_t module_idP, int CC_idP,
1, // tpc, none 1, // tpc, none
getRIV(N_RB_DL, first_rb, 4), // resource_block_coding getRIV(N_RB_DL, first_rb, 4), // resource_block_coding
ra->msg4_mcs, // mcs ra->msg4_mcs, // mcs
UE_list->UE_template[CC_idP][UE_id].oldNDI[ra->harq_pid], UE_list->UE_template[CC_idP][UE_id].oldNDI[ra->harq_pid],
round & 3, // rv round & 3, // rv
0); // vrb_flag 0); // vrb_flag
......
...@@ -46,7 +46,7 @@ ...@@ -46,7 +46,7 @@
#include "pdcp.h" #include "pdcp.h"
#if defined(ENABLE_ITTI) #if defined(ENABLE_ITTI)
#include "intertask_interface.h" #include "intertask_interface.h"
#endif #endif
#define ENABLE_MAC_PAYLOAD_DEBUG #define ENABLE_MAC_PAYLOAD_DEBUG
...@@ -78,228 +78,229 @@ int SIB1_BR_TBS_table[6] = { 208, 256, 328, 504, 712, 936 }; ...@@ -78,228 +78,229 @@ int SIB1_BR_TBS_table[6] = { 208, 256, 328, 504, 712, 936 };
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void void
schedule_SIB1_MBMS(module_id_t module_idP, schedule_SIB1_MBMS(module_id_t module_idP,
frame_t frameP, sub_frame_t subframeP) frame_t frameP, sub_frame_t subframeP)
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
{ {
#ifdef SCHEDULE_SIB1_MBMS #ifdef SCHEDULE_SIB1_MBMS
int8_t bcch_sdu_length; int8_t bcch_sdu_length;
int CC_id; int CC_id;
eNB_MAC_INST *eNB = RC.mac[module_idP]; eNB_MAC_INST *eNB = RC.mac[module_idP];
COMMON_channels_t *cc; COMMON_channels_t *cc;
uint8_t *vrb_map; uint8_t *vrb_map;
int first_rb = -1; int first_rb = -1;
int N_RB_DL; int N_RB_DL;
nfapi_dl_config_request_pdu_t *dl_config_pdu; nfapi_dl_config_request_pdu_t *dl_config_pdu;
nfapi_tx_request_pdu_t *TX_req; nfapi_tx_request_pdu_t *TX_req;
nfapi_dl_config_request_body_t *dl_req; nfapi_dl_config_request_body_t *dl_req;
int m, i, N_S_NB; int m, i, N_S_NB;
int *Sj; int *Sj;
int n_NB = 0; int n_NB = 0;
int TBS; int TBS;
int k = 0, rvidx; int k = 0, rvidx;
uint16_t sfn_sf = frameP<<4|subframeP; uint16_t sfn_sf = frameP<<4|subframeP;
for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
cc = &eNB->common_channels[CC_id];
vrb_map = (void *) &cc->vrb_map;
N_RB_DL = to_prb(cc->mib->message.dl_Bandwidth);
dl_req = &eNB->DL_req[CC_id].dl_config_request_body;
int foffset = cc->physCellId & 1;
int sfoffset = (cc->tdd_Config == NULL) ? 0 : 1;
for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { // Time-domain scheduling
if (cc->mib->message.schedulingInfoSIB1_BR_r13 == 0)
continue;
else
switch ((cc->mib->message.schedulingInfoSIB1_BR_r13 - 1) % 3) {
case 0: // repetition 4
k = (frameP >> 1) & 3;
if ((subframeP != (4 + sfoffset))
|| ((frameP & 1) != foffset))
continue;
break;
case 1: // repetition 8
k = frameP & 3;
AssertFatal(N_RB_DL > 15,
"SIB1-BR repetition 8 not allowed for N_RB_DL= %d\n",
N_RB_DL);
if ((foffset == 0) && (subframeP != (4 + sfoffset)))
continue;
else if ((foffset == 1)
&& (subframeP != ((9 + sfoffset) % 10)))
continue;
break;
case 2: // repetition 16
k = ((10 * frameP) + subframeP) & 3;
AssertFatal(N_RB_DL > 15,
"SIB1-BR repetition 16 not allowed for N_RB_DL= %d\n",
N_RB_DL);
if ((sfoffset == 1)
&& ((subframeP != 0) || (subframeP != 5)))
continue;
else if ((sfoffset == 0) && (foffset == 0)
&& (subframeP != 4) && (subframeP != 9))
continue;
else if ((sfoffset == 0) && (foffset == 1)
&& (subframeP != 0) && (subframeP != 9))
continue;
break;
}
// if we get here we have to schedule SIB1_BR in this frame/subframe
// keep counter of SIB1_BR repetitions in 8 frame period to choose narrowband on which to transmit
if ((frameP & 7) == 0)
cc->SIB1_BR_cnt = 0;
else
cc->SIB1_BR_cnt++;
// Frequency-domain scheduling
switch (N_RB_DL) {
case 6:
case 15:
default:
m = 1;
n_NB = 0;
N_S_NB = 0;
Sj = NULL;
break;
case 25:
m = 2;
N_S_NB = 2;
Sj = Sj25;
break;
case 50:
m = 2;
N_S_NB = 6;
Sj = Sj50;
break;
case 75:
m = 4;
N_S_NB = 10;
Sj = Sj75;
break;
case 100:
m = 4;
N_S_NB = 14;
Sj = Sj100;
break;
}
// Note: definition of k above and rvidx from 36.321 section 5.3.1
rvidx = (((3 * k) >> 1) + (k & 1)) & 3;
i = cc->SIB1_BR_cnt & (m - 1);
n_NB = Sj[((cc->physCellId % N_S_NB) + (i * N_S_NB / m)) % N_S_NB];
bcch_sdu_length = mac_rrc_data_req(module_idP, CC_id, frameP, BCCH_SIB1_BR, 1, &cc->BCCH_BR_pdu[0].payload[0], 0); // not used in this case
AssertFatal(cc->mib->message.schedulingInfoSIB1_BR_r13 < 19,
"schedulingInfoSIB1_BR_r13 %d > 18\n",
(int) cc->mib->message.schedulingInfoSIB1_BR_r13);
AssertFatal(bcch_sdu_length > 0,
"RRC returned 0 bytes for SIB1-BR\n");
TBS =
SIB1_BR_TBS_table[(cc->mib->message.schedulingInfoSIB1_BR_r13 -
1) / 3] >> 3;
AssertFatal(bcch_sdu_length <= TBS,
"length returned by RRC %d is not compatible with the TBS %d from MIB\n",
bcch_sdu_length, TBS);
if ((frameP & 1023) < 200)
LOG_D(MAC,
"[eNB %d] Frame %d Subframe %d: SIB1_BR->DLSCH CC_id %d, Received %d bytes, scheduling on NB %d (i %d,m %d,N_S_NB %d) rvidx %d\n",
module_idP, frameP, subframeP, CC_id, bcch_sdu_length,
n_NB, i, m, N_S_NB, rvidx);
// allocate all 6 PRBs in narrowband for SIB1_BR
first_rb = narrowband_to_first_rb(cc, n_NB);
vrb_map[first_rb] = 1;
vrb_map[first_rb + 1] = 1;
vrb_map[first_rb + 2] = 1;
vrb_map[first_rb + 3] = 1;
vrb_map[first_rb + 4] = 1;
vrb_map[first_rb + 5] = 1;
dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu];
memset((void *) dl_config_pdu, 0,
sizeof(nfapi_dl_config_request_pdu_t));
dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DLSCH_PDU_TYPE;
dl_config_pdu->pdu_size = (uint8_t) (2 + sizeof(nfapi_dl_config_dlsch_pdu));
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.tl.tag = NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL8_TAG;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.length = TBS;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pdu_index = eNB->pdu_index[CC_id];
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.rnti = 0xFFFF;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_allocation_type = 2; // format 1A/1B/1D
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.virtual_resource_block_assignment_flag = 0; // localized
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_block_coding = getRIV(N_RB_DL, first_rb, 6);
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.modulation = 2; //QPSK
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.redundancy_version = rvidx;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_blocks = 1; // first block
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_block_to_codeword_swap_flag = 0;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_scheme = (cc->p_eNB == 1) ? 0 : 1;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_layers = 1;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_subbands = 1;
// dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.codebook_index = ;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ue_category_capacity = 1;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pa = 4; // 0 dB
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.delta_power_offset_index = 0;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ngap = 0;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.nprb = get_subbandsize(cc->mib->message.dl_Bandwidth); // ignored
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_mode = (cc->p_eNB == 1) ? 1 : 2;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_prb_per_subband = 1;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_vector = 1;
// Rel10 fields
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel10.tl.tag = NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL10_TAG;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel10.pdsch_start = 3;
// Rel13 fields
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.tl.tag = NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL13_TAG;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.ue_type = CEMODEA;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.pdsch_payload_type = 0; // SIB1-BR
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.initial_transmission_sf_io = 0xFFFF; // absolute SFx
// dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.bf_vector = ;
dl_req->number_pdu++;
dl_req->tl.tag = NFAPI_DL_CONFIG_REQUEST_BODY_TAG;
// Program TX Request
TX_req = &eNB->TX_req[CC_id].tx_request_body.tx_pdu_list[eNB->TX_req[CC_id].tx_request_body.number_of_pdus];
TX_req->pdu_length = bcch_sdu_length;
TX_req->pdu_index = eNB->pdu_index[CC_id]++;
TX_req->num_segments = 1;
TX_req->segments[0].segment_length = bcch_sdu_length;
TX_req->segments[0].segment_data = cc->BCCH_BR_pdu[0].payload;
eNB->TX_req[CC_id].sfn_sf = sfn_sf;
eNB->TX_req[CC_id].tx_request_body.tl.tag = NFAPI_TX_REQUEST_BODY_TAG;
eNB->TX_req[CC_id].tx_request_body.number_of_pdus++;
eNB->TX_req[CC_id].header.message_id = NFAPI_TX_REQUEST;
if (opt_enabled == 1) {
trace_pdu(DIRECTION_DOWNLINK,
&cc->BCCH_BR_pdu[0].payload[0],
bcch_sdu_length,
0xffff, WS_SI_RNTI, 0xffff, eNB->frame, eNB->subframe, 0, 0);
LOG_D(OPT,
"[eNB %d][BCH] Frame %d trace pdu for CC_id %d rnti %x with size %d\n",
module_idP, frameP, CC_id, 0xffff, bcch_sdu_length);
}
cc = &eNB->common_channels[CC_id]; if (cc->tdd_Config != NULL) { //TDD
vrb_map = (void *) &cc->vrb_map; LOG_D(MAC,
N_RB_DL = to_prb(cc->mib->message.dl_Bandwidth); "[eNB] Frame %d : Scheduling BCCH-BR 0->DLSCH (TDD) for CC_id %d SIB1-BR %d bytes\n",
dl_req = &eNB->DL_req[CC_id].dl_config_request_body; frameP, CC_id, bcch_sdu_length);
} else {
int foffset = cc->physCellId & 1; LOG_D(MAC,
int sfoffset = (cc->tdd_Config == NULL) ? 0 : 1; "[eNB] Frame %d : Scheduling BCCH-BR 0->DLSCH (FDD) for CC_id %d SIB1-BR %d bytes\n",
frameP, CC_id, bcch_sdu_length);
// Time-domain scheduling
if (cc->mib->message.schedulingInfoSIB1_BR_r13 == 0)
continue;
else
switch ((cc->mib->message.schedulingInfoSIB1_BR_r13 - 1) % 3) {
case 0: // repetition 4
k = (frameP >> 1) & 3;
if ((subframeP != (4 + sfoffset))
|| ((frameP & 1) != foffset))
continue;
break;
case 1: // repetition 8
k = frameP & 3;
AssertFatal(N_RB_DL > 15,
"SIB1-BR repetition 8 not allowed for N_RB_DL= %d\n",
N_RB_DL);
if ((foffset == 0) && (subframeP != (4 + sfoffset)))
continue;
else if ((foffset == 1)
&& (subframeP != ((9 + sfoffset) % 10)))
continue;
break;
case 2: // repetition 16
k = ((10 * frameP) + subframeP) & 3;
AssertFatal(N_RB_DL > 15,
"SIB1-BR repetition 16 not allowed for N_RB_DL= %d\n",
N_RB_DL);
if ((sfoffset == 1)
&& ((subframeP != 0) || (subframeP != 5)))
continue;
else if ((sfoffset == 0) && (foffset == 0)
&& (subframeP != 4) && (subframeP != 9))
continue;
else if ((sfoffset == 0) && (foffset == 1)
&& (subframeP != 0) && (subframeP != 9))
continue;
break;
}
// if we get here we have to schedule SIB1_BR in this frame/subframe
// keep counter of SIB1_BR repetitions in 8 frame period to choose narrowband on which to transmit
if ((frameP & 7) == 0)
cc->SIB1_BR_cnt = 0;
else
cc->SIB1_BR_cnt++;
// Frequency-domain scheduling
switch (N_RB_DL) {
case 6:
case 15:
default:
m = 1;
n_NB = 0;
N_S_NB = 0;
Sj = NULL;
break;
case 25:
m = 2;
N_S_NB = 2;
Sj = Sj25;
break;
case 50:
m = 2;
N_S_NB = 6;
Sj = Sj50;
break;
case 75:
m = 4;
N_S_NB = 10;
Sj = Sj75;
break;
case 100:
m = 4;
N_S_NB = 14;
Sj = Sj100;
break;
}
// Note: definition of k above and rvidx from 36.321 section 5.3.1
rvidx = (((3 * k) >> 1) + (k & 1)) & 3;
i = cc->SIB1_BR_cnt & (m - 1);
n_NB = Sj[((cc->physCellId % N_S_NB) + (i * N_S_NB / m)) % N_S_NB];
bcch_sdu_length = mac_rrc_data_req(module_idP, CC_id, frameP, BCCH_SIB1_BR, 1, &cc->BCCH_BR_pdu[0].payload[0], 0); // not used in this case
AssertFatal(cc->mib->message.schedulingInfoSIB1_BR_r13 < 19,
"schedulingInfoSIB1_BR_r13 %d > 18\n",
(int) cc->mib->message.schedulingInfoSIB1_BR_r13);
AssertFatal(bcch_sdu_length > 0,
"RRC returned 0 bytes for SIB1-BR\n");
TBS =
SIB1_BR_TBS_table[(cc->mib->message.schedulingInfoSIB1_BR_r13 -
1) / 3] >> 3;
AssertFatal(bcch_sdu_length <= TBS,
"length returned by RRC %d is not compatible with the TBS %d from MIB\n",
bcch_sdu_length, TBS);
if ((frameP & 1023) < 200)
LOG_D(MAC,
"[eNB %d] Frame %d Subframe %d: SIB1_BR->DLSCH CC_id %d, Received %d bytes, scheduling on NB %d (i %d,m %d,N_S_NB %d) rvidx %d\n",
module_idP, frameP, subframeP, CC_id, bcch_sdu_length,
n_NB, i, m, N_S_NB, rvidx);
// allocate all 6 PRBs in narrowband for SIB1_BR
first_rb = narrowband_to_first_rb(cc, n_NB);
vrb_map[first_rb] = 1;
vrb_map[first_rb + 1] = 1;
vrb_map[first_rb + 2] = 1;
vrb_map[first_rb + 3] = 1;
vrb_map[first_rb + 4] = 1;
vrb_map[first_rb + 5] = 1;
dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu];
memset((void *) dl_config_pdu, 0,
sizeof(nfapi_dl_config_request_pdu_t));
dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DLSCH_PDU_TYPE;
dl_config_pdu->pdu_size = (uint8_t) (2 + sizeof(nfapi_dl_config_dlsch_pdu));
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.tl.tag = NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL8_TAG;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.length = TBS;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pdu_index = eNB->pdu_index[CC_id];
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.rnti = 0xFFFF;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_allocation_type = 2; // format 1A/1B/1D
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.virtual_resource_block_assignment_flag = 0; // localized
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_block_coding = getRIV(N_RB_DL, first_rb, 6);
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.modulation = 2; //QPSK
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.redundancy_version = rvidx;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_blocks = 1; // first block
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_block_to_codeword_swap_flag = 0;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_scheme = (cc->p_eNB == 1) ? 0 : 1;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_layers = 1;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_subbands = 1;
// dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.codebook_index = ;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ue_category_capacity = 1;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pa = 4; // 0 dB
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.delta_power_offset_index = 0;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ngap = 0;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.nprb = get_subbandsize(cc->mib->message.dl_Bandwidth); // ignored
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_mode = (cc->p_eNB == 1) ? 1 : 2;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_prb_per_subband = 1;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_vector = 1;
// Rel10 fields
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel10.tl.tag = NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL10_TAG;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel10.pdsch_start = 3;
// Rel13 fields
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.tl.tag = NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL13_TAG;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.ue_type = CEMODEA;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.pdsch_payload_type = 0; // SIB1-BR
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.initial_transmission_sf_io = 0xFFFF; // absolute SFx
// dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.bf_vector = ;
dl_req->number_pdu++;
dl_req->tl.tag = NFAPI_DL_CONFIG_REQUEST_BODY_TAG;
// Program TX Request
TX_req = &eNB->TX_req[CC_id].tx_request_body.tx_pdu_list[eNB->TX_req[CC_id].tx_request_body.number_of_pdus];
TX_req->pdu_length = bcch_sdu_length;
TX_req->pdu_index = eNB->pdu_index[CC_id]++;
TX_req->num_segments = 1;
TX_req->segments[0].segment_length = bcch_sdu_length;
TX_req->segments[0].segment_data = cc->BCCH_BR_pdu[0].payload;
eNB->TX_req[CC_id].sfn_sf = sfn_sf;
eNB->TX_req[CC_id].tx_request_body.tl.tag = NFAPI_TX_REQUEST_BODY_TAG;
eNB->TX_req[CC_id].tx_request_body.number_of_pdus++;
eNB->TX_req[CC_id].header.message_id = NFAPI_TX_REQUEST;
if (opt_enabled == 1) {
trace_pdu(DIRECTION_DOWNLINK,
&cc->BCCH_BR_pdu[0].payload[0],
bcch_sdu_length,
0xffff, WS_SI_RNTI, 0xffff, eNB->frame, eNB->subframe, 0, 0);
LOG_D(OPT,
"[eNB %d][BCH] Frame %d trace pdu for CC_id %d rnti %x with size %d\n",
module_idP, frameP, CC_id, 0xffff, bcch_sdu_length);
}
if (cc->tdd_Config != NULL) { //TDD
LOG_D(MAC,
"[eNB] Frame %d : Scheduling BCCH-BR 0->DLSCH (TDD) for CC_id %d SIB1-BR %d bytes\n",
frameP, CC_id, bcch_sdu_length);
} else {
LOG_D(MAC,
"[eNB] Frame %d : Scheduling BCCH-BR 0->DLSCH (FDD) for CC_id %d SIB1-BR %d bytes\n",
frameP, CC_id, bcch_sdu_length);
}
} }
}
#endif #endif
} }
...@@ -307,227 +308,227 @@ schedule_SIB1_MBMS(module_id_t module_idP, ...@@ -307,227 +308,227 @@ schedule_SIB1_MBMS(module_id_t module_idP,
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void void
schedule_SIB1_BR(module_id_t module_idP, schedule_SIB1_BR(module_id_t module_idP,
frame_t frameP, sub_frame_t subframeP) frame_t frameP, sub_frame_t subframeP)
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
{ {
int8_t bcch_sdu_length; int8_t bcch_sdu_length;
int CC_id; int CC_id;
eNB_MAC_INST *eNB = RC.mac[module_idP]; eNB_MAC_INST *eNB = RC.mac[module_idP];
COMMON_channels_t *cc; COMMON_channels_t *cc;
uint8_t *vrb_map; uint8_t *vrb_map;
int first_rb = -1; int first_rb = -1;
int N_RB_DL; int N_RB_DL;
nfapi_dl_config_request_pdu_t *dl_config_pdu; nfapi_dl_config_request_pdu_t *dl_config_pdu;
nfapi_tx_request_pdu_t *TX_req; nfapi_tx_request_pdu_t *TX_req;
nfapi_dl_config_request_body_t *dl_req; nfapi_dl_config_request_body_t *dl_req;
int m, i, N_S_NB; int m, i, N_S_NB;
int *Sj; int *Sj;
int n_NB = 0; int n_NB = 0;
int TBS; int TBS;
int k = 0, rvidx; int k = 0, rvidx;
uint16_t sfn_sf = frameP<<4|subframeP; uint16_t sfn_sf = frameP<<4|subframeP;
for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
cc = &eNB->common_channels[CC_id];
vrb_map = (void *) &cc->vrb_map;
N_RB_DL = to_prb(cc->mib->message.dl_Bandwidth);
dl_req = &eNB->DL_req[CC_id].dl_config_request_body;
int foffset = cc->physCellId & 1;
int sfoffset = (cc->tdd_Config == NULL) ? 0 : 1;
for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { // Time-domain scheduling
if (cc->mib->message.schedulingInfoSIB1_BR_r13 == 0)
continue;
else
switch ((cc->mib->message.schedulingInfoSIB1_BR_r13 - 1) % 3) {
case 0: // repetition 4
k = (frameP >> 1) & 3;
if ((subframeP != (4 + sfoffset))
|| ((frameP & 1) != foffset))
continue;
break;
case 1: // repetition 8
k = frameP & 3;
AssertFatal(N_RB_DL > 15,
"SIB1-BR repetition 8 not allowed for N_RB_DL= %d\n",
N_RB_DL);
if ((foffset == 0) && (subframeP != (4 + sfoffset)))
continue;
else if ((foffset == 1)
&& (subframeP != ((9 + sfoffset) % 10)))
continue;
break;
case 2: // repetition 16
k = ((10 * frameP) + subframeP) & 3;
AssertFatal(N_RB_DL > 15,
"SIB1-BR repetition 16 not allowed for N_RB_DL= %d\n",
N_RB_DL);
if ((sfoffset == 1)
&& ((subframeP != 0) || (subframeP != 5)))
continue;
else if ((sfoffset == 0) && (foffset == 0)
&& (subframeP != 4) && (subframeP != 9))
continue;
else if ((sfoffset == 0) && (foffset == 1)
&& (subframeP != 0) && (subframeP != 9))
continue;
break;
}
// if we get here we have to schedule SIB1_BR in this frame/subframe
// keep counter of SIB1_BR repetitions in 8 frame period to choose narrowband on which to transmit
if ((frameP & 7) == 0)
cc->SIB1_BR_cnt = 0;
else
cc->SIB1_BR_cnt++;
// Frequency-domain scheduling
switch (N_RB_DL) {
case 6:
case 15:
default:
m = 1;
n_NB = 0;
N_S_NB = 0;
Sj = NULL;
break;
case 25:
m = 2;
N_S_NB = 2;
Sj = Sj25;
break;
case 50:
m = 2;
N_S_NB = 6;
Sj = Sj50;
break;
case 75:
m = 4;
N_S_NB = 10;
Sj = Sj75;
break;
case 100:
m = 4;
N_S_NB = 14;
Sj = Sj100;
break;
}
// Note: definition of k above and rvidx from 36.321 section 5.3.1
rvidx = (((3 * k) >> 1) + (k & 1)) & 3;
i = cc->SIB1_BR_cnt & (m - 1);
n_NB = Sj[((cc->physCellId % N_S_NB) + (i * N_S_NB / m)) % N_S_NB];
bcch_sdu_length = mac_rrc_data_req(module_idP, CC_id, frameP, BCCH_SIB1_BR, 0xFFFF, 1, &cc->BCCH_BR_pdu[0].payload[0], 0); // not used in this case
AssertFatal(cc->mib->message.schedulingInfoSIB1_BR_r13 < 19,
"schedulingInfoSIB1_BR_r13 %d > 18\n",
(int) cc->mib->message.schedulingInfoSIB1_BR_r13);
AssertFatal(bcch_sdu_length > 0,
"RRC returned 0 bytes for SIB1-BR\n");
TBS =
SIB1_BR_TBS_table[(cc->mib->message.schedulingInfoSIB1_BR_r13 -
1) / 3] >> 3;
AssertFatal(bcch_sdu_length <= TBS,
"length returned by RRC %d is not compatible with the TBS %d from MIB\n",
bcch_sdu_length, TBS);
if ((frameP & 1023) < 200)
LOG_D(MAC,
"[eNB %d] Frame %d Subframe %d: SIB1_BR->DLSCH CC_id %d, Received %d bytes, scheduling on NB %d (i %d,m %d,N_S_NB %d) rvidx %d\n",
module_idP, frameP, subframeP, CC_id, bcch_sdu_length,
n_NB, i, m, N_S_NB, rvidx);
// allocate all 6 PRBs in narrowband for SIB1_BR
first_rb = narrowband_to_first_rb(cc, n_NB);
vrb_map[first_rb] = 1;
vrb_map[first_rb + 1] = 1;
vrb_map[first_rb + 2] = 1;
vrb_map[first_rb + 3] = 1;
vrb_map[first_rb + 4] = 1;
vrb_map[first_rb + 5] = 1;
dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu];
memset((void *) dl_config_pdu, 0,
sizeof(nfapi_dl_config_request_pdu_t));
dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DLSCH_PDU_TYPE;
dl_config_pdu->pdu_size = (uint8_t) (2 + sizeof(nfapi_dl_config_dlsch_pdu));
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.tl.tag = NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL8_TAG;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.length = TBS;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pdu_index = eNB->pdu_index[CC_id];
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.rnti = 0xFFFF;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_allocation_type = 2; // format 1A/1B/1D
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.virtual_resource_block_assignment_flag = 0; // localized
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_block_coding = getRIV(N_RB_DL, first_rb, 6);
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.modulation = 2; //QPSK
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.redundancy_version = rvidx;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_blocks = 1; // first block
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_block_to_codeword_swap_flag = 0;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_scheme = (cc->p_eNB == 1) ? 0 : 1;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_layers = 1;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_subbands = 1;
// dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.codebook_index = ;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ue_category_capacity = 1;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pa = 4; // 0 dB
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.delta_power_offset_index = 0;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ngap = 0;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.nprb = get_subbandsize(cc->mib->message.dl_Bandwidth); // ignored
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_mode = (cc->p_eNB == 1) ? 1 : 2;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_prb_per_subband = 1;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_vector = 1;
// Rel10 fields
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel10.tl.tag = NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL10_TAG;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel10.pdsch_start = 3;
// Rel13 fields
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.tl.tag = NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL13_TAG;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.ue_type = CEMODEA;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.pdsch_payload_type = 0; // SIB1-BR
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.initial_transmission_sf_io = 0xFFFF; // absolute SFx
// dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.bf_vector = ;
dl_req->number_pdu++;
dl_req->tl.tag = NFAPI_DL_CONFIG_REQUEST_BODY_TAG;
// Program TX Request
TX_req = &eNB->TX_req[CC_id].tx_request_body.tx_pdu_list[eNB->TX_req[CC_id].tx_request_body.number_of_pdus];
TX_req->pdu_length = bcch_sdu_length;
TX_req->pdu_index = eNB->pdu_index[CC_id]++;
TX_req->num_segments = 1;
TX_req->segments[0].segment_length = bcch_sdu_length;
TX_req->segments[0].segment_data = cc->BCCH_BR_pdu[0].payload;
eNB->TX_req[CC_id].sfn_sf = sfn_sf;
eNB->TX_req[CC_id].tx_request_body.tl.tag = NFAPI_TX_REQUEST_BODY_TAG;
eNB->TX_req[CC_id].tx_request_body.number_of_pdus++;
eNB->TX_req[CC_id].header.message_id = NFAPI_TX_REQUEST;
if (opt_enabled == 1) {
trace_pdu(DIRECTION_DOWNLINK,
&cc->BCCH_BR_pdu[0].payload[0],
bcch_sdu_length,
0xffff, WS_SI_RNTI, 0xffff, eNB->frame, eNB->subframe, 0, 0);
LOG_D(OPT,
"[eNB %d][BCH] Frame %d trace pdu for CC_id %d rnti %x with size %d\n",
module_idP, frameP, CC_id, 0xffff, bcch_sdu_length);
}
cc = &eNB->common_channels[CC_id]; if (cc->tdd_Config != NULL) { //TDD
vrb_map = (void *) &cc->vrb_map; LOG_D(MAC,
N_RB_DL = to_prb(cc->mib->message.dl_Bandwidth); "[eNB] Frame %d : Scheduling BCCH-BR 0->DLSCH (TDD) for CC_id %d SIB1-BR %d bytes\n",
dl_req = &eNB->DL_req[CC_id].dl_config_request_body; frameP, CC_id, bcch_sdu_length);
} else {
int foffset = cc->physCellId & 1; LOG_D(MAC,
int sfoffset = (cc->tdd_Config == NULL) ? 0 : 1; "[eNB] Frame %d : Scheduling BCCH-BR 0->DLSCH (FDD) for CC_id %d SIB1-BR %d bytes\n",
frameP, CC_id, bcch_sdu_length);
// Time-domain scheduling
if (cc->mib->message.schedulingInfoSIB1_BR_r13 == 0)
continue;
else
switch ((cc->mib->message.schedulingInfoSIB1_BR_r13 - 1) % 3) {
case 0: // repetition 4
k = (frameP >> 1) & 3;
if ((subframeP != (4 + sfoffset))
|| ((frameP & 1) != foffset))
continue;
break;
case 1: // repetition 8
k = frameP & 3;
AssertFatal(N_RB_DL > 15,
"SIB1-BR repetition 8 not allowed for N_RB_DL= %d\n",
N_RB_DL);
if ((foffset == 0) && (subframeP != (4 + sfoffset)))
continue;
else if ((foffset == 1)
&& (subframeP != ((9 + sfoffset) % 10)))
continue;
break;
case 2: // repetition 16
k = ((10 * frameP) + subframeP) & 3;
AssertFatal(N_RB_DL > 15,
"SIB1-BR repetition 16 not allowed for N_RB_DL= %d\n",
N_RB_DL);
if ((sfoffset == 1)
&& ((subframeP != 0) || (subframeP != 5)))
continue;
else if ((sfoffset == 0) && (foffset == 0)
&& (subframeP != 4) && (subframeP != 9))
continue;
else if ((sfoffset == 0) && (foffset == 1)
&& (subframeP != 0) && (subframeP != 9))
continue;
break;
}
// if we get here we have to schedule SIB1_BR in this frame/subframe
// keep counter of SIB1_BR repetitions in 8 frame period to choose narrowband on which to transmit
if ((frameP & 7) == 0)
cc->SIB1_BR_cnt = 0;
else
cc->SIB1_BR_cnt++;
// Frequency-domain scheduling
switch (N_RB_DL) {
case 6:
case 15:
default:
m = 1;
n_NB = 0;
N_S_NB = 0;
Sj = NULL;
break;
case 25:
m = 2;
N_S_NB = 2;
Sj = Sj25;
break;
case 50:
m = 2;
N_S_NB = 6;
Sj = Sj50;
break;
case 75:
m = 4;
N_S_NB = 10;
Sj = Sj75;
break;
case 100:
m = 4;
N_S_NB = 14;
Sj = Sj100;
break;
}
// Note: definition of k above and rvidx from 36.321 section 5.3.1
rvidx = (((3 * k) >> 1) + (k & 1)) & 3;
i = cc->SIB1_BR_cnt & (m - 1);
n_NB = Sj[((cc->physCellId % N_S_NB) + (i * N_S_NB / m)) % N_S_NB];
bcch_sdu_length = mac_rrc_data_req(module_idP, CC_id, frameP, BCCH_SIB1_BR, 0xFFFF, 1, &cc->BCCH_BR_pdu[0].payload[0], 0); // not used in this case
AssertFatal(cc->mib->message.schedulingInfoSIB1_BR_r13 < 19,
"schedulingInfoSIB1_BR_r13 %d > 18\n",
(int) cc->mib->message.schedulingInfoSIB1_BR_r13);
AssertFatal(bcch_sdu_length > 0,
"RRC returned 0 bytes for SIB1-BR\n");
TBS =
SIB1_BR_TBS_table[(cc->mib->message.schedulingInfoSIB1_BR_r13 -
1) / 3] >> 3;
AssertFatal(bcch_sdu_length <= TBS,
"length returned by RRC %d is not compatible with the TBS %d from MIB\n",
bcch_sdu_length, TBS);
if ((frameP & 1023) < 200)
LOG_D(MAC,
"[eNB %d] Frame %d Subframe %d: SIB1_BR->DLSCH CC_id %d, Received %d bytes, scheduling on NB %d (i %d,m %d,N_S_NB %d) rvidx %d\n",
module_idP, frameP, subframeP, CC_id, bcch_sdu_length,
n_NB, i, m, N_S_NB, rvidx);
// allocate all 6 PRBs in narrowband for SIB1_BR
first_rb = narrowband_to_first_rb(cc, n_NB);
vrb_map[first_rb] = 1;
vrb_map[first_rb + 1] = 1;
vrb_map[first_rb + 2] = 1;
vrb_map[first_rb + 3] = 1;
vrb_map[first_rb + 4] = 1;
vrb_map[first_rb + 5] = 1;
dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu];
memset((void *) dl_config_pdu, 0,
sizeof(nfapi_dl_config_request_pdu_t));
dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DLSCH_PDU_TYPE;
dl_config_pdu->pdu_size = (uint8_t) (2 + sizeof(nfapi_dl_config_dlsch_pdu));
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.tl.tag = NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL8_TAG;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.length = TBS;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pdu_index = eNB->pdu_index[CC_id];
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.rnti = 0xFFFF;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_allocation_type = 2; // format 1A/1B/1D
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.virtual_resource_block_assignment_flag = 0; // localized
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_block_coding = getRIV(N_RB_DL, first_rb, 6);
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.modulation = 2; //QPSK
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.redundancy_version = rvidx;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_blocks = 1; // first block
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_block_to_codeword_swap_flag = 0;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_scheme = (cc->p_eNB == 1) ? 0 : 1;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_layers = 1;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_subbands = 1;
// dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.codebook_index = ;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ue_category_capacity = 1;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pa = 4; // 0 dB
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.delta_power_offset_index = 0;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ngap = 0;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.nprb = get_subbandsize(cc->mib->message.dl_Bandwidth); // ignored
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_mode = (cc->p_eNB == 1) ? 1 : 2;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_prb_per_subband = 1;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_vector = 1;
// Rel10 fields
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel10.tl.tag = NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL10_TAG;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel10.pdsch_start = 3;
// Rel13 fields
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.tl.tag = NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL13_TAG;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.ue_type = CEMODEA;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.pdsch_payload_type = 0; // SIB1-BR
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.initial_transmission_sf_io = 0xFFFF; // absolute SFx
// dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.bf_vector = ;
dl_req->number_pdu++;
dl_req->tl.tag = NFAPI_DL_CONFIG_REQUEST_BODY_TAG;
// Program TX Request
TX_req = &eNB->TX_req[CC_id].tx_request_body.tx_pdu_list[eNB->TX_req[CC_id].tx_request_body.number_of_pdus];
TX_req->pdu_length = bcch_sdu_length;
TX_req->pdu_index = eNB->pdu_index[CC_id]++;
TX_req->num_segments = 1;
TX_req->segments[0].segment_length = bcch_sdu_length;
TX_req->segments[0].segment_data = cc->BCCH_BR_pdu[0].payload;
eNB->TX_req[CC_id].sfn_sf = sfn_sf;
eNB->TX_req[CC_id].tx_request_body.tl.tag = NFAPI_TX_REQUEST_BODY_TAG;
eNB->TX_req[CC_id].tx_request_body.number_of_pdus++;
eNB->TX_req[CC_id].header.message_id = NFAPI_TX_REQUEST;
if (opt_enabled == 1) {
trace_pdu(DIRECTION_DOWNLINK,
&cc->BCCH_BR_pdu[0].payload[0],
bcch_sdu_length,
0xffff, WS_SI_RNTI, 0xffff, eNB->frame, eNB->subframe, 0, 0);
LOG_D(OPT,
"[eNB %d][BCH] Frame %d trace pdu for CC_id %d rnti %x with size %d\n",
module_idP, frameP, CC_id, 0xffff, bcch_sdu_length);
}
if (cc->tdd_Config != NULL) { //TDD
LOG_D(MAC,
"[eNB] Frame %d : Scheduling BCCH-BR 0->DLSCH (TDD) for CC_id %d SIB1-BR %d bytes\n",
frameP, CC_id, bcch_sdu_length);
} else {
LOG_D(MAC,
"[eNB] Frame %d : Scheduling BCCH-BR 0->DLSCH (FDD) for CC_id %d SIB1-BR %d bytes\n",
frameP, CC_id, bcch_sdu_length);
}
} }
}
} }
int si_WindowLength_BR_r13tab[LTE_SystemInformationBlockType1_v1310_IEs__bandwidthReducedAccessRelatedInfo_r13__si_WindowLength_BR_r13_spare] = { 20, 40, 60, 80, 120, 160, 200 }; int si_WindowLength_BR_r13tab[LTE_SystemInformationBlockType1_v1310_IEs__bandwidthReducedAccessRelatedInfo_r13__si_WindowLength_BR_r13_spare] = { 20, 40, 60, 80, 120, 160, 200 };
...@@ -538,7 +539,7 @@ int si_WindowLength_MBMS_r14tab[8] = { 1, 2, 5, 10, 15, 20, 40, 80 }; ...@@ -538,7 +539,7 @@ int si_WindowLength_MBMS_r14tab[8] = { 1, 2, 5, 10, 15, 20, 40, 80 };
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void void
schedule_SI_BR(module_id_t module_idP, frame_t frameP, schedule_SI_BR(module_id_t module_idP, frame_t frameP,
sub_frame_t subframeP) sub_frame_t subframeP)
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
{ {
int8_t bcch_sdu_length; int8_t bcch_sdu_length;
...@@ -555,55 +556,48 @@ schedule_SI_BR(module_id_t module_idP, frame_t frameP, ...@@ -555,55 +556,48 @@ schedule_SI_BR(module_id_t module_idP, frame_t frameP,
int rvidx; int rvidx;
int absSF = (frameP*10)+subframeP; int absSF = (frameP*10)+subframeP;
for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
cc = &eNB->common_channels[CC_id]; cc = &eNB->common_channels[CC_id];
vrb_map = (void*)&cc->vrb_map; vrb_map = (void *)&cc->vrb_map;
N_RB_DL = to_prb(cc->mib->message.dl_Bandwidth); N_RB_DL = to_prb(cc->mib->message.dl_Bandwidth);
dl_req = &eNB->DL_req[CC_id].dl_config_request_body; dl_req = &eNB->DL_req[CC_id].dl_config_request_body;
// Time-domain scheduling // Time-domain scheduling
if (cc->mib->message.schedulingInfoSIB1_BR_r13==0) continue; if (cc->mib->message.schedulingInfoSIB1_BR_r13==0) continue;
else { else {
AssertFatal(cc->sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13!=NULL, AssertFatal(cc->sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13!=NULL,
"sib_v13ext->bandwidthReducedAccessRelatedInfo_r13 is null\n"); "sib_v13ext->bandwidthReducedAccessRelatedInfo_r13 is null\n");
LTE_SchedulingInfoList_BR_r13_t *schedulingInfoList_BR_r13 = cc->sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13->schedulingInfoList_BR_r13; LTE_SchedulingInfoList_BR_r13_t *schedulingInfoList_BR_r13 = cc->sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13->schedulingInfoList_BR_r13;
AssertFatal(schedulingInfoList_BR_r13!=NULL, AssertFatal(schedulingInfoList_BR_r13!=NULL,
"sib_v13ext->schedulingInfoList_BR_r13 is null\n"); "sib_v13ext->schedulingInfoList_BR_r13 is null\n");
LTE_SchedulingInfoList_t *schedulingInfoList = cc->schedulingInfoList; LTE_SchedulingInfoList_t *schedulingInfoList = cc->schedulingInfoList;
AssertFatal(schedulingInfoList_BR_r13->list.count==schedulingInfoList->list.count, AssertFatal(schedulingInfoList_BR_r13->list.count==schedulingInfoList->list.count,
"schedulingInfolist_BR.r13->list.count %d != schedulingInfoList.list.count %d\n", "schedulingInfolist_BR.r13->list.count %d != schedulingInfoList.list.count %d\n",
schedulingInfoList_BR_r13->list.count,schedulingInfoList->list.count); schedulingInfoList_BR_r13->list.count,schedulingInfoList->list.count);
AssertFatal(cc->sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13->si_WindowLength_BR_r13<=
AssertFatal(cc->sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13->si_WindowLength_BR_r13<=LTE_SystemInformationBlockType1_v1310_IEs__bandwidthReducedAccessRelatedInfo_r13__si_WindowLength_BR_r13_ms200, LTE_SystemInformationBlockType1_v1310_IEs__bandwidthReducedAccessRelatedInfo_r13__si_WindowLength_BR_r13_ms200,
"si_WindowLength_BR_r13 %d > %d\n", "si_WindowLength_BR_r13 %d > %d\n",
(int)cc->sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13->si_WindowLength_BR_r13, (int)cc->sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13->si_WindowLength_BR_r13,
LTE_SystemInformationBlockType1_v1310_IEs__bandwidthReducedAccessRelatedInfo_r13__si_WindowLength_BR_r13_ms200); LTE_SystemInformationBlockType1_v1310_IEs__bandwidthReducedAccessRelatedInfo_r13__si_WindowLength_BR_r13_ms200);
// check that SI frequency-hopping is disabled // check that SI frequency-hopping is disabled
AssertFatal(cc->sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13->si_HoppingConfigCommon_r13==LTE_SystemInformationBlockType1_v1310_IEs__bandwidthReducedAccessRelatedInfo_r13__si_HoppingConfigCommon_r13_off, AssertFatal(cc->sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13->si_HoppingConfigCommon_r13==
"Deactivate SI_HoppingConfigCommon_r13 in configuration file, not supported for now\n"); LTE_SystemInformationBlockType1_v1310_IEs__bandwidthReducedAccessRelatedInfo_r13__si_HoppingConfigCommon_r13_off,
"Deactivate SI_HoppingConfigCommon_r13 in configuration file, not supported for now\n");
long si_WindowLength_BR_r13 = si_WindowLength_BR_r13tab[cc->sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13->si_WindowLength_BR_r13]; long si_WindowLength_BR_r13 = si_WindowLength_BR_r13tab[cc->sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13->si_WindowLength_BR_r13];
long si_RepetitionPattern_r13 = cc->sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13->si_RepetitionPattern_r13; long si_RepetitionPattern_r13 = cc->sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13->si_RepetitionPattern_r13;
AssertFatal(si_RepetitionPattern_r13<=LTE_SystemInformationBlockType1_v1310_IEs__bandwidthReducedAccessRelatedInfo_r13__si_RepetitionPattern_r13_every8thRF, AssertFatal(si_RepetitionPattern_r13<=LTE_SystemInformationBlockType1_v1310_IEs__bandwidthReducedAccessRelatedInfo_r13__si_RepetitionPattern_r13_every8thRF,
"si_RepetitionPattern_r13 %d > %d\n", "si_RepetitionPattern_r13 %d > %d\n",
(int)si_RepetitionPattern_r13, (int)si_RepetitionPattern_r13,
LTE_SystemInformationBlockType1_v1310_IEs__bandwidthReducedAccessRelatedInfo_r13__si_RepetitionPattern_r13_every8thRF); LTE_SystemInformationBlockType1_v1310_IEs__bandwidthReducedAccessRelatedInfo_r13__si_RepetitionPattern_r13_every8thRF);
// cycle through SIB list // cycle through SIB list
for (i=0;i<schedulingInfoList_BR_r13->list.count;i++) { for (i=0; i<schedulingInfoList_BR_r13->list.count; i++) {
long si_Periodicity = schedulingInfoList->list.array[i]->si_Periodicity; long si_Periodicity = schedulingInfoList->list.array[i]->si_Periodicity;
long si_Narrowband_r13 = schedulingInfoList_BR_r13->list.array[i]->si_Narrowband_r13; long si_Narrowband_r13 = schedulingInfoList_BR_r13->list.array[i]->si_Narrowband_r13;
long si_TBS_r13 = si_TBS_r13tab[schedulingInfoList_BR_r13->list.array[i]->si_TBS_r13]; long si_TBS_r13 = si_TBS_r13tab[schedulingInfoList_BR_r13->list.array[i]->si_TBS_r13];
// check if the SI is to be scheduled now // check if the SI is to be scheduled now
int period_in_sf; int period_in_sf;
if ((si_Periodicity >= 0) && (si_Periodicity < 25)) { if ((si_Periodicity >= 0) && (si_Periodicity < 25)) {
// 2^i * 80 subframes, note: si_Periodicity is 2^i * 80ms // 2^i * 80 subframes, note: si_Periodicity is 2^i * 80ms
period_in_sf = 80 << ((int) si_Periodicity); period_in_sf = 80 << ((int) si_Periodicity);
...@@ -612,19 +606,17 @@ schedule_SI_BR(module_id_t module_idP, frame_t frameP, ...@@ -612,19 +606,17 @@ schedule_SI_BR(module_id_t module_idP, frame_t frameP,
} else if (si_Periodicity > 24) { } else if (si_Periodicity > 24) {
period_in_sf = 80 << 24; period_in_sf = 80 << 24;
} }
int sf_mod_period = absSF % period_in_sf; int sf_mod_period = absSF % period_in_sf;
int k = sf_mod_period & 3; int k = sf_mod_period & 3;
// Note: definition of k and rvidx from 36.321 section 5.3.1 // Note: definition of k and rvidx from 36.321 section 5.3.1
rvidx = (((3 * k) >> 1) + (k & 1)) & 3; rvidx = (((3 * k) >> 1) + (k & 1)) & 3;
if ((sf_mod_period < si_WindowLength_BR_r13) if ((sf_mod_period < si_WindowLength_BR_r13)
&& ((frameP & (((1 << si_RepetitionPattern_r13) - 1))) == 0)) { // this SIB is to be scheduled && ((frameP & (((1 << si_RepetitionPattern_r13) - 1))) == 0)) { // this SIB is to be scheduled
bcch_sdu_length = mac_rrc_data_req(module_idP, CC_id, frameP, BCCH_SI_BR + i, 0xFFFF, 1, &cc->BCCH_BR_pdu[i + 1].payload[0], 0); // not used in this case
bcch_sdu_length = mac_rrc_data_req(module_idP, CC_id, frameP, BCCH_SI_BR + i, 0xFFFF, 1, &cc->BCCH_BR_pdu[i + 1].payload[0], 0); // not used in this case
AssertFatal(bcch_sdu_length > 0, AssertFatal(bcch_sdu_length > 0,
"RRC returned 0 bytes for SI-BR %d\n", i); "RRC returned 0 bytes for SI-BR %d\n", i);
if (bcch_sdu_length > 0) { if (bcch_sdu_length > 0) {
AssertFatal(bcch_sdu_length <= (si_TBS_r13 >> 3), AssertFatal(bcch_sdu_length <= (si_TBS_r13 >> 3),
...@@ -647,23 +639,20 @@ schedule_SI_BR(module_id_t module_idP, frame_t frameP, ...@@ -647,23 +639,20 @@ schedule_SI_BR(module_id_t module_idP, frame_t frameP,
if ((frameP&1023) < 200) if ((frameP&1023) < 200)
LOG_D(MAC,"[eNB %d] Frame %d Subframe %d: SI_BR->DLSCH CC_id %d, Narrowband %d rvidx %d (sf_mod_period %d : si_WindowLength_BR_r13 %d : si_RepetitionPattern_r13 %d) bcch_sdu_length %d\n", LOG_D(MAC,"[eNB %d] Frame %d Subframe %d: SI_BR->DLSCH CC_id %d, Narrowband %d rvidx %d (sf_mod_period %d : si_WindowLength_BR_r13 %d : si_RepetitionPattern_r13 %d) bcch_sdu_length %d\n",
module_idP,frameP,subframeP,CC_id,(int)si_Narrowband_r13-1,rvidx, module_idP,frameP,subframeP,CC_id,(int)si_Narrowband_r13-1,rvidx,
sf_mod_period,(int)si_WindowLength_BR_r13,(int)si_RepetitionPattern_r13, sf_mod_period,(int)si_WindowLength_BR_r13,(int)si_RepetitionPattern_r13,
bcch_sdu_length); bcch_sdu_length);
//// Rel10 fields (for PDSCH starting symbol) //// Rel10 fields (for PDSCH starting symbol)
//dl_config_pdu->dlsch_pdu.dlsch_pdu_rel10.pdsch_start = cc[CC_id].sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13->startSymbolBR_r13; //dl_config_pdu->dlsch_pdu.dlsch_pdu_rel10.pdsch_start = cc[CC_id].sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13->startSymbolBR_r13;
//// Rel13 fields //// Rel13 fields
// dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.tl.tag = NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL13_TAG; // dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.tl.tag = NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL13_TAG;
//dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.ue_type = 1; // CEModeA UE //dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.ue_type = 1; // CEModeA UE
//dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.pdsch_payload_type = 1; // SI-BR //dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.pdsch_payload_type = 1; // SI-BR
//dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.initial_transmission_sf_io = absSF - sf_mod_period; //dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.initial_transmission_sf_io = absSF - sf_mod_period;
//// dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.bf_vector = ; //// dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.bf_vector = ;
//dl_req->number_pdu++; //dl_req->number_pdu++;
// dl_req->tl.tag = NFAPI_DL_CONFIG_REQUEST_BODY_TAG; // dl_req->tl.tag = NFAPI_DL_CONFIG_REQUEST_BODY_TAG;
dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu];
memset((void *) dl_config_pdu, 0, sizeof(nfapi_dl_config_request_pdu_t)); memset((void *) dl_config_pdu, 0, sizeof(nfapi_dl_config_request_pdu_t));
dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DLSCH_PDU_TYPE; dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DLSCH_PDU_TYPE;
...@@ -681,7 +670,7 @@ schedule_SI_BR(module_id_t module_idP, frame_t frameP, ...@@ -681,7 +670,7 @@ schedule_SI_BR(module_id_t module_idP, frame_t frameP,
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_scheme = (cc->p_eNB==1 ) ? 0 : 1; dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_scheme = (cc->p_eNB==1 ) ? 0 : 1;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_layers = 1; dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_layers = 1;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_subbands = 1; dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_subbands = 1;
// dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.codebook_index = ; // dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.codebook_index = ;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ue_category_capacity = 1; dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ue_category_capacity = 1;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pa = 4; // 0 dB dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pa = 4; // 0 dB
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.delta_power_offset_index = 0; dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.delta_power_offset_index = 0;
...@@ -696,10 +685,8 @@ schedule_SI_BR(module_id_t module_idP, frame_t frameP, ...@@ -696,10 +685,8 @@ schedule_SI_BR(module_id_t module_idP, frame_t frameP,
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.ue_type = CEMODEA; dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.ue_type = CEMODEA;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.pdsch_payload_type = 1; // SI-BR dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.pdsch_payload_type = 1; // SI-BR
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.initial_transmission_sf_io = absSF - sf_mod_period; dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.initial_transmission_sf_io = absSF - sf_mod_period;
// dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.bf_vector = ;
// dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.bf_vector = ;
dl_req->number_pdu++; dl_req->number_pdu++;
// Program TX Request // Program TX Request
TX_req = &eNB->TX_req[CC_id].tx_request_body.tx_pdu_list[eNB->TX_req[CC_id].tx_request_body.number_of_pdus]; TX_req = &eNB->TX_req[CC_id].tx_request_body.tx_pdu_list[eNB->TX_req[CC_id].tx_request_body.number_of_pdus];
TX_req->pdu_length = bcch_sdu_length; TX_req->pdu_length = bcch_sdu_length;
...@@ -710,28 +697,30 @@ schedule_SI_BR(module_id_t module_idP, frame_t frameP, ...@@ -710,28 +697,30 @@ schedule_SI_BR(module_id_t module_idP, frame_t frameP,
eNB->TX_req[CC_id].tx_request_body.number_of_pdus++; eNB->TX_req[CC_id].tx_request_body.number_of_pdus++;
if (opt_enabled == 1) { if (opt_enabled == 1) {
trace_pdu(DIRECTION_DOWNLINK, trace_pdu(DIRECTION_DOWNLINK,
&cc->BCCH_BR_pdu[i + 1].payload[0], &cc->BCCH_BR_pdu[i + 1].payload[0],
bcch_sdu_length, bcch_sdu_length,
0xffff, 0xffff,
WS_SI_RNTI, WS_SI_RNTI,
0xffff, eNB->frame, eNB->subframe, 0, 0xffff, eNB->frame, eNB->subframe, 0,
0); 0);
LOG_D(OPT, "[eNB %d][BCH] Frame %d trace pdu for CC_id %d rnti %x with size %d\n", LOG_D(OPT, "[eNB %d][BCH] Frame %d trace pdu for CC_id %d rnti %x with size %d\n",
module_idP, frameP, CC_id, 0xffff, bcch_sdu_length); module_idP, frameP, CC_id, 0xffff, bcch_sdu_length);
} }
if (cc->tdd_Config != NULL) { //TDD
LOG_D(MAC, "[eNB] Frame %d : Scheduling BCCH-BR %d->DLSCH (TDD) for CC_id %d SI-BR %d bytes\n", if (cc->tdd_Config != NULL) { //TDD
frameP, i, CC_id, bcch_sdu_length); LOG_D(MAC, "[eNB] Frame %d : Scheduling BCCH-BR %d->DLSCH (TDD) for CC_id %d SI-BR %d bytes\n",
frameP, i, CC_id, bcch_sdu_length);
} else { } else {
LOG_D(MAC, "[eNB] Frame %d : Scheduling BCCH-BR %d->DLSCH (FDD) for CC_id %d SI-BR %d bytes\n", LOG_D(MAC, "[eNB] Frame %d : Scheduling BCCH-BR %d->DLSCH (FDD) for CC_id %d SI-BR %d bytes\n",
frameP, i, CC_id, bcch_sdu_length); frameP, i, CC_id, bcch_sdu_length);
} }
} }
} // scheduling in current frame/subframe } // scheduling in current frame/subframe
} //for SI List } //for SI List
} // eMTC is activated } // eMTC is activated
} // CC_id } // CC_id
return; return;
} }
...@@ -739,300 +728,281 @@ schedule_SI_BR(module_id_t module_idP, frame_t frameP, ...@@ -739,300 +728,281 @@ schedule_SI_BR(module_id_t module_idP, frame_t frameP,
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void void
schedule_SI_MBMS(module_id_t module_idP, frame_t frameP, schedule_SI_MBMS(module_id_t module_idP, frame_t frameP,
sub_frame_t subframeP) sub_frame_t subframeP)
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
{ {
int8_t bcch_sdu_length; int8_t bcch_sdu_length;
int mcs = -1; int mcs = -1;
int CC_id; int CC_id;
eNB_MAC_INST *eNB = RC.mac[module_idP]; eNB_MAC_INST *eNB = RC.mac[module_idP];
COMMON_channels_t *cc; COMMON_channels_t *cc;
uint8_t *vrb_map; uint8_t *vrb_map;
int first_rb = -1; int first_rb = -1;
int N_RB_DL; int N_RB_DL;
nfapi_dl_config_request_t *dl_config_request; nfapi_dl_config_request_t *dl_config_request;
nfapi_dl_config_request_pdu_t *dl_config_pdu; nfapi_dl_config_request_pdu_t *dl_config_pdu;
nfapi_tx_request_pdu_t *TX_req; nfapi_tx_request_pdu_t *TX_req;
nfapi_dl_config_request_body_t *dl_req; nfapi_dl_config_request_body_t *dl_req;
uint16_t sfn_sf = frameP << 4 | subframeP; uint16_t sfn_sf = frameP << 4 | subframeP;
start_meas(&eNB->schedule_si_mbms);
start_meas(&eNB->schedule_si_mbms);
// Only schedule LTE System Information in subframe 0
// Only schedule LTE System Information in subframe 0 if (subframeP == 0) {
if (subframeP == 0) { for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
cc = &eNB->common_channels[CC_id];
for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { vrb_map = (void *) &cc->vrb_map;
N_RB_DL = to_prb(cc->mib->message.dl_Bandwidth);
cc = &eNB->common_channels[CC_id]; dl_config_request = &eNB->DL_req[CC_id];
vrb_map = (void *) &cc->vrb_map; dl_req = &eNB->DL_req[CC_id].dl_config_request_body;
N_RB_DL = to_prb(cc->mib->message.dl_Bandwidth); bcch_sdu_length = mac_rrc_data_req(module_idP, CC_id, frameP, BCCH_SI_MBMS,0xFFFF, 1, &cc->BCCH_MBMS_pdu.payload[0], 0); // not used in this case
dl_config_request = &eNB->DL_req[CC_id];
dl_req = &eNB->DL_req[CC_id].dl_config_request_body; if (bcch_sdu_length > 0) {
LOG_D(MAC, "[eNB %d] Frame %d : BCCH-MBMS->DLSCH CC_id %d, Received %d bytes \n", module_idP, frameP, CC_id, bcch_sdu_length);
bcch_sdu_length = mac_rrc_data_req(module_idP, CC_id, frameP, BCCH_SI_MBMS,0xFFFF, 1, &cc->BCCH_MBMS_pdu.payload[0], 0); // not used in this case // Allocate 4 PRBs in a random location
/*
if (bcch_sdu_length > 0) { while (1) {
LOG_D(MAC, "[eNB %d] Frame %d : BCCH-MBMS->DLSCH CC_id %d, Received %d bytes \n", module_idP, frameP, CC_id, bcch_sdu_length); first_rb = (unsigned char)(taus()%(PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.N_RB_DL-4));
if ((vrb_map[first_rb] != 1) &&
// Allocate 4 PRBs in a random location (vrb_map[first_rb+1] != 1) &&
/* (vrb_map[first_rb+2] != 1) &&
while (1) { (vrb_map[first_rb+3] != 1))
first_rb = (unsigned char)(taus()%(PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.N_RB_DL-4)); break;
if ((vrb_map[first_rb] != 1) && }
(vrb_map[first_rb+1] != 1) && */
(vrb_map[first_rb+2] != 1) && switch (N_RB_DL) {
(vrb_map[first_rb+3] != 1)) case 6:
break; first_rb = 0;
} break;
*/
switch (N_RB_DL) { case 15:
case 6: first_rb = 6;
first_rb = 0; break;
break;
case 15: case 25:
first_rb = 6; first_rb = 11;
break; break;
case 25:
first_rb = 11; case 50:
break; first_rb = 23;
case 50: break;
first_rb = 23;
break; case 100:
case 100: first_rb = 48;
first_rb = 48; break;
break; }
}
vrb_map[first_rb] = 1;
vrb_map[first_rb + 1] = 1;
vrb_map[first_rb + 2] = 1;
vrb_map[first_rb + 3] = 1;
// Get MCS for length of SI, 3 PRBs
if (bcch_sdu_length <= 7) {
mcs = 0;
} else if (bcch_sdu_length <= 11) {
mcs = 1;
} else if (bcch_sdu_length <= 18) {
mcs = 2;
} else if (bcch_sdu_length <= 22) {
mcs = 3;
} else if (bcch_sdu_length <= 26) {
mcs = 4;
} else if (bcch_sdu_length <= 28) {
mcs = 5;
} else if (bcch_sdu_length <= 32) {
mcs = 6;
} else if (bcch_sdu_length <= 41) {
mcs = 7;
} else if (bcch_sdu_length <= 49) {
mcs = 8;
}
dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu];
memset((void *) dl_config_pdu, 0,
sizeof(nfapi_dl_config_request_pdu_t));
dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE;
dl_config_pdu->pdu_size = (uint8_t) (2 + sizeof(nfapi_dl_config_dci_dl_pdu));
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tl.tag = NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG;
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format = NFAPI_DL_DCI_FORMAT_1A;
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level = 4;
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti = 0xFFFF;
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type = 2; // S-RNTI : see Table 4-10 from SCF082 - nFAPI specifications
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.transmission_power = 6000; // equal to RS power
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.harq_process = 0;
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tpc = 1; // no TPC
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.new_data_indicator_1 = 0;
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = mcs;
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_1 = 0;
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding = getRIV(N_RB_DL, first_rb, 4);
dl_config_request->sfn_sf = sfn_sf;
if (!CCE_allocation_infeasible(module_idP, CC_id, 0, subframeP,dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level, SI_RNTI)) {
LOG_D(MAC, "Frame %d: Subframe %d : Adding common DCI for S_RNTI MBMS\n", frameP, subframeP);
dl_req->number_dci++;
dl_req->number_pdu++;
dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu];
memset((void *) dl_config_pdu, 0,
sizeof(nfapi_dl_config_request_pdu_t));
dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DLSCH_PDU_TYPE;
dl_config_pdu->pdu_size = (uint8_t) (2 + sizeof(nfapi_dl_config_dlsch_pdu));
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pdu_index = eNB->pdu_index[CC_id];
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.tl.tag = NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL8_TAG;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.length = bcch_sdu_length;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.rnti = 0xFFFF;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_allocation_type = 2; // format 1A/1B/1D
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.virtual_resource_block_assignment_flag = 0; // localized
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_block_coding = getRIV(N_RB_DL, first_rb, 4);
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.modulation = 2; //QPSK
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.redundancy_version = 0;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_blocks = 1; // first block
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_block_to_codeword_swap_flag = 0; dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_scheme = (cc->p_eNB == 1) ? 0 : 1;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_layers = 1;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_subbands = 1;
// dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.codebook_index = ;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ue_category_capacity = 1;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pa = 4; // 0 dB
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.delta_power_offset_index = 0;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ngap = 0;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.nprb = get_subbandsize(cc->mib->message.dl_Bandwidth); // ignored
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_mode = (cc->p_eNB == 1) ? 1 : 2;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_prb_per_subband = 1;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_vector = 1;
// dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.bf_vector = ;
dl_req->number_pdu++;
// Rel10 fields
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel10.tl.tag = NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL10_TAG;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel10.pdsch_start = 3;
// Rel13 fields
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.tl.tag = NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL13_TAG;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.ue_type = NOCE; // regular UE
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.pdsch_payload_type = 2; // not BR
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.initial_transmission_sf_io = 0xFFFF; // absolute SF
dl_config_request->header.message_id = NFAPI_DL_CONFIG_REQUEST;
dl_config_request->sfn_sf = sfn_sf;
// Program TX Request
TX_req = &eNB->TX_req[CC_id].tx_request_body.tx_pdu_list[eNB->TX_req[CC_id].tx_request_body.number_of_pdus];
TX_req->pdu_length = bcch_sdu_length;
TX_req->pdu_index = eNB->pdu_index[CC_id]++;
TX_req->num_segments = 1;
TX_req->segments[0].segment_length = bcch_sdu_length;
TX_req->segments[0].segment_data = cc->BCCH_MBMS_pdu.payload;
eNB->TX_req[CC_id].tx_request_body.number_of_pdus++;
eNB->TX_req[CC_id].sfn_sf = sfn_sf;
eNB->TX_req[CC_id].tx_request_body.tl.tag = NFAPI_TX_REQUEST_BODY_TAG;
eNB->TX_req[CC_id].header.message_id = NFAPI_TX_REQUEST;
} else {
LOG_E(MAC,
"[eNB %d] CCid %d Frame %d, subframe %d : Cannot add DCI 1A for SI MBMS\n",
module_idP, CC_id, frameP, subframeP);
}
T(T_ENB_MAC_UE_DL_PDU_WITH_DATA, T_INT(module_idP), T_INT(CC_id), T_INT(0xffff),
T_INT(frameP), T_INT(subframeP), T_INT(0), T_BUFFER(cc->BCCH_MBMS_pdu.payload, bcch_sdu_length));
if (opt_enabled == 1) {
trace_pdu(DIRECTION_DOWNLINK,
&cc->BCCH_MBMS_pdu.payload[0],
bcch_sdu_length,
0xffff,
WS_SI_RNTI, 0xffff, eNB->frame, eNB->subframe, 0, 0);
LOG_D(OPT,
"[eNB %d][BCH-MBMS] Frame %d trace pdu for CC_id %d rnti %x with size %d\n",
module_idP, frameP, CC_id, 0xffff,
bcch_sdu_length);
}
if (0/*cc->tdd_Config != NULL*/) { //TDD not for FeMBMS
LOG_D(MAC,
"[eNB] Frame %d : Scheduling BCCH->DLSCH (TDD) for CC_id %d SI %d bytes (mcs %d, rb 3)\n",
frameP, CC_id, bcch_sdu_length, mcs);
} else {
LOG_D(MAC, "[eNB] Frame %d : Scheduling BCCH-MBMS->DLSCH (FDD) for CC_id %d SI %d bytes (mcs %d, rb 3)\n", frameP, CC_id, bcch_sdu_length, mcs);
}
eNB->eNB_stats[CC_id].total_num_bcch_pdu += 1;
eNB->eNB_stats[CC_id].bcch_buffer = bcch_sdu_length;
eNB->eNB_stats[CC_id].total_bcch_buffer += bcch_sdu_length;
eNB->eNB_stats[CC_id].bcch_mcs = mcs;
//printf("SI %d.%d\n", frameP, subframeP);/////////////////////////////////////////******************************
} else {
//LOG_D(MAC,"[eNB %d] Frame %d : BCCH not active \n",Mod_id,frame);
}
}
}
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
//schedule_SIB1_BR(module_idP, frameP, subframeP);
//schedule_SI_BR(module_idP, frameP, subframeP);
#endif
stop_meas(&eNB->schedule_si_mbms);
}
#endif
void vrb_map[first_rb] = 1;
schedule_mib(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP) vrb_map[first_rb + 1] = 1;
{ vrb_map[first_rb + 2] = 1;
eNB_MAC_INST *eNB = RC.mac[module_idP]; vrb_map[first_rb + 3] = 1;
COMMON_channels_t *cc;
nfapi_dl_config_request_pdu_t *dl_config_pdu; // Get MCS for length of SI, 3 PRBs
nfapi_tx_request_pdu_t *TX_req; if (bcch_sdu_length <= 7) {
int mib_sdu_length; mcs = 0;
int CC_id; } else if (bcch_sdu_length <= 11) {
nfapi_dl_config_request_t *dl_config_request; mcs = 1;
nfapi_dl_config_request_body_t *dl_req; } else if (bcch_sdu_length <= 18) {
uint16_t sfn_sf = frameP << 4 | subframeP; mcs = 2;
} else if (bcch_sdu_length <= 22) {
AssertFatal(subframeP == 0, "Subframe must be 0\n"); mcs = 3;
AssertFatal((frameP & 3) == 0, "Frame must be a multiple of 4\n"); } else if (bcch_sdu_length <= 26) {
mcs = 4;
} else if (bcch_sdu_length <= 28) {
mcs = 5;
} else if (bcch_sdu_length <= 32) {
mcs = 6;
} else if (bcch_sdu_length <= 41) {
mcs = 7;
} else if (bcch_sdu_length <= 49) {
mcs = 8;
}
for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu];
memset((void *) dl_config_pdu, 0,
sizeof(nfapi_dl_config_request_pdu_t));
dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE;
dl_config_pdu->pdu_size = (uint8_t) (2 + sizeof(nfapi_dl_config_dci_dl_pdu));
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tl.tag = NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG;
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format = NFAPI_DL_DCI_FORMAT_1A;
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level = 4;
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti = 0xFFFF;
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type = 2; // S-RNTI : see Table 4-10 from SCF082 - nFAPI specifications
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.transmission_power = 6000; // equal to RS power
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.harq_process = 0;
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tpc = 1; // no TPC
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.new_data_indicator_1 = 0;
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = mcs;
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_1 = 0;
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding = getRIV(N_RB_DL, first_rb, 4);
dl_config_request->sfn_sf = sfn_sf;
if (!CCE_allocation_infeasible(module_idP, CC_id, 0, subframeP,dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level, SI_RNTI)) {
LOG_D(MAC, "Frame %d: Subframe %d : Adding common DCI for S_RNTI MBMS\n", frameP, subframeP);
dl_req->number_dci++;
dl_req->number_pdu++;
dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu];
memset((void *) dl_config_pdu, 0,
sizeof(nfapi_dl_config_request_pdu_t));
dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DLSCH_PDU_TYPE;
dl_config_pdu->pdu_size = (uint8_t) (2 + sizeof(nfapi_dl_config_dlsch_pdu));
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pdu_index = eNB->pdu_index[CC_id];
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.tl.tag = NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL8_TAG;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.length = bcch_sdu_length;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.rnti = 0xFFFF;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_allocation_type = 2; // format 1A/1B/1D
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.virtual_resource_block_assignment_flag = 0; // localized
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_block_coding = getRIV(N_RB_DL, first_rb, 4);
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.modulation = 2; //QPSK
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.redundancy_version = 0;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_blocks = 1; // first block
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_block_to_codeword_swap_flag = 0;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_scheme = (cc->p_eNB == 1) ? 0 : 1;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_layers = 1;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_subbands = 1;
// dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.codebook_index = ;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ue_category_capacity = 1;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pa = 4; // 0 dB
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.delta_power_offset_index = 0;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ngap = 0;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.nprb = get_subbandsize(cc->mib->message.dl_Bandwidth); // ignored
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_mode = (cc->p_eNB == 1) ? 1 : 2;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_prb_per_subband = 1;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_vector = 1;
// dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.bf_vector = ;
dl_req->number_pdu++;
// Rel10 fields
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel10.tl.tag = NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL10_TAG;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel10.pdsch_start = 3;
// Rel13 fields
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.tl.tag = NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL13_TAG;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.ue_type = NOCE; // regular UE
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.pdsch_payload_type = 2; // not BR
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.initial_transmission_sf_io = 0xFFFF; // absolute SF
dl_config_request->header.message_id = NFAPI_DL_CONFIG_REQUEST;
dl_config_request->sfn_sf = sfn_sf;
// Program TX Request
TX_req = &eNB->TX_req[CC_id].tx_request_body.tx_pdu_list[eNB->TX_req[CC_id].tx_request_body.number_of_pdus];
TX_req->pdu_length = bcch_sdu_length;
TX_req->pdu_index = eNB->pdu_index[CC_id]++;
TX_req->num_segments = 1;
TX_req->segments[0].segment_length = bcch_sdu_length;
TX_req->segments[0].segment_data = cc->BCCH_MBMS_pdu.payload;
eNB->TX_req[CC_id].tx_request_body.number_of_pdus++;
eNB->TX_req[CC_id].sfn_sf = sfn_sf;
eNB->TX_req[CC_id].tx_request_body.tl.tag = NFAPI_TX_REQUEST_BODY_TAG;
eNB->TX_req[CC_id].header.message_id = NFAPI_TX_REQUEST;
} else {
LOG_E(MAC,
"[eNB %d] CCid %d Frame %d, subframe %d : Cannot add DCI 1A for SI MBMS\n",
module_idP, CC_id, frameP, subframeP);
}
dl_config_request = &eNB->DL_req[CC_id]; T(T_ENB_MAC_UE_DL_PDU_WITH_DATA, T_INT(module_idP), T_INT(CC_id), T_INT(0xffff),
dl_req = &dl_config_request->dl_config_request_body; T_INT(frameP), T_INT(subframeP), T_INT(0), T_BUFFER(cc->BCCH_MBMS_pdu.payload, bcch_sdu_length));
cc = &eNB->common_channels[CC_id];
mib_sdu_length = mac_rrc_data_req(module_idP, CC_id, frameP, MIBCH, 0xFFFF, 1, &cc->MIB_pdu.payload[0], 0); // not used in this case if (opt_enabled == 1) {
trace_pdu(DIRECTION_DOWNLINK,
&cc->BCCH_MBMS_pdu.payload[0],
bcch_sdu_length,
0xffff,
WS_SI_RNTI, 0xffff, eNB->frame, eNB->subframe, 0, 0);
LOG_D(OPT,
"[eNB %d][BCH-MBMS] Frame %d trace pdu for CC_id %d rnti %x with size %d\n",
module_idP, frameP, CC_id, 0xffff,
bcch_sdu_length);
}
LOG_D(MAC, "Frame %d, subframe %d: BCH PDU length %d\n", frameP, subframeP, mib_sdu_length); if (0/*cc->tdd_Config != NULL*/) { //TDD not for FeMBMS
LOG_D(MAC,
"[eNB] Frame %d : Scheduling BCCH->DLSCH (TDD) for CC_id %d SI %d bytes (mcs %d, rb 3)\n",
frameP, CC_id, bcch_sdu_length, mcs);
} else {
LOG_D(MAC, "[eNB] Frame %d : Scheduling BCCH-MBMS->DLSCH (FDD) for CC_id %d SI %d bytes (mcs %d, rb 3)\n", frameP, CC_id, bcch_sdu_length, mcs);
}
if (mib_sdu_length > 0) { eNB->eNB_stats[CC_id].total_num_bcch_pdu += 1;
eNB->eNB_stats[CC_id].bcch_buffer = bcch_sdu_length;
eNB->eNB_stats[CC_id].total_bcch_buffer += bcch_sdu_length;
eNB->eNB_stats[CC_id].bcch_mcs = mcs;
//printf("SI %d.%d\n", frameP, subframeP);/////////////////////////////////////////******************************
} else {
//LOG_D(MAC,"[eNB %d] Frame %d : BCCH not active \n",Mod_id,frame);
}
}
}
LOG_D(MAC, "Frame %d, subframe %d: Adding BCH PDU in position %d (length %d)\n", frameP, subframeP, dl_req->number_pdu, mib_sdu_length); #if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
//schedule_SIB1_BR(module_idP, frameP, subframeP);
//schedule_SI_BR(module_idP, frameP, subframeP);
#endif
stop_meas(&eNB->schedule_si_mbms);
}
#endif
if ((frameP & 1023) < 40) void
schedule_mib(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP) {
eNB_MAC_INST *eNB = RC.mac[module_idP];
COMMON_channels_t *cc;
nfapi_dl_config_request_pdu_t *dl_config_pdu;
nfapi_tx_request_pdu_t *TX_req;
int mib_sdu_length;
int CC_id;
nfapi_dl_config_request_t *dl_config_request;
nfapi_dl_config_request_body_t *dl_req;
uint16_t sfn_sf = frameP << 4 | subframeP;
AssertFatal(subframeP == 0, "Subframe must be 0\n");
AssertFatal((frameP & 3) == 0, "Frame must be a multiple of 4\n");
for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
dl_config_request = &eNB->DL_req[CC_id];
dl_req = &dl_config_request->dl_config_request_body;
cc = &eNB->common_channels[CC_id];
mib_sdu_length = mac_rrc_data_req(module_idP, CC_id, frameP, MIBCH, 0xFFFF, 1, &cc->MIB_pdu.payload[0], 0); // not used in this case
LOG_D(MAC, "Frame %d, subframe %d: BCH PDU length %d\n", frameP, subframeP, mib_sdu_length);
if (mib_sdu_length > 0) {
LOG_D(MAC, "Frame %d, subframe %d: Adding BCH PDU in position %d (length %d)\n", frameP, subframeP, dl_req->number_pdu, mib_sdu_length);
if ((frameP & 1023) < 40)
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) #if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
LOG_D(MAC, LOG_D(MAC,
"[eNB %d] Frame %d : MIB->BCH CC_id %d, Received %d bytes (cc->mib->message.schedulingInfoSIB1_BR_r13 %d)\n", "[eNB %d] Frame %d : MIB->BCH CC_id %d, Received %d bytes (cc->mib->message.schedulingInfoSIB1_BR_r13 %d)\n",
module_idP, frameP, CC_id, mib_sdu_length, module_idP, frameP, CC_id, mib_sdu_length,
(int) cc->mib->message.schedulingInfoSIB1_BR_r13); (int) cc->mib->message.schedulingInfoSIB1_BR_r13);
#else #else
LOG_D(MAC, LOG_D(MAC,
"[eNB %d] Frame %d : MIB->BCH CC_id %d, Received %d bytes\n", "[eNB %d] Frame %d : MIB->BCH CC_id %d, Received %d bytes\n",
module_idP, frameP, CC_id, mib_sdu_length); module_idP, frameP, CC_id, mib_sdu_length);
#endif #endif
dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu];
dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; memset((void *) dl_config_pdu, 0,
memset((void *) dl_config_pdu, 0, sizeof(nfapi_dl_config_request_pdu_t));
sizeof(nfapi_dl_config_request_pdu_t)); dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_BCH_PDU_TYPE, dl_config_pdu->pdu_size =
dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_BCH_PDU_TYPE, dl_config_pdu->pdu_size = 2 + sizeof(nfapi_dl_config_bch_pdu);
2 + sizeof(nfapi_dl_config_bch_pdu); dl_config_pdu->bch_pdu.bch_pdu_rel8.tl.tag = NFAPI_DL_CONFIG_REQUEST_BCH_PDU_REL8_TAG;
dl_config_pdu->bch_pdu.bch_pdu_rel8.tl.tag = NFAPI_DL_CONFIG_REQUEST_BCH_PDU_REL8_TAG; dl_config_pdu->bch_pdu.bch_pdu_rel8.length = mib_sdu_length;
dl_config_pdu->bch_pdu.bch_pdu_rel8.length = mib_sdu_length; dl_config_pdu->bch_pdu.bch_pdu_rel8.pdu_index = eNB->pdu_index[CC_id];
dl_config_pdu->bch_pdu.bch_pdu_rel8.pdu_index = eNB->pdu_index[CC_id]; dl_config_pdu->bch_pdu.bch_pdu_rel8.transmission_power = 6000;
dl_config_pdu->bch_pdu.bch_pdu_rel8.transmission_power = 6000; dl_req->tl.tag = NFAPI_DL_CONFIG_REQUEST_BODY_TAG;
dl_req->tl.tag = NFAPI_DL_CONFIG_REQUEST_BODY_TAG; dl_req->number_pdu++;
dl_req->number_pdu++; dl_config_request->header.message_id = NFAPI_DL_CONFIG_REQUEST;
dl_config_request->sfn_sf = sfn_sf;
dl_config_request->header.message_id = NFAPI_DL_CONFIG_REQUEST; LOG_D(MAC, "eNB->DL_req[0].number_pdu %d (%p)\n", dl_req->number_pdu, &dl_req->number_pdu);
dl_config_request->sfn_sf = sfn_sf; // DL request
TX_req = &eNB->TX_req[CC_id].tx_request_body.tx_pdu_list[eNB->TX_req[CC_id].tx_request_body.number_of_pdus];
LOG_D(MAC, "eNB->DL_req[0].number_pdu %d (%p)\n", dl_req->number_pdu, &dl_req->number_pdu); TX_req->pdu_length = 3;
// DL request TX_req->pdu_index = eNB->pdu_index[CC_id]++;
TX_req->num_segments = 1;
TX_req = &eNB->TX_req[CC_id].tx_request_body.tx_pdu_list[eNB->TX_req[CC_id].tx_request_body.number_of_pdus]; TX_req->segments[0].segment_length = 3;
TX_req->pdu_length = 3; TX_req->segments[0].segment_data = cc[CC_id].MIB_pdu.payload;
TX_req->pdu_index = eNB->pdu_index[CC_id]++; eNB->TX_req[CC_id].tx_request_body.number_of_pdus++;
TX_req->num_segments = 1; eNB->TX_req[CC_id].sfn_sf = sfn_sf;
TX_req->segments[0].segment_length = 3; eNB->TX_req[CC_id].tx_request_body.tl.tag = NFAPI_TX_REQUEST_BODY_TAG;
TX_req->segments[0].segment_data = cc[CC_id].MIB_pdu.payload; eNB->TX_req[CC_id].header.message_id = NFAPI_TX_REQUEST;
eNB->TX_req[CC_id].tx_request_body.number_of_pdus++;
eNB->TX_req[CC_id].sfn_sf = sfn_sf;
eNB->TX_req[CC_id].tx_request_body.tl.tag = NFAPI_TX_REQUEST_BODY_TAG;
eNB->TX_req[CC_id].header.message_id = NFAPI_TX_REQUEST;
}
} }
}
} }
...@@ -1041,224 +1011,214 @@ void ...@@ -1041,224 +1011,214 @@ void
schedule_SI(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP) schedule_SI(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP)
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
{ {
int8_t bcch_sdu_length;
int mcs = -1;
int CC_id;
eNB_MAC_INST *eNB = RC.mac[module_idP];
COMMON_channels_t *cc;
uint8_t *vrb_map;
int first_rb = -1;
int N_RB_DL;
nfapi_dl_config_request_t *dl_config_request;
nfapi_dl_config_request_pdu_t *dl_config_pdu;
nfapi_tx_request_pdu_t *TX_req;
nfapi_dl_config_request_body_t *dl_req;
uint16_t sfn_sf = frameP << 4 | subframeP;
start_meas(&eNB->schedule_si);
// Only schedule LTE System Information in subframe 5
if (subframeP == 5) {
for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
cc = &eNB->common_channels[CC_id];
vrb_map = (void *) &cc->vrb_map;
N_RB_DL = to_prb(cc->mib->message.dl_Bandwidth);
dl_config_request = &eNB->DL_req[CC_id];
dl_req = &eNB->DL_req[CC_id].dl_config_request_body;
bcch_sdu_length = mac_rrc_data_req(module_idP, CC_id, frameP, BCCH, 0xFFFF,1, &cc->BCCH_pdu.payload[0], 0); // not used in this case
if (bcch_sdu_length > 0) {
LOG_D(MAC, "[eNB %d] Frame %d : BCCH->DLSCH CC_id %d, Received %d bytes \n", module_idP, frameP, CC_id, bcch_sdu_length);
// Allocate 4 PRBs in a random location
/*
while (1) {
first_rb = (unsigned char)(taus()%(PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.N_RB_DL-4));
if ((vrb_map[first_rb] != 1) &&
(vrb_map[first_rb+1] != 1) &&
(vrb_map[first_rb+2] != 1) &&
(vrb_map[first_rb+3] != 1))
break;
}
*/
switch (N_RB_DL) {
case 6:
first_rb = 0;
break;
case 15:
first_rb = 6;
break;
case 25:
first_rb = 11;
break;
case 50:
first_rb = 23;
break;
case 100:
first_rb = 48;
break;
}
vrb_map[first_rb] = 1;
vrb_map[first_rb + 1] = 1;
vrb_map[first_rb + 2] = 1;
vrb_map[first_rb + 3] = 1;
// Get MCS for length of SI, 3 PRBs
if (bcch_sdu_length <= 7) {
mcs = 0;
} else if (bcch_sdu_length <= 11) {
mcs = 1;
} else if (bcch_sdu_length <= 18) {
mcs = 2;
} else if (bcch_sdu_length <= 22) {
mcs = 3;
} else if (bcch_sdu_length <= 26) {
mcs = 4;
} else if (bcch_sdu_length <= 28) {
mcs = 5;
} else if (bcch_sdu_length <= 32) {
mcs = 6;
} else if (bcch_sdu_length <= 41) {
mcs = 7;
} else if (bcch_sdu_length <= 49) {
mcs = 8;
} else if (bcch_sdu_length <= 59) {
mcs = 9;
} else AssertFatal(1==0,"Cannot Assign mcs for bcch_sdu_length %d (max mcs 9)\n",bcch_sdu_length);
dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu];
memset((void *) dl_config_pdu, 0,
sizeof(nfapi_dl_config_request_pdu_t));
dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE;
dl_config_pdu->pdu_size = (uint8_t) (2 + sizeof(nfapi_dl_config_dci_dl_pdu));
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tl.tag = NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG;
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format = NFAPI_DL_DCI_FORMAT_1A;
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level = 4;
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti = 0xFFFF;
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type = 2; // S-RNTI : see Table 4-10 from SCF082 - nFAPI specifications
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.transmission_power = 6000; // equal to RS power
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.harq_process = 0;
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tpc = 1; // no TPC
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.new_data_indicator_1 = 0;
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = mcs;
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_1 = 0;
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding = getRIV(N_RB_DL, first_rb, 4);
dl_config_request->sfn_sf = sfn_sf;
if (!CCE_allocation_infeasible(module_idP, CC_id, 0, subframeP,dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level, SI_RNTI)) {
LOG_D(MAC, "Frame %d: Subframe %d : Adding common DCI for S_RNTI\n", frameP, subframeP);
dl_req->number_dci++;
dl_req->number_pdu++;
dl_req->tl.tag = NFAPI_DL_CONFIG_REQUEST_BODY_TAG;
dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu];
memset((void *) dl_config_pdu, 0,
sizeof(nfapi_dl_config_request_pdu_t));
dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DLSCH_PDU_TYPE;
dl_config_pdu->pdu_size = (uint8_t) (2 + sizeof(nfapi_dl_config_dlsch_pdu));
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pdu_index = eNB->pdu_index[CC_id];
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.tl.tag = NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL8_TAG;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.length = bcch_sdu_length;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.rnti = 0xFFFF;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_allocation_type = 2; // format 1A/1B/1D
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.virtual_resource_block_assignment_flag = 0; // localized
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_block_coding = getRIV(N_RB_DL, first_rb, 4);
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.modulation = 2; //QPSK
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.redundancy_version = 0;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_blocks = 1; // first block
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_block_to_codeword_swap_flag = 0;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_scheme = (cc->p_eNB == 1) ? 0 : 1;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_layers = 1;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_subbands = 1;
// dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.codebook_index = ;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ue_category_capacity = 1;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pa = 4; // 0 dB
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.delta_power_offset_index = 0;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ngap = 0;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.nprb = get_subbandsize(cc->mib->message.dl_Bandwidth); // ignored
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_mode = (cc->p_eNB == 1) ? 1 : 2;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_prb_per_subband = 1;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_vector = 1;
// dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.bf_vector = ;
dl_req->number_pdu++;
dl_req->tl.tag = NFAPI_DL_CONFIG_REQUEST_BODY_TAG;
// Rel10 fields
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel10.tl.tag = NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL10_TAG;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel10.pdsch_start = 3;
// Rel13 fields
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.tl.tag = NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL13_TAG;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.ue_type = NOCE; // regular UE
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.pdsch_payload_type = 2; // not BR
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.initial_transmission_sf_io = 0xFFFF; // absolute SF
dl_config_request->header.message_id = NFAPI_DL_CONFIG_REQUEST;
dl_config_request->sfn_sf = sfn_sf;
// Program TX Request
TX_req = &eNB->TX_req[CC_id].tx_request_body.tx_pdu_list[eNB->TX_req[CC_id].tx_request_body.number_of_pdus];
TX_req->pdu_length = bcch_sdu_length;
TX_req->pdu_index = eNB->pdu_index[CC_id]++;
TX_req->num_segments = 1;
TX_req->segments[0].segment_length = bcch_sdu_length;
TX_req->segments[0].segment_data = cc->BCCH_pdu.payload;
eNB->TX_req[CC_id].tx_request_body.number_of_pdus++;
eNB->TX_req[CC_id].sfn_sf = sfn_sf;
eNB->TX_req[CC_id].tx_request_body.tl.tag = NFAPI_TX_REQUEST_BODY_TAG;
eNB->TX_req[CC_id].header.message_id = NFAPI_TX_REQUEST;
} else {
LOG_E(MAC,
"[eNB %d] CCid %d Frame %d, subframe %d : Cannot add DCI 1A for SI\n",
module_idP, CC_id, frameP, subframeP);
}
int8_t bcch_sdu_length; T(T_ENB_MAC_UE_DL_PDU_WITH_DATA, T_INT(module_idP), T_INT(CC_id), T_INT(0xffff),
int mcs = -1; T_INT(frameP), T_INT(subframeP), T_INT(0), T_BUFFER(cc->BCCH_pdu.payload, bcch_sdu_length));
int CC_id;
eNB_MAC_INST *eNB = RC.mac[module_idP]; if (opt_enabled == 1) {
COMMON_channels_t *cc; trace_pdu(DIRECTION_DOWNLINK,
uint8_t *vrb_map; &cc->BCCH_pdu.payload[0],
int first_rb = -1; bcch_sdu_length,
int N_RB_DL; 0xffff,
nfapi_dl_config_request_t *dl_config_request; WS_SI_RNTI, 0xffff, eNB->frame, eNB->subframe, 0, 0);
nfapi_dl_config_request_pdu_t *dl_config_pdu; LOG_D(OPT,
nfapi_tx_request_pdu_t *TX_req; "[eNB %d][BCH] Frame %d trace pdu for CC_id %d rnti %x with size %d\n",
nfapi_dl_config_request_body_t *dl_req; module_idP, frameP, CC_id, 0xffff,
uint16_t sfn_sf = frameP << 4 | subframeP; bcch_sdu_length);
}
start_meas(&eNB->schedule_si);
if (cc->tdd_Config != NULL) { //TDD
// Only schedule LTE System Information in subframe 5 LOG_D(MAC,
if (subframeP == 5) { "[eNB] Frame %d : Scheduling BCCH->DLSCH (TDD) for CC_id %d SI %d bytes (mcs %d, rb 3)\n",
frameP, CC_id, bcch_sdu_length, mcs);
for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { } else {
LOG_D(MAC, "[eNB] Frame %d : Scheduling BCCH->DLSCH (FDD) for CC_id %d SI %d bytes (mcs %d, rb 3)\n", frameP, CC_id, bcch_sdu_length, mcs);
cc = &eNB->common_channels[CC_id]; }
vrb_map = (void *) &cc->vrb_map;
N_RB_DL = to_prb(cc->mib->message.dl_Bandwidth); eNB->eNB_stats[CC_id].total_num_bcch_pdu += 1;
dl_config_request = &eNB->DL_req[CC_id]; eNB->eNB_stats[CC_id].bcch_buffer = bcch_sdu_length;
dl_req = &eNB->DL_req[CC_id].dl_config_request_body; eNB->eNB_stats[CC_id].total_bcch_buffer += bcch_sdu_length;
eNB->eNB_stats[CC_id].bcch_mcs = mcs;
//printf("SI %d.%d\n", frameP, subframeP);/////////////////////////////////////////******************************
bcch_sdu_length = mac_rrc_data_req(module_idP, CC_id, frameP, BCCH, 0xFFFF,1, &cc->BCCH_pdu.payload[0], 0); // not used in this case } else {
//LOG_D(MAC,"[eNB %d] Frame %d : BCCH not active \n",Mod_id,frame);
if (bcch_sdu_length > 0) { }
LOG_D(MAC, "[eNB %d] Frame %d : BCCH->DLSCH CC_id %d, Received %d bytes \n", module_idP, frameP, CC_id, bcch_sdu_length);
// Allocate 4 PRBs in a random location
/*
while (1) {
first_rb = (unsigned char)(taus()%(PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.N_RB_DL-4));
if ((vrb_map[first_rb] != 1) &&
(vrb_map[first_rb+1] != 1) &&
(vrb_map[first_rb+2] != 1) &&
(vrb_map[first_rb+3] != 1))
break;
}
*/
switch (N_RB_DL) {
case 6:
first_rb = 0;
break;
case 15:
first_rb = 6;
break;
case 25:
first_rb = 11;
break;
case 50:
first_rb = 23;
break;
case 100:
first_rb = 48;
break;
}
vrb_map[first_rb] = 1;
vrb_map[first_rb + 1] = 1;
vrb_map[first_rb + 2] = 1;
vrb_map[first_rb + 3] = 1;
// Get MCS for length of SI, 3 PRBs
if (bcch_sdu_length <= 7) {
mcs = 0;
} else if (bcch_sdu_length <= 11) {
mcs = 1;
} else if (bcch_sdu_length <= 18) {
mcs = 2;
} else if (bcch_sdu_length <= 22) {
mcs = 3;
} else if (bcch_sdu_length <= 26) {
mcs = 4;
} else if (bcch_sdu_length <= 28) {
mcs = 5;
} else if (bcch_sdu_length <= 32) {
mcs = 6;
} else if (bcch_sdu_length <= 41) {
mcs = 7;
} else if (bcch_sdu_length <= 49) {
mcs = 8;
} else if (bcch_sdu_length <= 59) {
mcs = 9;
}
else AssertFatal(1==0,"Cannot Assign mcs for bcch_sdu_length %d (max mcs 9)\n",bcch_sdu_length);
dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu];
memset((void *) dl_config_pdu, 0,
sizeof(nfapi_dl_config_request_pdu_t));
dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE;
dl_config_pdu->pdu_size = (uint8_t) (2 + sizeof(nfapi_dl_config_dci_dl_pdu));
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tl.tag = NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG;
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format = NFAPI_DL_DCI_FORMAT_1A;
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level = 4;
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti = 0xFFFF;
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type = 2; // S-RNTI : see Table 4-10 from SCF082 - nFAPI specifications
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.transmission_power = 6000; // equal to RS power
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.harq_process = 0;
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tpc = 1; // no TPC
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.new_data_indicator_1 = 0;
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = mcs;
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_1 = 0;
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding = getRIV(N_RB_DL, first_rb, 4);
dl_config_request->sfn_sf = sfn_sf;
if (!CCE_allocation_infeasible(module_idP, CC_id, 0, subframeP,dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level, SI_RNTI)) {
LOG_D(MAC, "Frame %d: Subframe %d : Adding common DCI for S_RNTI\n", frameP, subframeP);
dl_req->number_dci++;
dl_req->number_pdu++;
dl_req->tl.tag = NFAPI_DL_CONFIG_REQUEST_BODY_TAG;
dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu];
memset((void *) dl_config_pdu, 0,
sizeof(nfapi_dl_config_request_pdu_t));
dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DLSCH_PDU_TYPE;
dl_config_pdu->pdu_size = (uint8_t) (2 + sizeof(nfapi_dl_config_dlsch_pdu));
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pdu_index = eNB->pdu_index[CC_id];
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.tl.tag = NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL8_TAG;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.length = bcch_sdu_length;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.rnti = 0xFFFF;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_allocation_type = 2; // format 1A/1B/1D
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.virtual_resource_block_assignment_flag = 0; // localized
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_block_coding = getRIV(N_RB_DL, first_rb, 4);
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.modulation = 2; //QPSK
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.redundancy_version = 0;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_blocks = 1; // first block
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_block_to_codeword_swap_flag = 0;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_scheme = (cc->p_eNB == 1) ? 0 : 1;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_layers = 1;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_subbands = 1;
// dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.codebook_index = ;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ue_category_capacity = 1;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pa = 4; // 0 dB
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.delta_power_offset_index = 0;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ngap = 0;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.nprb = get_subbandsize(cc->mib->message.dl_Bandwidth); // ignored
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_mode = (cc->p_eNB == 1) ? 1 : 2;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_prb_per_subband = 1;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_vector = 1;
// dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.bf_vector = ;
dl_req->number_pdu++;
dl_req->tl.tag = NFAPI_DL_CONFIG_REQUEST_BODY_TAG;
// Rel10 fields
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel10.tl.tag = NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL10_TAG;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel10.pdsch_start = 3;
// Rel13 fields
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.tl.tag = NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL13_TAG;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.ue_type = NOCE; // regular UE
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.pdsch_payload_type = 2; // not BR
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.initial_transmission_sf_io = 0xFFFF; // absolute SF
dl_config_request->header.message_id = NFAPI_DL_CONFIG_REQUEST;
dl_config_request->sfn_sf = sfn_sf;
// Program TX Request
TX_req = &eNB->TX_req[CC_id].tx_request_body.tx_pdu_list[eNB->TX_req[CC_id].tx_request_body.number_of_pdus];
TX_req->pdu_length = bcch_sdu_length;
TX_req->pdu_index = eNB->pdu_index[CC_id]++;
TX_req->num_segments = 1;
TX_req->segments[0].segment_length = bcch_sdu_length;
TX_req->segments[0].segment_data = cc->BCCH_pdu.payload;
eNB->TX_req[CC_id].tx_request_body.number_of_pdus++;
eNB->TX_req[CC_id].sfn_sf = sfn_sf;
eNB->TX_req[CC_id].tx_request_body.tl.tag = NFAPI_TX_REQUEST_BODY_TAG;
eNB->TX_req[CC_id].header.message_id = NFAPI_TX_REQUEST;
} else {
LOG_E(MAC,
"[eNB %d] CCid %d Frame %d, subframe %d : Cannot add DCI 1A for SI\n",
module_idP, CC_id, frameP, subframeP);
}
T(T_ENB_MAC_UE_DL_PDU_WITH_DATA, T_INT(module_idP), T_INT(CC_id), T_INT(0xffff),
T_INT(frameP), T_INT(subframeP), T_INT(0), T_BUFFER(cc->BCCH_pdu.payload, bcch_sdu_length));
if (opt_enabled == 1) {
trace_pdu(DIRECTION_DOWNLINK,
&cc->BCCH_pdu.payload[0],
bcch_sdu_length,
0xffff,
WS_SI_RNTI, 0xffff, eNB->frame, eNB->subframe, 0, 0);
LOG_D(OPT,
"[eNB %d][BCH] Frame %d trace pdu for CC_id %d rnti %x with size %d\n",
module_idP, frameP, CC_id, 0xffff,
bcch_sdu_length);
}
if (cc->tdd_Config != NULL) { //TDD
LOG_D(MAC,
"[eNB] Frame %d : Scheduling BCCH->DLSCH (TDD) for CC_id %d SI %d bytes (mcs %d, rb 3)\n",
frameP, CC_id, bcch_sdu_length, mcs);
} else {
LOG_D(MAC, "[eNB] Frame %d : Scheduling BCCH->DLSCH (FDD) for CC_id %d SI %d bytes (mcs %d, rb 3)\n", frameP, CC_id, bcch_sdu_length, mcs);
}
eNB->eNB_stats[CC_id].total_num_bcch_pdu += 1;
eNB->eNB_stats[CC_id].bcch_buffer = bcch_sdu_length;
eNB->eNB_stats[CC_id].total_bcch_buffer += bcch_sdu_length;
eNB->eNB_stats[CC_id].bcch_mcs = mcs;
//printf("SI %d.%d\n", frameP, subframeP);/////////////////////////////////////////******************************
} else {
//LOG_D(MAC,"[eNB %d] Frame %d : BCCH not active \n",Mod_id,frame);
}
}
} }
}
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) #if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
schedule_SIB1_BR(module_idP, frameP, subframeP); schedule_SIB1_BR(module_idP, frameP, subframeP);
schedule_SI_BR(module_idP, frameP, subframeP); schedule_SI_BR(module_idP, frameP, subframeP);
#endif #endif
stop_meas(&eNB->schedule_si); stop_meas(&eNB->schedule_si);
} }
...@@ -565,7 +565,6 @@ schedule_ue_spec(module_id_t module_idP, ...@@ -565,7 +565,6 @@ schedule_ue_spec(module_id_t module_idP,
dl_Bandwidth = cc[CC_id].mib->message.dl_Bandwidth; dl_Bandwidth = cc[CC_id].mib->message.dl_Bandwidth;
N_RB_DL[CC_id] = to_prb(dl_Bandwidth); N_RB_DL[CC_id] = to_prb(dl_Bandwidth);
min_rb_unit[CC_id] = get_min_rb_unit(module_idP, CC_id); min_rb_unit[CC_id] = get_min_rb_unit(module_idP, CC_id);
// get number of PRBs less those used by common channels // get number of PRBs less those used by common channels
total_nb_available_rb[CC_id] = N_RB_DL[CC_id]; total_nb_available_rb[CC_id] = N_RB_DL[CC_id];
...@@ -622,7 +621,6 @@ schedule_ue_spec(module_id_t module_idP, ...@@ -622,7 +621,6 @@ schedule_ue_spec(module_id_t module_idP,
LOG_D(MAC, "doing schedule_ue_spec for CC_id %d UE %d\n", LOG_D(MAC, "doing schedule_ue_spec for CC_id %d UE %d\n",
CC_id, CC_id,
UE_id); UE_id);
continue_flag = 0; // reset the flag to allow allocation for the remaining UEs continue_flag = 0; // reset the flag to allow allocation for the remaining UEs
rnti = UE_RNTI(module_idP, UE_id); rnti = UE_RNTI(module_idP, UE_id);
ue_sched_ctrl = &UE_list->UE_sched_ctrl[UE_id]; ue_sched_ctrl = &UE_list->UE_sched_ctrl[UE_id];
...@@ -776,7 +774,8 @@ schedule_ue_spec(module_id_t module_idP, ...@@ -776,7 +774,8 @@ schedule_ue_spec(module_id_t module_idP,
if (ue_sched_ctrl->cdrx_configured) { if (ue_sched_ctrl->cdrx_configured) {
ue_sched_ctrl->drx_retransmission_timer[harq_pid] = 0; // stop drx retransmission ue_sched_ctrl->drx_retransmission_timer[harq_pid] = 0; // stop drx retransmission
/*
/*
* Note: contrary to the spec drx_retransmission_timer[harq_pid] is reset not stop. * Note: contrary to the spec drx_retransmission_timer[harq_pid] is reset not stop.
*/ */
if (harq_pid == 0) { if (harq_pid == 0) {
...@@ -1011,9 +1010,10 @@ schedule_ue_spec(module_id_t module_idP, ...@@ -1011,9 +1010,10 @@ schedule_ue_spec(module_id_t module_idP,
); );
if((rrc_release_info.num_UEs > 0) && (rlc_am_mui.rrc_mui_num > 0)) { if((rrc_release_info.num_UEs > 0) && (rlc_am_mui.rrc_mui_num > 0)) {
while(pthread_mutex_trylock(&rrc_release_freelist)){ while(pthread_mutex_trylock(&rrc_release_freelist)) {
/* spin... */ /* spin... */
} }
uint16_t release_total = 0; uint16_t release_total = 0;
for (release_num = 0, release_ctrl = &rrc_release_info.RRC_release_ctrl[0]; for (release_num = 0, release_ctrl = &rrc_release_info.RRC_release_ctrl[0];
...@@ -1060,10 +1060,10 @@ schedule_ue_spec(module_id_t module_idP, ...@@ -1060,10 +1060,10 @@ schedule_ue_spec(module_id_t module_idP,
if(release_total >= rrc_release_info.num_UEs) if(release_total >= rrc_release_info.num_UEs)
break; break;
} }
pthread_mutex_unlock(&rrc_release_freelist); pthread_mutex_unlock(&rrc_release_freelist);
} }
for (ra_ii = 0, ra = &eNB->common_channels[CC_id].ra[0]; ra_ii < NB_RA_PROC_MAX; ra_ii++, ra++) { for (ra_ii = 0, ra = &eNB->common_channels[CC_id].ra[0]; ra_ii < NB_RA_PROC_MAX; ra_ii++, ra++) {
if ((ra->rnti == rnti) && (ra->state == MSGCRNTI)) { if ((ra->rnti == rnti) && (ra->state == MSGCRNTI)) {
for (uint16_t mui_num = 0; mui_num < rlc_am_mui.rrc_mui_num; mui_num++) { for (uint16_t mui_num = 0; mui_num < rlc_am_mui.rrc_mui_num; mui_num++) {
...@@ -1254,7 +1254,6 @@ schedule_ue_spec(module_id_t module_idP, ...@@ -1254,7 +1254,6 @@ schedule_ue_spec(module_id_t module_idP,
header_length_total += header_length_last; header_length_total += header_length_last;
num_sdus++; num_sdus++;
ue_sched_ctrl->uplane_inactivity_timer = 0; ue_sched_ctrl->uplane_inactivity_timer = 0;
// reset RRC inactivity timer after uplane activity // reset RRC inactivity timer after uplane activity
ue_contextP = rrc_eNB_get_ue_context(RC.rrc[module_idP], rnti); ue_contextP = rrc_eNB_get_ue_context(RC.rrc[module_idP], rnti);
...@@ -1578,17 +1577,17 @@ schedule_ue_spec(module_id_t module_idP, ...@@ -1578,17 +1577,17 @@ schedule_ue_spec(module_id_t module_idP,
dl_req->tl.tag = NFAPI_DL_CONFIG_REQUEST_BODY_TAG; dl_req->tl.tag = NFAPI_DL_CONFIG_REQUEST_BODY_TAG;
eNB->DL_req[CC_id].sfn_sf = frameP << 4 | subframeP; eNB->DL_req[CC_id].sfn_sf = frameP << 4 | subframeP;
eNB->DL_req[CC_id].header.message_id = NFAPI_DL_CONFIG_REQUEST; eNB->DL_req[CC_id].header.message_id = NFAPI_DL_CONFIG_REQUEST;
/* CDRX */ /* CDRX */
ue_sched_ctrl->harq_rtt_timer[CC_id][harq_pid] = 1; // restart HARQ RTT timer ue_sched_ctrl->harq_rtt_timer[CC_id][harq_pid] = 1; // restart HARQ RTT timer
if (ue_sched_ctrl->cdrx_configured) { if (ue_sched_ctrl->cdrx_configured) {
ue_sched_ctrl->drx_inactivity_timer = 1; // restart drx inactivity timer when new transmission ue_sched_ctrl->drx_inactivity_timer = 1; // restart drx inactivity timer when new transmission
ue_sched_ctrl->drx_retransmission_timer[harq_pid] = 0; // stop drx retransmission ue_sched_ctrl->drx_retransmission_timer[harq_pid] = 0; // stop drx retransmission
/* /*
* Note: contrary to the spec drx_retransmission_timer[harq_pid] is reset not stop. * Note: contrary to the spec drx_retransmission_timer[harq_pid] is reset not stop.
*/ */
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DRX_INACTIVITY, (unsigned long) ue_sched_ctrl->drx_inactivity_timer); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DRX_INACTIVITY, (unsigned long) ue_sched_ctrl->drx_inactivity_timer);
if (harq_pid == 0) { if (harq_pid == 0) {
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DRX_RETRANSMISSION_HARQ0, (unsigned long) ue_sched_ctrl->drx_retransmission_timer[0]); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DRX_RETRANSMISSION_HARQ0, (unsigned long) ue_sched_ctrl->drx_retransmission_timer[0]);
} }
...@@ -3089,8 +3088,8 @@ schedule_PCH(module_id_t module_idP, ...@@ -3089,8 +3088,8 @@ schedule_PCH(module_id_t module_idP,
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format = NFAPI_DL_DCI_FORMAT_1A; dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format = NFAPI_DL_DCI_FORMAT_1A;
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.harq_process = 0; dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.harq_process = 0;
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tpc = 1; // no TPC dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tpc = 1; // no TPC
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.new_data_indicator_1 = 0; dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.new_data_indicator_1 = 0;
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_1 = 0; dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_1 = 0;
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding = getRIV(n_rb_dl, first_rb, 4); dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding = getRIV(n_rb_dl, first_rb, 4);
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.virtual_resource_block_assignment_flag = 0; dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.virtual_resource_block_assignment_flag = 0;
#endif #endif
......
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