Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
O
OpenXG-RAN
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
lizhongxiao
OpenXG-RAN
Commits
eb711f65
Commit
eb711f65
authored
Oct 05, 2023
by
Robert Schmidt
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add basic O1 telnet module to read cell parameters
parent
98cbf6c0
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
640 additions
and
0 deletions
+640
-0
common/utils/telnetsrv/CMakeLists.txt
common/utils/telnetsrv/CMakeLists.txt
+6
-0
common/utils/telnetsrv/DOC/telneto1.md
common/utils/telnetsrv/DOC/telneto1.md
+185
-0
common/utils/telnetsrv/DOC/telnetsrv.md
common/utils/telnetsrv/DOC/telnetsrv.md
+1
-0
common/utils/telnetsrv/telnetsrv_o1.c
common/utils/telnetsrv/telnetsrv_o1.c
+448
-0
No files found.
common/utils/telnetsrv/CMakeLists.txt
View file @
eb711f65
...
...
@@ -64,8 +64,14 @@ add_library(telnetsrv_bearer MODULE telnetsrv_bearer.c)
target_link_libraries
(
telnetsrv_bearer PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs
)
add_dependencies
(
telnetsrv telnetsrv_bearer
)
message
(
STATUS
"Add CI specific telnet functions in libtelnetsrv_o1.so"
)
add_library
(
telnetsrv_o1 MODULE telnetsrv_o1.c
)
target_link_libraries
(
telnetsrv_o1 PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs
)
add_dependencies
(
telnetsrv telnetsrv_o1
)
# all libraries should be written to root build dir
set_target_properties
(
telnetsrv telnetsrv_enb telnetsrv_5Gue telnetsrv_ci telnetsrv_bearer
telnetsrv_o1
PROPERTIES LIBRARY_OUTPUT_DIRECTORY ../../..
)
common/utils/telnetsrv/DOC/telneto1.md
0 → 100644
View file @
eb711f65
[[
_TOC_
]]
The telnet O1 module (
`telnetsrv_o1.c`
) can be used to perform some O1-related
actions (reading data, starting and stopping the nr-softmodem, reconfigurating
frequency and bandwidth).
# General usage
The usage is similar to the general telnet usage, but in short:
```
./build_oai --ninja -c --gNB --nrUE --build-lib telnetsrv
```
to build everything including the telnet library. Then, run the nr-softmodem
by activating telnet and loading the
`o1`
module:
```
./nr-softmodem -O <config> --telnetsrv --telnetsrv.shrmod o1
```
Afterwards, it should be possible to connect via telnet on localhost, port
9090.
Use
`help`
to get help on the different command sections, and type e.g.
`o1 stats`
to get statistics (more information further below):
```
$ telnet 127.0.0.1 9090
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
softmodem_gnb> help
[...]
module 4 = o1:
o1 stats
o1 config ?
o1 stop_modem
o1 start_modem
[...]
softmodem_gnb> o1 stats
[...]
softmodem_gnb> exit
Connection closed by foreign host.
```
It also possible to send a command "directly from the command line", by piping
the command into netcat:
```
echo o1 stats | nc -N 127.0.0.1 9090
```
Note that only one telnet client can be connected at a time.
# Get statistics
Use the
`o1 stats`
command. The output is in JSON format:
```
json
{
"o1-config"
:
{
"BWP"
:
{
"dl"
:
[
{
"bwp3gpp:isInitialBwp"
:
true
,
"bwp3gpp:numberOfRBs"
:
106
,
"bwp3gpp:startRB"
:
0
,
"bwp3gpp:subCarrierSpacing"
:
30
}
],
"ul"
:
[
{
"bwp3gpp:isInitialBwp"
:
true
,
"bwp3gpp:numberOfRBs"
:
106
,
"bwp3gpp:startRB"
:
0
,
"bwp3gpp:subCarrierSpacing"
:
30
}
]
},
"NRCELLDU"
:
{
"nrcelldu3gpp:ssbFrequency"
:
641280
,
"nrcelldu3gpp:arfcnDL"
:
640008
,
"nrcelldu3gpp:bSChannelBwDL"
:
40
,
"nrcelldu3gpp:arfcnUL"
:
640008
,
"nrcelldu3gpp:bSChannelBwUL"
:
40
,
"nrcelldu3gpp:nRPCI"
:
0
,
"nrcelldu3gpp:nRTAC"
:
1
,
"nrcelldu3gpp:mcc"
:
"208"
,
"nrcelldu3gpp:mnc"
:
"95"
,
"nrcelldu3gpp:sd"
:
16777215
,
"nrcelldu3gpp:sst"
:
1
},
"device"
:
{
"gnbId"
:
1
,
"gnbName"
:
"gNB-Eurecom-5GNRBox"
,
"vendor"
:
"OpenAirInterface"
}
},
"O1-Operational"
:
{
"frame-type"
:
"tdd"
,
"band-number"
:
78
,
"num-ues"
:
1
,
"ues"
:
[
6876
],
"load"
:
9
,
"ues-thp"
:
[
{
"rnti"
:
6876
,
"dl"
:
3279
,
"ul"
:
2725
}
]
}
}
```
Note that no actual JSON engine is used, so no actual verification is done; it
is for convenience of the consumer. To verify, you can employ
`jq`
:
```
echo o1 stats | nc -N 127.0.0.1 9090 | awk '/^{$/, /^}$/' | jq .
```
(
`awk`
's pattern matching makes that only everything between the first
`{`
and
its corresponding
`}`
is printed).
There are two sections:
1.
`.o1-config`
show some stats that map directly to the O1 Netconf model. Note
that only one MCC/MNC/SD/SST (each) are supported right now. Also, note that
as per 3GPP specifications, SD of value
`0xffffff`
(16777215 in decimal)
means "no SD".
`bSChannelBwDL/UL`
is reported in MHz.
2.
`.O1-operational`
output some statistics that do not map yet to any netconf
parameters, but that might be useful nevertheless for a consumer.
# Write a new configuration
Use
`o1 config`
to write a configuration:
```
echo o1 config nrcelldu3gpp:ssbFrequency 620736 nrcelldu3gpp:arfcnDL 620020 nrcelldu3gpp:bSChannelBwDL 51 bwp3gpp:numberOfRBs 51 bwp3gpp:startRB 0 | nc -N 127.0.0.1 9090
```
You have to pass the above parameters in exactly this order. The softmodem
needs to be stopped; it will pick up the new configuration when starting the
softmodem again.
Note that you cannot switch three-quarter sampling for this as of now.
For values of the configuration, refer to the next section.
# Use hardcoded configuration
Use
`o1 bwconfig`
to write a hard-coded configuration for 20 or 40 MHz cells:
```
echo o1 bwconfig 20 | nc -N 127.0.0.1 9090
echo o1 bwconfig 40 | nc -N 127.0.0.1 9090
```
The softmodem needs to be stopped; it will pick up the new configuration when
starting the softmodem again.
Use
`o1 stats`
to see which configurations are set by these commands for the
parameters
`nrcelldu3gpp:ssbFrequency`
,
`nrcelldu3gpp:arfcnDL`
,
`nrcelldu3gpp:arfcnUL`
,
`nrcelldu3gpp:bSChannelBwDL`
,
`nrcelldu3gpp:bSChannelBwUL`
, and
`bwp3gpp:numberOfRBsbwp3gpp:startRB`
.
Furthermore, for 20MHz, it
*disables*
three-quarter sampling, whereas it
*enables*
three-quarter sampling for 40MHz.
# Restart the softmodem
Use
`o1 stop_modem`
to stop the
`nr-softmodem`
. To restart the softmodem, use
`o1 start_modem`
:
```
echo o1 stop_modem | nc -N 127.0.0.1 9090
echo o1 start_modem | nc -N 127.0.0.1 9090
```
In fact, stopping terminates all L1 threads and, due to implementation details,
the RRC thread. It will be as if the softmodem "freezes", and no periodical
output of statistics will occur (the O1 telnet interface will still work,
though). Starting again will "defreeze" the softmodem.
`stop_modem`
works reliably at this point.
`start_modem`
comes with a couple of
caveats:
*
not all memory is freed properly: for instance, the configuration module runs
out of memory after a couple of restarts, and will stop everything.
*
it is advisable to disconnect any UE before stopping. The MAC runs in the
same thread as the L1, and since we stop the L1, it is as if the MAC
"freezes" in time. When you restart the softmodem, frame and slot numbers
might not match with data stored internally at the MAC, and the softmodem
might assert. Alse, any UE will be disconnected (USRP: no radio, RFsimulator:
TCP socket closed); this in itself is not a problem from a gNB perspective,
but of course the UE is not immediately operational after restarting.
common/utils/telnetsrv/DOC/telnetsrv.md
View file @
eb711f65
...
...
@@ -3,5 +3,6 @@ The oai embedded telnet server is an optional monitoring and debugging tool. It
*
[
Using the telnet server
](
telnetusage.md
)
*
[
Adding commands to the oai telnet server
](
telnetaddcmd.md
)
*
[
telnet server architecture
](
telnetarch.md
)
*
[
on the telnet O1 module
](
telneto1.md
)
[
oai Wikis home
](
https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/home
)
common/utils/telnetsrv/telnetsrv_o1.c
0 → 100644
View file @
eb711f65
/*
* 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
*/
#include <sys/types.h>
#include <stdio.h>
#include <ctype.h>
#include <unistd.h>
#include <errno.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#define TELNETSERVERCODE
#include "telnetsrv.h"
#include "openair2/RRC/NR/nr_rrc_defs.h"
#include "openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h"
#include "openair2/RRC/NR/nr_rrc_config.h"
#include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h"
#include "openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c"
#include "common/utils/nr/nr_common.h"
#define ERROR_MSG_RET(mSG, aRGS...) do { prnt("FAILURE: " mSG, ##aRGS); return 1; } while (0)
#define ISINITBWP "bwp3gpp:isInitialBwp"
//#define CYCLPREF "bwp3gpp:cyclicPrefix"
#define NUMRBS "bwp3gpp:numberOfRBs"
#define STARTRB "bwp3gpp:startRB"
#define BWPSCS "bwp3gpp:subCarrierSpacing"
#define SSBFREQ "nrcelldu3gpp:ssbFrequency"
#define ARFCNDL "nrcelldu3gpp:arfcnDL"
#define BWDL "nrcelldu3gpp:bSChannelBwDL"
#define ARFCNUL "nrcelldu3gpp:arfcnUL"
#define BWUL "nrcelldu3gpp:bSChannelBwUL"
#define PCI "nrcelldu3gpp:nRPCI"
#define TAC "nrcelldu3gpp:nRTAC"
#define MCC "nrcelldu3gpp:mcc"
#define MNC "nrcelldu3gpp:mnc"
#define SD "nrcelldu3gpp:sd"
#define SST "nrcelldu3gpp:sst"
typedef
struct
b
{
long
int
dl
;
long
int
ul
;
}
b_t
;
static
int
get_stats
(
char
*
buf
,
int
debug
,
telnet_printfunc_t
prnt
)
{
if
(
buf
)
ERROR_MSG_RET
(
"no parameter allowed
\n
"
);
const
gNB_MAC_INST
*
mac
=
RC
.
nrmac
[
0
];
AssertFatal
(
mac
!=
NULL
,
"need MAC
\n
"
);
const
gNB_RRC_INST
*
rrc
=
RC
.
nrrrc
[
0
];
const
gNB_RrcConfigurationReq
*
conf
=
&
rrc
->
configuration
;
AssertFatal
(
rrc
!=
NULL
,
"need RRC
\n
"
);
const
NR_ServingCellConfigCommon_t
*
scc
=
mac
->
common_channels
[
0
].
ServingCellConfigCommon
;
const
NR_FrequencyInfoDL_t
*
frequencyInfoDL
=
scc
->
downlinkConfigCommon
->
frequencyInfoDL
;
const
NR_FrequencyInfoUL_t
*
frequencyInfoUL
=
scc
->
uplinkConfigCommon
->
frequencyInfoUL
;
frame_type_t
frame_type
=
get_frame_type
(
*
frequencyInfoDL
->
frequencyBandList
.
list
.
array
[
0
],
*
scc
->
ssbSubcarrierSpacing
);
const
NR_BWP_t
*
initialDL
=
&
scc
->
downlinkConfigCommon
->
initialDownlinkBWP
->
genericParameters
;
const
NR_BWP_t
*
initialUL
=
&
scc
->
uplinkConfigCommon
->
initialUplinkBWP
->
genericParameters
;
int
scs
=
initialDL
->
subcarrierSpacing
;
AssertFatal
(
scs
==
initialUL
->
subcarrierSpacing
,
"different SCS for UL/DL not supported!
\n
"
);
int
band
=
*
frequencyInfoDL
->
frequencyBandList
.
list
.
array
[
0
];
int
nrb
=
frequencyInfoDL
->
scs_SpecificCarrierList
.
list
.
array
[
0
]
->
carrierBandwidth
;
AssertFatal
(
nrb
==
frequencyInfoUL
->
scs_SpecificCarrierList
.
list
.
array
[
0
]
->
carrierBandwidth
,
"different BW for UL/DL not supported!
\n
"
);
int
bw_index
=
get_supported_band_index
(
scs
,
band
,
nrb
);
int
bw_mhz
=
get_supported_bw_mhz
(
band
>
256
?
FR2
:
FR1
,
bw_index
);
int
num_ues
=
0
;
UE_iterator
((
NR_UE_info_t
**
)
mac
->
UE_info
.
list
,
it
)
{
num_ues
++
;
}
const
mac_stats_t
*
stat
=
&
mac
->
mac_stats
;
static
mac_stats_t
last
=
{
0
};
int
diff_used
=
stat
->
used_prb_aggregate
-
last
.
used_prb_aggregate
;
int
diff_total
=
stat
->
total_prb_aggregate
-
last
.
total_prb_aggregate
;
int
load
=
diff_total
>
0
?
100
*
diff_used
/
diff_total
:
0
;
last
=
*
stat
;
static
struct
timespec
tp_last
=
{
0
};
struct
timespec
tp_now
;
clock_gettime
(
CLOCK_MONOTONIC
,
&
tp_now
);
size_t
diff_msec
=
(
tp_now
.
tv_sec
-
tp_last
.
tv_sec
)
*
1000
+
(
tp_now
.
tv_nsec
-
tp_last
.
tv_nsec
)
/
1000000
;
tp_last
=
tp_now
;
const
int
srb_flag
=
0
;
const
int
rb_id
=
1
;
static
b_t
last_total
[
MAX_MOBILES_PER_GNB
]
=
{
0
};
b_t
thr
[
MAX_MOBILES_PER_GNB
]
=
{
0
};
int
i
=
0
;
{
UE_iterator
((
NR_UE_info_t
**
)
mac
->
UE_info
.
list
,
it
)
{
nr_rlc_statistics_t
rlc
=
{
0
};
nr_rlc_get_statistics
(
it
->
rnti
,
srb_flag
,
rb_id
,
&
rlc
);
// static var last_total: we might have old data, larger than what
// reports RLC, leading to a huge number -> cut off to zero
if
(
last_total
[
i
].
dl
>
rlc
.
txpdu_bytes
)
last_total
[
i
].
dl
=
rlc
.
txpdu_bytes
;
if
(
last_total
[
i
].
ul
>
rlc
.
rxpdu_bytes
)
last_total
[
i
].
ul
=
rlc
.
rxpdu_bytes
;
thr
[
i
].
dl
=
(
rlc
.
txpdu_bytes
-
last_total
[
i
].
dl
)
*
8
/
diff_msec
;
thr
[
i
].
ul
=
(
rlc
.
rxpdu_bytes
-
last_total
[
i
].
ul
)
*
8
/
diff_msec
;
last_total
[
i
].
dl
=
rlc
.
txpdu_bytes
;
last_total
[
i
].
ul
=
rlc
.
rxpdu_bytes
;
i
++
;
}
}
prnt
(
"{
\n
"
);
prnt
(
"
\"
o1-config
\"
: {
\n
"
);
prnt
(
"
\"
BWP
\"
: {
\n
"
);
prnt
(
"
\"
dl
\"
: [{
\n
"
);
prnt
(
"
\"
"
ISINITBWP
"
\"
: true,
\n
"
);
//prnt(" \"" CYCLPREF "\": %ld,\n", *initialDL->cyclicPrefix);
prnt
(
"
\"
"
NUMRBS
"
\"
: %ld,
\n
"
,
NRRIV2BW
(
initialDL
->
locationAndBandwidth
,
MAX_BWP_SIZE
));
prnt
(
"
\"
"
STARTRB
"
\"
: %ld,
\n
"
,
NRRIV2PRBOFFSET
(
initialDL
->
locationAndBandwidth
,
MAX_BWP_SIZE
));
prnt
(
"
\"
"
BWPSCS
"
\"
: %ld
\n
"
,
15
*
(
1U
<<
scs
));
prnt
(
" }],
\n
"
);
prnt
(
"
\"
ul
\"
: [{
\n
"
);
prnt
(
"
\"
"
ISINITBWP
"
\"
: true,
\n
"
);
//prnt(" \"" CYCLPREF "\": %ld,\n", *initialUL->cyclicPrefix);
prnt
(
"
\"
"
NUMRBS
"
\"
: %ld,
\n
"
,
NRRIV2BW
(
initialUL
->
locationAndBandwidth
,
MAX_BWP_SIZE
));
prnt
(
"
\"
"
STARTRB
"
\"
: %ld,
\n
"
,
NRRIV2PRBOFFSET
(
initialUL
->
locationAndBandwidth
,
MAX_BWP_SIZE
));
prnt
(
"
\"
"
BWPSCS
"
\"
: %ld
\n
"
,
15
*
(
1U
<<
scs
));
prnt
(
" }]
\n
"
);
prnt
(
" },
\n
"
);
prnt
(
"
\"
NRCELLDU
\"
: {
\n
"
);
prnt
(
"
\"
"
SSBFREQ
"
\"
: %ld,
\n
"
,
*
scc
->
downlinkConfigCommon
->
frequencyInfoDL
->
absoluteFrequencySSB
);
prnt
(
"
\"
"
ARFCNDL
"
\"
: %ld,
\n
"
,
frequencyInfoDL
->
absoluteFrequencyPointA
);
prnt
(
"
\"
"
BWDL
"
\"
: %ld,
\n
"
,
bw_mhz
);
prnt
(
"
\"
"
ARFCNUL
"
\"
: %ld,
\n
"
,
frequencyInfoUL
->
absoluteFrequencyPointA
?
*
frequencyInfoUL
->
absoluteFrequencyPointA
:
frequencyInfoDL
->
absoluteFrequencyPointA
);
prnt
(
"
\"
"
BWUL
"
\"
: %ld,
\n
"
,
bw_mhz
);
prnt
(
"
\"
"
PCI
"
\"
: %ld,
\n
"
,
*
scc
->
physCellId
);
prnt
(
"
\"
"
TAC
"
\"
: %ld,
\n
"
,
conf
->
tac
);
prnt
(
"
\"
"
MCC
"
\"
:
\"
%03d
\"
,
\n
"
,
conf
->
mcc
[
0
]);
prnt
(
"
\"
"
MNC
"
\"
:
\"
%0*d
\"
,
\n
"
,
conf
->
mnc_digit_length
[
0
],
conf
->
mnc
[
0
]);
prnt
(
"
\"
"
SD
"
\"
: %d,
\n
"
,
conf
->
sd
);
prnt
(
"
\"
"
SST
"
\"
: %d
\n
"
,
conf
->
sst
);
prnt
(
" },
\n
"
);
prnt
(
"
\"
device
\"
: {
\n
"
);
prnt
(
"
\"
gnbId
\"
: %d,
\n
"
,
rrc
->
nr_cellid
);
// TODO something else, e.g., gnb_id?
prnt
(
"
\"
gnbName
\"
:
\"
%s
\"
,
\n
"
,
rrc
->
node_name
);
prnt
(
"
\"
vendor
\"
:
\"
OpenAirInterface
\"\n
"
);
prnt
(
" }
\n
"
);
prnt
(
" },
\n
"
);
prnt
(
"
\"
O1-Operational
\"
: {
\n
"
);
prnt
(
"
\"
frame-type
\"
:
\"
%s
\"
,
\n
"
,
frame_type
==
TDD
?
"tdd"
:
"fdd"
);
prnt
(
"
\"
band-number
\"
: %ld,
\n
"
,
band
);
prnt
(
"
\"
num-ues
\"
: %d,
\n
"
,
num_ues
);
prnt
(
"
\"
ues
\"
: ["
);
{
bool
first
=
true
;
UE_iterator
((
NR_UE_info_t
**
)
mac
->
UE_info
.
list
,
it
)
{
if
(
!
first
)
{
prnt
(
", "
);
}
prnt
(
"%d"
,
it
->
rnti
);
first
=
false
;
}
}
prnt
(
" ],
\n
"
);
prnt
(
"
\"
load
\"
: %d,
\n
"
,
load
);
prnt
(
"
\"
ues-thp
\"
: [
\n
"
);
{
bool
first
=
true
;
int
i
=
0
;
UE_iterator
((
NR_UE_info_t
**
)
mac
->
UE_info
.
list
,
it
)
{
if
(
!
first
)
{
prnt
(
", "
);
}
prnt
(
" {
\"
rnti
\"
: %d,
\"
dl
\"
: %ld,
\"
ul
\"
: %ld}
\n
"
,
it
->
rnti
,
thr
[
i
].
dl
,
thr
[
i
].
ul
);
i
++
;
first
=
false
;
}
}
prnt
(
" ]
\n
"
);
prnt
(
" }
\n
"
);
prnt
(
"}
\n
"
);
prnt
(
"OK
\n
"
);
return
0
;
}
static
int
read_long
(
const
char
*
buf
,
const
char
*
end
,
const
char
*
id
,
long
*
val
)
{
const
char
*
curr
=
buf
;
while
(
isspace
(
*
curr
)
&&
curr
<
end
)
// skip leading spaces
curr
++
;
int
len
=
strlen
(
id
);
if
(
curr
+
len
>=
end
)
return
-
1
;
if
(
strncmp
(
curr
,
id
,
len
)
!=
0
)
// check buf has id
return
-
1
;
curr
+=
len
;
while
(
isspace
(
*
curr
)
&&
curr
<
end
)
// skip middle spaces
curr
++
;
if
(
curr
>=
end
)
return
-
1
;
int
nread
=
sscanf
(
curr
,
"%ld"
,
val
);
if
(
nread
!=
1
)
return
-
1
;
while
(
isdigit
(
*
curr
)
&&
curr
<
end
)
// skip all digits read above
curr
++
;
if
(
curr
>
end
)
return
-
1
;
return
curr
-
buf
;
}
bool
running
=
true
;
// in the beginning, the softmodem is started automatically
static
int
set_config
(
char
*
buf
,
int
debug
,
telnet_printfunc_t
prnt
)
{
if
(
!
buf
)
ERROR_MSG_RET
(
"need param: o1 config param1 val1 [param2 val2 ...]
\n
"
);
if
(
running
)
ERROR_MSG_RET
(
"cannot set parameters while L1 is running
\n
"
);
const
char
*
end
=
buf
+
strlen
(
buf
);
/* we need to update the following fields to change frequency and/or
* bandwidth:
* --gNBs.[0].servingCellConfigCommon.[0].absoluteFrequencySSB 620736 -> SSBFREQ
* --gNBs.[0].servingCellConfigCommon.[0].dl_absoluteFrequencyPointA 620020 -> ARFCNDL
* --gNBs.[0].servingCellConfigCommon.[0].dl_carrierBandwidth 51 -> BWDL
* --gNBs.[0].servingCellConfigCommon.[0].initialDLBWPlocationAndBandwidth 13750 -> NUMRBS + STARTRB
* --gNBs.[0].servingCellConfigCommon.[0].ul_carrierBandwidth 51 -> BWUL?
* --gNBs.[0].servingCellConfigCommon.[0].initialULBWPlocationAndBandwidth 13750 -> ?
*/
int
processed
=
0
;
int
pos
=
0
;
long
ssbfreq
;
processed
=
read_long
(
buf
+
pos
,
end
,
SSBFREQ
,
&
ssbfreq
);
if
(
processed
<
0
)
ERROR_MSG_RET
(
"could not read "
SSBFREQ
" at index %d
\n
"
,
pos
+
processed
);
pos
+=
processed
;
prnt
(
"setting "
SSBFREQ
": %ld [len %d]
\n
"
,
ssbfreq
,
pos
);
long
arfcn
;
processed
=
read_long
(
buf
+
pos
,
end
,
ARFCNDL
,
&
arfcn
);
if
(
processed
<
0
)
ERROR_MSG_RET
(
"could not read "
ARFCNDL
" at index %d
\n
"
,
pos
+
processed
);
pos
+=
processed
;
prnt
(
"setting "
ARFCNDL
": %ld [len %d]
\n
"
,
arfcn
,
pos
);
long
bwdl
;
processed
=
read_long
(
buf
+
pos
,
end
,
BWDL
,
&
bwdl
);
if
(
processed
<
0
)
ERROR_MSG_RET
(
"could not read "
BWDL
" at index %d
\n
"
,
pos
+
processed
);
pos
+=
processed
;
prnt
(
"setting "
BWDL
": %ld [len %d]
\n
"
,
bwdl
,
pos
);
long
numrbs
;
processed
=
read_long
(
buf
+
pos
,
end
,
NUMRBS
,
&
numrbs
);
if
(
processed
<
0
)
ERROR_MSG_RET
(
"could not read "
NUMRBS
" at index %d
\n
"
,
pos
+
processed
);
pos
+=
processed
;
prnt
(
"setting "
NUMRBS
": %ld [len %d]
\n
"
,
numrbs
,
pos
);
long
startrb
;
processed
=
read_long
(
buf
+
pos
,
end
,
STARTRB
,
&
startrb
);
if
(
processed
<
0
)
ERROR_MSG_RET
(
"could not read "
STARTRB
" at index %d
\n
"
,
pos
+
processed
);
pos
+=
processed
;
prnt
(
"setting "
STARTRB
": %ld [len %d]
\n
"
,
startrb
,
pos
);
int
locationAndBandwidth
=
PRBalloc_to_locationandbandwidth0
(
numrbs
,
startrb
,
MAX_BWP_SIZE
);
prnt
(
"inferred locationAndBandwidth: %d
\n
"
,
locationAndBandwidth
);
/*
gNB_RRC_INST *rrc = RC.nrrrc[0];
NR_ServingCellConfigCommon_t *scc = rrc->carrier.servingcellconfigcommon;
NR_FrequencyInfoDL_t *frequencyInfoDL = scc->downlinkConfigCommon->frequencyInfoDL;
NR_BWP_t *initialDL = &scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters;
NR_FrequencyInfoUL_t *frequencyInfoUL = scc->uplinkConfigCommon->frequencyInfoUL;
NR_BWP_t *initialUL = &scc->uplinkConfigCommon->initialUplinkBWP->genericParameters;
//--gNBs.[0].servingCellConfigCommon.[0].absoluteFrequencySSB 620736 -> SSBFREQ
*scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB = ssbfreq;
// --gNBs.[0].servingCellConfigCommon.[0].dl_absoluteFrequencyPointA 620020 -> ARFCNDL
frequencyInfoDL->absoluteFrequencyPointA = arfcn;
AssertFatal(frequencyInfoUL->absoluteFrequencyPointA == NULL, "only handle TDD\n");
// --gNBs.[0].servingCellConfigCommon.[0].dl_carrierBandwidth 51 -> BWDL
frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth = bwdl;
// --gNBs.[0].servingCellConfigCommon.[0].initialDLBWPlocationAndBandwidth 13750 -> NUMRBS + STARTRB
initialDL->locationAndBandwidth = locationAndBandwidth;
// --gNBs.[0].servingCellConfigCommon.[0].ul_carrierBandwidth 51 -> BWUL?
// we assume the same BW as DL
frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth = bwdl;
// --gNBs.[0].servingCellConfigCommon.[0].initialULBWPlocationAndBandwidth 13750 -> ?
// we assume same locationAndBandwidth as DL
initialUL->locationAndBandwidth = locationAndBandwidth;
*/
prnt
(
"OK
\n
"
);
return
0
;
}
extern
int8_t
threequarter_fs
;
extern
openair0_config_t
openair0_cfg
[
MAX_CARDS
];
static
int
set_bwconfig
(
char
*
buf
,
int
debug
,
telnet_printfunc_t
prnt
)
{
if
(
running
)
ERROR_MSG_RET
(
"cannot set parameters while L1 is running
\n
"
);
if
(
!
buf
)
ERROR_MSG_RET
(
"need param: o1 bwconfig <BW>
\n
"
);
char
*
end
=
NULL
;
if
(
NULL
!=
(
end
=
strchr
(
buf
,
'\n'
)))
*
end
=
0
;
if
(
NULL
!=
(
end
=
strchr
(
buf
,
'\r'
)))
*
end
=
0
;
gNB_MAC_INST
*
mac
=
RC
.
nrmac
[
0
];
NR_ServingCellConfigCommon_t
*
scc
=
mac
->
common_channels
[
0
].
ServingCellConfigCommon
;
NR_FrequencyInfoDL_t
*
frequencyInfoDL
=
scc
->
downlinkConfigCommon
->
frequencyInfoDL
;
NR_BWP_t
*
initialDL
=
&
scc
->
downlinkConfigCommon
->
initialDownlinkBWP
->
genericParameters
;
NR_FrequencyInfoUL_t
*
frequencyInfoUL
=
scc
->
uplinkConfigCommon
->
frequencyInfoUL
;
NR_BWP_t
*
initialUL
=
&
scc
->
uplinkConfigCommon
->
initialUplinkBWP
->
genericParameters
;
if
(
strcmp
(
buf
,
"40"
)
==
0
)
{
*
scc
->
downlinkConfigCommon
->
frequencyInfoDL
->
absoluteFrequencySSB
=
641280
;
frequencyInfoDL
->
absoluteFrequencyPointA
=
640008
;
AssertFatal
(
frequencyInfoUL
->
absoluteFrequencyPointA
==
NULL
,
"only handle TDD
\n
"
);
frequencyInfoDL
->
scs_SpecificCarrierList
.
list
.
array
[
0
]
->
carrierBandwidth
=
106
;
initialDL
->
locationAndBandwidth
=
28875
;
frequencyInfoUL
->
scs_SpecificCarrierList
.
list
.
array
[
0
]
->
carrierBandwidth
=
106
;
initialUL
->
locationAndBandwidth
=
28875
;
threequarter_fs
=
1
;
openair0_cfg
[
0
].
threequarter_fs
=
1
;
}
else
if
(
strcmp
(
buf
,
"20"
)
==
0
)
{
*
scc
->
downlinkConfigCommon
->
frequencyInfoDL
->
absoluteFrequencySSB
=
641280
;
frequencyInfoDL
->
absoluteFrequencyPointA
=
640596
;
AssertFatal
(
frequencyInfoUL
->
absoluteFrequencyPointA
==
NULL
,
"only handle TDD
\n
"
);
frequencyInfoDL
->
scs_SpecificCarrierList
.
list
.
array
[
0
]
->
carrierBandwidth
=
51
;
initialDL
->
locationAndBandwidth
=
13750
;
frequencyInfoUL
->
scs_SpecificCarrierList
.
list
.
array
[
0
]
->
carrierBandwidth
=
51
;
initialUL
->
locationAndBandwidth
=
13750
;
threequarter_fs
=
0
;
openair0_cfg
[
0
].
threequarter_fs
=
0
;
}
else
{
ERROR_MSG_RET
(
"unhandled option %s
\n
"
,
buf
);
}
free
(
RC
.
nrmac
[
0
]
->
sched_ctrlCommon
);
RC
.
nrmac
[
0
]
->
sched_ctrlCommon
=
NULL
;
free_MIB_NR
(
mac
->
common_channels
[
0
].
mib
);
mac
->
common_channels
[
0
].
mib
=
get_new_MIB_NR
(
scc
);
// due to outrightly CRAZY memory handling in get_SIB1_NR(), we need to set
// some structures to zero to prevent that we shoot ourselves into the foot
//struct NR_SIB1 *xyz = rrc->carrier.siblock1->message.choice.c1->choice.systemInformationBlockType1;
//xyz->servingCellConfigCommon = NULL;
//free_SIB1_NR(rrc->carrier.siblock1);
const
f1ap_served_cell_info_t
*
info
=
&
mac
->
f1_config
.
setup_req
->
cell
[
0
].
info
;
/*
NR_BCCH_DL_SCH_Message_t *sib1 = get_SIB1_NR(scc, &info->plmn, into->nr_cellid, *info.tac);
rrc->carrier.SIB1 = calloc(NR_MAX_SIB_LENGTH / 8, sizeof(*rrc->carrier.SIB1));
AssertFatal(rrc->carrier.SIB1 != NULL, "out of memory\n");
rrc->carrier.sizeof_SIB1 = encode_SIB1_NR(sib1, rrc->carrier.SIB1, NR_MAX_SIB_LENGTH / 8);
rrc->carrier.siblock1 = sib1;
*/
nr_mac_configure_sib1
(
mac
,
&
info
->
plmn
,
info
->
nr_cellid
,
*
info
->
tac
);
//nr_mac_config_scc(mac, scc, &mac->radio_config);
prnt
(
"OK
\n
"
);
return
0
;
}
extern
int
stop_L1L2
(
module_id_t
gnb_id
);
static
int
stop_modem
(
char
*
buf
,
int
debug
,
telnet_printfunc_t
prnt
)
{
if
(
!
running
)
ERROR_MSG_RET
(
"cannot stop, nr-softmodem not running
\n
"
);
/* make UEs out of sync and wait 20ms to ensure no PUCCH is scheduled. After
* a restart, the frame/slot numbers will be different, which "confuses" the
* scheduler, which has many PUCCH structures filled with expected frame/slot
* combinations that won't happen. */
const
gNB_MAC_INST
*
mac
=
RC
.
nrmac
[
0
];
UE_iterator
((
NR_UE_info_t
**
)
mac
->
UE_info
.
list
,
it
)
{
it
->
UE_sched_ctrl
.
rrc_processing_timer
=
1000
;
}
usleep
(
50000
);
stop_L1L2
(
0
);
running
=
false
;
prnt
(
"OK
\n
"
);
return
0
;
}
extern
int
start_L1L2
(
module_id_t
gnb_id
);
static
int
start_modem
(
char
*
buf
,
int
debug
,
telnet_printfunc_t
prnt
)
{
if
(
running
)
ERROR_MSG_RET
(
"cannot start, nr-softmodem already running
\n
"
);
start_L1L2
(
0
);
running
=
true
;
prnt
(
"OK
\n
"
);
return
0
;
}
static
telnetshell_cmddef_t
o1cmds
[]
=
{
{
"stats"
,
""
,
get_stats
},
{
"config"
,
"[]"
,
set_config
},
{
"bwconfig"
,
""
,
set_bwconfig
},
{
"stop_modem"
,
""
,
stop_modem
},
{
"start_modem"
,
""
,
start_modem
},
{
""
,
""
,
NULL
},
};
static
telnetshell_vardef_t
o1vars
[]
=
{
{
""
,
0
,
0
,
NULL
}
};
void
add_o1_cmds
(
void
)
{
add_telnetcmd
(
"o1"
,
o1vars
,
o1cmds
);
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment