mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-13 12:40:28 +00:00
Compare commits
7 Commits
split7.2_d
...
stats2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
71fb81e13a | ||
|
|
06971bd8e6 | ||
|
|
48906bf385 | ||
|
|
5b97df2971 | ||
|
|
1c0ff9b68d | ||
|
|
fbdc6f0fd0 | ||
|
|
6c201d6239 |
@@ -1212,6 +1212,7 @@ add_library(UTIL
|
||||
${OPENAIR2_DIR}/UTIL/MATH/oml.c
|
||||
${OPENAIR2_DIR}/UTIL/OPT/probe.c
|
||||
${OPENAIR_DIR}/common/utils/threadPool/thread-pool.c
|
||||
${OPENAIR_DIR}/common/utils/cpustats.c
|
||||
${OPENAIR_DIR}/common/utils/utils.c
|
||||
${OPENAIR_DIR}/common/utils/system.c
|
||||
${OPENAIR_DIR}/common/utils/backtrace.c
|
||||
|
||||
319
common/utils/cpustats.c
Normal file
319
common/utils/cpustats.c
Normal file
@@ -0,0 +1,319 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
/*
|
||||
* This file implements the cpu statistics for Level 1 in gnb and in UE.
|
||||
* Caveats: Note that we did not merge this development into file telnetsrv_gnb_measurements.c and telnetsrv_5Gue_measurements.c
|
||||
* belonging to telnetsrv shared library because we needed to provide an API for main programs exectuable without inserting a new
|
||||
* dependency on the telnetsrv shared library.
|
||||
*/
|
||||
#define _GNU_SOURCE
|
||||
#include <pthread.h>
|
||||
#include <stdbool.h>
|
||||
#include <errno.h>
|
||||
#include <linux/sched.h>
|
||||
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "common/utils/threadPool/thread-pool.h"
|
||||
#include "cpustats.h"
|
||||
#include "common/utils/time_meas.h"
|
||||
|
||||
#define UEL1_THREADNAME "L1_UE_stats_act"
|
||||
#define GNBL1_THREADNAME "L1_stats_act"
|
||||
|
||||
/* ==== Global variables ==== */
|
||||
|
||||
// IPC communication between main thread and the statistics one
|
||||
static notifiedFIFO_t GNBL1cpustats_fifo, UEL1cpustats_fifo;
|
||||
|
||||
static pthread_t UEL1cpustats_threadid = 0;
|
||||
static pthread_t gNBL1cpustats_threadid = 0;
|
||||
|
||||
// data structure for communication between main thread and the statistics one
|
||||
typedef struct {
|
||||
unsigned int msgid;
|
||||
telnet_printfunc_t prnt;
|
||||
} proto_stats_msg_t;
|
||||
|
||||
// PHY_vars_UE_g: declared in openair1/PHY/phy_vars_nr_ue.h and defined in nr-uesoftmodem.c
|
||||
extern PHY_VARS_NR_UE *** PHY_vars_UE_g;
|
||||
|
||||
/* ==== Static functions ==== */
|
||||
|
||||
/* return pointer to the global structure that contains the UE data including statistics*/
|
||||
static PHY_VARS_NR_UE * getglobal_uephy(void) { return PHY_vars_UE_g[0][0]; }
|
||||
|
||||
// RC.nb_nr_macrlc_inst in openair2/LAYER2/NR_MAC_gNB/main.c defines the RAN_CONTEXT RC variable that defines how many instances you will have
|
||||
// ru stands for 'radio unit' data structure
|
||||
static RU_t *getglobal_ru(void) { return RC.ru[0];}
|
||||
static void UEL1cpustats_display(telnet_printfunc_t prnt);
|
||||
static void UEL1cpustats_thread_main(void);
|
||||
static void gNBL1cpustats_display(telnet_printfunc_t prnt, PHY_VARS_gNB *param);
|
||||
static void gNBL1cpustats_thread_main (void * param);
|
||||
|
||||
/* xxx: these are the same statistics but with different formatting and list of content of those displayed by
|
||||
* telnetsrv_measurements.c:measurcmd_display_cpumeasures(). you could think about unifying the 2 functions.
|
||||
* XXX: this implementation should be fixed using a dynamically allocated buffer instead of a plain one
|
||||
* it is prone to sigSEGV
|
||||
*/
|
||||
static void
|
||||
UEL1cpustats_display(telnet_printfunc_t prnt)
|
||||
{
|
||||
/* PHY_vars_UE_g:
|
||||
* this global variable is allocated by nr-uesoftmodem.c and shared among threads makes the trick of passing statistics data to statistic thread
|
||||
* that will consume it. There is just one instance of UE created in nr-ue.c
|
||||
*/
|
||||
PHY_VARS_NR_UE *ue = getglobal_uephy();
|
||||
|
||||
prnt("Display CPU statistics for UE Level 1\n");
|
||||
|
||||
char output[TELNET_MAX_MSGLENGTH];
|
||||
int stroff = 0;
|
||||
stroff += print_meas_log(&ue->phy_proc_tx , "L1 TX processing" , NULL, NULL, output , TELNET_MAX_MSGLENGTH - stroff);
|
||||
stroff += print_meas_log(&ue->ulsch_encoding_stats , "ULSCH encoding" , NULL, NULL, output + stroff, TELNET_MAX_MSGLENGTH - stroff );
|
||||
stroff += print_meas_log(&ue->phy_proc_rx[0] , "L1 RX processing t0" , NULL, NULL, output + stroff, TELNET_MAX_MSGLENGTH - stroff);
|
||||
stroff += print_meas_log(&ue->phy_proc_rx[1] , "L1 RX processing t1" , NULL, NULL, output + stroff, TELNET_MAX_MSGLENGTH - stroff);
|
||||
stroff += print_meas_log(&ue->ue_ul_indication_stats , "UL Indication" , NULL, NULL, output + stroff, TELNET_MAX_MSGLENGTH - stroff);
|
||||
stroff += print_meas_log(&ue->rx_pdsch_stats , "PDSCH receiver" , NULL, NULL, output + stroff, TELNET_MAX_MSGLENGTH - stroff);
|
||||
stroff += print_meas_log(&ue->dlsch_decoding_stats[0] , "PDSCH decoding t0" , NULL, NULL, output + stroff, TELNET_MAX_MSGLENGTH - stroff);
|
||||
stroff += print_meas_log(&ue->dlsch_decoding_stats[1] , "PDSCH decoding t1" , NULL, NULL, output + stroff, TELNET_MAX_MSGLENGTH - stroff);
|
||||
stroff += print_meas_log(&ue->dlsch_deinterleaving_stats , " -> Deinterleive" , NULL, NULL, output + stroff, TELNET_MAX_MSGLENGTH - stroff);
|
||||
stroff += print_meas_log(&ue->dlsch_rate_unmatching_stats , " -> Rate Unmatch" , NULL, NULL, output + stroff, TELNET_MAX_MSGLENGTH - stroff);
|
||||
stroff += print_meas_log(&ue->dlsch_ldpc_decoding_stats , " -> LDPC Decode" , NULL, NULL, output + stroff, TELNET_MAX_MSGLENGTH - stroff);
|
||||
stroff += print_meas_log(&ue->dlsch_unscrambling_stats , "PDSCH unscrambling" , NULL, NULL, output + stroff, TELNET_MAX_MSGLENGTH - stroff);
|
||||
stroff += print_meas_log(&ue->dlsch_rx_pdcch_stats , "PDCCH handling" , NULL, NULL, output + stroff, TELNET_MAX_MSGLENGTH - stroff);
|
||||
|
||||
prnt("%s\n", output);
|
||||
}
|
||||
|
||||
static void
|
||||
UEL1cpustats_thread_main(void)
|
||||
{
|
||||
if (pthread_setname_np(pthread_self(), UEL1_THREADNAME))
|
||||
LOG_E(UTIL, "Error setting name on thread %s: %s\n", UEL1_THREADNAME, strerror(errno));
|
||||
|
||||
struct sched_param schedp;
|
||||
schedp.sched_priority = SCHED_NORMAL;
|
||||
if (pthread_setschedparam(pthread_self(), SCHED_IDLE, &schedp))
|
||||
LOG_E(UTIL, "Error setting priority in thread %s: %s\n", UEL1_THREADNAME, strerror(errno));
|
||||
|
||||
initNotifiedFIFO(&UEL1cpustats_fifo);
|
||||
|
||||
cpumeas(CPUMEAS_ENABLE);
|
||||
|
||||
while (1){
|
||||
/*
|
||||
* Infinite loop that waits for a message on the FIFO.
|
||||
* Behind the scenes it uses blocking pthread.h:pthread_cond_wait()
|
||||
*/
|
||||
notifiedFIFO_elt_t *msg = pullNotifiedFIFO(&UEL1cpustats_fifo);
|
||||
|
||||
proto_stats_msg_t *tsm = (proto_stats_msg_t *)NotifiedFifoData(msg);
|
||||
switch (tsm->msgid)
|
||||
{
|
||||
case TIMESTAT_MSGID_DISPLAY:
|
||||
|
||||
if (cpumeas(CPUMEAS_GETSTATE))
|
||||
UEL1cpustats_display(tsm->prnt);
|
||||
else
|
||||
tsm->prnt("ERR: before displaying meaningful stats, you need to activate their generation\n");
|
||||
break;
|
||||
case TIMESTAT_MSGID_DISABLE:
|
||||
cpumeas(CPUMEAS_DISABLE);
|
||||
UEL1cpustats_threadid = 0;
|
||||
pthread_exit(NULL);
|
||||
break;
|
||||
}
|
||||
delNotifiedFIFO_elt(msg);
|
||||
}
|
||||
LOG_I(UTIL, "Exiting thread %s\n", UEL1_THREADNAME);
|
||||
}
|
||||
|
||||
bool
|
||||
UEL1cpustats_enable(void)
|
||||
{
|
||||
if (UEL1cpustats_threadid){
|
||||
LOG_E(UTIL, "Thread '%s' is already running. Aborting your request to create a new one\n", UEL1_THREADNAME);
|
||||
return false;
|
||||
}
|
||||
|
||||
int rt = pthread_create(&UEL1cpustats_threadid, NULL, (void *(*)(void *))UEL1cpustats_thread_main, NULL);
|
||||
if (rt != 0)
|
||||
LOG_E(UTIL, "Error creating thread %s: %s\n",UEL1_THREADNAME, strerror(errno));
|
||||
|
||||
return (rt != 0) ? false : true;
|
||||
}
|
||||
|
||||
void
|
||||
UEL1cpustats_disable(void)
|
||||
{
|
||||
if (!UEL1cpustats_threadid) {
|
||||
LOG_W(UTIL, "Thread '%s' is not running. Discarding your request to disable stats\n", UEL1_THREADNAME);
|
||||
return;
|
||||
}
|
||||
|
||||
notifiedFIFO_elt_t *nfe = newNotifiedFIFO_elt(sizeof(time_stats_msg_t), 0, NULL, NULL);
|
||||
proto_stats_msg_t *msg = (proto_stats_msg_t *)NotifiedFifoData(nfe);
|
||||
msg->msgid = TIMESTAT_MSGID_DISABLE;
|
||||
pushNotifiedFIFO(&UEL1cpustats_fifo, nfe);
|
||||
}
|
||||
|
||||
void
|
||||
UEL1cpustats_measurcmd_display (telnet_printfunc_t prnt)
|
||||
{
|
||||
if (!UEL1cpustats_threadid) {
|
||||
prnt("Thread '%s' is not running. Aborting your request to display stats, you need first to enable statistics\n", UEL1_THREADNAME);
|
||||
return;
|
||||
}
|
||||
|
||||
notifiedFIFO_elt_t *nfe = newNotifiedFIFO_elt(sizeof(time_stats_msg_t), 0, NULL, NULL);
|
||||
proto_stats_msg_t *msg = (proto_stats_msg_t *)NotifiedFifoData(nfe);
|
||||
msg->prnt = prnt;
|
||||
msg->msgid = TIMESTAT_MSGID_DISPLAY;
|
||||
pushNotifiedFIFO(&UEL1cpustats_fifo, nfe);
|
||||
}
|
||||
|
||||
/* Display info from specific instance of gNB and from radio unit */
|
||||
static void
|
||||
gNBL1cpustats_display(telnet_printfunc_t prnt, PHY_VARS_gNB *gNB)
|
||||
{
|
||||
RU_t *ru = getglobal_ru();
|
||||
|
||||
char output[TELNET_MAX_MSGLENGTH];
|
||||
int stroff = 0;
|
||||
prnt("%s\n");
|
||||
// XXX: header will be printed automatically by print_meas_log() just the first time it is called in the program. It means that if you
|
||||
// use a mechanism like 'loop measur show gnb_L1', you will lose the header after the first iteration.
|
||||
// You should fix the logic of 'print_meas_log() to avoid it printing any header.
|
||||
stroff += print_meas_log(&gNB->phy_proc_tx , "L1 Tx processing" , NULL, NULL, output , TELNET_MAX_MSGLENGTH - stroff);
|
||||
stroff += print_meas_log(&gNB->dlsch_encoding_stats , "DLSCH encoding" , NULL, NULL, output+stroff, TELNET_MAX_MSGLENGTH - stroff);
|
||||
stroff += print_meas_log(&gNB->phy_proc_rx , "L1 Rx processing" , NULL, NULL, output+stroff, TELNET_MAX_MSGLENGTH - stroff);
|
||||
stroff += print_meas_log(&gNB->ul_indication_stats , "UL Indication" , NULL, NULL, output+stroff, TELNET_MAX_MSGLENGTH - stroff);
|
||||
stroff += print_meas_log(&gNB->rx_pusch_stats , "PUSCH inner-receiver", NULL, NULL, output+stroff, TELNET_MAX_MSGLENGTH - stroff);
|
||||
stroff += print_meas_log(&gNB->ulsch_decoding_stats , "PUSCH decoding" , NULL, NULL, output+stroff, TELNET_MAX_MSGLENGTH - stroff);
|
||||
stroff += print_meas_log(&gNB->schedule_response_stats, "Schedule Response" , NULL, NULL, output+stroff, TELNET_MAX_MSGLENGTH - stroff);
|
||||
if (ru->feprx)
|
||||
stroff += print_meas_log(&ru->ofdm_demod_stats , "feprx" , NULL, NULL, output+stroff, TELNET_MAX_MSGLENGTH - stroff);
|
||||
|
||||
if (ru->feptx_ofdm) {
|
||||
stroff += print_meas_log(&ru->precoding_stats , "feptx_prec" , NULL, NULL, output+stroff, TELNET_MAX_MSGLENGTH - stroff);
|
||||
stroff += print_meas_log(&ru->txdataF_copy_stats , "txdataF_copy" , NULL, NULL, output+stroff, TELNET_MAX_MSGLENGTH - stroff);
|
||||
stroff += print_meas_log(&ru->ofdm_mod_stats , "feptx_ofdm" , NULL, NULL, output+stroff, TELNET_MAX_MSGLENGTH - stroff);
|
||||
stroff += print_meas_log(&ru->ofdm_total_stats , "feptx_total" , NULL, NULL, output+stroff, TELNET_MAX_MSGLENGTH - stroff);
|
||||
}
|
||||
|
||||
if (ru->fh_north_asynch_in)
|
||||
stroff += print_meas_log(&ru->rx_fhaul , "rx_fhaul" , NULL, NULL, output+stroff, TELNET_MAX_MSGLENGTH - stroff);
|
||||
|
||||
stroff += print_meas_log(&ru->tx_fhaul , "tx_fhaul" , NULL, NULL, output+stroff, TELNET_MAX_MSGLENGTH - stroff);
|
||||
|
||||
if (ru->fh_north_out) {
|
||||
stroff += print_meas_log(&ru->compression , "compression" , NULL, NULL, output+stroff, TELNET_MAX_MSGLENGTH - stroff);
|
||||
stroff += print_meas_log(&ru->transport , "transport" , NULL, NULL, output+stroff, TELNET_MAX_MSGLENGTH - stroff);
|
||||
}
|
||||
|
||||
prnt("%s\n", output);
|
||||
}
|
||||
|
||||
static void
|
||||
gNBL1cpustats_thread_main(void * param)
|
||||
{
|
||||
if (pthread_setname_np(pthread_self(), GNBL1_THREADNAME))
|
||||
LOG_E(UTIL, "Error setting name on thread %s: %s\n", GNBL1_THREADNAME, strerror(errno));
|
||||
|
||||
struct sched_param schedp;
|
||||
schedp.sched_priority = SCHED_NORMAL;
|
||||
if (pthread_setschedparam(pthread_self(), SCHED_IDLE, &schedp))
|
||||
LOG_E(UTIL, "Error setting priority in thread %s: %s\n", GNBL1_THREADNAME, strerror(errno));
|
||||
|
||||
initNotifiedFIFO(&GNBL1cpustats_fifo);
|
||||
|
||||
cpumeas(CPUMEAS_ENABLE);
|
||||
|
||||
while (1){
|
||||
/*
|
||||
* Infinite loop that waits for a message on the FIFO.
|
||||
* Behind the scenes it uses blocking pthread.h:pthread_cond_wait()
|
||||
*/
|
||||
notifiedFIFO_elt_t *msg = pullNotifiedFIFO(&GNBL1cpustats_fifo);
|
||||
|
||||
proto_stats_msg_t *tsm = (proto_stats_msg_t *)NotifiedFifoData(msg);
|
||||
switch (tsm->msgid)
|
||||
{
|
||||
case TIMESTAT_MSGID_DISPLAY:
|
||||
if (cpumeas(CPUMEAS_GETSTATE))
|
||||
gNBL1cpustats_display(tsm->prnt, (PHY_VARS_gNB *)param);
|
||||
else
|
||||
tsm->prnt("ERR: before displaying meaningful stats, you need to activate their generation\n");
|
||||
break;
|
||||
case TIMESTAT_MSGID_DISABLE:
|
||||
cpumeas(CPUMEAS_DISABLE);
|
||||
gNBL1cpustats_threadid = 0;
|
||||
pthread_exit(NULL);
|
||||
break;
|
||||
}
|
||||
delNotifiedFIFO_elt(msg);
|
||||
}
|
||||
LOG_I(UTIL, "Exiting thread '%s'\n", GNBL1_THREADNAME);
|
||||
}
|
||||
|
||||
void
|
||||
gNBL1cpustats_measurcmd_display (telnet_printfunc_t prnt)
|
||||
{
|
||||
if (!gNBL1cpustats_threadid) {
|
||||
prnt("gNB thread %s is not running. Aborting your request to display stats as you need first to enable statistics\n", GNBL1_THREADNAME);
|
||||
return;
|
||||
}
|
||||
|
||||
notifiedFIFO_elt_t *nfe = newNotifiedFIFO_elt(sizeof(time_stats_msg_t), 0, NULL, NULL);
|
||||
proto_stats_msg_t *msg = (proto_stats_msg_t *)NotifiedFifoData(nfe);
|
||||
msg->prnt = prnt;
|
||||
msg->msgid = TIMESTAT_MSGID_DISPLAY;
|
||||
pushNotifiedFIFO(&GNBL1cpustats_fifo, nfe);
|
||||
}
|
||||
|
||||
bool
|
||||
gNBL1cpustats_enable(PHY_VARS_gNB *gNB)
|
||||
{
|
||||
if (gNBL1cpustats_threadid) {
|
||||
LOG_E(UTIL, "Thread '%s' already running, aborting your request to create a new one\n", GNBL1_THREADNAME);
|
||||
return false;
|
||||
}
|
||||
|
||||
int rt = pthread_create(&gNBL1cpustats_threadid, NULL, (void *(*)(void *))gNBL1cpustats_thread_main, gNB);
|
||||
if (rt != 0)
|
||||
LOG_E(UTIL, "Error creating thread '%s': %s\n", GNBL1_THREADNAME, strerror(errno));
|
||||
|
||||
return (rt != 0) ? false : true;
|
||||
}
|
||||
|
||||
void
|
||||
gNBL1cpustats_disable(void)
|
||||
{
|
||||
if (!gNBL1cpustats_threadid) {
|
||||
LOG_W(UTIL, "Thread '%s' is not running. Discarding your request to disable stats\n", GNBL1_THREADNAME);
|
||||
return;
|
||||
}
|
||||
|
||||
notifiedFIFO_elt_t *nfe = newNotifiedFIFO_elt(sizeof(time_stats_msg_t), 0, NULL, NULL);
|
||||
proto_stats_msg_t *msg = (proto_stats_msg_t *)NotifiedFifoData(nfe);
|
||||
msg->msgid = TIMESTAT_MSGID_DISABLE;
|
||||
pushNotifiedFIFO(&GNBL1cpustats_fifo, nfe);
|
||||
}
|
||||
20
common/utils/cpustats.h
Normal file
20
common/utils/cpustats.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef _CPUSTATS_H
|
||||
#define _CPUSTATS_H
|
||||
/*
|
||||
* Activation, deactivation and printing functionalities of cpu statistics for UE and gNB Level 1/PHY indicators
|
||||
*/
|
||||
#include "common/utils/telnetsrv/telnetsrv.h"
|
||||
#include "openair1/PHY/defs_nr_UE.h"
|
||||
#include "openair1/PHY/defs_gNB.h"
|
||||
|
||||
#define UE_STATS_L1 "phycpunew"
|
||||
void UEL1cpustats_measurcmd_display(telnet_printfunc_t prnt);
|
||||
bool UEL1cpustats_enable(void);
|
||||
void UEL1cpustats_disable(void);
|
||||
|
||||
#define GNB_STATS_L1 "gnb_L1"
|
||||
bool gNBL1cpustats_enable(PHY_VARS_gNB *gNB);
|
||||
void gNBL1cpustats_disable(void);
|
||||
void gNBL1cpustats_measurcmd_display (telnet_printfunc_t prnt);
|
||||
|
||||
#endif
|
||||
@@ -46,6 +46,7 @@
|
||||
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "common/config/config_userapi.h"
|
||||
#include "common/utils/cpustats.h"
|
||||
#include "telnetsrv_measurements.h"
|
||||
#include "telnetsrv_ltemeasur_def.h"
|
||||
#include "telnetsrv_cpumeasur_def.h"
|
||||
@@ -63,7 +64,9 @@ void measurcmd_display_pdcpcpu(telnet_printfunc_t prnt);
|
||||
static telnet_measurgroupdef_t nrUEmeasurgroups[] = {
|
||||
// {"ue", GROUP_LTESTATS,0, measurcmd_display_macstats, {NULL}},
|
||||
// {"rlc", GROUP_LTESTATS,0, measurcmd_display_rlcstats, {NULL}},
|
||||
{"phycpu",GROUP_CPUSTATS,0, measurcmd_display_phycpu, {NULL}},
|
||||
{"phycpu" , GROUP_CPUSTATS, 0, measurcmd_display_phycpu , {NULL}},
|
||||
{UE_STATS_L1, GROUP_CPUSTATS, 0, UEL1cpustats_measurcmd_display, {NULL}}
|
||||
|
||||
// {"maccpu",GROUP_CPUSTATS,0, measurcmd_display_maccpu, {NULL}},
|
||||
// {"pdcpcpu",GROUP_CPUSTATS,0, measurcmd_display_pdcpcpu, {NULL}},
|
||||
};
|
||||
|
||||
275
common/utils/telnetsrv/telnetsrv_gnb_measurements.c
Normal file
275
common/utils/telnetsrv/telnetsrv_gnb_measurements.c
Normal file
@@ -0,0 +1,275 @@
|
||||
#define TELNETSERVERCODE
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "telnetsrv.h"
|
||||
#include "telnetsrv_measurements.h"
|
||||
#include "telnetsrv_ltemeasur_def.h"
|
||||
#include "common/utils/cpustats.h"
|
||||
#include "openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h"
|
||||
|
||||
static void gNBL2pstats_measurcmd_display(telnet_printfunc_t prnt);
|
||||
static char *gNBL2pstats_gethdrline1(char * bufhdr, size_t maxlen);
|
||||
static char *gNBL2pstats_gethdrline2(char * bufhdr, size_t maxlen);
|
||||
static const char *scale_number (float n, int width);
|
||||
/*
|
||||
* caveats: 5th fiels of nrgNBmeasurgroups[] entries is NULL as we are not yet defining in this module the statistics content to
|
||||
* be passed from statistics thread. That field was created for future extensibility work on reuniting statistics management.
|
||||
*/
|
||||
static telnet_measurgroupdef_t nrgNBmeasurgroups[] = {
|
||||
{GNB_STATS_L2_MAC, GROUP_LTESTATS, 0, gNBL2pstats_measurcmd_display , {NULL}},
|
||||
{GNB_STATS_L1 , GROUP_CPUSTATS, 0, gNBL1cpustats_measurcmd_display, {NULL}}
|
||||
};
|
||||
|
||||
const char SPACE_LABEL=' ';
|
||||
const char MINUS_LABEL='-';
|
||||
const char * ULSCH_LABEL="[UL sch]";
|
||||
const char * DLSCH_LABEL="[DL sch]";
|
||||
|
||||
int get_measurgroups(telnet_measurgroupdef_t **measurgroups)
|
||||
{
|
||||
*measurgroups = nrgNBmeasurgroups;
|
||||
return sizeof(nrgNBmeasurgroups)/sizeof(telnet_measurgroupdef_t);
|
||||
}
|
||||
|
||||
// magic numbers for the below table
|
||||
#define TELNETSRV_TBL_HARQ_DL 10
|
||||
#define TELNETSRV_TBL_HARQ_UL 16
|
||||
// XXX: table below would need a bit of tuning to understand expected values ranges and avoid massive use of scaling functionality
|
||||
static const struct itemtable_t{
|
||||
int width; // field width in ASCII characters
|
||||
bool tobescaled; // 1(true), 0(false) scaling the value to i.e. Kb, Mb, etc..
|
||||
char *itemlabel; // the new libproc item enum identifier
|
||||
enum {TELNETSRV_SCH_NONE = 0, TELNETSRV_SCH_DL, TELNETSRV_SCH_UL} scheduler;
|
||||
} itemtable[] = {
|
||||
{2, false, "UE" , TELNETSRV_SCH_NONE}, // UE number
|
||||
{4, false, "RNTI" , TELNETSRV_SCH_NONE},
|
||||
{2, false, "PH" , TELNETSRV_SCH_NONE},
|
||||
{5, false, "PCMax" , TELNETSRV_SCH_NONE},
|
||||
{7, false, "RSRPavg" , TELNETSRV_SCH_NONE},
|
||||
{8, false, "RSRPmeas", TELNETSRV_SCH_NONE},
|
||||
{3, false, "cqi" , TELNETSRV_SCH_NONE},
|
||||
{2, false, "ri" , TELNETSRV_SCH_NONE},
|
||||
{5, false, "pmix1" , TELNETSRV_SCH_NONE}, // uint8
|
||||
{5, false, "pmix2" , TELNETSRV_SCH_NONE}, // uint8
|
||||
{4, true , "HARQ" , TELNETSRV_SCH_DL }, // special case pointed by TELNETSRV_TBL_HARQ_DL. Given that we do not know how many dl_rounds elements you
|
||||
// will have,width here is related to each of the dl_rounds. It is similar reasoning for UL below
|
||||
{4, true , "E" , TELNETSRV_SCH_DL },
|
||||
{3, false, "dtx" , TELNETSRV_SCH_DL },
|
||||
{5, true , "bler" , TELNETSRV_SCH_DL }, // float
|
||||
{3, false, "mcs" , TELNETSRV_SCH_DL },
|
||||
{6, true , "bdlsch" , TELNETSRV_SCH_UL }, // tot bytes scheduled
|
||||
{4, true , "HARQ" , TELNETSRV_SCH_UL }, // special case pointed by TELNETSRV_TBL_HARQ_UL. See HARQ for DL above
|
||||
{4, true , "E" , TELNETSRV_SCH_UL },
|
||||
{3, false, "dtx" , TELNETSRV_SCH_UL },
|
||||
{5, true , "bler" , TELNETSRV_SCH_UL }, // float
|
||||
{3, false, "mcs" , TELNETSRV_SCH_UL },
|
||||
{6, true , "bulsch" , TELNETSRV_SCH_UL }, // tot bytes scheduled
|
||||
{6, true , "brxtot" , TELNETSRV_SCH_UL } // tot bytes received
|
||||
|
||||
};
|
||||
|
||||
static char * gNBL2pstats_gethdrline1(char *bufhdr, size_t maxlen)
|
||||
{
|
||||
unsigned int idx;
|
||||
int bufhdr_idx=0;
|
||||
|
||||
int empty_spaces = 0;
|
||||
int dl_sch = 0;
|
||||
int ul_sch = 0;
|
||||
int width = 0;
|
||||
gNB_MAC_INST *gNB = RC.nrmac[0];
|
||||
|
||||
for (idx=0; idx < (sizeof(itemtable)/sizeof(struct itemtable_t)); idx++)
|
||||
{
|
||||
if ((bufhdr_idx + itemtable[idx].width + 1) > maxlen)
|
||||
return NULL;
|
||||
|
||||
// handling special case of HARQ configurable numbers of rounds
|
||||
width = itemtable[idx].width + 1;
|
||||
if (idx == TELNETSRV_TBL_HARQ_DL)
|
||||
width = width * gNB->dl_bler.harq_round_max;
|
||||
else if (idx == TELNETSRV_TBL_HARQ_UL)
|
||||
width = width * gNB->ul_bler.harq_round_max;
|
||||
|
||||
switch (itemtable[idx].scheduler)
|
||||
{
|
||||
case TELNETSRV_SCH_NONE:
|
||||
empty_spaces += width;
|
||||
memset(bufhdr + bufhdr_idx, SPACE_LABEL, width);
|
||||
break;
|
||||
case TELNETSRV_SCH_DL:
|
||||
dl_sch += width;
|
||||
memset(bufhdr + bufhdr_idx, MINUS_LABEL, width);
|
||||
break;
|
||||
case TELNETSRV_SCH_UL:
|
||||
ul_sch += width;
|
||||
memset(bufhdr + bufhdr_idx, MINUS_LABEL, width);
|
||||
break;
|
||||
}
|
||||
bufhdr_idx += width;
|
||||
}
|
||||
bufhdr[bufhdr_idx] = '\n';
|
||||
bufhdr_idx++;
|
||||
bufhdr[bufhdr_idx] = '\0';
|
||||
|
||||
// now, overwite some parts if there is enough space
|
||||
if (dl_sch > (sizeof(DLSCH_LABEL) + 4 ))
|
||||
{
|
||||
bufhdr[empty_spaces + 2] = SPACE_LABEL;
|
||||
memcpy(bufhdr + empty_spaces + 3, DLSCH_LABEL, strlen(DLSCH_LABEL));
|
||||
bufhdr[empty_spaces + 3 + sizeof(DLSCH_LABEL)] = SPACE_LABEL;
|
||||
bufhdr[empty_spaces + dl_sch - 1] = SPACE_LABEL;
|
||||
}
|
||||
if (ul_sch > (sizeof(ULSCH_LABEL) + 4 ))
|
||||
{
|
||||
bufhdr[empty_spaces + dl_sch + 2] = SPACE_LABEL;
|
||||
memcpy(bufhdr + empty_spaces + dl_sch + 3, ULSCH_LABEL, strlen(ULSCH_LABEL));
|
||||
bufhdr[empty_spaces + dl_sch + 3 + sizeof(ULSCH_LABEL)] = SPACE_LABEL;
|
||||
bufhdr[empty_spaces + dl_sch + ul_sch - 1] = SPACE_LABEL;
|
||||
}
|
||||
|
||||
return bufhdr;
|
||||
}
|
||||
|
||||
static char * gNBL2pstats_gethdrline2(char *bufhdr, size_t maxlen)
|
||||
{
|
||||
unsigned int idx;
|
||||
int printed=0;
|
||||
int width;
|
||||
gNB_MAC_INST *gNB = RC.nrmac[0];
|
||||
|
||||
for (idx=0; idx < (sizeof(itemtable)/sizeof(struct itemtable_t)); idx++)
|
||||
{
|
||||
if ((printed + itemtable[idx].width + 1) > maxlen)
|
||||
return NULL;
|
||||
width = itemtable[idx].width;
|
||||
if (idx == TELNETSRV_TBL_HARQ_DL)
|
||||
width = (width + 1)*gNB->dl_bler.harq_round_max - 1;
|
||||
else if (idx == TELNETSRV_TBL_HARQ_UL)
|
||||
width = (width + 1)*gNB->ul_bler.harq_round_max - 1;
|
||||
printed += snprintf(bufhdr + printed, maxlen - printed, "%*s ", width, itemtable[idx].itemlabel);
|
||||
}
|
||||
|
||||
bufhdr[printed] = '\n';
|
||||
printed++;
|
||||
bufhdr[printed] = '\0';
|
||||
|
||||
return bufhdr;
|
||||
}
|
||||
|
||||
static const char *scale_number (float n, int width)
|
||||
{
|
||||
static char buf[128];
|
||||
buf[0] = '\0';
|
||||
|
||||
if (width >= snprintf(buf, sizeof(buf), "%*.0f", width, n))
|
||||
return buf;
|
||||
|
||||
char *plabel;
|
||||
char scale_labels[] = { 'k', 'M', 'G', 'T', 'P', 'E', 0 };// E=exabytes are enough, no need for zettabytes and over
|
||||
for (plabel = scale_labels; *plabel != 0; plabel++)
|
||||
{
|
||||
n /= 1000.0;
|
||||
if (width >= snprintf(buf, sizeof(buf), "%*.1f%c", width - 1, n, *plabel))
|
||||
return buf;
|
||||
// let's retry with one decimal less to see if fits.
|
||||
if (width >= snprintf(buf, sizeof(buf), "%*.0f%c", width - 1, n, *plabel))
|
||||
return buf;
|
||||
}
|
||||
// worst case...
|
||||
snprintf(buf, sizeof(buf), "%*s" , width, "?");
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display UE statistics collected at gNB node related to MAC protocol (OSI Layer 2). This is for the moment limited to one instance of gNB
|
||||
* This function is meant to be used in combination with 'telnet set loopd 1000' and 'loop' command prepended to the 'measur' one to provide
|
||||
* refresh of 1000ms of the CLI.
|
||||
*
|
||||
* XXX: You should anyway consider about keeping an historic on the screen for these stats, one line per iteration,
|
||||
* not overwriting like loop command does until a specific command is pressed. One idea is to implement that as option of the loop command,
|
||||
* that forces to go in append instead of refreshing the position on the screen.
|
||||
*
|
||||
* XXX: note that max line length is TELNET_MAX_MSGLENGTH that is equal to 2048 chars. We do not check it yet in this function.
|
||||
*/
|
||||
static void gNBL2pstats_measurcmd_display(telnet_printfunc_t prnt)
|
||||
{
|
||||
const int gnb_inst = 0;
|
||||
gNB_MAC_INST *gNB = RC.nrmac[gnb_inst]; // CAVEATS: using global vars as signature of this function can't be change to fit more params.
|
||||
pthread_mutex_lock(&gNB->UE_info.mutex);
|
||||
|
||||
static char buf[1024];
|
||||
prnt(gNBL2pstats_gethdrline1(buf, sizeof(buf)));
|
||||
prnt(gNBL2pstats_gethdrline2(buf, sizeof(buf)));
|
||||
|
||||
/* loop over all the UEs registered: to each UE will be given a number that is just a progressive counter*/
|
||||
int uenum = 1;
|
||||
UE_iterator(gNB->UE_info.list, UE)
|
||||
{
|
||||
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
|
||||
NR_mac_stats_t *stats = &UE->mac_stats;
|
||||
const int avg_rsrp = stats->num_rsrp_meas > 0 ? stats->cumul_rsrp / stats->num_rsrp_meas : 0;
|
||||
|
||||
prnt("%*d" , itemtable[0].width , uenum++);
|
||||
prnt(" %0*x" , itemtable[1].width , UE->rnti);
|
||||
prnt(" %*d" , itemtable[2].width , sched_ctrl->ph);
|
||||
prnt(" %*d" , itemtable[3].width , sched_ctrl->pcmax);
|
||||
prnt(" %*d" , itemtable[4].width , avg_rsrp);
|
||||
prnt(" %*d" , itemtable[5].width , stats->num_rsrp_meas);
|
||||
prnt(" %*d" , itemtable[6].width , UE->UE_sched_ctrl.CSI_report.cri_ri_li_pmi_cqi_report.wb_cqi_1tb);
|
||||
prnt(" %*d" , itemtable[7].width , UE->UE_sched_ctrl.CSI_report.cri_ri_li_pmi_cqi_report.ri+1);
|
||||
prnt(" %*d" , itemtable[8].width , UE->UE_sched_ctrl.CSI_report.cri_ri_li_pmi_cqi_report.pmi_x1);
|
||||
prnt(" %*d" , itemtable[9].width , UE->UE_sched_ctrl.CSI_report.cri_ri_li_pmi_cqi_report.pmi_x2);
|
||||
prnt(" ");
|
||||
|
||||
for (int i=0; i<gNB->dl_bler.harq_round_max; i++){
|
||||
if (i!=0)
|
||||
prnt("/");
|
||||
prnt(scale_number(stats->dl.rounds[i], itemtable[TELNETSRV_TBL_HARQ_DL].width));
|
||||
}
|
||||
prnt(" %*"PRIu64"", itemtable[11].width, stats->dl.errors);
|
||||
prnt(" %*d" , itemtable[12].width, stats->pucch0_DTX);
|
||||
prnt(" %*.3f" , itemtable[13].width, sched_ctrl->dl_bler_stats.bler);
|
||||
prnt(" %*d" , itemtable[14].width, sched_ctrl->dl_bler_stats.mcs);
|
||||
prnt(" ");
|
||||
prnt(scale_number(stats->dl.total_bytes, itemtable[15].width));
|
||||
prnt(" ");
|
||||
for (int i=0; i<gNB->ul_bler.harq_round_max; i++){
|
||||
if (i!=0)
|
||||
prnt("/");
|
||||
prnt(scale_number(stats->ul.rounds[0], itemtable[TELNETSRV_TBL_HARQ_UL].width));
|
||||
}
|
||||
|
||||
prnt(" %*"PRIu64"", itemtable[17].width, stats->ul.errors);
|
||||
prnt(" %*d" , itemtable[18].width, stats->ulsch_DTX);
|
||||
prnt(" %*.3f" , itemtable[19].width, sched_ctrl->ul_bler_stats.bler);
|
||||
prnt(" %*d" , itemtable[20].width, sched_ctrl->ul_bler_stats.mcs);
|
||||
prnt(" ");
|
||||
prnt(scale_number(stats->ulsch_total_bytes_scheduled, itemtable[21].width));
|
||||
prnt(" ");
|
||||
prnt(scale_number(stats->ul.total_bytes, itemtable[22].width));
|
||||
prnt("\n");
|
||||
|
||||
/*
|
||||
* XXX-TODO: the values below
|
||||
* values: stats->dl.lc_bytes[lc_id] for lc_id = 0 ..63;
|
||||
* values: stats->ul.lc_bytes[lc_id] for lc_id = 0 ..63;
|
||||
* were included in the previous version of the stats. We will think about including as they are too many
|
||||
* to be added to one line stats display.
|
||||
*/
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&gNB->UE_info.mutex);
|
||||
|
||||
/*
|
||||
* XXX-TODO: also the values below
|
||||
* print_meas(&gNB->eNB_scheduler, "DL & UL scheduling timing stats", NULL, NULL);
|
||||
* print_meas(&gNB->schedule_dlsch,"dlsch scheduler",NULL,NULL);
|
||||
* print_meas(&gNB->rlc_data_req, "rlc_data_req",NULL,NULL);
|
||||
* print_meas(&gNB->rlc_status_ind,"rlc_status_ind",NULL,NULL);
|
||||
* were included in the previous version of the stats. They were using print_meas() to display to stderr and should be changed to
|
||||
* leverage prnt() function. This can be done via using print_meas_log() that prints to buffer, but unfortunately this function will include
|
||||
* the header of the fields you are printing (and we want to have just one line header, see gNBL2pstats_gethdrline2()), so you probably would
|
||||
* need to create a new print function i.e. print_meas_lograw().
|
||||
*/
|
||||
}
|
||||
@@ -47,7 +47,7 @@
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "common/config/config_userapi.h"
|
||||
#include "telnetsrv_measurements.h"
|
||||
|
||||
#include "common/utils/cpustats.h"
|
||||
|
||||
static char *grouptypes[] = {"ltestats","cpustats"};
|
||||
static double cpufreq;
|
||||
@@ -285,6 +285,94 @@ int measurcmd_async(char *buf, int debug, telnet_printfunc_t prnt) {
|
||||
free(subcmd);
|
||||
return CMDSTATUS_FOUND;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse command "measur enable STATNAME" and take action. STATNAME can be retrieved from 'measur show groups '
|
||||
*
|
||||
* @param[in] buf buffer containing the command to be parsed. Expected "<stats name>"
|
||||
* @param[in] debug if > 0, it print debugging information on the log file for telnet
|
||||
* @param[in] prnt printing function for telnet CLI
|
||||
*
|
||||
* @return 0(success), error code otherwise
|
||||
*/
|
||||
int
|
||||
measurcmd_enablestats(char *buf, int debug, telnet_printfunc_t prnt)
|
||||
{
|
||||
char *statname = NULL;
|
||||
int ret = CMDSTATUS_NOTFOUND;
|
||||
|
||||
if (debug > 0)
|
||||
prnt("measurcmd_enablestats received %s\n", buf);
|
||||
|
||||
if (buf == NULL)
|
||||
return ret;
|
||||
|
||||
if (sscanf(buf, "%ms\n", &statname) != 1){
|
||||
prnt("Error parsing commandline for enable stats: %s\n", strerror(errno));
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (strcmp (statname, UE_STATS_L1) == 0){
|
||||
if (UEL1cpustats_enable() ==false)
|
||||
prnt ("Error when enabling statistics. See log file of UE for exact cause\n");
|
||||
else
|
||||
ret = CMDSTATUS_FOUND;
|
||||
} else if (strcmp (statname, GNB_STATS_L1) == 0){
|
||||
if (gNBL1cpustats_enable(RC.gNB[0]) == false)
|
||||
prnt ("Error when enabling statistics. See log file of gNB for exact cause\n");
|
||||
else
|
||||
ret = CMDSTATUS_FOUND;
|
||||
} else if (strcmp (statname, GNB_STATS_L2_MAC) == 0){
|
||||
prnt ("Nothing to do for this type of statistic. Already activated\n");
|
||||
ret = CMDSTATUS_FOUND;
|
||||
} else {
|
||||
prnt ("ERR: unsupported stat %s\n", statname);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse command "measur disable STATNAME" and take action. STATNAME can be retrieved from 'measur show groups '
|
||||
*
|
||||
* @param[in] buf buffer containing the command to be parsed. Expected "<stats name>"
|
||||
* @param[in] debug if > 0, it print debugging information on the log file for telnet
|
||||
* @param[in] prnt printing function for telnet CLI
|
||||
*
|
||||
* @return 0(success), error code otherwise
|
||||
*/
|
||||
int
|
||||
measurcmd_disablestats(char *buf, int debug, telnet_printfunc_t prnt)
|
||||
{
|
||||
char *statname = NULL;
|
||||
int ret = CMDSTATUS_NOTFOUND;
|
||||
|
||||
if (debug > 0)
|
||||
prnt("measurcmd_disablestats received %s\n", buf);
|
||||
|
||||
if (buf == NULL)
|
||||
return ret;
|
||||
|
||||
if (sscanf(buf, "%ms\n", &statname) != 1){
|
||||
prnt("Error parsing commandline for disable stats: %s\n", strerror(errno));
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (strcmp (statname, UE_STATS_L1) == 0){
|
||||
UEL1cpustats_disable();
|
||||
ret = CMDSTATUS_FOUND;
|
||||
} else if (strcmp (statname, GNB_STATS_L1) == 0){
|
||||
gNBL1cpustats_disable();
|
||||
ret = CMDSTATUS_FOUND;
|
||||
} else if (strcmp (statname, GNB_STATS_L2_MAC) == 0){
|
||||
prnt ("Nothing to do for this type of statistic. They are always activated\n");
|
||||
ret = CMDSTATUS_FOUND;
|
||||
} else {
|
||||
prnt ("ERR: unsupported statistic to be disabled: %s\n", statname);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
/*-------------------------------------------------------------------------------------*/
|
||||
|
||||
/* function called at telnet server init to add the measur command */
|
||||
|
||||
@@ -79,16 +79,24 @@ typedef struct mesurgroupdef {
|
||||
#define MACSTATS_NAME(valptr) #valptr
|
||||
#define LTEMAC_MEASURGROUP_NAME "ltemac"
|
||||
#define PHYCPU_MEASURGROUP_NAME "phycpu"
|
||||
#define GNB_STATS_L2_MAC "gnb_L2"
|
||||
|
||||
#ifdef TELNETSRV_MEASURMENTS_MAIN
|
||||
int measurcmd_show(char *buf, int debug, telnet_printfunc_t prnt);
|
||||
int measurcmd_cpustats(char *buf, int debug, telnet_printfunc_t prnt);
|
||||
int measurcmd_async(char *buf, int debug, telnet_printfunc_t prnt);
|
||||
int measurcmd_enablestats(char *buf, int debug, telnet_printfunc_t prnt);
|
||||
int measurcmd_disablestats(char *buf, int debug, telnet_printfunc_t prnt);
|
||||
|
||||
|
||||
|
||||
telnetshell_cmddef_t measur_cmdarray[] = {
|
||||
{"show", "groups | <group name> | inq" , measurcmd_show},
|
||||
{"cpustats","[enable | disable]",measurcmd_cpustats},
|
||||
{"async","[enable | disable]",measurcmd_async},
|
||||
{"","",NULL}
|
||||
{"cpustats", "[enable | disable]", measurcmd_cpustats},
|
||||
{"enable", "<stat name>", measurcmd_enablestats},
|
||||
{"disable", "<stat name>", measurcmd_disablestats},
|
||||
{"async", "[enable | disable]", measurcmd_async},
|
||||
{"", "", NULL}
|
||||
};
|
||||
|
||||
telnetshell_vardef_t measur_vardef[] = {
|
||||
|
||||
@@ -87,6 +87,8 @@
|
||||
#include <openair1/PHY/NR_TRANSPORT/nr_dlsch.h>
|
||||
#include <PHY/NR_ESTIMATION/nr_ul_estimation.h>
|
||||
|
||||
#include "common/utils/cpustats.h"
|
||||
|
||||
//#define USRP_DEBUG 1
|
||||
// Fix per CC openair rf/if device update
|
||||
// extern openair0_device openair0;
|
||||
@@ -466,8 +468,12 @@ void init_gNB_Tpool(int inst) {
|
||||
pushNotifiedFIFO(&gNB->L1_tx_free, msgL1Tx); // to unblock the process in the beginning
|
||||
}
|
||||
|
||||
if ((!get_softmodem_params()->emulate_l1) && (!IS_SOFTMODEM_NOSTATS_BIT))
|
||||
threadCreate(&proc->L1_stats_thread,nrL1_stats_thread,(void*)gNB,"L1_stats",-1,OAI_PRIORITY_RT_LOW);
|
||||
if ((!get_softmodem_params()->emulate_l1) && (!IS_SOFTMODEM_NOSTATS_BIT)){
|
||||
bool ret = gNBL1cpustats_enable(gNB);
|
||||
if (ret == false)
|
||||
LOG_E(PHY,"Failure activating statistics thread L1 for gNB instance #%d", inst);
|
||||
threadCreate(&proc->L1_stats_thread,nrL1_stats_thread,(void*)gNB,"L1_stats",-1,OAI_PRIORITY_RT_LOW);
|
||||
}
|
||||
|
||||
threadCreate(&proc->pthread_tx_reorder, tx_reorder_thread, (void *)gNB, "thread_tx_reorder", -1, OAI_PRIORITY_RT_MAX);
|
||||
|
||||
|
||||
@@ -1043,7 +1043,6 @@ void *ru_thread( void *param ) {
|
||||
int frame = 1023;
|
||||
char threadname[40];
|
||||
int initial_wait=0;
|
||||
int opp_enabled0 = opp_enabled;
|
||||
|
||||
nfapi_nr_config_request_scf_t *cfg = &ru->config;
|
||||
// set default return value
|
||||
@@ -1174,10 +1173,9 @@ void *ru_thread( void *param ) {
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (proc->frame_rx>=300) {
|
||||
if (proc->frame_rx>=300)
|
||||
initial_wait=0;
|
||||
opp_enabled = opp_enabled0;
|
||||
}
|
||||
|
||||
if (initial_wait == 0 && ru->rx_fhaul.trials > 1000) reset_meas(&ru->rx_fhaul);
|
||||
proc->timestamp_tx = proc->timestamp_rx;
|
||||
int sl=proc->tti_tx;
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
#include "LAYER2/nr_pdcp/nr_pdcp_entity.h"
|
||||
#include "SCHED_NR_UE/pucch_uci_ue_nr.h"
|
||||
#include "openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h"
|
||||
|
||||
#include "common/utils/cpustats.h"
|
||||
/*
|
||||
* NR SLOT PROCESSING SEQUENCE
|
||||
*
|
||||
@@ -1114,6 +1114,8 @@ void init_NR_UE_threads(int nb_inst) {
|
||||
LOG_I(PHY,"Intializing UE Threads for instance %d (%p,%p)...\n",inst,PHY_vars_UE_g[inst],PHY_vars_UE_g[inst][0]);
|
||||
threadCreate(&threads[inst], UE_thread, (void *)UE, "UEthread", -1, OAI_PRIORITY_RT_MAX);
|
||||
if (!IS_SOFTMODEM_NOSTATS_BIT) {
|
||||
if (UEL1cpustats_enable() == false)
|
||||
LOG_E(PHY,"Failure activating Statistics thread L1");
|
||||
pthread_t stat_pthread;
|
||||
threadCreate(&stat_pthread, nrL1_UE_stats_thread, UE, "L1_UE_stats", -1, OAI_PRIORITY_RT_LOW);
|
||||
}
|
||||
|
||||
@@ -176,12 +176,11 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ((slot == 0) && (frame & 127) == 0) {
|
||||
char stats_output[16384];
|
||||
stats_output[0] = '\0';
|
||||
dump_mac_stats(RC.nrmac[module_idP], stats_output, sizeof(stats_output), true);
|
||||
LOG_I(NR_MAC, "Frame.Slot %d.%d\n%s\n", frame, slot, stats_output);
|
||||
if ( (!IS_SOFTMODEM_NOSTATS_BIT) && ((slot == 0) && (frame & 127) == 0)) {
|
||||
char stats_output[16384];
|
||||
stats_output[0]='\0';
|
||||
dump_mac_stats(RC.nrmac[module_idP], stats_output, sizeof(stats_output), true);
|
||||
LOG_I(NR_MAC,"Frame.Slot %d.%d\n%s\n",frame,slot,stats_output);
|
||||
}
|
||||
|
||||
nr_mac_update_timers(module_idP, frame, slot);
|
||||
|
||||
@@ -238,7 +238,7 @@ void mac_top_init_gNB(ngran_node_t node_type)
|
||||
RC.nrmac[i]->pre_processor_ul = nr_init_fr1_ulsch_preprocessor(i, 0);
|
||||
}
|
||||
if (!IS_SOFTMODEM_NOSTATS_BIT)
|
||||
threadCreate(&RC.nrmac[i]->stats_thread, nrmac_stats_thread, (void*)RC.nrmac[i], "MAC_STATS", -1, sched_get_priority_min(SCHED_OAI)+1 );
|
||||
pthread_create(&RC.nrmac[i]->stats_thread, NULL, nrmac_stats_thread, (void*)RC.nrmac[i]); // this is a printing thread only.
|
||||
mac_rrc_init(RC.nrmac[i], node_type);
|
||||
}//END for (i = 0; i < RC.nb_nr_macrlc_inst; i++)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user