mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-17 06:30:31 +00:00
Compare commits
128 Commits
test_jf
...
wraparound
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
32471f94ba | ||
|
|
479be40b30 | ||
|
|
44c64a2ed0 | ||
|
|
b987b033d5 | ||
|
|
c9902a8615 | ||
|
|
5b92859cce | ||
|
|
be08d655b1 | ||
|
|
f744c4d4bc | ||
|
|
d569e7ddc9 | ||
|
|
10852cc89b | ||
|
|
7688af6293 | ||
|
|
55c8a7bef0 | ||
|
|
f2a7fb5336 | ||
|
|
45827ee213 | ||
|
|
63f3fb55ae | ||
|
|
e44b17668c | ||
|
|
91e7030cf8 | ||
|
|
e54153ef5c | ||
|
|
8f88efd97c | ||
|
|
a3a6c6d5e9 | ||
|
|
e5050416e4 | ||
|
|
f46ddb6aa8 | ||
|
|
f5b885e803 | ||
|
|
8d2478662d | ||
|
|
5c3c374c1b | ||
|
|
805c968b59 | ||
|
|
ca0cc079a6 | ||
|
|
98618a7dc8 | ||
|
|
5d4e17f8ca | ||
|
|
2230606f42 | ||
|
|
b137478dc8 | ||
|
|
3e5d868018 | ||
|
|
b2878f4ab1 | ||
|
|
88d1964f9c | ||
|
|
b547dfe056 | ||
|
|
eb9ac76f4d | ||
|
|
ca04193680 | ||
|
|
aa7d3668e3 | ||
|
|
0e7e030907 | ||
|
|
18edbc0f15 | ||
|
|
d28ae49eee | ||
|
|
04ac7eb4b9 | ||
|
|
04318f64ea | ||
|
|
388ad30f6b | ||
|
|
f35a1cd775 | ||
|
|
8f89637f8c | ||
|
|
5af58cc686 | ||
|
|
9e45f38fbd | ||
|
|
ad1c92af4f | ||
|
|
a9e7018b98 | ||
|
|
1140c59bbd | ||
|
|
ce7cb165dd | ||
|
|
a1b4220a91 | ||
|
|
7da7dda71b | ||
|
|
e3b0def6dc | ||
|
|
9c8274f6bd | ||
|
|
56f20d49bc | ||
|
|
d56945e45e | ||
|
|
e454fc41d1 | ||
|
|
2e80700d78 | ||
|
|
1603077171 | ||
|
|
6fe7581eed | ||
|
|
2ff7a56b95 | ||
|
|
68a4bb9a61 | ||
|
|
662c6e1aec | ||
|
|
c8b4aa2abd | ||
|
|
8300ab5a61 | ||
|
|
1368bb5a5c | ||
|
|
923b2ec188 | ||
|
|
d6e4e49fcb | ||
|
|
f6135ff1ff | ||
|
|
8ea95a0e52 | ||
|
|
f0151c21bd | ||
|
|
d5eb935ecf | ||
|
|
b1b120551d | ||
|
|
0226510c4a | ||
|
|
0f6b567ae9 | ||
|
|
df041a0f8c | ||
|
|
4b7970d601 | ||
|
|
110bbd10bc | ||
|
|
87adaafcfc | ||
|
|
b3c99d8ead | ||
|
|
10247cfbed | ||
|
|
1e610af168 | ||
|
|
8966dc2c4f | ||
|
|
c87a6ecfba | ||
|
|
0c4882940c | ||
|
|
b7454cf5d4 | ||
|
|
e8732ed8c8 | ||
|
|
95affc2a41 | ||
|
|
8943975eb3 | ||
|
|
c9c935af01 | ||
|
|
894491f2e5 | ||
|
|
0360175042 | ||
|
|
0386751da8 | ||
|
|
96ec2be887 | ||
|
|
bff0e53645 | ||
|
|
fea86247da | ||
|
|
176b71ae70 | ||
|
|
e1dd62df53 | ||
|
|
6512a7a9ca | ||
|
|
92107b18fe | ||
|
|
a283ef263b | ||
|
|
842b16092d | ||
|
|
62fe88d6f4 | ||
|
|
59af5e4ad2 | ||
|
|
43722e6bac | ||
|
|
1947f4d60c | ||
|
|
b60a40ccbf | ||
|
|
654fadb116 | ||
|
|
0bf99d9d16 | ||
|
|
f9a8898e20 | ||
|
|
389ca60d5e | ||
|
|
19301afcb1 | ||
|
|
19bb463049 | ||
|
|
163c8de371 | ||
|
|
96b944e5c9 | ||
|
|
0ad393f28e | ||
|
|
4233b89530 | ||
|
|
d542021f86 | ||
|
|
d4b5291c62 | ||
|
|
ad6d7a2220 | ||
|
|
a96d2d0118 | ||
|
|
09d9bb5b6a | ||
|
|
c83bd87459 | ||
|
|
e08d904af0 | ||
|
|
3247c2933f | ||
|
|
244819c627 |
66
CHANGELOG.md
66
CHANGELOG.md
@@ -1,5 +1,71 @@
|
||||
# RELEASE NOTES: #
|
||||
|
||||
## [v2.4.0](https://gitlab.eurecom.fr/oai/openairinterface5g/-/tags/v2.4.0) -> December 2025. ##
|
||||
|
||||
General new features and improvements (both RAN and UE):
|
||||
- Rework LDPC BBdev/AAL interface and support both AMD T2/Intel vRAN Boost
|
||||
(VRB) 1 accelerators
|
||||
- Add a taps client for vrtsim real-time simulator (check: vrtsim release?)
|
||||
- Add new RFemulator virtual radio driver to emulate radio (including noise
|
||||
generation) for gNB/UE standalone operation
|
||||
- RLC AM reception improvements for high-throughput scenarios (!3512)
|
||||
- Small NTN fixes (!3659, !3666, !3581, !3652)
|
||||
- Improvements to imScope
|
||||
|
||||
Stability and bug fixes:
|
||||
- RFsimulator: fix concurrency problems during multi-client connection
|
||||
- USRP driver: support synchronization of USRP B200
|
||||
- MAC scheduler improvements
|
||||
- General L1 improvements for efficiency and stability
|
||||
- Correct PRS bug and test in CI
|
||||
- Upgrade Ubuntu container images to Ubuntu 24.04
|
||||
- All build system targets compile (`make/ninja all`)
|
||||
- Minor cleanup, harmonization, and performance improvements all over the stack
|
||||
- Simplify CI code
|
||||
|
||||
RAN changes (gNB/CU/CU-CP/CU-UP/DU/DU-high/DU-low):
|
||||
- Support of N2 handover
|
||||
- Support of "UL-heavy" TDD patterns, e.g., DSUUU
|
||||
- Open Fronthaul M-plane: CM improvements, PM implementation, and additional
|
||||
v16.01 support
|
||||
- Improve interoperability with Nvidia Aerial L1 to support 2 layer UL
|
||||
- Add O-RAN OSC WLS library as FAPI transport and enable L1/L2 shared memory
|
||||
split
|
||||
- Implement FAPI Stop exchange
|
||||
- Improve interoperability with srsRAN_Project DU
|
||||
- Add new synchronized real-time data recording application (!3462)
|
||||
- Support for measurement gaps and general handover fixes
|
||||
- Support of RRC PDU session release procedure
|
||||
- Add CU-UP load tester
|
||||
- Correct BWP scheduling and support multiple BWPs per UE
|
||||
|
||||
nrUE changes:
|
||||
- Support one additional PDU session (see !3486)
|
||||
- L3 measurements for A2 measurement reports
|
||||
- Support for type0 PDSCH frequency allocation
|
||||
- UE symbol based PDCCH receiver
|
||||
|
||||
Regression or removals:
|
||||
- No known regressions
|
||||
- Unused L2 simulator code has been removed
|
||||
- Unused Benetel radio driver code (not FHI 7.2!) has been removed
|
||||
|
||||
Configuration file changes:
|
||||
- `gNBs.[0].servingCellConfigCommon.[0].ra_ResponseWindow` is automatically
|
||||
computed and can be removed
|
||||
- `gNBs.[0].bwp_list` has been added (moved from entries in
|
||||
`gNBs.[0].servingCellConfigDedicated`)
|
||||
- `gNBs.[0].phaseTrackingRS` has been added (moved from entries in
|
||||
`gNBs.[0].servingCellConfigDedicated`)
|
||||
- `gNBs.[0].local_s_portc` and `gNBs.[0].remote_s_portc` have no effect and
|
||||
should be removed
|
||||
- `gNBs.[0].CSI_report_type` has been added
|
||||
- `MACRLCs.[0].ulsch_max_frame_inactivity` is automatically computed and can be
|
||||
removed
|
||||
- `MACRLCs.[0].local_n_portc` and `MACRLCs.[0].remote_n_portc` have no effect and
|
||||
should be removed
|
||||
- `MACRLCs.[0].stats_max_ue` has been added
|
||||
|
||||
## [v2.3.0](https://gitlab.eurecom.fr/oai/openairinterface5g/-/tags/v2.3.0) -> July 2025. ##
|
||||
|
||||
General new features and improvements (both RAN and UE):
|
||||
|
||||
@@ -464,6 +464,9 @@ target_include_directories(f1ap PUBLIC F1AP_DIR)
|
||||
target_link_libraries(f1ap PUBLIC asn1_f1ap GTPV1U)
|
||||
target_link_libraries(f1ap PRIVATE ngap nr_rrc HASHTABLE f1ap_lib)
|
||||
target_include_directories(f1ap PRIVATE ${F1AP_DIR}/lib)
|
||||
if(E2_AGENT)
|
||||
target_compile_definitions(f1ap PRIVATE E2_AGENT)
|
||||
endif()
|
||||
|
||||
# LPP
|
||||
##############
|
||||
@@ -1288,6 +1291,9 @@ add_library(L2
|
||||
)
|
||||
target_link_libraries(L2 PRIVATE x2ap s1ap lte_rrc m2ap)
|
||||
target_link_libraries(L2 PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs)
|
||||
if(E2_AGENT)
|
||||
target_compile_definitions(L2 PRIVATE ${E2AP_VERSION} ${KPM_VERSION} E2_AGENT)
|
||||
endif()
|
||||
|
||||
add_library(MAC_UE_NR ${MAC_NR_SRC_UE})
|
||||
target_link_libraries(MAC_UE_NR PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs PUBLIC nr_ue_power_procedures nr_ue_ra_procedures)
|
||||
@@ -1303,6 +1309,9 @@ add_library(L2_NR
|
||||
target_link_libraries(L2_NR PRIVATE ds alg)
|
||||
target_link_libraries(L2_NR PRIVATE f1ap_lib)
|
||||
target_include_directories(L2_NR PRIVATE ${F1AP_DIR}/lib)
|
||||
if(E2_AGENT)
|
||||
target_compile_definitions(L2_NR PRIVATE ${E2AP_VERSION} ${KPM_VERSION} E2_AGENT)
|
||||
endif()
|
||||
|
||||
add_library(e1_if
|
||||
${NR_RRC_DIR}/cucp_cuup_direct.c
|
||||
|
||||
@@ -397,9 +397,9 @@ class Cluster:
|
||||
# Analyze the logs
|
||||
collectInfo = {}
|
||||
for image, lf in log_files:
|
||||
ret = cls_containerize.AnalyzeBuildLogs(image, lf)
|
||||
imgStatus = ret['status']
|
||||
msg = f"size {imageSize[image]}, analysis of {os.path.basename(lf)}: {ret['errors']} errors, {ret['warnings']} warnings"
|
||||
imgStatus, errors = cls_containerize.AnalyzeBuildLogs(image, lf)
|
||||
info = f"Analysis of {os.path.basename(lf)}: {imgStatus=}, size {imageSize[image]}, {len(errors)} errors"
|
||||
msg = "\n".join([info] + errors)
|
||||
HTML.CreateHtmlTestRowQueue(image, 'OK' if imgStatus else 'KO', [msg])
|
||||
status = status and imgStatus
|
||||
|
||||
|
||||
@@ -86,9 +86,9 @@ def CreateTag(ranCommitID, ranBranch, ranAllowMerge):
|
||||
return tagToUse
|
||||
|
||||
def AnalyzeBuildLogs(image, lf):
|
||||
errorandwarnings = {}
|
||||
committed = False
|
||||
tagged = False
|
||||
errors = []
|
||||
with open(lf, mode='r') as inputfile:
|
||||
for line in inputfile:
|
||||
lineHasTag = re.search(f'Successfully tagged {image}:', str(line)) is not None
|
||||
@@ -97,11 +97,13 @@ def AnalyzeBuildLogs(image, lf):
|
||||
# the OpenShift Cluster builder prepends image registry URL
|
||||
lineHasCommit = re.search(r'COMMIT [a-zA-Z0-9\.:/\-]*' + image, str(line)) is not None
|
||||
committed = committed or lineHasCommit
|
||||
errorandwarnings['errors'] = 0 if committed or tagged else 1
|
||||
errorandwarnings['warnings'] = 0
|
||||
errorandwarnings['status'] = committed or tagged
|
||||
logging.info(f"Analyzing {image}, file {lf}: {errorandwarnings}")
|
||||
return errorandwarnings
|
||||
if re.search(r'error:|Errors|ERROR', line):
|
||||
errors.append(f"=> {line.strip()}")
|
||||
status = (committed or tagged) and len(errors) == 0
|
||||
logging.info(f"Analyzing {image}, file {lf}: {status=}, {len(errors)} errors")
|
||||
for e in errors:
|
||||
logging.info(e)
|
||||
return status, errors
|
||||
|
||||
def GetImageName(ssh, svcName, file):
|
||||
ret = ssh.run(f"docker compose -f {file} config --format json {svcName} | jq -r '.services.\"{svcName}\".image'", silent=True)
|
||||
@@ -460,9 +462,9 @@ class Containerize():
|
||||
|
||||
# Analyze the logs
|
||||
for name, lf in log_files:
|
||||
ret = AnalyzeBuildLogs(name, lf)
|
||||
imgStatus = ret['status']
|
||||
msg = f"size {allImagesSize[name]}, analysis of {os.path.basename(lf)}: {ret['errors']} errors, {ret['warnings']} warnings"
|
||||
imgStatus, errors = AnalyzeBuildLogs(name, lf)
|
||||
info = f"Analysis of {os.path.basename(lf)}: {imgStatus=}, size {allImagesSize[name]}, {len(errors)} errors"
|
||||
msg = "\n".join([info] + errors)
|
||||
HTML.CreateHtmlTestRowQueue(name, 'OK' if imgStatus else 'KO', [msg])
|
||||
status = status and imgStatus
|
||||
|
||||
|
||||
@@ -111,10 +111,11 @@ class Module_UE:
|
||||
return self._collectTrace(ctx)
|
||||
return None
|
||||
|
||||
def attach(self, attach_tries = 4, attach_timeout = 60):
|
||||
def attach(self, attach_tries = 3, attach_timeout = 0):
|
||||
ip = None
|
||||
while attach_tries > 0:
|
||||
self._command(self.cmd_dict["attach"])
|
||||
attach_timeout += 20
|
||||
timeout = attach_timeout
|
||||
logging.debug("Waiting for IP address to be assigned")
|
||||
ip = self.getIP(silent=False, reportNonZero=True)
|
||||
|
||||
@@ -53,7 +53,7 @@ security = {
|
||||
# preferred ciphering algorithms
|
||||
# the first one of the list that an UE supports in chosen
|
||||
# valid values: nea0, nea1, nea2, nea3
|
||||
ciphering_algorithms = ( "nea0" );
|
||||
ciphering_algorithms = ( "nea2", "nea0" );
|
||||
|
||||
# preferred integrity algorithms
|
||||
# the first one of the list that an UE supports in chosen
|
||||
@@ -63,7 +63,7 @@ security = {
|
||||
# setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter
|
||||
# what 'ciphering_algorithms' configures; same thing for 'drb_integrity'
|
||||
drb_ciphering = "yes";
|
||||
drb_integrity = "no";
|
||||
drb_integrity = "yes";
|
||||
};
|
||||
|
||||
log_config :
|
||||
|
||||
@@ -146,7 +146,11 @@ gNBs =
|
||||
);
|
||||
|
||||
first_active_bwp = 1;
|
||||
bwp_list = ({ scs = 1; bwpStart = 0; bwpSize = 106;});
|
||||
bwp_list = (
|
||||
{ scs = 1; bwpStart = 0; bwpSize = 106;},
|
||||
{ scs = 1; bwpStart = 0; bwpSize = 36;},
|
||||
{ scs = 1; bwpStart = 36; bwpSize = 70;}
|
||||
);
|
||||
|
||||
# ------- SCTP definitions
|
||||
SCTP :
|
||||
|
||||
@@ -195,6 +195,7 @@ RUs = (
|
||||
max_pdschReferenceSignalPower = -27;
|
||||
max_rxgain = 50;
|
||||
eNB_instances = [0];
|
||||
sl_ahead = 3;
|
||||
sdr_addrs = "addr=192.168.10.2,second_addr=192.168.20.2";
|
||||
}
|
||||
);
|
||||
|
||||
@@ -209,7 +209,7 @@ security = {
|
||||
# preferred ciphering algorithms
|
||||
# the first one of the list that an UE supports in chosen
|
||||
# valid values: nea0, nea1, nea2, nea3
|
||||
ciphering_algorithms = ( "nea0" );
|
||||
ciphering_algorithms = ( "nea2", "nea0" );
|
||||
|
||||
# preferred integrity algorithms
|
||||
# the first one of the list that an UE supports in chosen
|
||||
@@ -219,7 +219,7 @@ security = {
|
||||
# setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter
|
||||
# what 'ciphering_algorithms' configures; same thing for 'drb_integrity'
|
||||
drb_ciphering = "yes";
|
||||
drb_integrity = "no";
|
||||
drb_integrity = "yes";
|
||||
};
|
||||
|
||||
log_config :
|
||||
|
||||
@@ -247,6 +247,7 @@
|
||||
<testCase id="060000">
|
||||
<class>UndeployCoreNetwork</class>
|
||||
<desc>Terminate EPC</desc>
|
||||
<always_exec>true</always_exec>
|
||||
<cn_id>ltebox-nepes</cn_id>
|
||||
</testCase>
|
||||
|
||||
|
||||
@@ -30,20 +30,28 @@
|
||||
310000
|
||||
800813
|
||||
330101
|
||||
330102
|
||||
330103
|
||||
310001
|
||||
400001
|
||||
350000
|
||||
370001
|
||||
370000
|
||||
370002
|
||||
370003
|
||||
370004
|
||||
370002
|
||||
360001
|
||||
100002
|
||||
360002
|
||||
350000
|
||||
410002
|
||||
370012
|
||||
400002
|
||||
410003
|
||||
370013
|
||||
400003
|
||||
410000
|
||||
350000
|
||||
400000
|
||||
410001
|
||||
350000
|
||||
400001
|
||||
310011
|
||||
310002
|
||||
330201
|
||||
@@ -88,24 +96,10 @@
|
||||
</testCase>
|
||||
<testCase id="330101">
|
||||
<class>Deploy_Object</class>
|
||||
<desc>Deploy gNB-CU-CP in a container</desc>
|
||||
<desc>Deploy gNB-CU-CP/gNB-CU-UP/gNB-DU (TDD/n76/40MHz/B200)</desc>
|
||||
<node>ofqot</node>
|
||||
<yaml_path>ci-scripts/yaml_files/sa_e1_b200_gnb</yaml_path>
|
||||
<services>gnb_cucp</services>
|
||||
</testCase>
|
||||
<testCase id="330102">
|
||||
<class>Deploy_Object</class>
|
||||
<desc>Deploy gNB-CU-UP in a container</desc>
|
||||
<node>ofqot</node>
|
||||
<yaml_path>ci-scripts/yaml_files/sa_e1_b200_gnb</yaml_path>
|
||||
<services>gnb_cuup</services>
|
||||
</testCase>
|
||||
<testCase id="330103">
|
||||
<class>Deploy_Object</class>
|
||||
<desc>Deploy gNB-DU (TDD/Band78/40MHz/B200) in a container</desc>
|
||||
<node>ofqot</node>
|
||||
<yaml_path>ci-scripts/yaml_files/sa_e1_b200_gnb</yaml_path>
|
||||
<services>gnb_du_tdd</services>
|
||||
<services>gnb_cucp gnb_cuup gnb_du_tdd</services>
|
||||
</testCase>
|
||||
|
||||
<testCase id="300000">
|
||||
@@ -132,16 +126,6 @@
|
||||
<ping_rttavg_threshold>25</ping_rttavg_threshold>
|
||||
</testCase>
|
||||
|
||||
<testCase id="370000">
|
||||
<class>Iperf</class>
|
||||
<desc>iperf (DL/80Mbps/UDP)(30 sec)</desc>
|
||||
<iperf_args>-u -b 80M -t 30 -R</iperf_args>
|
||||
<id>idefix</id>
|
||||
<svr_id>sabox-nepes</svr_id>
|
||||
<iperf_packetloss_threshold>10</iperf_packetloss_threshold>
|
||||
<iperf_bitrate_threshold>95</iperf_bitrate_threshold>
|
||||
</testCase>
|
||||
|
||||
<testCase id="400001">
|
||||
<class>Custom_Command</class>
|
||||
<desc>Check UE is on dedicated BWP ID 1</desc>
|
||||
@@ -149,19 +133,76 @@
|
||||
<command>echo ci get_current_bwp | nc -N 127.0.0.1 9091 | grep 'DL BWP ID 1 (dedicated) UL BWP ID 1 (dedicated)'</command>
|
||||
</testCase>
|
||||
|
||||
<testCase id="370001">
|
||||
<testCase id="410001">
|
||||
<class>Custom_Command</class>
|
||||
<desc>Switch to dedicated BWP ID 1</desc>
|
||||
<node>ofqot</node>
|
||||
<command>echo ci trigger_bwp_switch 1 | nc -N 127.0.0.1 9091 | grep 'triggered BWP switch to BWP ID 1 for UE'</command>
|
||||
</testCase>
|
||||
|
||||
<testCase id="400000">
|
||||
<class>Custom_Command</class>
|
||||
<desc>Check UE is on initial BWP ID 0</desc>
|
||||
<node>ofqot</node>
|
||||
<command>echo ci get_current_bwp | nc -N 127.0.0.1 9091 | grep 'DL BWP ID 0 (initial) UL BWP ID 0 (initial)'</command>
|
||||
</testCase>
|
||||
|
||||
<testCase id="410002">
|
||||
<class>Custom_Command</class>
|
||||
<desc>Switch to dedicated BWP ID 2</desc>
|
||||
<node>ofqot</node>
|
||||
<command>echo ci trigger_bwp_switch 2 | nc -N 127.0.0.1 9091 | grep 'triggered BWP switch to BWP ID 2 for UE'</command>
|
||||
</testCase>
|
||||
|
||||
<testCase id="370012">
|
||||
<class>Iperf</class>
|
||||
<desc>iperf (UL/8Mbps/UDP)(30 sec)</desc>
|
||||
<iperf_args>-u -b 8M -t 30</iperf_args>
|
||||
<desc>iperf (DL/TCP)(10 sec)(single-ue profile)</desc>
|
||||
<iperf_args>-t 10 -R</iperf_args>
|
||||
<id>idefix</id>
|
||||
<svr_id>sabox-nepes</svr_id>
|
||||
<iperf_packetloss_threshold>1</iperf_packetloss_threshold>
|
||||
<iperf_bitrate_threshold>95</iperf_bitrate_threshold>
|
||||
<iperf_tcp_rate_target>35</iperf_tcp_rate_target>
|
||||
</testCase>
|
||||
|
||||
<testCase id="400002">
|
||||
<class>Custom_Command</class>
|
||||
<desc>Check UE is on dedicated BWP ID 2</desc>
|
||||
<node>ofqot</node>
|
||||
<command>echo ci get_current_bwp | nc -N 127.0.0.1 9091 | grep 'DL BWP ID 2 (dedicated) UL BWP ID 2 (dedicated)'</command>
|
||||
</testCase>
|
||||
|
||||
<testCase id="410003">
|
||||
<class>Custom_Command</class>
|
||||
<desc>Switch to dedicated BWP ID 3</desc>
|
||||
<node>ofqot</node>
|
||||
<command>echo ci trigger_bwp_switch 3 | nc -N 127.0.0.1 9091 | grep 'triggered BWP switch to BWP ID 3 for UE'</command>
|
||||
</testCase>
|
||||
|
||||
<testCase id="370013">
|
||||
<class>Iperf</class>
|
||||
<desc>iperf (DL/TCP)(10 sec)(single-ue profile)</desc>
|
||||
<iperf_args>-t 10 -R</iperf_args>
|
||||
<id>idefix</id>
|
||||
<svr_id>sabox-nepes</svr_id>
|
||||
<iperf_tcp_rate_target>85</iperf_tcp_rate_target>
|
||||
</testCase>
|
||||
|
||||
<testCase id="400003">
|
||||
<class>Custom_Command</class>
|
||||
<desc>Check UE is on dedicated BWP ID 3</desc>
|
||||
<node>ofqot</node>
|
||||
<command>echo ci get_current_bwp | nc -N 127.0.0.1 9091 | grep 'DL BWP ID 3 (dedicated) UL BWP ID 3 (dedicated)'</command>
|
||||
</testCase>
|
||||
|
||||
<testCase id="410000">
|
||||
<class>Custom_Command</class>
|
||||
<desc>Switch to initial BWP ID 0</desc>
|
||||
<node>ofqot</node>
|
||||
<command>echo ci trigger_bwp_switch 0 | nc -N 127.0.0.1 9091 | grep 'triggered BWP switch to BWP ID 0 for UE'</command>
|
||||
</testCase>
|
||||
|
||||
<testCase id="370002">
|
||||
<class>Iperf</class>
|
||||
<desc>iperf (BIDIR TCP)(10 sec)(single-ue profile)</desc>
|
||||
<desc>iperf (BIDIR TCP)(20 sec)(single-ue profile)</desc>
|
||||
<iperf_args>-t 20 --bidir</iperf_args>
|
||||
<id>idefix</id>
|
||||
<svr_id>sabox-nepes</svr_id>
|
||||
@@ -169,17 +210,17 @@
|
||||
|
||||
<testCase id="370003">
|
||||
<class>Iperf</class>
|
||||
<desc>iperf (DL/TCP)(30 sec)(single-ue profile)</desc>
|
||||
<iperf_args>-t 30 -R</iperf_args>
|
||||
<desc>iperf (DL/TCP)(20 sec)(single-ue profile)</desc>
|
||||
<iperf_args>-t 20 -R</iperf_args>
|
||||
<id>idefix</id>
|
||||
<svr_id>sabox-nepes</svr_id>
|
||||
<iperf_tcp_rate_target>30</iperf_tcp_rate_target>
|
||||
<iperf_tcp_rate_target>140</iperf_tcp_rate_target>
|
||||
</testCase>
|
||||
|
||||
<testCase id="370004">
|
||||
<class>Iperf</class>
|
||||
<desc>iperf (UL/TCP)(30 sec)(single-ue profile)</desc>
|
||||
<iperf_args>-t 30</iperf_args>
|
||||
<desc>iperf (UL/TCP)(20 sec)(single-ue profile)</desc>
|
||||
<iperf_args>-t 20</iperf_args>
|
||||
<id>idefix</id>
|
||||
<svr_id>sabox-nepes</svr_id>
|
||||
<iperf_tcp_rate_target>15</iperf_tcp_rate_target>
|
||||
|
||||
@@ -123,7 +123,7 @@ services:
|
||||
--rfsim --rfsimulator.prop_delay 20 --rfsimulator.options chanmod
|
||||
--rfsimulator.serveraddr 192.168.71.140
|
||||
--time-sync-I 0.1 --ntn-initial-time-drift -46
|
||||
--autonomous-ta --initial-fo 57340 --cont-fo-comp 2
|
||||
--initial-fo 57340 --cont-fo-comp 2
|
||||
--log_config.global_log_options level,nocolor,time
|
||||
--num-ul-actors 1
|
||||
depends_on:
|
||||
|
||||
@@ -33,7 +33,7 @@ services:
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
oai-gnb-aerial:
|
||||
cpuset: "13-14"
|
||||
cpuset: "13-16"
|
||||
image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb-aerial}:${TAG:-develop}
|
||||
depends_on:
|
||||
nv-cubb:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
diff --git a/wls_lib/Makefile b/wls_lib/Makefile
|
||||
index 2f8e4b2..e657488 100644
|
||||
index 2f8e4b2..7b99a26 100644
|
||||
--- a/wls_lib/Makefile
|
||||
+++ b/wls_lib/Makefile
|
||||
@@ -1,20 +1,6 @@
|
||||
@@ -23,7 +23,7 @@ index 2f8e4b2..e657488 100644
|
||||
+################################################################
|
||||
+# <COPYRIGHT_TAG>
|
||||
+################################################################
|
||||
|
||||
|
||||
MYCUSTOMTAB=' '
|
||||
MYCUSTOMSPACE='============================================================================================'
|
||||
@@ -24,11 +10,17 @@ MYCUSTOMSPACE1='------------------------------------------------------------'
|
||||
@@ -48,9 +48,12 @@ index 2f8e4b2..e657488 100644
|
||||
else ifeq ($(WIRELESS_SDK_TOOLCHAIN),icx)
|
||||
CC := icx
|
||||
CPP := icx
|
||||
@@ -44,9 +36,9 @@ ifeq ($(WIRELESS_SDK_TARGET_ISA),sse)
|
||||
@@ -42,11 +34,11 @@ endif
|
||||
ifeq ($(WIRELESS_SDK_TARGET_ISA),sse)
|
||||
TARGET_PROCESSOR := -xSSE4.2
|
||||
else ifeq ($(WIRELESS_SDK_TARGET_ISA),avx2)
|
||||
TARGET_PROCESSOR := -xCORE-AVX2
|
||||
- TARGET_PROCESSOR := -xCORE-AVX2
|
||||
+ TARGET_PROCESSOR := -march=core-avx2
|
||||
else ifeq ($(WIRELESS_SDK_TARGET_ISA),avx512)
|
||||
- TARGET_PROCESSOR := -xCORE-AVX512
|
||||
+ TARGET_PROCESSOR := -march=skylake-avx512
|
||||
@@ -63,7 +66,7 @@ index 2f8e4b2..e657488 100644
|
||||
@@ -66,15 +58,38 @@ PROJECT_DIR := ./
|
||||
BUILDDIR := make
|
||||
PROJECT_BINARY := $(PROJECT_NAME).so
|
||||
|
||||
|
||||
+PKGCONF ?= pkg-config
|
||||
+LIBDPDK_VERSION=20.11.3
|
||||
+
|
||||
@@ -79,7 +82,7 @@ index 2f8e4b2..e657488 100644
|
||||
+$(error "Please define RTE_SDK environment variable OR install DPDK version $(LIBDPDK_VERSION)")
|
||||
+endif
|
||||
endif
|
||||
|
||||
|
||||
-RTE_INC := $(shell PKG_CONFIG_PATH=/usr/lib64/pkgconfig:$(RTE_SDK)/build/meson-uninstalled pkgconf --cflags-only-I libdpdk)
|
||||
+# At least one of the options is defined
|
||||
+
|
||||
@@ -88,10 +91,10 @@ index 2f8e4b2..e657488 100644
|
||||
+else ifeq ($(DPDK_INSTALLED),1)
|
||||
+ RTE_INC := $(shell PKG_CONFIG_PATH=/usr/lib64/pkgconfig $(PKGCONF) --cflags-only-I libdpdk)
|
||||
+endif
|
||||
|
||||
|
||||
CC_SRC = wls_lib_dpdk.c \
|
||||
syslib.c
|
||||
|
||||
|
||||
+CC_HDR = syslib.h \
|
||||
+ ttypes.h \
|
||||
+ wls.h \
|
||||
@@ -104,74 +107,74 @@ index 2f8e4b2..e657488 100644
|
||||
@@ -84,18 +99,19 @@ CC_FLAGS += -std=gnu11 -Wall -Wno-deprecated-declarations \
|
||||
-Wimplicit-function-declaration \
|
||||
-g -O3 -mcmodel=large $(TARGET_PROCESSOR)
|
||||
|
||||
|
||||
-INC := -I$(RTE_INC)
|
||||
+INC := -I$(RTE_INC) -I../intel_fapi/
|
||||
DEF :=
|
||||
|
||||
|
||||
AS_FLAGS :=
|
||||
AR_FLAGS := rc
|
||||
|
||||
|
||||
PROJECT_OBJ_DIR := $(BUILDDIR)/obj
|
||||
+PROJECT_DEP_DIR := $(PROJECT_OBJ_DIR)/$(PROJECT_NAME).dep.d
|
||||
|
||||
|
||||
CC_OBJS := $(patsubst %.c,%.o,$(CC_SRC))
|
||||
AS_OBJS := $(patsubst %.s,%.o,$(AS_SRC))
|
||||
OBJS := $(CC_OBJS) $(AS_OBJS) $(LIBS)
|
||||
-DIRLIST := $(addprefix $(PROJECT_OBJ_DIR)/,$(sort $(dir $(OBJS))))
|
||||
+DIRLIST := $(addprefix $(PROJECT_OBJ_DIR)/,$(sort $(dir $(OBJS)))) $(PROJECT_DEP_DIR)
|
||||
|
||||
|
||||
CC_OBJTARGETS := $(addprefix $(PROJECT_OBJ_DIR)/,$(CC_OBJS))
|
||||
|
||||
|
||||
@@ -104,9 +120,7 @@ CC_FLAGS_FULL := $(CC_FLAGS) $(INC) $(DEF)
|
||||
|
||||
|
||||
AS_FLAGS := $(AS_FLAGS) $(INC)
|
||||
|
||||
|
||||
-PROJECT_DEP_FILE := $(PROJECT_OBJ_DIR)/$(PROJECT_NAME).dep
|
||||
-
|
||||
-ifeq ($(wildcard $(PROJECT_DEP_FILE)),$(PROJECT_DEP_FILE))
|
||||
+ifeq ($(wildcard $(PROJECT_DEP_DIR)),$(PROJECT_DEP_DIR))
|
||||
GENERATE_DEPS :=
|
||||
else
|
||||
|
||||
|
||||
@@ -119,11 +133,11 @@ all : welcome_line $(PROJECT_BINARY)
|
||||
|
||||
|
||||
.PHONY : clear_dep
|
||||
clear_dep:
|
||||
- @$(RM) $(PROJECT_DEP_FILE)
|
||||
- @echo [DEP] $(subst $(PROJECT_OBJ_DIR)/,,$(PROJECT_DEP_FILE))
|
||||
+ @echo [DEP] rm $(PROJECT_DEP_DIR)/$(@F).dep
|
||||
+ @$(RM) $(PROJECT_DEP_DIR)/$(@F).dep
|
||||
|
||||
|
||||
-$(CC_DEPS) :
|
||||
- @$(CC) -MM $(subst __up__,../,$(subst __dep__,,$@)) -MT $(PROJECT_OBJ_DIR)/$(patsubst %.c,%.o,$(subst __up__,../,$(subst __dep__,,$@))) $(CC_FLAGS_FULL) >> $(PROJECT_DEP_FILE)
|
||||
+$(CC_DEPS) : $(PROJECT_DEP_DIR)
|
||||
+ @$(CC) $(CC_FLAGS_FULL) -MM $(subst __up__,../,$(subst __dep__,,$@)) -MT $(PROJECT_OBJ_DIR)/$(patsubst %.c,%.o,$(subst __up__,../,$(subst __dep__,,$@))) >> $(PROJECT_DEP_DIR)/$(@F).dep
|
||||
|
||||
|
||||
.PHONY : generate_deps
|
||||
generate_deps : clear_dep $(CC_DEPS)
|
||||
@@ -136,17 +150,17 @@ echo_start_build :
|
||||
$(DIRLIST) :
|
||||
-@$(MD) $@
|
||||
|
||||
|
||||
-$(CC_OBJTARGETS) :
|
||||
+$(CC_OBJTARGETS) : $(GENERATE_DEPS)
|
||||
@echo [CC] $(subst $(PROJECT_OBJ_DIR)/,,$@)
|
||||
@$(CC) -c $(CC_FLAGS_FULL) -o"$@" $(patsubst %.o,%.c,$(subst $(PROJECT_OBJ_DIR)/,,$@))
|
||||
|
||||
|
||||
-$(AS_OBJTARGETS) :
|
||||
+$(AS_OBJTARGETS) : $(CC_OBJTARGETS) $(CPP_OBJTARGETS)
|
||||
@echo [AS] $(subst $(PROJECT_OBJ_DIR)/,,$@)
|
||||
@$(AS) $(AS_FLAGS) -o"$@" $(patsubst %.o,%.s,$(subst $(PROJECT_OBJ_DIR)/,,$@))
|
||||
|
||||
|
||||
-ifeq ($(wildcard $(PROJECT_DEP_FILE)),$(PROJECT_DEP_FILE))
|
||||
+ifeq ($(wildcard $(PROJECT_DEP_DIR)),$(PROJECT_DEP_DIR))
|
||||
|
||||
|
||||
-include $(PROJECT_DEP_FILE)
|
||||
+include $(PROJECT_DEP_DIR)/*
|
||||
|
||||
|
||||
endif
|
||||
|
||||
|
||||
@@ -156,7 +170,7 @@ clean:
|
||||
@$(RM) $(CC_OBJTARGETS) $(AS_OBJTARGETS)
|
||||
ifneq ($(wildcard $(PROJECT_DIR)/$(PROJECT_MAKE)),)
|
||||
@@ -179,17 +182,17 @@ index 2f8e4b2..e657488 100644
|
||||
- @$(RM) $(PROJECT_BINARY) $(PROJECT_BINARY_LIB) $(PROJECT_DEP_FILE)
|
||||
+ @$(RM) -rf $(PROJECT_BINARY) $(PROJECT_BINARY_LIB) $(PROJECT_DEP_DIR)
|
||||
endif
|
||||
|
||||
|
||||
xclean: clean
|
||||
@@ -172,7 +186,24 @@ welcome_line :
|
||||
debug : all
|
||||
release : all
|
||||
|
||||
|
||||
-$(PROJECT_BINARY) : $(DIRLIST) echo_start_build $(GENERATE_DEPS) $(PRE_BUILD) $(CC_OBJTARGETS) $(AS_OBJTARGETS)
|
||||
+$(PROJECT_BINARY) : $(DIRLIST) echo_start_build $(GENERATE_DEPS) $(CC_OBJTARGETS) $(AS_OBJTARGETS)
|
||||
@echo [AR] $(subst $(BUILDDIR)/,,$@)
|
||||
@$(CC) $(CC_OBJTARGETS) $(AS_OBJTARGETS) -shared -fPIC -o $@
|
||||
|
||||
|
||||
+##############################################################
|
||||
+# Install configuration
|
||||
+##############################################################
|
||||
|
||||
@@ -23,3 +23,4 @@ endif()
|
||||
add_subdirectory(barrier)
|
||||
add_subdirectory(actor)
|
||||
add_subdirectory(shm_iq_channel)
|
||||
add_subdirectory(wraparound_buffer)
|
||||
|
||||
@@ -21,7 +21,7 @@ The following options can be specified to trigger the information added in the h
|
||||
- `line_num`: adds the (source code) line number
|
||||
- `time`: add the time since the system started in format `ss.ssssss` (seconds and microseconds sourced from `CLOCK_MONOTONIC`)
|
||||
- `wall_clock`: add the system-wide clock time that measures real (i.e., wall-clock) time in format `ss.ssssss` (seconds and microseconds since 1970-01-01 00:00:00 Coordinated Universal Time (UTC))
|
||||
- `utc_time`: add the UTC (Coordinated Universal Time) time in format `YYYY-MM-DD hh:mm:ss.ssssss UTC`. Note that this time is independent of the current time zone (it shows GMT). Also, printing this time has additional overhead compared to other time methods (due to time conversion and formatting).
|
||||
- `utc_time`: add the UTC (Coordinated Universal Time) time in format `[hh:mm:ss.ssssss]`. Note that this time is independent of the current time zone (it shows GMT). Also, printing this time has additional overhead compared to other time methods (due to time conversion and formatting).
|
||||
|
||||
Note: `time`, `utc_time` and `wall_clock` are mutually exclusive and cannot be used together.
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include "openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.h"
|
||||
#include "openair2/LAYER2/nr_rlc/nr_rlc_entity_am.h"
|
||||
#include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h"
|
||||
#include "openair2/LAYER2/NR_MAC_gNB/mac_config.h"
|
||||
#include "openair2/RRC/NR/rrc_gNB_mobility.h"
|
||||
#include "openair3/NGAP/ngap_gNB_ue_context.h"
|
||||
|
||||
@@ -276,6 +277,8 @@ static int get_current_bwp(char *buf, int debug, telnet_printfunc_t prnt)
|
||||
if (rnti < 0)
|
||||
ERROR_MSG_RET("could not identify UE (no UE, no such RNTI, or multiple UEs)\n");
|
||||
NR_UE_info_t *UE = find_nr_UE(&RC.nrmac[0]->UE_info, rnti);
|
||||
if (!UE)
|
||||
ERROR_MSG_RET("could not find UE with RNTI %04x\n", rnti);
|
||||
int dl_bwp = UE->current_DL_BWP.bwp_id;
|
||||
const char *dl_bwp_text = dl_bwp > 0 ? "dedicated" : "initial";
|
||||
int ul_bwp = UE->current_UL_BWP.bwp_id;
|
||||
@@ -348,7 +351,7 @@ static int trigger_ngap_pdu_session_release(char *buf, int debug, telnet_printfu
|
||||
if (sid < 1 || sid > 255) {
|
||||
ERROR_MSG_RET("Invalid pdusession_id(int): %s (must be between 1 and 255)\n", tokens[i]);
|
||||
}
|
||||
msg->pdusession_release_params[nb_sessions++].pdusession_id = sid;
|
||||
msg->pdusession_ids[nb_sessions++] = sid;
|
||||
}
|
||||
|
||||
msg->nb_pdusessions_torelease = nb_sessions;
|
||||
@@ -356,7 +359,7 @@ static int trigger_ngap_pdu_session_release(char *buf, int debug, telnet_printfu
|
||||
if (prnt) {
|
||||
prnt("Triggering NGAP PDU Session Release for gNB_ue_ngap_id=%d: releasing pdusession_id=%d", gNB_ue_ngap_id);
|
||||
for (int i = 0; i < nb_sessions; ++i) {
|
||||
prnt(" %d,", msg->pdusession_release_params[i].pdusession_id);
|
||||
prnt(" %d,", msg->pdusession_ids[i]);
|
||||
}
|
||||
prnt("\n");
|
||||
}
|
||||
@@ -365,6 +368,24 @@ static int trigger_ngap_pdu_session_release(char *buf, int debug, telnet_printfu
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int trigger_bwp_switch(char *buf, int debug, telnet_printfunc_t prnt)
|
||||
{
|
||||
char *sbwpId = strtok(buf, " ");
|
||||
int bwpId = atoi(sbwpId);
|
||||
char *srnti = strtok(NULL, " ");
|
||||
prnt("bwpId %d rnti %s\n", bwpId, srnti);
|
||||
int rnti = fetch_rnti(srnti, prnt);
|
||||
if (rnti < 0)
|
||||
ERROR_MSG_RET("could not identify UE (no UE, no such RNTI, or multiple UEs)\n");
|
||||
if (!nr_trigger_bwp_switch(rnti, bwpId)) {
|
||||
prnt("failed trigger BWP switch for UE %04x BWP ID %d\n", rnti, bwpId);
|
||||
return -1;
|
||||
} else {
|
||||
prnt("triggered BWP switch to BWP ID %d for UE %04x\n", bwpId, rnti);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static telnetshell_cmddef_t cicmds[] = {
|
||||
{"get_single_rnti", "", get_single_rnti},
|
||||
{"force_reestab", "[rnti(hex,opt)]", trigger_reestab},
|
||||
@@ -374,6 +395,7 @@ static telnetshell_cmddef_t cicmds[] = {
|
||||
{"trigger_f1_ho", "[rrc_ue_id(int,opt)]", rrc_gNB_trigger_f1_ho},
|
||||
{"fetch_du_by_ue_id", "[rrc_ue_id(int,opt)]", fetch_du_by_ue_id},
|
||||
{"get_current_bwp", "[rnti(hex,opt)]", get_current_bwp},
|
||||
{"trigger_bwp_switch", "newBWPId [rnti(hex,opt)]", trigger_bwp_switch},
|
||||
{"trigger_n2_ho", "[neighbour_pci(uint32_t),ueId(uint32_t)]", rrc_gNB_trigger_n2_ho},
|
||||
{"pdu_session_release", "[gNB_ue_ngap_id(int,opt)]", trigger_ngap_pdu_session_release},
|
||||
{"", "", NULL},
|
||||
|
||||
6
common/utils/wraparound_buffer/CMakeLists.txt
Normal file
6
common/utils/wraparound_buffer/CMakeLists.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
add_library(wraparound_buffer wraparound_buffer.cpp)
|
||||
target_include_directories(wraparound_buffer PUBLIC ./)
|
||||
target_link_libraries(wraparound_buffer PUBLIC LOG)
|
||||
if (ENABLE_TESTS)
|
||||
add_subdirectory(tests)
|
||||
endif()
|
||||
5
common/utils/wraparound_buffer/tests/CMakeLists.txt
Normal file
5
common/utils/wraparound_buffer/tests/CMakeLists.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
add_executable(test_wraparound_buffer test_wraparound_buffer.cpp)
|
||||
add_dependencies(tests test_wraparound_buffer)
|
||||
target_link_libraries(test_wraparound_buffer PRIVATE wraparound_buffer pthread LOG minimal_lib GTest::gtest)
|
||||
add_test(NAME test_wraparound_buffer
|
||||
COMMAND ./test_wraparound_buffer)
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* 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 <gtest/gtest.h>
|
||||
#include "wraparound_buffer.h"
|
||||
#include "log.h"
|
||||
#include <unistd.h>
|
||||
|
||||
// Thread safety can be ensured through core affinity - if two actors
|
||||
// are running on the same core they are thread safe
|
||||
TEST(wraparound_buffer, basic_logic)
|
||||
{
|
||||
size_t buf_size = getpagesize() * 2;
|
||||
void *buffer = malloc_wraparound_buffer(buf_size);
|
||||
ASSERT_NE(buffer, nullptr);
|
||||
uint8_t *buffptr = static_cast<uint8_t *>(buffer);
|
||||
memset(buffer, 0, buf_size);
|
||||
buffptr[0] = 1;
|
||||
EXPECT_EQ(buffptr[buf_size], 1);
|
||||
free_wraparound_buffer(buffer);
|
||||
}
|
||||
|
||||
TEST(wraparound_buffer, full_range)
|
||||
{
|
||||
size_t buf_size = getpagesize() * 2;
|
||||
void *buffer = malloc_wraparound_buffer(buf_size);
|
||||
ASSERT_NE(buffer, nullptr);
|
||||
uint8_t *buffptr = static_cast<uint8_t *>(buffer);
|
||||
memset(buffer, 0, buf_size);
|
||||
for (auto i = 0U; i < buf_size; i++) {
|
||||
buffptr[i] = (uint8_t)i;
|
||||
EXPECT_EQ(buffptr[i + buf_size], (uint8_t)i);
|
||||
}
|
||||
free_wraparound_buffer(buffer);
|
||||
}
|
||||
|
||||
TEST(wraparound_buffer, size)
|
||||
{
|
||||
size_t buf_size = getpagesize() * 2 + 1;
|
||||
void *buffer = malloc_wraparound_buffer(buf_size);
|
||||
ASSERT_EQ(buffer, nullptr);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
logInit();
|
||||
g_log->log_component[UTIL].level = OAILOG_DEBUG;
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
86
common/utils/wraparound_buffer/wraparound_buffer.cpp
Normal file
86
common/utils/wraparound_buffer/wraparound_buffer.cpp
Normal file
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* 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 "wraparound_buffer.h"
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/syscall.h>
|
||||
#include "log.h"
|
||||
#include "assertions.h"
|
||||
|
||||
struct {
|
||||
std::map<void*, size_t> map;
|
||||
std::mutex mtx;
|
||||
} internal_state;
|
||||
|
||||
|
||||
extern "C" void* malloc_wraparound_buffer(size_t size)
|
||||
{
|
||||
size_t pagesize = getpagesize();
|
||||
if (size % pagesize != 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int fd = memfd_create("wraparound", MFD_CLOEXEC);
|
||||
if (fd == -1) return NULL;
|
||||
if (ftruncate(fd, size) != 0) {
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void* region = mmap(NULL, size * 2, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
if (region == MAP_FAILED) {
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void* buf = mmap(region, size, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, fd, 0);
|
||||
if (buf == MAP_FAILED) {
|
||||
munmap(region, size * 2);
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint8_t *second_half = (uint8_t *)region + size;
|
||||
void* mirror = mmap(second_half, size, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, fd, 0);
|
||||
if (mirror == MAP_FAILED) {
|
||||
munmap(region, size * 2);
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
std::lock_guard<std::mutex> lock(internal_state.mtx);
|
||||
internal_state.map[buf] = size;
|
||||
return buf;
|
||||
}
|
||||
|
||||
extern "C" void free_wraparound_buffer(void* buf) {
|
||||
if (buf == nullptr) return;
|
||||
std::lock_guard<std::mutex> lock(internal_state.mtx);
|
||||
size_t size = internal_state.map[buf];
|
||||
if (munmap(buf, size * 2) != 0) {
|
||||
LOG_W(UTIL, "munmap failed\n");
|
||||
}
|
||||
}
|
||||
36
common/utils/wraparound_buffer/wraparound_buffer.h
Normal file
36
common/utils/wraparound_buffer/wraparound_buffer.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
#ifndef __WRAPAROUND_BUFFER_H__
|
||||
#define __WRAPAROUND_BUFFER_H__
|
||||
#include <memory.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void *malloc_wraparound_buffer(size_t size);
|
||||
void free_wraparound_buffer(void *buf);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -82,7 +82,7 @@ of the FAPI 10.04 version of the SRS PDU, and RX_Beamforming PDU.
|
||||
| Applicative Threads | Allocated CPUs |
|
||||
|------------------------|----------------|
|
||||
| PTP & PHC2SYS Services | 41 |
|
||||
| OAI `nr-softmodem` | 13-14 |
|
||||
| OAI `nr-softmodem` | 13-16 |
|
||||
|
||||
## PTP configuration
|
||||
|
||||
|
||||
@@ -352,7 +352,9 @@ These modes of operation are supported:
|
||||
- Formats 0,1,2,3, A1-A3, B1-B3
|
||||
* NTN
|
||||
- TA adjustemt based on ntn-Config-r17 information
|
||||
- Autonomous TA adjustemt between SIB19 receptions based on DL time tracking
|
||||
- Different TA adjustemt algorithms between SIB19 receptions:
|
||||
- Autonomous TA adjustemt based on DL time tracking
|
||||
- Standard compliant epoch time based TA adjustment including orbital propagation
|
||||
- UL Doppler pre-compensation based on continuous DL FO estimation
|
||||
* Highly efficient 3GPP compliant LDPC encoder and decoder (BG1 and BG2 are supported)
|
||||
* Highly efficient 3GPP compliant polar encoder and decoder
|
||||
|
||||
@@ -420,3 +420,29 @@ Note that you should increase the aggregation level candidates as described in
|
||||
[the corresponding section above](#pdcch-aggregation-level). This is because the
|
||||
scheduler has to schedule multiple DCIs in a single DL slots for multiple UL
|
||||
slots. As a suggestion, you could try `uess_agg_levels = [4, 2, 2, 0, 0]`.
|
||||
|
||||
## Multiple Dedicated BWPs
|
||||
|
||||
A maximum of 4 dedicated BWPs can be configured for a UE per standard, but only
|
||||
1 BWP can be active in UL and DL direction at a given time. In the code we
|
||||
only configure a single BWP for the UE at a given time and we would switch by
|
||||
reconfiguring this BWP. All this procedure is transparent for users and LOGs
|
||||
mark BWP switching according to the configuration file enumeration. It is
|
||||
possible to configure multiple dedicated BWPs and 1st active BWP via
|
||||
configuration file.
|
||||
|
||||
### Setup of the Configuration files ##
|
||||
|
||||
In the configuration file you have the option to select the 1st active BWP, the
|
||||
BWP location and SCS of each BWP in the following way (example with 2
|
||||
additional BWPs):
|
||||
|
||||
```
|
||||
first_active_bwp = 1;
|
||||
bwp_list = ({ scs = 1; bwpStart = 0; bwpSize = 106;},
|
||||
{ scs = 1; bwpStart = 0; bwpSize = 24;});
|
||||
```
|
||||
|
||||
This example configures 3 additional BWPs, with IDs from 1 to 3. A similar
|
||||
example can be found in configuration file
|
||||
`ci-scripts/conf_files/gnb-du.sa.band78.106prb.usrpb200.conf` tested in CI.
|
||||
|
||||
@@ -1243,8 +1243,8 @@ In OAI gNB, we support:
|
||||
```
|
||||
|
||||
The reference specifications:
|
||||
* `O-RAN.WG4.MP.0-v05.00`
|
||||
* `O-RAN.WG4.MP-YANGs-v04.00`
|
||||
* `O-RAN.WG4.MP.0-R004-v16.01`
|
||||
* `O-RAN.WG4.MP-YANGs-R004-v16.01`
|
||||
|
||||
## M-plane prerequisites
|
||||
Before proceeding, please make sure you have a support for 7.2 interface, as described in [Prerequisites](#prerequisites).
|
||||
@@ -1366,7 +1366,7 @@ sudo ldconfig
|
||||
If you would like to install these libraries in the custom path, please replace `/usr/local` default path to e.g. `/opt/mplane-v2`.
|
||||
|
||||
## Benetel O-RU
|
||||
Note: Only v1.2.2 RAN550 and RAN650 have been successfully tested.
|
||||
Note: RAN550/650 v1.2.2 and v1.4.1 have been successfully tested.
|
||||
|
||||
### One time steps
|
||||
Connect to the RU as user `root`, enable the mplane service, and reboot:
|
||||
@@ -1400,6 +1400,8 @@ The reference DU configuration file for two Benetel RAN650:
|
||||
[gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650-mplane.conf](../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650-mplane.conf)
|
||||
|
||||
In order to run gNB/DU with M-plane, we need to modify Tx gain `att_tx` in RU section, as well as the `fhi_72` section in the configuration file.
|
||||
|
||||
**Important note: Benetel v1.4.1 requires only one VF if the same VLAN tag is used for both C-/U-planes. Otherwise, C-plane will not be properly configured. Benetel v1.2.2 will receive the C-plane packets no matter the DU MAC address value.**
|
||||
Example for one RU:
|
||||
```bash
|
||||
fhi_72 = {
|
||||
@@ -1573,14 +1575,14 @@ sequenceDiagram
|
||||
|
||||
|
||||
<details>
|
||||
<summary>4x4 MIMO and 100MHz BW with Benetel 550 RU example run</summary>
|
||||
<summary>4x4 MIMO and 100MHz BW with Benetel 550 RU v1.2.2 example run</summary>
|
||||
|
||||
```
|
||||
[HW] [MPLANE] RPC request to RU "192.168.80.9" = <connect> with username "oranbenetel" and port ID "830".
|
||||
[HW] [MPLANE] Successfuly connected to RU "192.168.80.9" with username "oranbenetel" and port ID "830".
|
||||
[HW] [MPLANE] RPC request to RU "192.168.80.9" = <get> operational datastore.
|
||||
[HW] [MPLANE] Successfully retrieved operational datastore from RU "192.168.80.9".
|
||||
[HW] [MPLANE] RU is already PTP synchronized.
|
||||
[HW] [MPLANE] RU is in "LOCKED" sync state.
|
||||
[HW] [MPLANE] RPC request to RU "192.168.80.9" = <subscribe> with stream "NETCONF" and filter "(null)".
|
||||
[HW] [MPLANE] RPC reply = OK.
|
||||
[HW] [MPLANE] Successfully subscribed to all notifications from RU "192.168.80.9".
|
||||
@@ -2223,6 +2225,861 @@ sequenceDiagram
|
||||
```
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>4x4 MIMO and 100MHz BW with Benetel 550 RU v1.4.1 example run</summary>
|
||||
|
||||
```
|
||||
[HW] [MPLANE] RPC request to RU "192.168.81.4" = <connect> with username "oranbenetel" and port ID "830".
|
||||
[HW] [MPLANE] Successfuly connected to RU "192.168.81.4" with username "oranbenetel" and port ID "830".
|
||||
[HW] [MPLANE] RPC request to RU "192.168.81.4" = <get> operational datastore.
|
||||
[HW] [MPLANE] Successfully retrieved operational datastore from RU "192.168.81.4".
|
||||
[HW] [MPLANE] RU is already PTP synchronized.
|
||||
[HW] [MPLANE] RPC request to RU "192.168.81.4" = <subscribe> with stream "NETCONF" and filter "(null)".
|
||||
[HW] [MPLANE] RPC reply = OK.
|
||||
[HW] [MPLANE] Successfully subscribed to all notifications from RU "192.168.81.4".
|
||||
[HW] [MPLANE] RPC request to RU "192.168.81.4" = "<supervision-watchdog-reset xmlns="urn:o-ran:supervision:1.0">
|
||||
<supervision-notification-interval>65535</supervision-notification-interval>
|
||||
<guard-timer-overhead>65535</guard-timer-overhead>
|
||||
</supervision-watchdog-reset>".
|
||||
[HW] [MPLANE] Successfully updated supervision timer to (65535+65535)[s] for RU "192.168.81.4".
|
||||
[HW] [MPLANE] Watchdog timer answer:
|
||||
<next-update-at xmlns="urn:o-ran:supervision:1.0">2025-08-29T06:49:32+02:00</next-update-at>
|
||||
|
||||
[HW] [MPLANE] Interface MTU 1500 unreliable/not correctly reported by Benetel O-RU, hardcoding to 9600.
|
||||
[HW] [MPLANE] IQ bitwidth 16 unreliable/not correctly reported by Benetel O-RU, hardcoding to 9.
|
||||
[HW] [MPLANE] Storing the following information to forward to xran:
|
||||
RU MAC address 70:b3:d5:e1:5b:81
|
||||
MTU 9600
|
||||
IQ bitwidth 9
|
||||
PRACH offset 4
|
||||
DU port bitmask 61440
|
||||
Band sector bitmask 3840
|
||||
CC ID bitmask 240
|
||||
RU port ID bitmask 15
|
||||
DU port ID 0
|
||||
Band sector ID 0
|
||||
CC ID 0
|
||||
RU port ID 0
|
||||
max Tx gain 24.0
|
||||
[HW] [MPLANE] Successfully retrieved all the U-plane info - interface name, TX/RX carrier names, and TX/RX endpoint names.
|
||||
[HW] [MPLANE] Successfully retreived all performance measurement names.
|
||||
[HW] [MPLANE] RPC request to RU "192.168.81.4" = <get-schema> for module "ietf-yang-metadata".
|
||||
[HW] [MPLANE] RPC request to RU "192.168.81.4" = <get-schema> for module "yang".
|
||||
[HW] [MPLANE] RPC request to RU "192.168.81.4" = <get-schema> for module "ietf-inet-types".
|
||||
[HW] [MPLANE] RPC request to RU "192.168.81.4" = <get-schema> for module "ietf-yang-types".
|
||||
[HW] [MPLANE] RPC request to RU "192.168.81.4" = <get-schema> for module "ietf-yang-schema-mount".
|
||||
[HW] [MPLANE] RPC request to RU "192.168.81.4" = <get-schema> for module "ietf-yang-structure-ext".
|
||||
[HW] [MPLANE] RPC request to RU "192.168.81.4" = <get-schema> for module "ietf-datastores".
|
||||
[HW] [MPLANE] RPC request to RU "192.168.81.4" = <get-schema> for module "sysrepo".
|
||||
[HW] [MPLANE] RPC request to RU "192.168.81.4" = <get-schema> for module "ietf-netconf-acm".
|
||||
[HW] [MPLANE] RPC request to RU "192.168.81.4" = <get-schema> for module "ietf-factory-default".
|
||||
[HW] [MPLANE] RPC request to RU "192.168.81.4" = <get-schema> for module "sysrepo-factory-default".
|
||||
[HW] [MPLANE] RPC request to RU "192.168.81.4" = <get-schema> for module "ietf-yang-library".
|
||||
[HW] [MPLANE] RPC request to RU "192.168.81.4" = <get-schema> for module "sysrepo-monitoring".
|
||||
[HW] [MPLANE] RPC request to RU "192.168.81.4" = <get-schema> for module "sysrepo-plugind".
|
||||
[HW] [MPLANE] RPC request to RU "192.168.81.4" = <get-schema> for module "ietf-netconf".
|
||||
[HW] [MPLANE] RPC request to RU "192.168.81.4" = <get-schema> for module "ietf-netconf-with-defaults".
|
||||
[HW] [MPLANE] RPC request to RU "192.168.81.4" = <get-schema> for module "ietf-netconf-notifications".
|
||||
[HW] [MPLANE] RPC request to RU "192.168.81.4" = <get-schema> for module "ietf-origin".
|
||||
[HW] [MPLANE] RPC request to RU "192.168.81.4" = <get-schema> for module "ietf-netconf-monitoring".
|
||||
[HW] [MPLANE] RPC request to RU "192.168.81.4" = <get-schema> for module "ietf-netconf-nmda".
|
||||
[HW] [MPLANE] RPC request to RU "192.168.81.4" = <get-schema> for module "nc-notifications".
|
||||
[HW] [MPLANE] [LIBYANG] ERROR: Data model "notifications" not found in local searchdirs. (path: (null)).
|
||||
[HW] [MPLANE] [LIBYANG] ERROR: Loading "notifications" module failed. (path: (null)).
|
||||
[HW] [MPLANE] [LIBYANG] ERROR: Parsing module "nc-notifications" failed. (path: (null)).
|
||||
[HW] [MPLANE] Unable to load module "nc-notifications" from RU "192.168.81.4".
|
||||
[HW] [MPLANE] Unable to load all yang modules from operational datastore for RU "192.168.81.4". Using yang models present in "models" subfolder.
|
||||
[HW] [MPLANE] Successfully loaded all yang modules for RU "192.168.81.4".
|
||||
[HW] [MPLANE] RPC request to RU "192.168.81.4" = <edit-config>:
|
||||
<interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">
|
||||
<interface>
|
||||
<name>INTERFACE_0</name>
|
||||
<type xmlns:ianaift="urn:ietf:params:xml:ns:yang:iana-if-type">ianaift:l2vlan</type>
|
||||
<enabled>true</enabled>
|
||||
<mac-address xmlns="urn:o-ran:interfaces:1.0">70:b3:d5:e1:5b:81</mac-address>
|
||||
<base-interface xmlns="urn:o-ran:interfaces:1.0">eth0</base-interface>
|
||||
<vlan-id xmlns="urn:o-ran:interfaces:1.0">3</vlan-id>
|
||||
</interface>
|
||||
</interfaces>
|
||||
<performance-measurement-objects xmlns="urn:o-ran:performance-management:1.0">
|
||||
<rx-window-measurement-interval>10</rx-window-measurement-interval>
|
||||
<tx-measurement-interval>10</tx-measurement-interval>
|
||||
<notification-interval>10</notification-interval>
|
||||
<rx-window-measurement-objects>
|
||||
<measurement-object>RX_ON_TIME</measurement-object>
|
||||
<active>false</active>
|
||||
<object-unit>RU</object-unit>
|
||||
<report-info>COUNT</report-info>
|
||||
</rx-window-measurement-objects>
|
||||
<rx-window-measurement-objects>
|
||||
<measurement-object>RX_EARLY</measurement-object>
|
||||
<active>false</active>
|
||||
<object-unit>RU</object-unit>
|
||||
<report-info>COUNT</report-info>
|
||||
</rx-window-measurement-objects>
|
||||
<rx-window-measurement-objects>
|
||||
<measurement-object>RX_LATE</measurement-object>
|
||||
<active>false</active>
|
||||
<object-unit>RU</object-unit>
|
||||
<report-info>COUNT</report-info>
|
||||
</rx-window-measurement-objects>
|
||||
<rx-window-measurement-objects>
|
||||
<measurement-object>RX_TOTAL</measurement-object>
|
||||
<active>false</active>
|
||||
<object-unit>RU</object-unit>
|
||||
<report-info>COUNT</report-info>
|
||||
</rx-window-measurement-objects>
|
||||
<rx-window-measurement-objects>
|
||||
<measurement-object>RX_ON_TIME_C</measurement-object>
|
||||
<active>false</active>
|
||||
<object-unit>RU</object-unit>
|
||||
<report-info>COUNT</report-info>
|
||||
</rx-window-measurement-objects>
|
||||
<rx-window-measurement-objects>
|
||||
<measurement-object>RX_EARLY_C</measurement-object>
|
||||
<active>false</active>
|
||||
<object-unit>RU</object-unit>
|
||||
<report-info>COUNT</report-info>
|
||||
</rx-window-measurement-objects>
|
||||
<rx-window-measurement-objects>
|
||||
<measurement-object>RX_LATE_C</measurement-object>
|
||||
<active>false</active>
|
||||
<object-unit>RU</object-unit>
|
||||
<report-info>COUNT</report-info>
|
||||
</rx-window-measurement-objects>
|
||||
<tx-measurement-objects>
|
||||
<measurement-object>TX_TOTAL</measurement-object>
|
||||
<active>false</active>
|
||||
<object-unit>RU</object-unit>
|
||||
<report-info>COUNT</report-info>
|
||||
</tx-measurement-objects>
|
||||
</performance-measurement-objects>
|
||||
<processing-elements xmlns="urn:o-ran:processing-element:1.0">
|
||||
<transport-session-type>ETH-INTERFACE</transport-session-type>
|
||||
<ru-elements>
|
||||
<name>PLANE_0</name>
|
||||
<transport-flow>
|
||||
<interface-name>INTERFACE_0</interface-name>
|
||||
<eth-flow>
|
||||
<ru-mac-address>70:b3:d5:e1:5b:81</ru-mac-address>
|
||||
<vlan-id>3</vlan-id>
|
||||
<o-du-mac-address>00:11:22:33:44:66</o-du-mac-address>
|
||||
</eth-flow>
|
||||
</transport-flow>
|
||||
</ru-elements>
|
||||
</processing-elements>
|
||||
<user-plane-configuration xmlns="urn:o-ran:uplane-conf:1.0">
|
||||
<low-level-tx-links>
|
||||
<name>PdschLink0</name>
|
||||
<processing-element>PLANE_0</processing-element>
|
||||
<tx-array-carrier>TxArray0</tx-array-carrier>
|
||||
<low-level-tx-endpoint>LowLevelTxEndpoint0</low-level-tx-endpoint>
|
||||
</low-level-tx-links>
|
||||
<low-level-tx-links>
|
||||
<name>PdschLink1</name>
|
||||
<processing-element>PLANE_0</processing-element>
|
||||
<tx-array-carrier>TxArray1</tx-array-carrier>
|
||||
<low-level-tx-endpoint>LowLevelTxEndpoint1</low-level-tx-endpoint>
|
||||
</low-level-tx-links>
|
||||
<low-level-tx-links>
|
||||
<name>PdschLink2</name>
|
||||
<processing-element>PLANE_0</processing-element>
|
||||
<tx-array-carrier>TxArray2</tx-array-carrier>
|
||||
<low-level-tx-endpoint>LowLevelTxEndpoint2</low-level-tx-endpoint>
|
||||
</low-level-tx-links>
|
||||
<low-level-tx-links>
|
||||
<name>PdschLink3</name>
|
||||
<processing-element>PLANE_0</processing-element>
|
||||
<tx-array-carrier>TxArray3</tx-array-carrier>
|
||||
<low-level-tx-endpoint>LowLevelTxEndpoint3</low-level-tx-endpoint>
|
||||
</low-level-tx-links>
|
||||
<low-level-rx-links>
|
||||
<name>PuschLink0</name>
|
||||
<processing-element>PLANE_0</processing-element>
|
||||
<rx-array-carrier>RxArray0</rx-array-carrier>
|
||||
<low-level-rx-endpoint>LowLevelRxEndpoint0</low-level-rx-endpoint>
|
||||
</low-level-rx-links>
|
||||
<low-level-rx-links>
|
||||
<name>PrachLink0</name>
|
||||
<processing-element>PLANE_0</processing-element>
|
||||
<rx-array-carrier>RxArray0</rx-array-carrier>
|
||||
<low-level-rx-endpoint>LowLevelRxPrachEndpoint0</low-level-rx-endpoint>
|
||||
</low-level-rx-links>
|
||||
<low-level-rx-links>
|
||||
<name>PuschLink1</name>
|
||||
<processing-element>PLANE_0</processing-element>
|
||||
<rx-array-carrier>RxArray1</rx-array-carrier>
|
||||
<low-level-rx-endpoint>LowLevelRxEndpoint1</low-level-rx-endpoint>
|
||||
</low-level-rx-links>
|
||||
<low-level-rx-links>
|
||||
<name>PrachLink1</name>
|
||||
<processing-element>PLANE_0</processing-element>
|
||||
<rx-array-carrier>RxArray1</rx-array-carrier>
|
||||
<low-level-rx-endpoint>LowLevelRxPrachEndpoint1</low-level-rx-endpoint>
|
||||
</low-level-rx-links>
|
||||
<low-level-rx-links>
|
||||
<name>PuschLink2</name>
|
||||
<processing-element>PLANE_0</processing-element>
|
||||
<rx-array-carrier>RxArray2</rx-array-carrier>
|
||||
<low-level-rx-endpoint>LowLevelRxEndpoint2</low-level-rx-endpoint>
|
||||
</low-level-rx-links>
|
||||
<low-level-rx-links>
|
||||
<name>PrachLink2</name>
|
||||
<processing-element>PLANE_0</processing-element>
|
||||
<rx-array-carrier>RxArray2</rx-array-carrier>
|
||||
<low-level-rx-endpoint>LowLevelRxPrachEndpoint2</low-level-rx-endpoint>
|
||||
</low-level-rx-links>
|
||||
<low-level-rx-links>
|
||||
<name>PuschLink3</name>
|
||||
<processing-element>PLANE_0</processing-element>
|
||||
<rx-array-carrier>RxArray3</rx-array-carrier>
|
||||
<low-level-rx-endpoint>LowLevelRxEndpoint3</low-level-rx-endpoint>
|
||||
</low-level-rx-links>
|
||||
<low-level-rx-links>
|
||||
<name>PrachLink3</name>
|
||||
<processing-element>PLANE_0</processing-element>
|
||||
<rx-array-carrier>RxArray3</rx-array-carrier>
|
||||
<low-level-rx-endpoint>LowLevelRxPrachEndpoint3</low-level-rx-endpoint>
|
||||
</low-level-rx-links>
|
||||
<low-level-tx-endpoints>
|
||||
<name>LowLevelTxEndpoint0</name>
|
||||
<compression>
|
||||
<iq-bitwidth>9</iq-bitwidth>
|
||||
<compression-type>STATIC</compression-type>
|
||||
</compression>
|
||||
<frame-structure>193</frame-structure>
|
||||
<cp-type>NORMAL</cp-type>
|
||||
<cp-length>352</cp-length>
|
||||
<cp-length-other>288</cp-length-other>
|
||||
<offset-to-absolute-frequency-center>0</offset-to-absolute-frequency-center>
|
||||
<e-axcid>
|
||||
<o-du-port-bitmask>61440</o-du-port-bitmask>
|
||||
<band-sector-bitmask>3840</band-sector-bitmask>
|
||||
<ccid-bitmask>240</ccid-bitmask>
|
||||
<ru-port-bitmask>15</ru-port-bitmask>
|
||||
<eaxc-id>0</eaxc-id>
|
||||
</e-axcid>
|
||||
</low-level-tx-endpoints>
|
||||
<low-level-tx-endpoints>
|
||||
<name>LowLevelTxEndpoint1</name>
|
||||
<compression>
|
||||
<iq-bitwidth>9</iq-bitwidth>
|
||||
<compression-type>STATIC</compression-type>
|
||||
</compression>
|
||||
<frame-structure>193</frame-structure>
|
||||
<cp-type>NORMAL</cp-type>
|
||||
<cp-length>352</cp-length>
|
||||
<cp-length-other>288</cp-length-other>
|
||||
<offset-to-absolute-frequency-center>0</offset-to-absolute-frequency-center>
|
||||
<e-axcid>
|
||||
<o-du-port-bitmask>61440</o-du-port-bitmask>
|
||||
<band-sector-bitmask>3840</band-sector-bitmask>
|
||||
<ccid-bitmask>240</ccid-bitmask>
|
||||
<ru-port-bitmask>15</ru-port-bitmask>
|
||||
<eaxc-id>1</eaxc-id>
|
||||
</e-axcid>
|
||||
</low-level-tx-endpoints>
|
||||
<low-level-tx-endpoints>
|
||||
<name>LowLevelTxEndpoint2</name>
|
||||
<compression>
|
||||
<iq-bitwidth>9</iq-bitwidth>
|
||||
<compression-type>STATIC</compression-type>
|
||||
</compression>
|
||||
<frame-structure>193</frame-structure>
|
||||
<cp-type>NORMAL</cp-type>
|
||||
<cp-length>352</cp-length>
|
||||
<cp-length-other>288</cp-length-other>
|
||||
<offset-to-absolute-frequency-center>0</offset-to-absolute-frequency-center>
|
||||
<e-axcid>
|
||||
<o-du-port-bitmask>61440</o-du-port-bitmask>
|
||||
<band-sector-bitmask>3840</band-sector-bitmask>
|
||||
<ccid-bitmask>240</ccid-bitmask>
|
||||
<ru-port-bitmask>15</ru-port-bitmask>
|
||||
<eaxc-id>2</eaxc-id>
|
||||
</e-axcid>
|
||||
</low-level-tx-endpoints>
|
||||
<low-level-tx-endpoints>
|
||||
<name>LowLevelTxEndpoint3</name>
|
||||
<compression>
|
||||
<iq-bitwidth>9</iq-bitwidth>
|
||||
<compression-type>STATIC</compression-type>
|
||||
</compression>
|
||||
<frame-structure>193</frame-structure>
|
||||
<cp-type>NORMAL</cp-type>
|
||||
<cp-length>352</cp-length>
|
||||
<cp-length-other>288</cp-length-other>
|
||||
<offset-to-absolute-frequency-center>0</offset-to-absolute-frequency-center>
|
||||
<e-axcid>
|
||||
<o-du-port-bitmask>61440</o-du-port-bitmask>
|
||||
<band-sector-bitmask>3840</band-sector-bitmask>
|
||||
<ccid-bitmask>240</ccid-bitmask>
|
||||
<ru-port-bitmask>15</ru-port-bitmask>
|
||||
<eaxc-id>3</eaxc-id>
|
||||
</e-axcid>
|
||||
</low-level-tx-endpoints>
|
||||
<low-level-rx-endpoints>
|
||||
<name>LowLevelRxEndpoint0</name>
|
||||
<compression>
|
||||
<iq-bitwidth>9</iq-bitwidth>
|
||||
<compression-type>STATIC</compression-type>
|
||||
</compression>
|
||||
<frame-structure>193</frame-structure>
|
||||
<cp-type>NORMAL</cp-type>
|
||||
<cp-length>352</cp-length>
|
||||
<cp-length-other>288</cp-length-other>
|
||||
<offset-to-absolute-frequency-center>0</offset-to-absolute-frequency-center>
|
||||
<ul-fft-sampling-offsets>
|
||||
<scs>KHZ_30</scs>
|
||||
<ul-fft-sampling-offset>0</ul-fft-sampling-offset>
|
||||
</ul-fft-sampling-offsets>
|
||||
<e-axcid>
|
||||
<o-du-port-bitmask>61440</o-du-port-bitmask>
|
||||
<band-sector-bitmask>3840</band-sector-bitmask>
|
||||
<ccid-bitmask>240</ccid-bitmask>
|
||||
<ru-port-bitmask>15</ru-port-bitmask>
|
||||
<eaxc-id>0</eaxc-id>
|
||||
</e-axcid>
|
||||
<non-time-managed-delay-enabled>true</non-time-managed-delay-enabled>
|
||||
</low-level-rx-endpoints>
|
||||
<low-level-rx-endpoints>
|
||||
<name>LowLevelRxPrachEndpoint0</name>
|
||||
<compression>
|
||||
<iq-bitwidth>9</iq-bitwidth>
|
||||
<compression-type>STATIC</compression-type>
|
||||
</compression>
|
||||
<frame-structure>193</frame-structure>
|
||||
<cp-type>NORMAL</cp-type>
|
||||
<cp-length>352</cp-length>
|
||||
<cp-length-other>288</cp-length-other>
|
||||
<offset-to-absolute-frequency-center>0</offset-to-absolute-frequency-center>
|
||||
<ul-fft-sampling-offsets>
|
||||
<scs>KHZ_30</scs>
|
||||
<ul-fft-sampling-offset>0</ul-fft-sampling-offset>
|
||||
</ul-fft-sampling-offsets>
|
||||
<e-axcid>
|
||||
<o-du-port-bitmask>61440</o-du-port-bitmask>
|
||||
<band-sector-bitmask>3840</band-sector-bitmask>
|
||||
<ccid-bitmask>240</ccid-bitmask>
|
||||
<ru-port-bitmask>15</ru-port-bitmask>
|
||||
<eaxc-id>4</eaxc-id>
|
||||
</e-axcid>
|
||||
<non-time-managed-delay-enabled>true</non-time-managed-delay-enabled>
|
||||
</low-level-rx-endpoints>
|
||||
<low-level-rx-endpoints>
|
||||
<name>LowLevelRxEndpoint1</name>
|
||||
<compression>
|
||||
<iq-bitwidth>9</iq-bitwidth>
|
||||
<compression-type>STATIC</compression-type>
|
||||
</compression>
|
||||
<frame-structure>193</frame-structure>
|
||||
<cp-type>NORMAL</cp-type>
|
||||
<cp-length>352</cp-length>
|
||||
<cp-length-other>288</cp-length-other>
|
||||
<offset-to-absolute-frequency-center>0</offset-to-absolute-frequency-center>
|
||||
<ul-fft-sampling-offsets>
|
||||
<scs>KHZ_30</scs>
|
||||
<ul-fft-sampling-offset>0</ul-fft-sampling-offset>
|
||||
</ul-fft-sampling-offsets>
|
||||
<e-axcid>
|
||||
<o-du-port-bitmask>61440</o-du-port-bitmask>
|
||||
<band-sector-bitmask>3840</band-sector-bitmask>
|
||||
<ccid-bitmask>240</ccid-bitmask>
|
||||
<ru-port-bitmask>15</ru-port-bitmask>
|
||||
<eaxc-id>1</eaxc-id>
|
||||
</e-axcid>
|
||||
<non-time-managed-delay-enabled>true</non-time-managed-delay-enabled>
|
||||
</low-level-rx-endpoints>
|
||||
<low-level-rx-endpoints>
|
||||
<name>LowLevelRxPrachEndpoint1</name>
|
||||
<compression>
|
||||
<iq-bitwidth>9</iq-bitwidth>
|
||||
<compression-type>STATIC</compression-type>
|
||||
</compression>
|
||||
<frame-structure>193</frame-structure>
|
||||
<cp-type>NORMAL</cp-type>
|
||||
<cp-length>352</cp-length>
|
||||
<cp-length-other>288</cp-length-other>
|
||||
<offset-to-absolute-frequency-center>0</offset-to-absolute-frequency-center>
|
||||
<ul-fft-sampling-offsets>
|
||||
<scs>KHZ_30</scs>
|
||||
<ul-fft-sampling-offset>0</ul-fft-sampling-offset>
|
||||
</ul-fft-sampling-offsets>
|
||||
<e-axcid>
|
||||
<o-du-port-bitmask>61440</o-du-port-bitmask>
|
||||
<band-sector-bitmask>3840</band-sector-bitmask>
|
||||
<ccid-bitmask>240</ccid-bitmask>
|
||||
<ru-port-bitmask>15</ru-port-bitmask>
|
||||
<eaxc-id>5</eaxc-id>
|
||||
</e-axcid>
|
||||
<non-time-managed-delay-enabled>true</non-time-managed-delay-enabled>
|
||||
</low-level-rx-endpoints>
|
||||
<low-level-rx-endpoints>
|
||||
<name>LowLevelRxEndpoint2</name>
|
||||
<compression>
|
||||
<iq-bitwidth>9</iq-bitwidth>
|
||||
<compression-type>STATIC</compression-type>
|
||||
</compression>
|
||||
<frame-structure>193</frame-structure>
|
||||
<cp-type>NORMAL</cp-type>
|
||||
<cp-length>352</cp-length>
|
||||
<cp-length-other>288</cp-length-other>
|
||||
<offset-to-absolute-frequency-center>0</offset-to-absolute-frequency-center>
|
||||
<ul-fft-sampling-offsets>
|
||||
<scs>KHZ_30</scs>
|
||||
<ul-fft-sampling-offset>0</ul-fft-sampling-offset>
|
||||
</ul-fft-sampling-offsets>
|
||||
<e-axcid>
|
||||
<o-du-port-bitmask>61440</o-du-port-bitmask>
|
||||
<band-sector-bitmask>3840</band-sector-bitmask>
|
||||
<ccid-bitmask>240</ccid-bitmask>
|
||||
<ru-port-bitmask>15</ru-port-bitmask>
|
||||
<eaxc-id>2</eaxc-id>
|
||||
</e-axcid>
|
||||
<non-time-managed-delay-enabled>true</non-time-managed-delay-enabled>
|
||||
</low-level-rx-endpoints>
|
||||
<low-level-rx-endpoints>
|
||||
<name>LowLevelRxPrachEndpoint2</name>
|
||||
<compression>
|
||||
<iq-bitwidth>9</iq-bitwidth>
|
||||
<compression-type>STATIC</compression-type>
|
||||
</compression>
|
||||
<frame-structure>193</frame-structure>
|
||||
<cp-type>NORMAL</cp-type>
|
||||
<cp-length>352</cp-length>
|
||||
<cp-length-other>288</cp-length-other>
|
||||
<offset-to-absolute-frequency-center>0</offset-to-absolute-frequency-center>
|
||||
<ul-fft-sampling-offsets>
|
||||
<scs>KHZ_30</scs>
|
||||
<ul-fft-sampling-offset>0</ul-fft-sampling-offset>
|
||||
</ul-fft-sampling-offsets>
|
||||
<e-axcid>
|
||||
<o-du-port-bitmask>61440</o-du-port-bitmask>
|
||||
<band-sector-bitmask>3840</band-sector-bitmask>
|
||||
<ccid-bitmask>240</ccid-bitmask>
|
||||
<ru-port-bitmask>15</ru-port-bitmask>
|
||||
<eaxc-id>6</eaxc-id>
|
||||
</e-axcid>
|
||||
<non-time-managed-delay-enabled>true</non-time-managed-delay-enabled>
|
||||
</low-level-rx-endpoints>
|
||||
<low-level-rx-endpoints>
|
||||
<name>LowLevelRxEndpoint3</name>
|
||||
<compression>
|
||||
<iq-bitwidth>9</iq-bitwidth>
|
||||
<compression-type>STATIC</compression-type>
|
||||
</compression>
|
||||
<frame-structure>193</frame-structure>
|
||||
<cp-type>NORMAL</cp-type>
|
||||
<cp-length>352</cp-length>
|
||||
<cp-length-other>288</cp-length-other>
|
||||
<offset-to-absolute-frequency-center>0</offset-to-absolute-frequency-center>
|
||||
<ul-fft-sampling-offsets>
|
||||
<scs>KHZ_30</scs>
|
||||
<ul-fft-sampling-offset>0</ul-fft-sampling-offset>
|
||||
</ul-fft-sampling-offsets>
|
||||
<e-axcid>
|
||||
<o-du-port-bitmask>61440</o-du-port-bitmask>
|
||||
<band-sector-bitmask>3840</band-sector-bitmask>
|
||||
<ccid-bitmask>240</ccid-bitmask>
|
||||
<ru-port-bitmask>15</ru-port-bitmask>
|
||||
<eaxc-id>3</eaxc-id>
|
||||
</e-axcid>
|
||||
<non-time-managed-delay-enabled>true</non-time-managed-delay-enabled>
|
||||
</low-level-rx-endpoints>
|
||||
<low-level-rx-endpoints>
|
||||
<name>LowLevelRxPrachEndpoint3</name>
|
||||
<compression>
|
||||
<iq-bitwidth>9</iq-bitwidth>
|
||||
<compression-type>STATIC</compression-type>
|
||||
</compression>
|
||||
<frame-structure>193</frame-structure>
|
||||
<cp-type>NORMAL</cp-type>
|
||||
<cp-length>352</cp-length>
|
||||
<cp-length-other>288</cp-length-other>
|
||||
<offset-to-absolute-frequency-center>0</offset-to-absolute-frequency-center>
|
||||
<ul-fft-sampling-offsets>
|
||||
<scs>KHZ_30</scs>
|
||||
<ul-fft-sampling-offset>0</ul-fft-sampling-offset>
|
||||
</ul-fft-sampling-offsets>
|
||||
<e-axcid>
|
||||
<o-du-port-bitmask>61440</o-du-port-bitmask>
|
||||
<band-sector-bitmask>3840</band-sector-bitmask>
|
||||
<ccid-bitmask>240</ccid-bitmask>
|
||||
<ru-port-bitmask>15</ru-port-bitmask>
|
||||
<eaxc-id>7</eaxc-id>
|
||||
</e-axcid>
|
||||
<non-time-managed-delay-enabled>true</non-time-managed-delay-enabled>
|
||||
</low-level-rx-endpoints>
|
||||
<tx-array-carriers>
|
||||
<name>TxArray0</name>
|
||||
<absolute-frequency-center>623334</absolute-frequency-center>
|
||||
<center-of-channel-bandwidth>3350010000</center-of-channel-bandwidth>
|
||||
<channel-bandwidth>100000000</channel-bandwidth>
|
||||
<active>ACTIVE</active>
|
||||
<gain>24.0</gain>
|
||||
<downlink-radio-frame-offset>0</downlink-radio-frame-offset>
|
||||
<downlink-sfn-offset>0</downlink-sfn-offset>
|
||||
</tx-array-carriers>
|
||||
<tx-array-carriers>
|
||||
<name>TxArray1</name>
|
||||
<absolute-frequency-center>623334</absolute-frequency-center>
|
||||
<center-of-channel-bandwidth>3350010000</center-of-channel-bandwidth>
|
||||
<channel-bandwidth>100000000</channel-bandwidth>
|
||||
<active>ACTIVE</active>
|
||||
<gain>24.0</gain>
|
||||
<downlink-radio-frame-offset>0</downlink-radio-frame-offset>
|
||||
<downlink-sfn-offset>0</downlink-sfn-offset>
|
||||
</tx-array-carriers>
|
||||
<tx-array-carriers>
|
||||
<name>TxArray2</name>
|
||||
<absolute-frequency-center>623334</absolute-frequency-center>
|
||||
<center-of-channel-bandwidth>3350010000</center-of-channel-bandwidth>
|
||||
<channel-bandwidth>100000000</channel-bandwidth>
|
||||
<active>ACTIVE</active>
|
||||
<gain>24.0</gain>
|
||||
<downlink-radio-frame-offset>0</downlink-radio-frame-offset>
|
||||
<downlink-sfn-offset>0</downlink-sfn-offset>
|
||||
</tx-array-carriers>
|
||||
<tx-array-carriers>
|
||||
<name>TxArray3</name>
|
||||
<absolute-frequency-center>623334</absolute-frequency-center>
|
||||
<center-of-channel-bandwidth>3350010000</center-of-channel-bandwidth>
|
||||
<channel-bandwidth>100000000</channel-bandwidth>
|
||||
<active>ACTIVE</active>
|
||||
<gain>24.0</gain>
|
||||
<downlink-radio-frame-offset>0</downlink-radio-frame-offset>
|
||||
<downlink-sfn-offset>0</downlink-sfn-offset>
|
||||
</tx-array-carriers>
|
||||
<rx-array-carriers>
|
||||
<name>RxArray0</name>
|
||||
<absolute-frequency-center>623334</absolute-frequency-center>
|
||||
<center-of-channel-bandwidth>3350010000</center-of-channel-bandwidth>
|
||||
<channel-bandwidth>100000000</channel-bandwidth>
|
||||
<active>ACTIVE</active>
|
||||
<downlink-radio-frame-offset>0</downlink-radio-frame-offset>
|
||||
<downlink-sfn-offset>0</downlink-sfn-offset>
|
||||
<gain-correction>0.0</gain-correction>
|
||||
<n-ta-offset>0</n-ta-offset>
|
||||
</rx-array-carriers>
|
||||
<rx-array-carriers>
|
||||
<name>RxArray1</name>
|
||||
<absolute-frequency-center>623334</absolute-frequency-center>
|
||||
<center-of-channel-bandwidth>3350010000</center-of-channel-bandwidth>
|
||||
<channel-bandwidth>100000000</channel-bandwidth>
|
||||
<active>ACTIVE</active>
|
||||
<downlink-radio-frame-offset>0</downlink-radio-frame-offset>
|
||||
<downlink-sfn-offset>0</downlink-sfn-offset>
|
||||
<gain-correction>0.0</gain-correction>
|
||||
<n-ta-offset>0</n-ta-offset>
|
||||
</rx-array-carriers>
|
||||
<rx-array-carriers>
|
||||
<name>RxArray2</name>
|
||||
<absolute-frequency-center>623334</absolute-frequency-center>
|
||||
<center-of-channel-bandwidth>3350010000</center-of-channel-bandwidth>
|
||||
<channel-bandwidth>100000000</channel-bandwidth>
|
||||
<active>ACTIVE</active>
|
||||
<downlink-radio-frame-offset>0</downlink-radio-frame-offset>
|
||||
<downlink-sfn-offset>0</downlink-sfn-offset>
|
||||
<gain-correction>0.0</gain-correction>
|
||||
<n-ta-offset>0</n-ta-offset>
|
||||
</rx-array-carriers>
|
||||
<rx-array-carriers>
|
||||
<name>RxArray3</name>
|
||||
<absolute-frequency-center>623334</absolute-frequency-center>
|
||||
<center-of-channel-bandwidth>3350010000</center-of-channel-bandwidth>
|
||||
<channel-bandwidth>100000000</channel-bandwidth>
|
||||
<active>ACTIVE</active>
|
||||
<downlink-radio-frame-offset>0</downlink-radio-frame-offset>
|
||||
<downlink-sfn-offset>0</downlink-sfn-offset>
|
||||
<gain-correction>0.0</gain-correction>
|
||||
<n-ta-offset>0</n-ta-offset>
|
||||
</rx-array-carriers>
|
||||
</user-plane-configuration>
|
||||
|
||||
[HW] [MPLANE] RPC reply = OK.
|
||||
[HW] [MPLANE] Successfully edited the candidate datastore for RU "192.168.81.4".
|
||||
[HW] [MPLANE] RPC request to RU "192.168.81.4" = <validate> candidate datastore.
|
||||
[HW] [MPLANE] RPC reply = OK.
|
||||
[HW] [MPLANE] Successfully validated candidate datastore for RU "192.168.81.4".
|
||||
[HW] [MPLANE] RPC request to RU "192.168.81.4" = <commit> candidate datastore.
|
||||
[HW] [MPLANE] RPC reply = OK.
|
||||
[HW] [MPLANE] Successfully commited configuration into running datastore for RU "192.168.81.4".
|
||||
[HW] [MPLANE] Received notification from RU "192.168.81.4" at (2025-08-28T10:37:19.335228846+00:00)
|
||||
{
|
||||
"o-ran-uplane-conf:rx-array-carriers-state-change": {
|
||||
"rx-array-carriers": [
|
||||
{
|
||||
"name": "RxArray0",
|
||||
"state": "BUSY"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
[HW] [MPLANE] Received notification from RU "192.168.81.4" at (2025-08-28T10:37:19.368360865+00:00)
|
||||
{
|
||||
"o-ran-uplane-conf:rx-array-carriers-state-change": {
|
||||
"rx-array-carriers": [
|
||||
{
|
||||
"name": "RxArray1",
|
||||
"state": "BUSY"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
[HW] [MPLANE] Received notification from RU "192.168.81.4" at (2025-08-28T10:37:19.414703766+00:00)
|
||||
{
|
||||
"o-ran-uplane-conf:rx-array-carriers-state-change": {
|
||||
"rx-array-carriers": [
|
||||
{
|
||||
"name": "RxArray2",
|
||||
"state": "BUSY"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
[HW] [MPLANE] Received notification from RU "192.168.81.4" at (2025-08-28T10:37:19.452921618+00:00)
|
||||
{
|
||||
"o-ran-uplane-conf:rx-array-carriers-state-change": {
|
||||
"rx-array-carriers": [
|
||||
{
|
||||
"name": "RxArray3",
|
||||
"state": "BUSY"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
[HW] [MPLANE] Received notification from RU "192.168.81.4" at (2025-08-28T10:37:19.471419021+00:00)
|
||||
{
|
||||
"ietf-netconf-notifications:netconf-config-change": {
|
||||
"changed-by": {
|
||||
"username": "root",
|
||||
"session-id": 0
|
||||
},
|
||||
"datastore": "running",
|
||||
"edit": [
|
||||
{
|
||||
"target": "/ietf-interfaces:interfaces/interface[name='INTERFACE_0']",
|
||||
"operation": "create"
|
||||
},
|
||||
{
|
||||
"target": "/ietf-interfaces:interfaces/interface[name='INTERFACE_0']/name",
|
||||
"operation": "create"
|
||||
},
|
||||
...
|
||||
[HW] [MPLANE] Received notification from RU "192.168.81.4" at (2025-08-28T10:37:19.678251110+00:00)
|
||||
{
|
||||
"o-ran-uplane-conf:tx-array-carriers-state-change": {
|
||||
"tx-array-carriers": [
|
||||
{
|
||||
"name": "TxArray0",
|
||||
"state": "BUSY"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
[HW] [MPLANE] Received notification from RU "192.168.81.4" at (2025-08-28T10:37:19.715498360+00:00)
|
||||
{
|
||||
"o-ran-uplane-conf:tx-array-carriers-state-change": {
|
||||
"tx-array-carriers": [
|
||||
{
|
||||
"name": "TxArray1",
|
||||
"state": "BUSY"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
[HW] [MPLANE] Received notification from RU "192.168.81.4" at (2025-08-28T10:37:19.830268973+00:00)
|
||||
{
|
||||
"o-ran-uplane-conf:tx-array-carriers-state-change": {
|
||||
"tx-array-carriers": [
|
||||
{
|
||||
"name": "TxArray2",
|
||||
"state": "BUSY"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
[HW] [MPLANE] Received notification from RU "192.168.81.4" at (2025-08-28T10:37:19.853387657+00:00)
|
||||
{
|
||||
"o-ran-uplane-conf:tx-array-carriers-state-change": {
|
||||
"tx-array-carriers": [
|
||||
{
|
||||
"name": "TxArray3",
|
||||
"state": "BUSY"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
[HW] [MPLANE] Received notification from RU "192.168.81.4" at (2025-08-28T10:37:24.515262267+00:00)
|
||||
{
|
||||
"o-ran-uplane-conf:rx-array-carriers-state-change": {
|
||||
"rx-array-carriers": [
|
||||
{
|
||||
"name": "RxArray0",
|
||||
"state": "READY"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
[HW] [MPLANE] Received notification from RU "192.168.81.4" at (2025-08-28T10:37:24.535692962+00:00)
|
||||
{
|
||||
"o-ran-uplane-conf:rx-array-carriers-state-change": {
|
||||
"rx-array-carriers": [
|
||||
{
|
||||
"name": "RxArray1",
|
||||
"state": "READY"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
[HW] [MPLANE] Received notification from RU "192.168.81.4" at (2025-08-28T10:37:24.557423764+00:00)
|
||||
{
|
||||
"o-ran-uplane-conf:rx-array-carriers-state-change": {
|
||||
"rx-array-carriers": [
|
||||
{
|
||||
"name": "RxArray2",
|
||||
"state": "READY"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
[HW] [MPLANE] Received notification from RU "192.168.81.4" at (2025-08-28T10:37:24.579066867+00:00)
|
||||
{
|
||||
"o-ran-uplane-conf:rx-array-carriers-state-change": {
|
||||
"rx-array-carriers": [
|
||||
{
|
||||
"name": "RxArray3",
|
||||
"state": "READY"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
[HW] [MPLANE] Received notification from RU "192.168.81.4" at (2025-08-28T10:37:24.604192995+00:00)
|
||||
{
|
||||
"o-ran-uplane-conf:tx-array-carriers-state-change": {
|
||||
"tx-array-carriers": [
|
||||
{
|
||||
"name": "TxArray0",
|
||||
"state": "READY"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
[HW] [MPLANE] Received notification from RU "192.168.81.4" at (2025-08-28T10:37:24.629830498+00:00)
|
||||
{
|
||||
"o-ran-uplane-conf:tx-array-carriers-state-change": {
|
||||
"tx-array-carriers": [
|
||||
{
|
||||
"name": "TxArray1",
|
||||
"state": "READY"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
[HW] [MPLANE] Received notification from RU "192.168.81.4" at (2025-08-28T10:37:24.651062685+00:00)
|
||||
{
|
||||
"o-ran-uplane-conf:tx-array-carriers-state-change": {
|
||||
"tx-array-carriers": [
|
||||
{
|
||||
"name": "TxArray2",
|
||||
"state": "READY"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
[HW] [MPLANE] Received notification from RU "192.168.81.4" at (2025-08-28T10:37:24.672865767+00:00)
|
||||
{
|
||||
"o-ran-uplane-conf:tx-array-carriers-state-change": {
|
||||
"tx-array-carriers": [
|
||||
{
|
||||
"name": "TxArray3",
|
||||
"state": "READY"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
[HW] [MPLANE] RU "192.168.81.4" is now ready.
|
||||
[HW] [MPLANE] RPC request to RU "192.168.81.4" = <edit-config>:
|
||||
<performance-measurement-objects xmlns="urn:o-ran:performance-management:1.0">
|
||||
<rx-window-measurement-interval>10</rx-window-measurement-interval>
|
||||
<tx-measurement-interval>10</tx-measurement-interval>
|
||||
<notification-interval>10</notification-interval>
|
||||
<rx-window-measurement-objects>
|
||||
<measurement-object>RX_ON_TIME</measurement-object>
|
||||
<active>true</active>
|
||||
<object-unit>RU</object-unit>
|
||||
<report-info>COUNT</report-info>
|
||||
</rx-window-measurement-objects>
|
||||
<rx-window-measurement-objects>
|
||||
<measurement-object>RX_EARLY</measurement-object>
|
||||
<active>true</active>
|
||||
<object-unit>RU</object-unit>
|
||||
<report-info>COUNT</report-info>
|
||||
</rx-window-measurement-objects>
|
||||
<rx-window-measurement-objects>
|
||||
<measurement-object>RX_LATE</measurement-object>
|
||||
<active>true</active>
|
||||
<object-unit>RU</object-unit>
|
||||
<report-info>COUNT</report-info>
|
||||
</rx-window-measurement-objects>
|
||||
<rx-window-measurement-objects>
|
||||
<measurement-object>RX_TOTAL</measurement-object>
|
||||
<active>true</active>
|
||||
<object-unit>RU</object-unit>
|
||||
<report-info>COUNT</report-info>
|
||||
</rx-window-measurement-objects>
|
||||
<rx-window-measurement-objects>
|
||||
<measurement-object>RX_ON_TIME_C</measurement-object>
|
||||
<active>true</active>
|
||||
<object-unit>RU</object-unit>
|
||||
<report-info>COUNT</report-info>
|
||||
</rx-window-measurement-objects>
|
||||
<rx-window-measurement-objects>
|
||||
<measurement-object>RX_EARLY_C</measurement-object>
|
||||
<active>true</active>
|
||||
<object-unit>RU</object-unit>
|
||||
<report-info>COUNT</report-info>
|
||||
</rx-window-measurement-objects>
|
||||
<rx-window-measurement-objects>
|
||||
<measurement-object>RX_LATE_C</measurement-object>
|
||||
<active>true</active>
|
||||
<object-unit>RU</object-unit>
|
||||
<report-info>COUNT</report-info>
|
||||
</rx-window-measurement-objects>
|
||||
<tx-measurement-objects>
|
||||
<measurement-object>TX_TOTAL</measurement-object>
|
||||
<active>true</active>
|
||||
<object-unit>RU</object-unit>
|
||||
<report-info>COUNT</report-info>
|
||||
</tx-measurement-objects>
|
||||
</performance-measurement-objects>
|
||||
|
||||
[HW] [MPLANE] RPC reply = OK.
|
||||
[HW] [MPLANE] Successfully edited the candidate datastore for RU "192.168.81.4".
|
||||
[HW] [MPLANE] RPC request to RU "192.168.81.4" = <validate> candidate datastore.
|
||||
[HW] [MPLANE] RPC reply = OK.
|
||||
[HW] [MPLANE] Successfully validated candidate datastore for RU "192.168.81.4".
|
||||
[HW] [MPLANE] RPC request to RU "192.168.81.4" = <commit> candidate datastore.
|
||||
[HW] [MPLANE] RPC reply = OK.
|
||||
[HW] [MPLANE] Successfully commited configuration into running datastore for RU "192.168.81.4".
|
||||
[HW] [MPLANE] Sucessfully activated PM after start-up procedure for RU "192.168.81.4".
|
||||
```
|
||||
</details>
|
||||
|
||||
Note: If you wish to run the fronthaul without M-plane, no need for recompilation, as the library `oran_fhlib_5g` already exists.
|
||||
The only mandatory step is to link `oran_fhlib_5g` to `oai_transpro` library.
|
||||
|
||||
@@ -356,7 +356,9 @@ sudo ./ran_build/build/nr-uesoftmodem -O ../targets/PROJECTS/GENERIC-NR-5GC/CONF
|
||||
|
||||
For LEO satellite scenarios, the parameter `--ntn-initial-time-drift` must be provided via command line, as the UE needs this value to compensate for the time drift during initial sync, before SIB19 was received.
|
||||
This parameter provides the drift rate of the complete DL timing (incl. feeder link and service link) in µs/s.
|
||||
Also, to perform an autonomous TA update based on the DL drift, the boolean parameter `--autonomous-ta` should be added in case of a LEO satellite scenario.
|
||||
|
||||
To perform an autonomous TA update based on the DL drift, the boolean parameter `--autonomous-ta` can be added.
|
||||
If that parameter is omitted, the TA is continuously computed based on the SIB19 information.
|
||||
|
||||
For LEO satellite scenario we assume the LO to be very accurate and the main FO contribution comes from Doppler shift.
|
||||
Therefore, we use the command line parameter `--cont-fo-comp 2` to continuously compensate the DL Doppler and pre-compensate the UL Doppler.
|
||||
@@ -367,7 +369,7 @@ For other information on optional NR UE command line options, please refer [here
|
||||
So an example NR UE command for FDD, 5MHz BW, 15 kHz SCS, transparent LEO satellite 5G NR NTN is this:
|
||||
```
|
||||
cd cmake_targets
|
||||
sudo ./ran_build/build/nr-uesoftmodem -O ../targets/PROJECTS/GENERIC-NR-5GC/CONF/ue.conf --band 254 -C 2488400000 --CO -873500000 -r 25 --numerology 0 --ssb 60 --rfsim --rfsimulator.prop_delay 20 --rfsimulator.options chanmod --time-sync-I 0.1 --ntn-initial-time-drift -46 --autonomous-ta --initial-fo 57340 --cont-fo-comp 2
|
||||
sudo ./ran_build/build/nr-uesoftmodem -O ../targets/PROJECTS/GENERIC-NR-5GC/CONF/ue.conf --band 254 -C 2488400000 --CO -873500000 -r 25 --numerology 0 --ssb 60 --rfsim --rfsimulator.prop_delay 20 --rfsimulator.options chanmod --time-sync-I 0.1 --ntn-initial-time-drift -46 --initial-fo 57340 --cont-fo-comp 2
|
||||
```
|
||||
|
||||
# Specific OAI modes
|
||||
@@ -468,19 +470,30 @@ The hardcoded DRBs will be treated like GBR Flows. Due to code limitations at th
|
||||
|
||||
## IF setup with OAI
|
||||
|
||||
OAI is also compatible with Intermediate Frequency (IF) equipment. This allows to use RF front-end that with arbitrary frequencies bands that do not comply with the standardised 3GPP NR bands.
|
||||
OAI is also compatible with Intermediate Frequency (IF) equipment, allowing the
|
||||
use of RF front-ends operating on arbitrary frequency bands that do not conform
|
||||
to the standardized 3GPP NR bands.
|
||||
|
||||
To configure the IF frequencies it is necessary to use two command-line options at UE side:
|
||||
- `if_freq`, downlink frequency in Hz
|
||||
- `if_freq_off`, uplink frequency offset in Hz
|
||||
### OAIUE configuration
|
||||
To configure IF frequencies on the UE side, provide the following command-line
|
||||
options:
|
||||
- `if_freq`: DL frequency in Hz
|
||||
- `if_freq_off`: UL frequency offset in Hz
|
||||
|
||||
Accordingly, the following parameters must be configured in the RUs section of the gNB configuration file:
|
||||
- `if_freq`
|
||||
- `if_offset`
|
||||
### gNB configuration
|
||||
On the gNB side, the corresponding parameters must be set in the RUs section of
|
||||
the configuration file:
|
||||
- `if_freq`: DL frequency in Hz
|
||||
- `if_offset`: UL frequency offset in Hz
|
||||
|
||||
> Note: When using a libconfig-based configuration file for the gNB, ensure that
|
||||
> `if_freq` numeric value is suffixed with "L" so it is correctly parsed as
|
||||
> 64-bit integer.
|
||||
|
||||
### Run OAI with custom DL/UL arbitrary frequencies
|
||||
|
||||
The following example uses DL frequency 2169.080 MHz and UL frequency offset -400 MHz, with a configuration file for band 66 (FDD) at gNB side.
|
||||
The following example uses DL frequency 2169.080 MHz and UL frequency offset
|
||||
-400 MHz, with a configuration file for band 66 (FDD) at gNB side.
|
||||
|
||||
On two separate machines with USRPs, run:
|
||||
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
# Procedure to add dedicated Bandwidth part (BWP)
|
||||
|
||||
## Contributed by 5G Testbed IISc
|
||||
|
||||
### Developers: Abhijith A, Shruthi S
|
||||
|
||||
# Terminology #
|
||||
|
||||
## Bandwidth part (BWP) ##
|
||||
Bandwidth Part (BWP) is a set of contiguous Resource Blocks in the resource grid.
|
||||
|
||||
Parameters of a BWP are communicated to UE using RRC parameters: BWP-Downlink and BWP-Uplink.
|
||||
|
||||
A UE can be configured with a set of 4 BWPs in uplink (UL) and downlink (DL) direction (3GPP TS 38.331 Annex B.2 Description of BWP configuration options). But only 1 BWP can be active in UL and DL direction at a given time.
|
||||
|
||||
# Procedure to run multiple dedicated BWPs #
|
||||
|
||||
A maximum of 4 dedicated BWPs can be configured for a UE.
|
||||
|
||||
To configure multiple BWPs, add the following parameters in the physical parameters section:
|
||||
|
||||
## Setup of the Configuration files ##
|
||||
|
||||
In the configuration file you have the option to select the 1st active BWP, the RIV and SCS of each BWP in the following way (example with 3 additional BWPs):
|
||||
```
|
||||
first_active_bwp = 1;
|
||||
bwp_list = ({ scs = 1; bwpStart = 0; bwpSize = 106;},
|
||||
{ scs = 1; bwpStart = 0; bwpSize = 51;},
|
||||
{ scs = 1; bwpStart = 0; bwpSize = 24;});
|
||||
```
|
||||
|
||||
This example configures 3 additional BWPs, with IDs from 1 to 3. Find these parameters in this configuration file: "ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.neighbour.conf"
|
||||
|
||||
# Testing gNB and UE in RF simulator
|
||||
|
||||
## gNB command:
|
||||
```
|
||||
sudo ./nr-softmodem -O ../../../ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.neighbour.conf --rfsim --rfsimulator.serveraddr server
|
||||
```
|
||||
|
||||
## UE command:
|
||||
```
|
||||
sudo ./nr-uesoftmodem -C 3319680000 -r 106 --numerology 1 --ssb 516 --band 78 --rfsim --rfsimulator.serveraddr 127.0.0.1
|
||||
```
|
||||
@@ -9,7 +9,8 @@ OAI uses/supports a number of environment variables, documented in the following
|
||||
- `NVRAM_DIR`: directory to read/write NVRAM data in (5G) `nvram` tool; if not defined, will use `PWD` (working directory)
|
||||
- `OAI_CONFIGMODULE`: can be used to pass the configuration file instead of `-O`
|
||||
- `OAI_GDBSTACKS`: if defined when hitting an assertion (`DevAssert()`, `AssertFatal()`, ...), OAI will load `gdb` and provide a backtrace for every thread
|
||||
- `OAI_RNGSEED`: overwrites any seed for random number generators (RNG) in simulators
|
||||
- `OAI_RNGSEED`: provide a fixed seed for random number generators (RNG). If
|
||||
this variable is absent, a random seed will be read (from `/dev/urandom`).
|
||||
- `USIM_DIR`: directory to read/write USIM data in (4G) `usim` tool; if not defined, will use `PWD` (working directory)
|
||||
|
||||
Furthermore, these variables appear in code that is not maintained and maybe not even compiled anywhere:
|
||||
|
||||
@@ -1,6 +1,15 @@
|
||||
This tutorial explains how to perform handovers. It covers both F1 handovers
|
||||
(intra-gNB, within a single gNB between DUs) and N2 handovers (inter-gNB).
|
||||
|
||||
This document assumes familiarity with the F1 split architecture and basic
|
||||
OAI knowledge. Please refer to the prerequisite documentation listed below:
|
||||
|
||||
- To run the [Core Network](https://gitlab.eurecom.fr/oai/openairinterface5g/-/blob/develop/doc/NR_SA_Tutorial_OAI_CN5G.md)
|
||||
- To run [OAI full stack with COTS UE](https://gitlab.eurecom.fr/oai/openairinterface5g/-/blob/develop/doc/NR_SA_Tutorial_COTS_UE.md)
|
||||
- [F1 split design document](https://gitlab.eurecom.fr/oai/openairinterface5g/-/blob/develop/doc/F1AP/F1-design.md?ref_type=heads)
|
||||
for details on the F1 architecture and the networking relationships between
|
||||
the CU and the associated DUs.
|
||||
|
||||
[[_TOC_]]
|
||||
|
||||
# Considered setup for F1 handover
|
||||
@@ -13,22 +22,22 @@ same.
|
||||
|
||||

|
||||
|
||||
# What is a gNB neighbor?
|
||||
# gNB neighbour definition
|
||||
|
||||
Network continuity is a key aspect of 5G. In the 5G architecture, gNB neighbors
|
||||
Network continuity is a key aspect of 5G. In the 5G architecture, gNB neighbours
|
||||
play a central role in maintaining service continuity through mechanisms such
|
||||
as handover and load balancing. By definition, a gNB neighbor is another gNB
|
||||
as handover and load balancing. By definition, a gNB neighbour is another gNB
|
||||
that can be measured and linked by the UE. If the current serving gNB is no
|
||||
longer optimal, the UE may connect to a neighbor gNB.
|
||||
longer optimal, the UE may connect to a neighbour gNB.
|
||||
|
||||
To support this behavior, the network configuration specifies additional frequencies
|
||||
and cells that the UE should measure. The UE reports these measurements to the
|
||||
network, which then decides whether or not to initiate a handover.
|
||||
|
||||
Neighbor types include:
|
||||
- **Intra-gNB neighbors** - cells belonging to the same gNB
|
||||
- **Inter-gNB neighbors** - cells belonging to different gNBs
|
||||
- **Inter-RAT neighbors** - cells belonging to another RAT (e.g., LTE)
|
||||
Neighbour types include:
|
||||
- **Intra-gNB neighbours** - cells belonging to the same gNB
|
||||
- **Inter-gNB neighbours** - cells belonging to different gNBs
|
||||
- **Inter-RAT neighbours** - cells belonging to another RAT (e.g., LTE)
|
||||
|
||||
# Steps to run F1 handover with OAI UE
|
||||
|
||||
@@ -46,10 +55,6 @@ build both gNB and UE as well as activate the build of telnet to that purpose:
|
||||
|
||||
## Run the setup
|
||||
|
||||
This tutorial assumes you have a core network running; [refer to the
|
||||
corresponding tutorial](./NR_SA_Tutorial_OAI_CN5G.md) if this is not the case
|
||||
yet.
|
||||
|
||||
We will use the TDD configuration files in the repository for the
|
||||
[CU](../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-cu.sa.f1.conf) as well for
|
||||
[DU0](../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band78.106prb.rfsim.pci0.conf)
|
||||
@@ -139,19 +144,23 @@ directory of the CU.
|
||||
You can do handover across DUs with a COTS UE. Note that these DUs should be
|
||||
separated by at least multiple meters to ensure that the UE will receive
|
||||
different signal strengths when moving between cells.
|
||||
In the CI setup we use a digital 4 channel attenuator that allows us to "control"
|
||||
the transmitted signal from both RUs. This allows us to create a setup in
|
||||
which the UE thinks it's changing positions between 2 cells, but in reality
|
||||
it's not moving.
|
||||
|
||||
We support both intra-frequency and inter-frequency handovers. We have verified with USRPs
|
||||
only, although other radios should work as well.
|
||||
We support both intra-frequency and inter-frequency handovers. We have verified
|
||||
with USRPs only, although other radios should work as well.
|
||||
|
||||
For UEs, we verified Quectel modules and iPhones. Note, though, that not all
|
||||
phones might work; for instance, we did not achieve handovers with a OnePlus
|
||||
Nord, yet.
|
||||
For UEs, we verified Quectel modules, iPhones and Samsung S23 Ultra. Note,
|
||||
though, that not all phones might work; for instance, we did not achieve
|
||||
handovers with a OnePlus Nord, yet.
|
||||
|
||||
## Steps
|
||||
|
||||
First, make sure that you can run both DUs with the CU independently. Use the
|
||||
same radio hardware for both radios to ensure that both cells can be received
|
||||
equally good by the UE.
|
||||
First, make sure that you can run both DUs with the CU independently.
|
||||
Use the same radio hardware for both radios to ensure that both cells can be
|
||||
received equally good by the UE.
|
||||
|
||||
In order to enable handovers (triggered by the UE), you have to configure the
|
||||
neighbour relation of the DUs at the CU. To do so, proceed as follows:
|
||||
@@ -163,11 +172,13 @@ neighbour relation of the DUs at the CU. To do so, proceed as follows:
|
||||
```
|
||||
cat nrRRC_stats.log
|
||||
```
|
||||
1. Fill in the [`neighbour-config.conf`](../ci-scripts/conf_files/neighbour-config.conf) configuration file as shown below, and
|
||||
`@include` it in the CU file.
|
||||
1. Start the CU and both DUs.
|
||||
1. Fill in the [`neighbour-config.conf`](../ci-scripts/conf_files/neighbour-config.conf)
|
||||
configuration file as shown below, and `@include` it in the CU file.
|
||||
1. Start the CU and both DUs. If you are using an attenuator, make sure that
|
||||
the signal on one DU is stronger than the other.
|
||||
|
||||
1. Bring the phone close to one cell, and leave flight mode. It should connect
|
||||
to the DU to which it is closer.
|
||||
to the DU to which it is closer/stronger signal.
|
||||
1. Move the UE towards the other DU; it should trigger an "A3 event" (Neighbour
|
||||
Becomes Better than Serving), and the CU will trigger the handover to the
|
||||
other DU.
|
||||
@@ -175,7 +186,14 @@ neighbour relation of the DUs at the CU. To do so, proceed as follows:
|
||||
The output on the terminal should be the same as with RFsim. If no handover is
|
||||
triggered:
|
||||
|
||||
- Make sure that both DUs use the same hardware.
|
||||
- Make sure that both DUs use the same hardware. In case of USRPs, make sure that
|
||||
they are synched:
|
||||
- By connecting them to a GPS or an Octoclock to provide a common time and clock
|
||||
reference.
|
||||
- By synchronizing the RU hosts.
|
||||
- By using Openairinterface starting tag [2025.w42](https://gitlab.eurecom.fr/oai/openairinterface5g/-/tree/2025.w42?ref_type=tags)
|
||||
(A fix was added to force the USRP to "use" the time/clock provided by the
|
||||
external source instead to its own master clock. for more info see [MR](https://gitlab.eurecom.fr/oai/openairinterface5g/-/merge_requests/3693)).
|
||||
- Make sure that the UE sees both cells. For instance, you can switch to flight
|
||||
mode, go closer to the other DU, and switch off flight mode -- the UE should
|
||||
connect to that second DU.
|
||||
@@ -187,6 +205,17 @@ decision about a handover is always at the network-side, the UE only "assists"
|
||||
through measurements telling the CU that one DU is stronger than others.
|
||||
Hence, "forcing" a handover just means that you manually trigger the handover,
|
||||
instead of waiting for UE measurement report.)
|
||||
|
||||
Our CI setup consists of:
|
||||
- 2 USRPs B210 that are synchronized by connecting them to an Octoclock over
|
||||
10MHz refrence and a PPS signal. The RU hosts are synchronized via NTP.
|
||||
- Mini-Circuits RC4DAT-6G-60 programmable attenuator. To control the digital attenuator,
|
||||
a Python script was developed `ci-scripts/attenuatorctl.py`.
|
||||
- Quectel RM520 as a UE.
|
||||
- The setup is run using Docker `ci-scripts/yaml_files/5g_sa_f1_b210_ho`.
|
||||
|
||||
To run the setup using Docker:
|
||||
- We consider 2 synchronized servers. One for each DU.
|
||||
|
||||
## Example neighbour configuration
|
||||
|
||||
@@ -209,70 +238,100 @@ Concretely, the first cell is `12345678` (on DU `[2]`), and it has `11111111`
|
||||
|
||||
The below configuration further enables periodic measurements, A2 event
|
||||
("Serving becomes worse than threshold"), and A3 events ("Neighbour Becomes
|
||||
Better than Serving"). The A2 event can be disabled by setting `enable = 0`. A3
|
||||
events cannot be disabled as of now. Further, the A3 events can be made
|
||||
specific to cells; `cell_id = -1` means "any cell".
|
||||
Better than Serving").
|
||||
The A2 event can be disabled by setting `enable = 0`.
|
||||
The A3 event cannot be disabled as of now. It can be made
|
||||
specific to cells or set to `cell_id = -1` which means "any cell".
|
||||
|
||||
`hysteresis` is a margin added to the serving cell measurements to
|
||||
prevent unnecessary or frequent handovers. It ensures that the neighbouring
|
||||
cell must show sufficiently better signal quality before a handover is
|
||||
triggered. It is an integer between 0 and 30.
|
||||
|
||||
`timeToTrigger` the time during which specific criteria for the event
|
||||
needs to be met in order to trigger a measurement report. It is an enumerated
|
||||
parameter and in the configuration below it is set to 1 which corresponds to
|
||||
`ms40` or 40 milliseconds.
|
||||
|
||||
*Note*: For more information please refer to 3GPP TS 38.331 specifications.
|
||||
```
|
||||
neighbour_list = (
|
||||
{
|
||||
nr_cellid = 12345678;
|
||||
neighbour_cell_configuration = (
|
||||
{
|
||||
gNB_ID = 0xe01;
|
||||
nr_cellid = 11111111;
|
||||
physical_cellId = 1;
|
||||
absoluteFrequencySSB = 643296;
|
||||
subcarrierSpacing = 1; #30 KHz
|
||||
band = 78;
|
||||
plmn = { mcc = 001; mnc = 01; mnc_length = 2};
|
||||
tracking_area_code = 1;
|
||||
}
|
||||
)
|
||||
},
|
||||
{
|
||||
nr_cellid = 11111111;
|
||||
neighbour_cell_configuration = (
|
||||
{
|
||||
gNB_ID = 0xe00;
|
||||
nr_cellid = 12345678;
|
||||
physical_cellId = 0;
|
||||
absoluteFrequencySSB = 643296;
|
||||
subcarrierSpacing = 1; #30 KHz
|
||||
band = 78;
|
||||
plmn = { mcc = 001; mnc = 01; mnc_length = 2};
|
||||
tracking_area_code = 1;
|
||||
}
|
||||
)
|
||||
}
|
||||
);
|
||||
############################################################
|
||||
# gNB-to-gNB neighbour list + measurement configuration #
|
||||
# for the 2-cell rfsim setup (gNB_ID 0xe00 & 0xb00) #
|
||||
############################################################
|
||||
|
||||
neighbour_list = (
|
||||
##########################################################
|
||||
# Entry USED BY gNB_ID = 0xe00 (nr_cellid = 12345678L) #
|
||||
##########################################################
|
||||
{
|
||||
nr_cellid = 12345678; # Serving cell of gNB 0xe00
|
||||
neighbour_cell_configuration = (
|
||||
{
|
||||
gNB_ID = 0xe01;
|
||||
nr_cellid = 11111111; # Cell served by gNB 0xe01
|
||||
physical_cellId = 1;
|
||||
absoluteFrequencySSB = 643296;
|
||||
subcarrierSpacing = 1; # 30 kHz
|
||||
band = 77;
|
||||
plmn = { mcc = 001; mnc = 01; mnc_length = 2 };
|
||||
tracking_area_code = 1;
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
##########################################################
|
||||
# Entry USED BY gNB_ID = 0xe01 (nr_cellid = 11111111) #
|
||||
##########################################################
|
||||
{
|
||||
nr_cellid = 11111111; # Serving cell of gNB 0xe01
|
||||
neighbour_cell_configuration = (
|
||||
{
|
||||
gNB_ID = 0xe00;
|
||||
nr_cellid = 12345678L; # Cell served by gNB 0xe00
|
||||
physical_cellId = 0;
|
||||
absoluteFrequencySSB = 643296;
|
||||
subcarrierSpacing = 1; # 30 kHz
|
||||
band = 77;
|
||||
plmn = { mcc = 001; mnc = 01; mnc_length = 2 };
|
||||
tracking_area_code = 1;
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
############################################################
|
||||
# Common NR measurement-event configuration #
|
||||
############################################################
|
||||
|
||||
nr_measurement_configuration = {
|
||||
Periodical = {
|
||||
enable = 1;
|
||||
includeBeamMeasurements = 1;
|
||||
maxNrofRS_IndexesToReport = 4;
|
||||
enable = 1;
|
||||
includeBeamMeasurements = 1;
|
||||
maxNrofRS_IndexesToReport = 4;
|
||||
};
|
||||
|
||||
A2 = {
|
||||
enable = 1;
|
||||
threshold = 60;
|
||||
enable = 1;
|
||||
threshold = 60;
|
||||
timeToTrigger = 1;
|
||||
};
|
||||
|
||||
A3 = ({
|
||||
cell_id = -1; #Default
|
||||
offset = 10;
|
||||
hysteresis = 0;
|
||||
timeToTrigger = 1
|
||||
})
|
||||
A3 = (
|
||||
{
|
||||
cell_id = -1;
|
||||
offset = 10;
|
||||
hysteresis = 0;
|
||||
timeToTrigger = 1;
|
||||
}
|
||||
)
|
||||
};
|
||||
```
|
||||
|
||||
`@include` this configuration file inside the gNB section of CU file as shown below.
|
||||
|
||||
```
|
||||
plmn_list = ({ mcc = 222; mnc = 01; mnc_length = 2; snssaiList = ({ sst = 1, sd = 0xffffff })});
|
||||
plmn_list = ({ mcc = 001; mnc = 01; mnc_length = 2; snssaiList = ({ sst = 1, sd = 0xffffff })});
|
||||
|
||||
|
||||
@include "neighbour-config.conf"
|
||||
@@ -364,30 +423,37 @@ done
|
||||
|
||||
## Run the setup
|
||||
|
||||
An N2 handover involves the transfer of a UE from one gNB to another via the 5G core network. Unlike F1 handover, where the CU handles the process internally between its DUs, N2 handover requires signaling through the AMF, making it a core-network-based handover.
|
||||
An N2 handover involves the transfer of a UE from one gNB to another via the
|
||||
5G core network. Unlike F1 handover, where the CU handles the process internally
|
||||
between its DUs, N2 handover requires signaling through the AMF, making it
|
||||
a core-network-based handover.
|
||||
|
||||
We assume:
|
||||
|
||||
* Two independent gNBs connected to the same 5GC via N2 interface.
|
||||
* A UE initially connected to gNB-PCI0, which will be handed over to gNB-PCI1.
|
||||
* Handover is triggered by either a decision based measurement event (e.g. A3) or telnet command.
|
||||
* Handover is triggered by either a decision based measurement event (e.g. A3) or
|
||||
telnet command.
|
||||
|
||||
## Steps to run N2 handover with OAI UE
|
||||
|
||||
**Note for same-machine setup:** When running both gNBs on the same machine, you need to assign a unique IP address to the second gNB to avoid network conflicts. For example:
|
||||
**Note for same-machine setup:** When running both gNBs on the same machine,
|
||||
you need to assign a unique IP address to the second gNB to avoid network conflicts.
|
||||
For example:
|
||||
|
||||
```sh
|
||||
sudo ip addr add 192.168.71.180/24 dev rfsim5g-public
|
||||
```
|
||||
|
||||
1. Similarly to F1 handover, UE does not support any measurement reporting and handover is triggered by
|
||||
telnet command. Therefore, ensure that both gNBs and UE are built with telnet support:
|
||||
1. Similarly to F1 handover, UE does not support any measurement reporting and
|
||||
handover is triggered by telnet command. Therefore, ensure that both gNBs and
|
||||
UE are built with telnet support:
|
||||
|
||||
```sh
|
||||
./build_oai --ninja --nrUE --gNB --build-lib telnetsrv
|
||||
```
|
||||
|
||||
Run the 5G Core Network if not already running. See [OAI CN5G tutorial](./NR_SA_Tutorial_OAI_CN5G.md).
|
||||
Run the 5G Core Network if not already running.
|
||||
|
||||
2. Start the source gNB (gNB-PCI0) e.g.
|
||||
|
||||
@@ -409,7 +475,8 @@ Ensure the UE successfully registers with the network.
|
||||
sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.pci1.rfsim.conf --rfsim --telnetsrv --telnetsrv.shrmod ci --gNBs.[0].min_rxtxtime 6 --rfsimulator.serveraddr 127.0.0.1
|
||||
```
|
||||
|
||||
**Note for same-machine setup:** When running both gNBs on the same machine, add the following network interface options to the target gNB command, e.g.:
|
||||
**Note for same-machine setup:** When running both gNBs on the same machine,
|
||||
add the following network interface options to the target gNB command, e.g.:
|
||||
|
||||
```sh
|
||||
--gNBs.[0].NETWORK_INTERFACES.GNB_IPV4_ADDRESS_FOR_NG_AMF 192.168.71.180
|
||||
@@ -423,96 +490,15 @@ From gNB-PCI0, trigger handover on target gNB with PCI 1 for UE ID 1:
|
||||
```sh
|
||||
echo ci trigger_n2_ho 1,1 | nc 127.0.0.1 9090 && echo
|
||||
```
|
||||
where the input parameters correspond to the PCI of the neighbor cell and the RRC ID of the UE.
|
||||
where the input parameters correspond to the PCI of the neighbour cell and the RRC ID of the UE.
|
||||
|
||||
This will initiate the N2 handover on the source gNB.
|
||||
|
||||
## Neighbour list and measurement configuration
|
||||
|
||||
Make sure the configuration file contains a neighbour list and measurement configuration, e.g. [neighbour-config-rfsim.conf](../../ci-scripts/conf_files/neighbour-config.conf). This configuration can also be present in a different file and included in the gNB configuration file with `@include "neighbour-config-rfsim.conf"`.
|
||||
Make sure the configuration file contains a neighbour list and measurement configuration, e.g. [neighbour-config-rfsim.conf](../../ci-scripts/conf_files/neighbour-config.conf).
|
||||
This configuration can also be present in a different file and included in the gNB configuration file with `@include "neighbour-config-rfsim.conf"`.
|
||||
|
||||
For each gNB there is a `neighbour_cell_configuration` linked to its serving cell ID.
|
||||
|
||||
The measurement configuration is based on A2 and A3 measurement events in 5G NR. These events are used by the UE to report radio conditions to the gNB. The A2 Measurement Event indicates that the serving cell’s signal quality has degraded below a defined threshold and the UE shall initiate measurement of neighboring cells. The A3 Measurement Event indicates that a neighboring cell’s signal quality is better than that of the serving cell by a certain offset and the UE shall trigger handover to a stronger neighboring cell
|
||||
|
||||
This is an example with comments on how to use the configuration file:
|
||||
|
||||
```
|
||||
############################################################
|
||||
# gNB-to-gNB neighbour list + measurement configuration #
|
||||
# for the 2-cell rfsim setup (gNB_ID 0xe00 & 0xb00) #
|
||||
############################################################
|
||||
|
||||
neighbour_list = (
|
||||
##########################################################
|
||||
# Entry USED BY gNB_ID = 0xe00 (nr_cellid = 12345678L) #
|
||||
##########################################################
|
||||
{
|
||||
nr_cellid = 12345678L; # Serving cell of gNB 0xe00
|
||||
neighbour_cell_configuration = (
|
||||
{
|
||||
gNB_ID = 0xb00;
|
||||
nr_cellid = 720898; # Cell served by gNB 0xb00
|
||||
physical_cellId = 1;
|
||||
absoluteFrequencySSB= 621312;
|
||||
subcarrierSpacing = 1; # 30 kHz
|
||||
band = 78;
|
||||
plmn = { mcc = 208; mnc = 99; mnc_length = 2 };
|
||||
tracking_area_code = 1;
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
##########################################################
|
||||
# Entry USED BY gNB_ID = 0xb00 (nr_cellid = 720898) #
|
||||
##########################################################
|
||||
{
|
||||
nr_cellid = 720898; # Serving cell of gNB 0xb00
|
||||
neighbour_cell_configuration = (
|
||||
{
|
||||
gNB_ID = 0xe00;
|
||||
nr_cellid = 12345678L; # Cell served by gNB 0xe00
|
||||
physical_cellId = 0;
|
||||
absoluteFrequencySSB= 641280;
|
||||
subcarrierSpacing = 1; # 30 kHz
|
||||
band = 78;
|
||||
plmn = { mcc = 208; mnc = 99; mnc_length = 2 };
|
||||
tracking_area_code = 1;
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
############################################################
|
||||
# Common NR measurement-event configuration #
|
||||
############################################################
|
||||
|
||||
nr_measurement_configuration = {
|
||||
Periodical = {
|
||||
enable = 1;
|
||||
includeBeamMeasurements = 1;
|
||||
maxNrofRS_IndexesToReport = 4;
|
||||
};
|
||||
|
||||
A2 = {
|
||||
enable = 1;
|
||||
threshold = 60;
|
||||
timeToTrigger = 1;
|
||||
};
|
||||
|
||||
A3 = (
|
||||
{
|
||||
cell_id = 720898; # neighbour of gNB 0xe00
|
||||
offset = 10;
|
||||
hysteresis = 0;
|
||||
timeToTrigger = 1;
|
||||
},
|
||||
{
|
||||
cell_id = 12345678; # neighbour of gNB 0xb00
|
||||
offset = 5;
|
||||
hysteresis = 1;
|
||||
timeToTrigger = 2;
|
||||
}
|
||||
);
|
||||
};
|
||||
```
|
||||
See the example above for `neighbour-config-ho.conf`. The same configuration is for both F1 and N2 handover.
|
||||
|
||||
62
doc/nfapi.md
62
doc/nfapi.md
@@ -1,3 +1,5 @@
|
||||
# FAPI/nFAPI split in OAI
|
||||
|
||||
This document describes the SmallCellForum (SCF) (n)FAPI split in 5G, i.e.,
|
||||
between the MAC/L2 and PHY/L1. It also describes how to make use of the
|
||||
multiple transport mechanisms between the 2.
|
||||
@@ -10,7 +12,7 @@ about nFAPI can be found in SCF 225.2.0.
|
||||
|
||||
[[_TOC_]]
|
||||
|
||||
# Quickstart
|
||||
## Quickstart
|
||||
|
||||
Compile OAI as normal. Start the CN and make sure that the VNF configuration
|
||||
matches the PLMN/IP addresses. Then, run the VNF
|
||||
@@ -29,7 +31,7 @@ VNF!)
|
||||
You should not observe a difference between nFAPI split and monolithic.
|
||||
|
||||
|
||||
# Status
|
||||
## Status
|
||||
|
||||
All FAPI message can be transferred between VNF and PNF. This is because OAI
|
||||
uses FAPI with its corresponding messages internally, whether a split is in use
|
||||
@@ -54,7 +56,7 @@ When using RFsim, the system might run slower than in monolithic. This is
|
||||
because the PNF needs to slow down the execution time of a specific slot,
|
||||
because it has to send a Slot.indication to the VNF for scheduling.
|
||||
|
||||
# Configuration
|
||||
## Configuration
|
||||
|
||||
Both PNF and VNF are run through the `nr-softmodem` executable. The type of
|
||||
mode is switched through the `--nfapi` switch, with options `MONOLITHIC`
|
||||
@@ -173,6 +175,26 @@ After installing WLS, you can run the build command as shown below:
|
||||
|
||||
Refer to the above steps in [Quickstart](#quickstart), but run the PNF first as it is the WLS "master".
|
||||
|
||||
To optimize the performance of your setup, you can provide the option
|
||||
`--thread-pool <list of allocated CPUs>` in the PNF command line. This allows
|
||||
you to pin PNF processing threads to specific CPU cores, as they might
|
||||
otherwise interfere with DPDK used by WLS.
|
||||
|
||||
Before selecting which CPU cores to allocate: run `nr-softmodem` without the
|
||||
`--thread-pool` option and use a process monitoring tool such as htop to check
|
||||
CPU availability. Check for lightly loaded cores, and use them in the
|
||||
thread-pool for the PNF.
|
||||
|
||||
Example commands for running an OTA test with USRP B200 on 40MHz:
|
||||
|
||||
Run PNF
|
||||
|
||||
sudo NFAPI_TRACE_LEVEL=info ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-pnf.band78.rfsim.conf --nfapi PNF --continuous-tx -E --thread-pool 1,2,3,4,5
|
||||
|
||||
Run VNF
|
||||
|
||||
sudo NFAPI_TRACE_LEVEL=info ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-vnf.sa.band78.106prb.nfapi.conf --nfapi VNF
|
||||
|
||||
#### How to run OAI PNF with OSC/Radisys O-DU
|
||||
|
||||
Set up the hugepages for DPDK (1GB page size, 6 pages; this only needs to be
|
||||
@@ -194,14 +216,19 @@ Clone the Radisys repository (We're currently using the `oai_integration` branch
|
||||
|
||||
git clone https://gerrit.o-ran-sc.org/r/o-du/l2 -b oai-integration
|
||||
|
||||
Build the O-DU
|
||||
Build the O-DU (More details can be found in O-RAN's documentation page [here](https://docs.o-ran-sc.org/projects/o-ran-sc-o-du-l2/en/latest/user-guide.html#i-execution-on-locally-compiling-o-du-high-source-code))
|
||||
|
||||
cd ~/l2/build/odu
|
||||
make clean_all;make odu PHY=INTEL_L1 MACHINE=BIT64 MODE=TDD;make cu_stub NODE=TEST_STUB MACHINE=BIT64 MODE=TDD;make ric_stub NODE=TEST_STUB MACHINE=BIT64 MODE=TDD
|
||||
|
||||
The O-DU requires some virtual interfaces to be setup in order to enable communication between the O-DU, CU_stub and RIC_stub
|
||||
Setup local interfaces for the cu_stub, ric_stub and o_du
|
||||
The IP addresses shown match the ones specified in OSC ODU configuration file, found in <o-du directory>/build/config/tdd_odu_config.xml
|
||||
The parameters referenced are <DU_IP_V4_ADDR>, <CU_IP_V4_ADDR> and <RIC_IP_V4_ADDR>
|
||||
|
||||
sudo ifconfig enp7s0:ODU "192.168.130.81" && sudo ifconfig enp7s0:CU_STUB "192.168.130.82" && sudo ifconfig enp7s0:RIC_STUB "192.168.130.80"
|
||||
sudo ifconfig <interface name>:ODU "192.168.130.81"
|
||||
sudo ifconfig <interface name>:CU_STUB "192.168.130.82"
|
||||
sudo ifconfig <interface name>:RIC_STUB "192.168.130.80"
|
||||
|
||||
Run cu_stu and ric_stub in separate terminals
|
||||
|
||||
@@ -231,7 +258,7 @@ Run the OAI-UE
|
||||
|
||||
sudo ./nr-uesoftmodem -r 273 --numerology 1 --band 78 -C 3400140000 --ssb 1518 --uicc0.imsi 001010000000001 --rfsim
|
||||
|
||||
# nFAPI logging system
|
||||
## nFAPI logging system
|
||||
|
||||
nFAPI has its own logging system, independent of OAI's. It can be activated by
|
||||
setting the `NFAPI_TRACE_LEVEL` environment variable to an appropriate value;
|
||||
@@ -258,3 +285,26 @@ done over virtual time, i.e., frames/slots as executed by the 5G Systems. For
|
||||
instance, these numbers might be slightly higher or slower in RFsim than in
|
||||
wall-clock time, depending if the system advances faster or slower than
|
||||
wall-clock time.
|
||||
|
||||
## Troubleshoot
|
||||
|
||||
When operating using the FAPI split, the PNF needs to give the VNF extra time
|
||||
to schedule the next slot. Especially since the current nFAPI split still
|
||||
relies on slot indications, extra time due to transport delays need to be
|
||||
accounted for. Currently, this delay is set conservatively, meaning that it
|
||||
should work for most systems, but can create problems during random access:
|
||||
|
||||
[NR_MAC] exceeded RA window: preamble at 411.19 now 413.0 (diff 21), ra_ResponseWindow 5/20 slots
|
||||
[NR_MAC] sfn: 413.0 UE RA-RNTI 010b TC-RNTI 5d82: exceeded RA window, cannot schedule Msg2
|
||||
|
||||
means that the VNF received a preamble (411.19), but the current slot to be
|
||||
scheduled (413.0) is beyond the random access response window (20 slots). In
|
||||
this case, try one of the following:
|
||||
|
||||
- If the radio allows, reduce the L1 TX advance `RUs.[0].sl_ahead` by some
|
||||
slots, but note that this could make the system less stable.
|
||||
- Change the code to reduce `sl_ahead` inside function `handle_nr_slot_ind()`,
|
||||
to reduce the FAPI scheduling slot time budget.
|
||||
- Non-standard: You can manually increase the response window by setting
|
||||
`gNBs.[0].servingCellConfigCommon.[0].ra_ResponseWindow` to, e.g., 6. Note
|
||||
that the maximum allowed response window is 10ms.
|
||||
|
||||
@@ -73,6 +73,10 @@ ENV TINI_VERSION=v0.19.0
|
||||
ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini-${TARGETARCH} /tini
|
||||
RUN chmod +x /tini
|
||||
|
||||
ENV YQ_VERSION=v4.2.0
|
||||
RUN wget https://github.com/mikefarah/yq/releases/download/${YQ_VERSION}/yq_linux_${TARGETARCH} -O /usr/local/bin/yq &&\
|
||||
chmod +x /usr/local/bin/yq
|
||||
|
||||
# In some network environments, GIT proxy is required
|
||||
RUN /bin/bash -c "if [[ -v NEEDED_GIT_PROXY ]]; then git config --global http.proxy $NEEDED_GIT_PROXY; fi"
|
||||
|
||||
|
||||
@@ -66,6 +66,10 @@ ENV TINI_VERSION=v0.19.0
|
||||
ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini-${TARGETARCH} /tini
|
||||
RUN chmod +x /tini
|
||||
|
||||
ENV YQ_VERSION=v4.2.0
|
||||
RUN wget https://github.com/mikefarah/yq/releases/download/${YQ_VERSION}/yq_linux_${TARGETARCH} -O /usr/local/bin/yq &&\
|
||||
chmod +x /usr/local/bin/yq
|
||||
|
||||
# Copying only the needed files to create ran-base
|
||||
WORKDIR /oai-ran/cmake_targets/tools
|
||||
COPY cmake_targets/tools/build_helper \
|
||||
|
||||
@@ -60,6 +60,10 @@ RUN apt-get update && \
|
||||
ENV TINI_VERSION=v0.19.0
|
||||
RUN wget https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini-${TARGETARCH} -O /tini && chmod +x /tini
|
||||
|
||||
ENV YQ_VERSION=v4.2.0
|
||||
RUN wget https://github.com/mikefarah/yq/releases/download/${YQ_VERSION}/yq_linux_${TARGETARCH} -O /usr/local/bin/yq &&\
|
||||
chmod +x /usr/local/bin/yq
|
||||
|
||||
# In some network environments, GIT proxy is required
|
||||
RUN /bin/bash -c "if [[ -v NEEDED_GIT_PROXY ]]; then git config --global http.proxy $NEEDED_GIT_PROXY; fi"
|
||||
|
||||
|
||||
@@ -110,6 +110,8 @@ RUN ldconfig && \
|
||||
/usr/local/lib/libnvipc.so
|
||||
|
||||
WORKDIR /opt/oai-gnb
|
||||
|
||||
COPY --from=ran-build /usr/local/bin/yq /usr/local/bin/yq
|
||||
COPY --from=ran-build /tini /tini
|
||||
ENTRYPOINT ["/tini", "-v", "--", "/opt/oai-gnb/bin/entrypoint.sh"]
|
||||
CMD ["/opt/oai-gnb/bin/nr-softmodem"]
|
||||
|
||||
@@ -101,6 +101,7 @@ RUN ln -s /usr/local/lib/libaw2sori_transpro.so /usr/local/lib/libthirdparty_tra
|
||||
|
||||
WORKDIR /opt/oai-gnb-aw2s
|
||||
|
||||
COPY --from=gnb-base /usr/local/bin/yq /usr/local/bin/yq
|
||||
COPY --from=gnb-base /tini /tini
|
||||
ENTRYPOINT ["/tini", "-v", "--", "/opt/oai-gnb-aw2s/bin/entrypoint.sh"]
|
||||
CMD ["/opt/oai-gnb-aw2s/bin/nr-softmodem"]
|
||||
|
||||
@@ -51,7 +51,8 @@ RUN dnf update -y && \
|
||||
lksctp-tools \
|
||||
tzdata \
|
||||
net-tools \
|
||||
iputils && \
|
||||
iputils \
|
||||
yaml-cpp-devel && \
|
||||
echo "/usr/local/lib" > /etc/ld.so.conf.d/local-lib.conf && \
|
||||
echo "/usr/local/lib64" >> /etc/ld.so.conf.d/local-lib.conf
|
||||
|
||||
@@ -95,6 +96,7 @@ RUN ln -s /usr/local/lib/libaw2sori_transpro.so /usr/local/lib/libthirdparty_tra
|
||||
|
||||
WORKDIR /opt/oai-gnb-aw2s
|
||||
|
||||
COPY --from=gnb-base /usr/local/bin/yq /usr/local/bin/yq
|
||||
COPY --from=gnb-base /tini /tini
|
||||
ENTRYPOINT ["/tini", "-v", "--", "/opt/oai-gnb-aw2s/bin/entrypoint.sh"]
|
||||
CMD ["/opt/oai-gnb-aw2s/bin/nr-softmodem"]
|
||||
|
||||
@@ -95,6 +95,7 @@ RUN /bin/bash -c "ln -s /usr/local/lib/libaw2sori_transpro.so /usr/local/lib/lib
|
||||
|
||||
WORKDIR /opt/oai-gnb-aw2s
|
||||
|
||||
COPY --from=gnb-base /usr/local/bin/yq /usr/local/bin/yq
|
||||
COPY --from=gnb-base /tini /tini
|
||||
ENTRYPOINT ["/tini", "-v", "--", "/opt/oai-gnb-aw2s/bin/entrypoint.sh"]
|
||||
CMD ["/opt/oai-gnb-aw2s/bin/nr-softmodem"]
|
||||
|
||||
@@ -126,6 +126,8 @@ RUN ldconfig && \
|
||||
/opt/phy/fhi_lib/lib/build/libxran.so
|
||||
|
||||
WORKDIR /opt/oai-gnb
|
||||
|
||||
COPY --from=gnb-base /usr/local/bin/yq /usr/local/bin/yq
|
||||
COPY --from=gnb-base /tini /tini
|
||||
ENTRYPOINT ["/tini", "-v", "--", "/opt/oai-gnb/bin/entrypoint.sh"]
|
||||
CMD ["/opt/oai-gnb/bin/nr-softmodem"]
|
||||
|
||||
@@ -49,7 +49,8 @@ RUN dnf update -y && \
|
||||
python3 \
|
||||
python3-pip \
|
||||
net-tools \
|
||||
iputils && \
|
||||
iputils \
|
||||
yaml-cpp-devel && \
|
||||
pip3 install six && \
|
||||
pip3 install requests && \
|
||||
echo "/usr/local/lib" > /etc/ld.so.conf.d/local-lib.conf && \
|
||||
@@ -114,6 +115,8 @@ RUN ldconfig && \
|
||||
/opt/phy/fhi_lib/lib/build/libxran.so
|
||||
|
||||
WORKDIR /opt/oai-gnb
|
||||
|
||||
COPY --from=gnb-base /usr/local/bin/yq /usr/local/bin/yq
|
||||
COPY --from=gnb-base /tini /tini
|
||||
ENTRYPOINT ["/tini", "-v", "--", "/opt/oai-gnb/bin/entrypoint.sh"]
|
||||
CMD ["/opt/oai-gnb/bin/nr-softmodem"]
|
||||
|
||||
@@ -111,6 +111,8 @@ RUN ldconfig && \
|
||||
/opt/phy/fhi_lib/lib/build/libxran.so
|
||||
|
||||
WORKDIR /opt/oai-gnb
|
||||
|
||||
COPY --from=gnb-base /usr/local/bin/yq /usr/local/bin/yq
|
||||
COPY --from=gnb-base /tini /tini
|
||||
ENTRYPOINT ["/tini", "-v", "--", "/opt/oai-gnb/bin/entrypoint.sh"]
|
||||
CMD ["/opt/oai-gnb/bin/nr-softmodem"]
|
||||
|
||||
@@ -130,6 +130,7 @@ WORKDIR /opt/oai-gnb
|
||||
#EXPOSE 50000/udp # IF5 / ORI (control)
|
||||
#EXPOSE 50001/udp # IF5 / ECPRI (data)
|
||||
|
||||
COPY --from=gnb-base /usr/local/bin/yq /usr/local/bin/yq
|
||||
COPY --from=gnb-base /tini /tini
|
||||
ENTRYPOINT ["/tini", "-v", "--", "/opt/oai-gnb/bin/entrypoint.sh"]
|
||||
CMD ["/opt/oai-gnb/bin/nr-softmodem"]
|
||||
|
||||
@@ -47,7 +47,8 @@ RUN dnf update -y && \
|
||||
python3 \
|
||||
python3-pip \
|
||||
net-tools \
|
||||
iputils && \
|
||||
iputils \
|
||||
yaml-cpp-devel && \
|
||||
pip3 install six && \
|
||||
pip3 install requests && \
|
||||
echo "/usr/local/lib" > /etc/ld.so.conf.d/local-lib.conf && \
|
||||
@@ -124,6 +125,7 @@ WORKDIR /opt/oai-gnb
|
||||
#EXPOSE 50000/udp # IF5 / ORI (control)
|
||||
#EXPOSE 50001/udp # IF5 / ECPRI (data)
|
||||
|
||||
COPY --from=gnb-base /usr/local/bin/yq /usr/local/bin/yq
|
||||
COPY --from=gnb-base /tini /tini
|
||||
ENTRYPOINT ["/tini", "-v", "--", "/opt/oai-gnb/bin/entrypoint.sh"]
|
||||
CMD ["/opt/oai-gnb/bin/nr-softmodem"]
|
||||
|
||||
@@ -128,6 +128,7 @@ WORKDIR /opt/oai-gnb
|
||||
#EXPOSE 50000/udp # IF5 / ORI (control)
|
||||
#EXPOSE 50001/udp # IF5 / ECPRI (data)
|
||||
|
||||
COPY --from=gnb-base /usr/local/bin/yq /usr/local/bin/yq
|
||||
COPY --from=gnb-base /tini /tini
|
||||
ENTRYPOINT ["/tini", "-v", "--", "/opt/oai-gnb/bin/entrypoint.sh"]
|
||||
CMD ["/opt/oai-gnb/bin/nr-softmodem"]
|
||||
|
||||
@@ -35,6 +35,9 @@ RUN cp /oai-ran/docker/scripts/gnb_entrypoint.sh /oai-ran/docker/scripts/entrypo
|
||||
FROM registry.access.redhat.com/ubi9/ubi:latest AS oai-nr-cuup
|
||||
ENV TZ=Europe/Paris
|
||||
|
||||
# Install EPEL
|
||||
RUN dnf install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm
|
||||
|
||||
RUN yum repolist --disablerepo=* && \
|
||||
yum update -y && \
|
||||
yum install -y \
|
||||
@@ -42,7 +45,8 @@ RUN yum repolist --disablerepo=* && \
|
||||
lksctp-tools \
|
||||
tzdata \
|
||||
net-tools \
|
||||
iputils && \
|
||||
iputils \
|
||||
yaml-cpp-devel && \
|
||||
echo "/usr/local/lib" > /etc/ld.so.conf.d/local-lib.conf && \
|
||||
echo "/usr/local/lib64" >> /etc/ld.so.conf.d/local-lib.conf
|
||||
|
||||
@@ -55,6 +59,7 @@ COPY --from=gnb-build \
|
||||
COPY --from=gnb-build \
|
||||
/oai-ran/cmake_targets/ran_build/build/libparams_libconfig.so \
|
||||
/oai-ran/cmake_targets/ran_build/build/libtelnetsrv.so \
|
||||
/oai-ran/cmake_targets/ran_build/build/libparams_yaml.so \
|
||||
/usr/local/lib/
|
||||
|
||||
COPY --from=gnb-base \
|
||||
@@ -73,6 +78,7 @@ WORKDIR /opt/oai-gnb/etc
|
||||
|
||||
WORKDIR /opt/oai-gnb
|
||||
|
||||
COPY --from=gnb-base /usr/local/bin/yq /usr/local/bin/yq
|
||||
COPY --from=gnb-base /tini /tini
|
||||
ENTRYPOINT ["/tini", "-v", "--", "/opt/oai-gnb/bin/entrypoint.sh"]
|
||||
CMD ["/opt/oai-gnb/bin/nr-cuup", "-O", "/opt/oai-gnb/etc/gnb.conf"]
|
||||
|
||||
@@ -43,7 +43,8 @@ RUN yum repolist --disablerepo=* && \
|
||||
lksctp-tools \
|
||||
tzdata \
|
||||
net-tools \
|
||||
iputils && \
|
||||
iputils \
|
||||
yaml-cpp-devel && \
|
||||
echo "/usr/local/lib" > /etc/ld.so.conf.d/local-lib.conf && \
|
||||
echo "/usr/local/lib64" >> /etc/ld.so.conf.d/local-lib.conf
|
||||
|
||||
@@ -56,6 +57,7 @@ COPY --from=gnb-build \
|
||||
COPY --from=gnb-build \
|
||||
/oai-ran/cmake_targets/ran_build/build/libparams_libconfig.so \
|
||||
/oai-ran/cmake_targets/ran_build/build/libtelnetsrv.so \
|
||||
/oai-ran/cmake_targets/ran_build/build/libparams_yaml.so \
|
||||
/usr/local/lib/
|
||||
|
||||
COPY --from=gnb-base \
|
||||
@@ -71,6 +73,7 @@ WORKDIR /opt/oai-gnb/etc
|
||||
|
||||
WORKDIR /opt/oai-gnb
|
||||
|
||||
COPY --from=gnb-base /usr/local/bin/yq /usr/local/bin/yq
|
||||
COPY --from=gnb-base /tini /tini
|
||||
ENTRYPOINT ["/tini", "-v", "--", "/opt/oai-gnb/bin/entrypoint.sh"]
|
||||
CMD ["/opt/oai-gnb/bin/nr-cuup", "-O", "/opt/oai-gnb/etc/gnb.conf"]
|
||||
|
||||
@@ -42,7 +42,8 @@ RUN apt-get update && \
|
||||
libconfig9 \
|
||||
iproute2 \
|
||||
net-tools \
|
||||
openssl && \
|
||||
openssl \
|
||||
libyaml-cpp-dev && \
|
||||
# if the --sanitize option was used to build, additional packages are required
|
||||
/bin/bash -c 'if [[ "$BUILD_OPTION" = "--sanitize" ]]; then DEBIAN_FRONTEND=noninteractive apt-get install --yes \
|
||||
libasan8 \
|
||||
@@ -61,6 +62,7 @@ COPY ./docker/scripts/gnb_entrypoint.sh ./entrypoint.sh
|
||||
COPY --from=gnb-build \
|
||||
/oai-ran/cmake_targets/ran_build/build/libparams_libconfig.so \
|
||||
/oai-ran/cmake_targets/ran_build/build/libtelnetsrv.so \
|
||||
/oai-ran/cmake_targets/ran_build/build/libparams_yaml.so \
|
||||
/usr/local/lib/
|
||||
|
||||
RUN ldconfig && ldd /opt/oai-gnb/bin/nr-cuup
|
||||
@@ -69,6 +71,8 @@ RUN ldconfig && ldd /opt/oai-gnb/bin/nr-cuup
|
||||
WORKDIR /opt/oai-gnb/etc
|
||||
|
||||
WORKDIR /opt/oai-gnb
|
||||
|
||||
COPY --from=gnb-base /usr/local/bin/yq /usr/local/bin/yq
|
||||
COPY --from=gnb-base /tini /tini
|
||||
ENTRYPOINT ["/tini", "-v", "--", "/opt/oai-gnb/bin/entrypoint.sh"]
|
||||
CMD ["/opt/oai-gnb/bin/nr-cuup", "-O", "/opt/oai-gnb/etc/gnb.conf"]
|
||||
|
||||
@@ -122,6 +122,8 @@ RUN /bin/bash -c "ln -s /usr/local/lib/liboai_usrpdevif.so /usr/local/lib/liboai
|
||||
/usr/local/lib64/libuhd.so.4.8.0
|
||||
|
||||
WORKDIR /opt/oai-nr-ue
|
||||
|
||||
COPY --from=nr-ue-base /usr/local/bin/yq /usr/local/bin/yq
|
||||
COPY --from=nr-ue-base /tini /tini
|
||||
CMD ["/opt/oai-nr-ue/bin/nr-uesoftmodem"]
|
||||
ENTRYPOINT ["/tini", "-v", "--", "/opt/oai-nr-ue/bin/entrypoint.sh"]
|
||||
|
||||
@@ -48,7 +48,8 @@ RUN dnf update -y && \
|
||||
python3 \
|
||||
python3-pip \
|
||||
libXpm \
|
||||
libX11 && \
|
||||
libX11 \
|
||||
yaml-cpp-devel && \
|
||||
pip3 install six && \
|
||||
pip3 install requests && \
|
||||
echo "/usr/local/lib" > /etc/ld.so.conf.d/local-lib.conf && \
|
||||
@@ -119,6 +120,8 @@ RUN /bin/bash -c "ln -s /usr/local/lib/liboai_usrpdevif.so /usr/local/lib/liboai
|
||||
/usr/local/lib64/libuhd.so.4.8.0
|
||||
|
||||
WORKDIR /opt/oai-nr-ue
|
||||
|
||||
COPY --from=nr-ue-base /usr/local/bin/yq /usr/local/bin/yq
|
||||
COPY --from=nr-ue-base /tini /tini
|
||||
CMD ["/opt/oai-nr-ue/bin/nr-uesoftmodem"]
|
||||
ENTRYPOINT ["/tini", "-v", "--", "/opt/oai-nr-ue/bin/entrypoint.sh"]
|
||||
|
||||
@@ -119,6 +119,8 @@ RUN /bin/bash -c "ln -s /usr/local/lib/liboai_usrpdevif.so /usr/local/lib/liboai
|
||||
/usr/local/lib/libuhd.so.4.8.0
|
||||
|
||||
WORKDIR /opt/oai-nr-ue
|
||||
|
||||
COPY --from=nr-ue-base /usr/local/bin/yq /usr/local/bin/yq
|
||||
COPY --from=nr-ue-base /tini /tini
|
||||
CMD ["/opt/oai-nr-ue/bin/nr-uesoftmodem"]
|
||||
ENTRYPOINT ["/tini", "-v", "--", "/opt/oai-nr-ue/bin/entrypoint.sh"]
|
||||
|
||||
@@ -405,7 +405,6 @@ int main ( int argc, char **argv )
|
||||
#if T_TRACER
|
||||
T_Config_Init();
|
||||
#endif
|
||||
//randominit (0);
|
||||
set_taus_seed (0);
|
||||
printf("configuring for RAU/RRU\n");
|
||||
|
||||
|
||||
@@ -492,7 +492,6 @@ int main( int argc, char **argv ) {
|
||||
#if T_TRACER
|
||||
T_Config_Init();
|
||||
#endif
|
||||
//randominit (0);
|
||||
set_taus_seed (0);
|
||||
cpuf=get_cpu_freq_GHz();
|
||||
pthread_cond_init(&sync_cond,NULL);
|
||||
|
||||
@@ -247,7 +247,7 @@ int connect_rau(RU_t *ru) {
|
||||
void fh_if5_south_out(RU_t *ru, int frame, int slot, uint64_t timestamp) {
|
||||
if (ru == RC.ru[0])
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, ru->proc.timestamp_tx & 0xffffffff);
|
||||
int offset = ru->nr_frame_parms->get_samples_slot_timestamp(slot,ru->nr_frame_parms,0);
|
||||
int offset = get_samples_slot_timestamp(ru->nr_frame_parms, slot);
|
||||
void *buffs[ru->nb_tx];
|
||||
for (int aid = 0; aid < ru->nb_tx; aid++)
|
||||
buffs[aid] = (void*)&ru->common.txdata[aid][offset];
|
||||
@@ -260,15 +260,9 @@ void fh_if5_south_out(RU_t *ru, int frame, int slot, uint64_t timestamp) {
|
||||
timestamp,
|
||||
buffs[0],
|
||||
buffs[1],
|
||||
10 * log10((double)signal_energy(buffs[0], ru->nr_frame_parms->get_samples_per_slot(slot, ru->nr_frame_parms))),
|
||||
10 * log10((double)signal_energy(buffs[0], get_samples_per_slot(slot, ru->nr_frame_parms))),
|
||||
(int)txmeas.tv_nsec);
|
||||
ru->ifdevice.trx_write_func2(&ru->ifdevice,
|
||||
timestamp,
|
||||
buffs,
|
||||
0,
|
||||
ru->nr_frame_parms->get_samples_per_slot(slot,ru->nr_frame_parms),
|
||||
0,
|
||||
ru->nb_tx);
|
||||
ru->ifdevice.trx_write_func2(&ru->ifdevice, timestamp, buffs, 0, get_samples_per_slot(slot, ru->nr_frame_parms), 0, ru->nb_tx);
|
||||
}
|
||||
|
||||
// southbound IF4p5 fronthaul
|
||||
@@ -295,11 +289,11 @@ void fh_if5_south_in(RU_t *ru,
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF5, 1 );
|
||||
start_meas(&ru->rx_fhaul);
|
||||
|
||||
ru->ifdevice.trx_read_func2(&ru->ifdevice, &proc->timestamp_rx, NULL, fp->get_samples_per_slot(*tti, fp));
|
||||
ru->ifdevice.trx_read_func2(&ru->ifdevice, &proc->timestamp_rx, NULL, get_samples_per_slot(*tti, fp));
|
||||
if (proc->first_rx == 1)
|
||||
ru->ts_offset = proc->timestamp_rx;
|
||||
proc->frame_rx = ((proc->timestamp_rx - ru->ts_offset) / (fp->samples_per_subframe * 10)) & 1023;
|
||||
proc->tti_rx = fp->get_slot_from_timestamp(proc->timestamp_rx - ru->ts_offset, fp);
|
||||
proc->tti_rx = get_slot_from_timestamp(proc->timestamp_rx - ru->ts_offset, fp);
|
||||
|
||||
if (proc->first_rx == 0) {
|
||||
if (proc->tti_rx != *tti) {
|
||||
@@ -383,7 +377,7 @@ void fh_if4p5_south_in(RU_t *ru,
|
||||
//caculate timestamp_rx, timestamp_tx based on frame and subframe
|
||||
proc->tti_rx = sl;
|
||||
proc->frame_rx = f;
|
||||
proc->timestamp_rx = (proc->frame_rx * fp->samples_per_subframe * 10) + fp->get_samples_slot_timestamp(proc->tti_rx, fp, 0);
|
||||
proc->timestamp_rx = (proc->frame_rx * fp->samples_per_subframe * 10) + get_samples_slot_timestamp(fp, proc->tti_rx);
|
||||
// proc->timestamp_tx = proc->timestamp_rx + (4*fp->samples_per_subframe);
|
||||
proc->tti_tx = (sl+ru->sl_ahead)%fp->slots_per_frame;
|
||||
proc->frame_tx = (sl > (fp->slots_per_frame - 1 - (ru->sl_ahead))) ? (f + 1) & 1023 : f;
|
||||
@@ -528,7 +522,7 @@ void fh_if4p5_north_asynch_in(RU_t *ru,int *frame,int *slot) {
|
||||
proc->frame_tx_unwrap += 1024;
|
||||
|
||||
proc->timestamp_tx =
|
||||
((uint64_t)frame_tx + proc->frame_tx_unwrap) * fp->samples_per_subframe * 10 + fp->get_samples_slot_timestamp(slot_tx, fp, 0);
|
||||
((uint64_t)frame_tx + proc->frame_tx_unwrap) * fp->samples_per_subframe * 10 + get_samples_slot_timestamp(fp, slot_tx);
|
||||
LOG_D(PHY, "RU %d/%d TST %lu, frame %d, subframe %d\n", ru->idx, 0, proc->timestamp_tx, frame_tx, slot_tx);
|
||||
|
||||
// dump VCD output for first RU in list
|
||||
@@ -566,14 +560,14 @@ static void rx_rf(RU_t *ru, int *frame, int *slot)
|
||||
RU_proc_t *proc = &ru->proc;
|
||||
NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
|
||||
openair0_config_t *cfg = &ru->openair0_cfg;
|
||||
uint32_t samples_per_slot = fp->get_samples_per_slot(*slot, fp);
|
||||
uint32_t samples_per_slot = get_samples_per_slot(*slot, fp);
|
||||
AssertFatal(*slot < fp->slots_per_frame && *slot >= 0, "slot %d is illegal (%d)\n", *slot, fp->slots_per_frame);
|
||||
|
||||
start_meas(&ru->rx_fhaul);
|
||||
int nb = ru->nb_rx * ru->num_beams_period;
|
||||
void *rxp[nb];
|
||||
for (int i = 0; i < nb; i++)
|
||||
rxp[i] = (void *)&ru->common.rxdata[i][fp->get_samples_slot_timestamp(*slot, fp, 0)];
|
||||
rxp[i] = (void *)&ru->common.rxdata[i][get_samples_slot_timestamp(fp, *slot)];
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1);
|
||||
openair0_timestamp old_ts = proc->timestamp_rx;
|
||||
@@ -590,7 +584,7 @@ static void rx_rf(RU_t *ru, int *frame, int *slot)
|
||||
LOG_E(PHY, "rx_rf: Asked for %d samples, got %d from USRP\n", samples_per_slot, rxs);
|
||||
|
||||
if (proc->first_rx != 1) {
|
||||
uint32_t samples_per_slot_prev = fp->get_samples_per_slot((*slot - 1) % fp->slots_per_frame, fp);
|
||||
uint32_t samples_per_slot_prev = get_samples_per_slot((*slot - 1) % fp->slots_per_frame, fp);
|
||||
|
||||
if (proc->timestamp_rx - old_ts != samples_per_slot_prev) {
|
||||
LOG_D(PHY,
|
||||
@@ -609,7 +603,7 @@ static void rx_rf(RU_t *ru, int *frame, int *slot)
|
||||
|
||||
// in fact the following line is the same as long as the timestamp_rx is synchronized to GPS.
|
||||
proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_subframe*10))&1023;
|
||||
proc->tti_rx = fp->get_slot_from_timestamp(proc->timestamp_rx,fp);
|
||||
proc->tti_rx = get_slot_from_timestamp(proc->timestamp_rx, fp);
|
||||
// synchronize first reception to frame 0 subframe 0
|
||||
LOG_D(PHY,
|
||||
"RU %d/%d TS %ld, GPS %f, SR %f, frame %d, slot %d.%d / %d\n",
|
||||
@@ -725,9 +719,9 @@ void tx_rf(RU_t *ru, int frame,int slot, uint64_t timestamp)
|
||||
T_INT(frame),
|
||||
T_INT(slot),
|
||||
T_INT(0),
|
||||
T_BUFFER(&ru->common.txdata[0][fp->get_samples_slot_timestamp(slot, fp, 0)], fp->get_samples_per_slot(slot, fp) * 4));
|
||||
T_BUFFER(&ru->common.txdata[0][get_samples_slot_timestamp(fp, slot)], get_samples_per_slot(slot, fp) * 4));
|
||||
int sf_extension = 0;
|
||||
int siglen=fp->get_samples_per_slot(slot,fp);
|
||||
int siglen = get_samples_per_slot(slot, fp);
|
||||
radio_tx_burst_flag_t flags_burst = TX_BURST_INVALID;
|
||||
radio_tx_gpio_flag_t flags_gpio = 0;
|
||||
|
||||
@@ -786,7 +780,7 @@ void tx_rf(RU_t *ru, int frame,int slot, uint64_t timestamp)
|
||||
int nt = ru->nb_tx * ru->num_beams_period;
|
||||
void *txp[nt];
|
||||
for (int i = 0; i < nt; i++)
|
||||
txp[i] = (void *)&ru->common.txdata[i][fp->get_samples_slot_timestamp(slot, fp, 0)] - sf_extension * sizeof(int32_t);
|
||||
txp[i] = (void *)&ru->common.txdata[i][get_samples_slot_timestamp(fp, slot)] - sf_extension * sizeof(int32_t);
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (timestamp + ru->ts_offset) & 0xffffffff);
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1);
|
||||
@@ -1176,7 +1170,7 @@ void *ru_thread(void *param)
|
||||
}
|
||||
proc->timestamp_tx = proc->timestamp_rx;
|
||||
for (int i = proc->tti_rx; i < proc->tti_rx + ru->sl_ahead; i++)
|
||||
proc->timestamp_tx += fp->get_samples_per_slot(i % fp->slots_per_frame, fp);
|
||||
proc->timestamp_tx += get_samples_per_slot(i % fp->slots_per_frame, fp);
|
||||
proc->tti_tx = (proc->tti_rx + ru->sl_ahead) % fp->slots_per_frame;
|
||||
proc->frame_tx = proc->tti_rx > proc->tti_tx ? (proc->frame_rx + 1) & 1023 : proc->frame_rx;
|
||||
LOG_D(PHY,
|
||||
|
||||
@@ -546,7 +546,6 @@ int main( int argc, char **argv ) {
|
||||
#if T_TRACER
|
||||
T_Config_Init();
|
||||
#endif
|
||||
//randominit (0);
|
||||
set_taus_seed (0);
|
||||
|
||||
cpuf=get_cpu_freq_GHz();
|
||||
@@ -720,6 +719,8 @@ int main( int argc, char **argv ) {
|
||||
itti_wait_tasks_end(NULL);
|
||||
printf("Returned from ITTI signal handler\n");
|
||||
|
||||
nfapi_stop_l1();
|
||||
|
||||
if (RC.nb_nr_L1_inst > 0 || RC.nb_RU > 0)
|
||||
stop_L1(0);
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#include "PHY/defs_nr_common.h"
|
||||
#define _GNU_SOURCE // For pthread_setname_np
|
||||
#include <pthread.h>
|
||||
#include <openair1/PHY/impl_defs_top.h>
|
||||
@@ -383,7 +384,7 @@ static void RU_write(nr_rxtx_thread_data_t *rxtxD, bool sl_tx_action, c16_t **tx
|
||||
openair0_timestamp writeTimestamp = proc->timestamp_tx;
|
||||
int writeBlockSize = rxtxD->writeBlockSize;
|
||||
// if writeBlockSize gets longer that slot size, fill with dummy
|
||||
const int maxWriteBlockSize = fp->get_samples_per_slot(proc->nr_slot_tx, fp);
|
||||
const int maxWriteBlockSize = get_samples_per_slot(proc->nr_slot_tx, fp);
|
||||
while (writeBlockSize > maxWriteBlockSize) {
|
||||
const int dummyBlockSize = min(writeBlockSize - maxWriteBlockSize, maxWriteBlockSize);
|
||||
int tmp = openair0_write_reorder(&UE->rfdevice, writeTimestamp, (void **)txp, dummyBlockSize, fp->nb_antennas_tx, flags);
|
||||
@@ -423,7 +424,7 @@ void processSlotTX(void *arg)
|
||||
NR_DL_FRAME_PARMS *fp = &UE->frame_parms;
|
||||
c16_t *txp[fp->nb_antennas_tx];
|
||||
for (int i = 0; i < fp->nb_antennas_tx; i++) {
|
||||
txp[i] = UE->common_vars.txData[i] + fp->get_samples_slot_timestamp(proc->nr_slot_tx, fp, 0);
|
||||
txp[i] = UE->common_vars.txData[i] + get_samples_slot_timestamp(fp, proc->nr_slot_tx);
|
||||
}
|
||||
|
||||
if (proc->tx_slot_type == NR_UPLINK_SLOT || proc->tx_slot_type == NR_MIXED_SLOT) {
|
||||
@@ -434,8 +435,10 @@ void processSlotTX(void *arg)
|
||||
nr_sidelink_indication_t sl_indication = {.module_id = UE->Mod_id,
|
||||
.gNB_index = proc->gNB_id,
|
||||
.cc_id = UE->CC_id,
|
||||
.hfn_tx = proc->hfn_tx,
|
||||
.frame_tx = proc->frame_tx,
|
||||
.slot_tx = proc->nr_slot_tx,
|
||||
.hfn_rx = proc->hfn_rx,
|
||||
.frame_rx = proc->frame_rx,
|
||||
.slot_rx = proc->nr_slot_rx,
|
||||
.slot_type = SIDELINK_SLOT_TYPE_TX,
|
||||
@@ -654,24 +657,25 @@ void readFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp, int duration_r
|
||||
void *rxp[NB_ANTENNAS_RX];
|
||||
if (toTrash)
|
||||
for (int i = 0; i < fp->nb_antennas_rx; i++)
|
||||
rxp[i] = malloc16(fp->get_samples_per_slot(0, fp) * 4);
|
||||
rxp[i] = malloc16(get_samples_per_slot(0, fp) * 4);
|
||||
|
||||
for (int x = 0; x < num_frames * NR_NUMBER_OF_SUBFRAMES_PER_FRAME; x++) { // two frames for initial sync
|
||||
for (int slot = 0; slot < fp->slots_per_subframe; slot++) {
|
||||
if (!toTrash)
|
||||
for (int i = 0; i < fp->nb_antennas_rx; i++)
|
||||
rxp[i] = ((void *)&UE->common_vars.rxdata[i][0])
|
||||
+ 4 * ((x * fp->samples_per_subframe) + fp->get_samples_slot_timestamp(slot, fp, 0));
|
||||
rxp[i] =
|
||||
((void *)&UE->common_vars.rxdata[i][0]) + 4 * ((x * fp->samples_per_subframe) + get_samples_slot_timestamp(fp, slot));
|
||||
|
||||
int read_block_size = fp->get_samples_per_slot(slot, fp);
|
||||
int read_block_size = get_samples_per_slot(slot, fp);
|
||||
int tmp = UE->rfdevice.trx_read_func(&UE->rfdevice, timestamp, rxp, read_block_size, fp->nb_antennas_rx);
|
||||
UEscopeCopy(UE, ueTimeDomainSamplesBeforeSync, rxp[0], sizeof(c16_t), 1, read_block_size, 0);
|
||||
AssertFatal(read_block_size == tmp, "");
|
||||
|
||||
if (IS_SOFTMODEM_RFSIM) {
|
||||
int ta = UE->timing_advance + UE->timing_advance_ntn;
|
||||
const openair0_timestamp writeTimestamp =
|
||||
*timestamp + fp->get_samples_slot_timestamp(slot, fp, duration_rx_to_tx) - UE->N_TA_offset - UE->timing_advance;
|
||||
dummyWrite(UE, writeTimestamp, fp->get_samples_per_slot(slot, fp));
|
||||
*timestamp + get_samples_slot_duration(fp, slot, duration_rx_to_tx) - UE->N_TA_offset - ta;
|
||||
dummyWrite(UE, writeTimestamp, get_samples_per_slot(slot, fp));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -692,12 +696,13 @@ static void syncInFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp, int d
|
||||
int slot = 0;
|
||||
int size = rx_offset;
|
||||
while (size > 0) {
|
||||
const int unitTransfer = min(fp->get_samples_per_slot(slot, fp), size);
|
||||
const int unitTransfer = min(get_samples_per_slot(slot, fp), size);
|
||||
const int res = UE->rfdevice.trx_read_func(&UE->rfdevice, timestamp, (void **)UE->common_vars.rxdata, unitTransfer, fp->nb_antennas_rx);
|
||||
DevAssert(unitTransfer == res);
|
||||
if (IS_SOFTMODEM_RFSIM) {
|
||||
int ta = UE->timing_advance + UE->timing_advance_ntn;
|
||||
const openair0_timestamp writeTimestamp =
|
||||
*timestamp + fp->get_samples_slot_timestamp(slot, fp, duration_rx_to_tx) - UE->N_TA_offset - UE->timing_advance;
|
||||
*timestamp + get_samples_slot_duration(fp, slot, duration_rx_to_tx) - UE->N_TA_offset - ta;
|
||||
dummyWrite(UE, writeTimestamp, unitTransfer);
|
||||
}
|
||||
slot = (slot + 1) % fp->slots_per_subframe;
|
||||
@@ -706,23 +711,72 @@ static void syncInFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp, int d
|
||||
}
|
||||
|
||||
static inline int get_firstSymSamp(uint16_t slot, NR_DL_FRAME_PARMS *fp) {
|
||||
if (fp->numerology_index == 0)
|
||||
return fp->nb_prefix_samples0 + fp->ofdm_symbol_size;
|
||||
int num_samples = (slot%(fp->slots_per_subframe/2)) ? fp->nb_prefix_samples : fp->nb_prefix_samples0;
|
||||
num_samples += fp->ofdm_symbol_size;
|
||||
return num_samples;
|
||||
return get_samples_symbol_duration(fp, slot, 0, 1);
|
||||
}
|
||||
|
||||
static inline int get_readBlockSize(uint16_t slot, NR_DL_FRAME_PARMS *fp) {
|
||||
int rem_samples = fp->get_samples_per_slot(slot, fp) - get_firstSymSamp(slot, fp);
|
||||
int rem_samples = get_samples_per_slot(slot, fp) - get_firstSymSamp(slot, fp);
|
||||
int next_slot_first_symbol = 0;
|
||||
if (slot < (fp->slots_per_frame-1))
|
||||
next_slot_first_symbol = get_firstSymSamp(slot+1, fp);
|
||||
return rem_samples + next_slot_first_symbol;
|
||||
}
|
||||
|
||||
#define SPEED_OF_LIGHT 299792458
|
||||
static inline void apply_ntn_timing_advance(PHY_VARS_NR_UE *UE, const NR_DL_FRAME_PARMS *fp, int abs_subframe_tx)
|
||||
{
|
||||
const fapi_nr_dl_ntn_config_command_pdu *ntn_config_params = &UE->ntn_config_message->ntn_config_params;
|
||||
|
||||
const int abs_subframe_epoch = ntn_config_params->epoch_subframe
|
||||
+ ntn_config_params->epoch_sfn * 10
|
||||
+ ntn_config_params->epoch_hfn * 10240;
|
||||
const int ms_since_epoch = abs_subframe_tx - abs_subframe_epoch;
|
||||
|
||||
const double omega = ntn_config_params->omega;
|
||||
const double cos_wt = cos(omega * ms_since_epoch);
|
||||
const double sin_wt = sin(omega * ms_since_epoch);
|
||||
|
||||
const position_t pos_sat_0 = ntn_config_params->pos_sat_0;
|
||||
const position_t pos_sat_90 = ntn_config_params->pos_sat_90;
|
||||
const position_t pos_sat = {pos_sat_0.X * cos_wt + pos_sat_90.X * sin_wt,
|
||||
pos_sat_0.Y * cos_wt + pos_sat_90.Y * sin_wt,
|
||||
pos_sat_0.Z * cos_wt + pos_sat_90.Z * sin_wt};
|
||||
|
||||
position_t pos_ue = {0};
|
||||
get_position_coordinates(UE->Mod_id, &pos_ue);
|
||||
|
||||
// calculate directional vector from SAT to UE
|
||||
const position_t dir_sat_ue = {pos_ue.X - pos_sat.X, pos_ue.Y - pos_sat.Y, pos_ue.Z - pos_sat.Z};
|
||||
|
||||
// calculate distance between SAT and UE
|
||||
const double distance = sqrt(dir_sat_ue.X * dir_sat_ue.X + dir_sat_ue.Y * dir_sat_ue.Y + dir_sat_ue.Z * dir_sat_ue.Z);
|
||||
|
||||
// calculate round-trip-time (factor 2) between SAT and UE in ms (factor 1000)
|
||||
const double N_UE_TA_adj = 2000 * distance / SPEED_OF_LIGHT;
|
||||
|
||||
const double N_common_ta_adj = ntn_config_params->N_common_ta_adj;
|
||||
const double N_common_ta_drift = ntn_config_params->N_common_ta_drift;
|
||||
const double N_common_ta_drift_variant = ntn_config_params->N_common_ta_drift_variant;
|
||||
|
||||
UE->timing_advance_ntn = (N_UE_TA_adj + N_common_ta_adj
|
||||
+ N_common_ta_drift * ms_since_epoch / 1e6
|
||||
+ N_common_ta_drift_variant * ((int64_t)ms_since_epoch * ms_since_epoch) / 1e9)
|
||||
* fp->samples_per_subframe;
|
||||
|
||||
LOG_D(PHY,
|
||||
"N_UE_TA_adj = %f ms, N_common_ta_adj = %f ms, N_common_ta_drift = %f µs/s, N_common_ta_drift_variant = %f µs/s², ms_since_epoch = %d ms, "
|
||||
"computed timing_advance_ntn = %d samples\n",
|
||||
N_UE_TA_adj,
|
||||
N_common_ta_adj,
|
||||
N_common_ta_drift,
|
||||
N_common_ta_drift_variant,
|
||||
ms_since_epoch,
|
||||
UE->timing_advance_ntn);
|
||||
}
|
||||
|
||||
static inline void apply_ntn_config(PHY_VARS_NR_UE *UE,
|
||||
NR_DL_FRAME_PARMS *fp,
|
||||
int hfn_rx,
|
||||
int frame_rx,
|
||||
int slot_rx,
|
||||
int *duration_rx_to_tx,
|
||||
@@ -737,39 +791,13 @@ static inline void apply_ntn_config(PHY_VARS_NR_UE *UE,
|
||||
|
||||
*duration_rx_to_tx = NR_UE_CAPABILITY_SLOT_RX_TO_TX + (koffset << mu);
|
||||
if (koffset > *ntn_koffset)
|
||||
*timing_advance += fp->get_samples_slot_timestamp(slot_rx, fp, (koffset - *ntn_koffset) << mu);
|
||||
*timing_advance += get_samples_slot_duration(fp, slot_rx, (koffset - *ntn_koffset) << mu);
|
||||
else if (koffset < *ntn_koffset)
|
||||
*timing_advance -= fp->get_samples_slot_timestamp(slot_rx, fp, (*ntn_koffset - koffset) << mu);
|
||||
*timing_advance -= get_samples_slot_duration(fp, slot_rx, (*ntn_koffset - koffset) << mu);
|
||||
*ntn_koffset = koffset;
|
||||
|
||||
const int abs_subframe_tx = 10 * frame_rx + ((slot_rx + *duration_rx_to_tx) >> mu);
|
||||
const int abs_subframe_epoch =
|
||||
10 * UE->ntn_config_message->ntn_config_params.epoch_sfn + UE->ntn_config_message->ntn_config_params.epoch_subframe;
|
||||
int ms_since_epoch = abs_subframe_tx - abs_subframe_epoch;
|
||||
// cope with sfn wrap-around
|
||||
// this currently limits us to epoch times that are not more than 5.12 seconds in the future (allowed are up to 10.24 seconds)
|
||||
// and ntn-UlSyncValidityDuration < 5.12 seconds (allowed are up to 900 seconds)
|
||||
// TODO: fix this limitation by introducing the hyper frame number HFN
|
||||
if (ms_since_epoch < -5120)
|
||||
ms_since_epoch += 10240;
|
||||
else if (ms_since_epoch > 5120)
|
||||
ms_since_epoch -= 10240;
|
||||
|
||||
const double total_ta_ms = UE->ntn_config_message->ntn_config_params.ntn_total_time_advance_ms;
|
||||
const double total_ta_drift = UE->ntn_config_message->ntn_config_params.ntn_total_time_advance_drift; // µs/s
|
||||
const double total_ta_drift_variant = UE->ntn_config_message->ntn_config_params.ntn_total_time_advance_drift_variant; // µs/s²
|
||||
UE->timing_advance = fp->samples_per_subframe * (total_ta_ms + (total_ta_drift / 1000.0) * (ms_since_epoch / 1000.0) + (total_ta_drift_variant / 1000.0) * (ms_since_epoch / 1000.0) * (ms_since_epoch / 1000.0));
|
||||
|
||||
LOG_I(PHY,
|
||||
"k_offset = %d ms (%d slots), total_ta_ms = %f ms, total_ta_drift = %f µs/s, total_ta_drift_variant = %f µs/s², ms_since_epoch = %d ms, computed "
|
||||
"timing_advance = %d samples\n",
|
||||
*ntn_koffset,
|
||||
*ntn_koffset << mu,
|
||||
total_ta_ms,
|
||||
total_ta_drift,
|
||||
total_ta_drift_variant,
|
||||
ms_since_epoch,
|
||||
UE->timing_advance);
|
||||
const int abs_subframe_tx = 10240 * hfn_rx + 10 * frame_rx + ((slot_rx + *duration_rx_to_tx) >> mu);
|
||||
apply_ntn_timing_advance(UE, fp, abs_subframe_tx);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -809,7 +837,7 @@ void *UE_thread(void *arg)
|
||||
int ntn_koffset = 0;
|
||||
|
||||
int duration_rx_to_tx = NR_UE_CAPABILITY_SLOT_RX_TO_TX;
|
||||
int timing_advance = UE->timing_advance;
|
||||
int timing_advance = UE->timing_advance + UE->timing_advance_ntn;
|
||||
UE->N_TA_offset = determine_N_TA_offset(UE);
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(UE->Mod_id);
|
||||
|
||||
@@ -968,6 +996,8 @@ void *UE_thread(void *arg)
|
||||
curMsg.proc.nr_slot_tx = (absolute_slot + duration_rx_to_tx) % nb_slot_frame;
|
||||
curMsg.proc.frame_rx = (absolute_slot / nb_slot_frame) % MAX_FRAME_NUMBER;
|
||||
curMsg.proc.frame_tx = ((absolute_slot + duration_rx_to_tx) / nb_slot_frame) % MAX_FRAME_NUMBER;
|
||||
curMsg.proc.hfn_rx = (absolute_slot / nb_slot_frame) / MAX_FRAME_NUMBER;
|
||||
curMsg.proc.hfn_tx = ((absolute_slot + duration_rx_to_tx) / nb_slot_frame) / MAX_FRAME_NUMBER;
|
||||
if (UE->received_config_request) {
|
||||
if (UE->sl_mode) {
|
||||
curMsg.proc.rx_slot_type = sl_nr_ue_slot_select(sl_cfg, curMsg.proc.nr_slot_rx, TDD);
|
||||
@@ -984,18 +1014,24 @@ void *UE_thread(void *arg)
|
||||
|
||||
int firstSymSamp = get_firstSymSamp(slot_nr, fp);
|
||||
for (int i = 0; i < fp->nb_antennas_rx; i++)
|
||||
rxp[i] = (void *)&UE->common_vars.rxdata[i][firstSymSamp + fp->get_samples_slot_timestamp(slot_nr, fp, 0)];
|
||||
rxp[i] = (void *)&UE->common_vars.rxdata[i][firstSymSamp + get_samples_slot_timestamp(fp, slot_nr)];
|
||||
|
||||
int iq_shift_to_apply = 0;
|
||||
if (slot_nr == nb_slot_frame - 1) {
|
||||
// we shift of half of measured drift, at each beginning of frame for both rx and tx
|
||||
iq_shift_to_apply = shiftForNextFrame;
|
||||
// TODO: remove this autonomous TA and use up-to-date values of ta-Common, ta-CommonDrift and ta-CommonDriftVariant from received SIB19 instead
|
||||
if (get_nrUE_params()->autonomous_ta)
|
||||
UE->timing_advance -= 2 * shiftForNextFrame;
|
||||
// autonomous timing advance calculation, which does not use SIB19 information
|
||||
if (ntn_koffset && get_nrUE_params()->autonomous_ta)
|
||||
UE->timing_advance_ntn -= 2 * shiftForNextFrame;
|
||||
shiftForNextFrame = -round(UE->max_pos_acc * get_nrUE_params()->time_sync_I);
|
||||
}
|
||||
|
||||
// Calculate new TA based on SIB19 information for each subframe in NTN mode, if "autonomous_ta" is not enabled
|
||||
if (ntn_koffset && !get_nrUE_params()->autonomous_ta && (absolute_slot + duration_rx_to_tx) % fp->slots_per_subframe == 0) {
|
||||
const int abs_subframe_tx = (absolute_slot + duration_rx_to_tx) / fp->slots_per_subframe;
|
||||
apply_ntn_timing_advance(UE, fp, abs_subframe_tx);
|
||||
}
|
||||
|
||||
const int readBlockSize = get_readBlockSize(slot_nr, fp) - iq_shift_to_apply;
|
||||
openair0_timestamp rx_timestamp;
|
||||
int tmp = UE->rfdevice.trx_read_func(&UE->rfdevice, &rx_timestamp, rxp, readBlockSize, fp->nb_antennas_rx);
|
||||
@@ -1025,8 +1061,8 @@ void *UE_thread(void *arg)
|
||||
}
|
||||
|
||||
// use previous timing_advance value to compute writeTimestamp
|
||||
const openair0_timestamp writeTimestamp = rx_timestamp + fp->get_samples_slot_timestamp(slot_nr, fp, duration_rx_to_tx)
|
||||
- firstSymSamp - UE->N_TA_offset - timing_advance;
|
||||
const openair0_timestamp writeTimestamp =
|
||||
rx_timestamp + get_samples_slot_duration(fp, slot_nr, duration_rx_to_tx) - firstSymSamp - UE->N_TA_offset - timing_advance;
|
||||
|
||||
// Calculate TX deadline, approximately 1 symbol before the first sample should be written
|
||||
const uint64_t samples_diff = writeTimestamp - rx_timestamp - fp->ofdm_symbol_size;
|
||||
@@ -1034,8 +1070,8 @@ void *UE_thread(void *arg)
|
||||
const uint64_t absolute_deadline_us = current_time.tv_sec * 1e6 + current_time.tv_nsec / 1e3 + deadline_us;
|
||||
|
||||
// but use current UE->timing_advance value to compute writeBlockSize
|
||||
int writeBlockSize = fp->get_samples_per_slot((slot_nr + duration_rx_to_tx) % nb_slot_frame, fp) - iq_shift_to_apply;
|
||||
int new_timing_advance = UE->timing_advance;
|
||||
int writeBlockSize = get_samples_per_slot((slot_nr + duration_rx_to_tx) % nb_slot_frame, fp) - iq_shift_to_apply;
|
||||
int new_timing_advance = UE->timing_advance + UE->timing_advance_ntn;
|
||||
if (new_timing_advance != timing_advance) {
|
||||
writeBlockSize -= new_timing_advance - timing_advance;
|
||||
timing_advance = new_timing_advance;
|
||||
@@ -1048,7 +1084,7 @@ void *UE_thread(void *arg)
|
||||
}
|
||||
|
||||
if (curMsg.proc.nr_slot_rx == 0)
|
||||
nr_ue_rrc_timer_trigger(UE->Mod_id, curMsg.proc.frame_rx, curMsg.proc.gNB_id);
|
||||
nr_ue_rrc_timer_trigger(UE->Mod_id, curMsg.proc.hfn_rx, curMsg.proc.frame_rx, curMsg.proc.gNB_id);
|
||||
|
||||
// RX slot processing. We launch and forget.
|
||||
notifiedFIFO_elt_t *newRx = newNotifiedFIFO_elt(sizeof(nr_rxtx_thread_data_t), curMsg.proc.nr_slot_tx, NULL, UE_dl_processing);
|
||||
@@ -1064,7 +1100,7 @@ void *UE_thread(void *arg)
|
||||
}
|
||||
|
||||
// apply new NTN timing information
|
||||
apply_ntn_config(UE, fp, curMsg.proc.frame_rx, curMsg.proc.nr_slot_rx, &duration_rx_to_tx, &timing_advance, &ntn_koffset);
|
||||
apply_ntn_config(UE, fp, curMsg.proc.hfn_rx, curMsg.proc.frame_rx, curMsg.proc.nr_slot_rx, &duration_rx_to_tx, &timing_advance, &ntn_koffset);
|
||||
|
||||
// Start TX slot processing here. It runs in parallel with RX slot processing
|
||||
// in current code, DURATION_RX_TO_TX constant is the limit to get UL data to encode from a RX slot
|
||||
|
||||
@@ -340,7 +340,6 @@ int main(int argc, char **argv)
|
||||
T_Config_Init();
|
||||
#endif
|
||||
initTpool(get_softmodem_params()->threadPoolConfig, &(nrUE_params.Tpool), cpumeas(CPUMEAS_GETSTATE));
|
||||
//randominit (0);
|
||||
set_taus_seed (0);
|
||||
|
||||
if (!has_cap_sys_nice())
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
*/
|
||||
|
||||
#include "position_interface.h"
|
||||
#include "executables/nr-uesoftmodem.h"
|
||||
|
||||
static void read_position_coordinates(char *sectionName, position_t *position)
|
||||
{
|
||||
|
||||
@@ -22,11 +22,6 @@
|
||||
#ifndef __POSITION_INTERFACE__H__
|
||||
#define __POSITION_INTERFACE__H__
|
||||
|
||||
#include <executables/nr-softmodem-common.h>
|
||||
#include <executables/softmodem-common.h>
|
||||
#include "PHY/defs_nr_UE.h"
|
||||
#include "executables/nr-uesoftmodem.h"
|
||||
|
||||
/* position configuration parameters name */
|
||||
#define CONFIG_STRING_POSITION_X "x"
|
||||
#define CONFIG_STRING_POSITION_Y "y"
|
||||
|
||||
@@ -63,12 +63,20 @@ char cpu_buf_recv[RECV_BUF_LEN];
|
||||
|
||||
uint16_t sfn = 0, slot = 0;
|
||||
nv_ipc_t *ipc;
|
||||
nfapi_vnf_config_t *vnf_config = 0;
|
||||
|
||||
void set_config(nfapi_vnf_config_t *conf)
|
||||
void nvIPC_Stop()
|
||||
{
|
||||
vnf_config = conf;
|
||||
LOG_I(NR_MAC, "Received STOP.indication\n");
|
||||
((vnf_t *)get_config())->terminate = true;
|
||||
}
|
||||
|
||||
void nvIPC_send_stop_request()
|
||||
{
|
||||
nfapi_nr_stop_request_scf_t req = {.header.message_id = NFAPI_NR_PHY_MSG_TYPE_STOP_REQUEST, .header.phy_id = 0};
|
||||
LOG_I(NR_MAC, "Sending NFAPI STOP.request\n");
|
||||
nfapi_nr_vnf_stop_req(get_config(), get_config()->pnf_list->p5_idx, &req);
|
||||
}
|
||||
|
||||
|
||||
static uint16_t old_sfn = 0;
|
||||
static uint16_t old_slot = 0;
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
@@ -84,6 +92,7 @@ static int ipc_handle_rx_msg(nv_ipc_t *ipc, nv_ipc_msg_t *msg)
|
||||
uint8_t *end = msg->msg_buf + msg->msg_len;
|
||||
|
||||
// unpack FAPI messages and handle them
|
||||
nfapi_vnf_config_t * vnf_config = get_config();
|
||||
if (vnf_config != 0) {
|
||||
// first, unpack the header
|
||||
fapi_phy_api_msg fapi_msg;
|
||||
@@ -479,7 +488,6 @@ static int aerial_recv_msg(nv_ipc_t *ipc, nv_ipc_msg_t *recv_msg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool recv_task_running = false;
|
||||
void *epoll_recv_task(void *arg)
|
||||
{
|
||||
struct epoll_event ev, events[MAX_EVENTS];
|
||||
@@ -497,11 +505,12 @@ void *epoll_recv_task(void *arg)
|
||||
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, ev.data.fd, &ev) == -1) {
|
||||
LOG_E(NFAPI_VNF, "%s epoll_ctl failed\n", __func__);
|
||||
}
|
||||
|
||||
while (1) {
|
||||
if (!recv_task_running) {
|
||||
recv_task_running = true;
|
||||
}
|
||||
// From here on out the thread is ready to receive data, simulate the reception
|
||||
// of a PARAM.response to get the VNF to send a CONFIG.request
|
||||
nfapi_nr_param_response_scf_t resp_msg = {.header.message_id = NFAPI_NR_PHY_MSG_TYPE_PARAM_RESPONSE};
|
||||
nfapi_vnf_config_t * vnf_config = get_config();
|
||||
vnf_config->nr_param_resp(vnf_config, 1, &resp_msg);
|
||||
while (((vnf_t *)vnf_config)->terminate == false) {
|
||||
LOG_D(NFAPI_VNF, "%s: epoll_wait fd_rx=%d ...\n", __func__, ipc_rx_event_fd);
|
||||
|
||||
int nfds;
|
||||
@@ -524,6 +533,7 @@ void *epoll_recv_task(void *arg)
|
||||
}
|
||||
}
|
||||
close(epoll_fd);
|
||||
ipc->ipc_destroy(ipc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -568,21 +578,18 @@ int nvIPC_Init(nvipc_params_t nvipc_params_s)
|
||||
LOG_I(NFAPI_VNF, "%s: create IPC interface successful\n", __func__);
|
||||
sleep(1);
|
||||
create_recv_thread(nvipc_params_s.nvipc_poll_core);
|
||||
while(!recv_task_running){usleep(100000);}
|
||||
nfapi_nr_param_response_scf_t resp_msg;
|
||||
vnf_config->nr_param_resp(vnf_config, 1, &resp_msg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int oai_fapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req)
|
||||
{
|
||||
nfapi_vnf_p7_config_t *p7_config = (((vnf_info *)vnf_config->user_data)->p7_vnfs[0].config);
|
||||
nfapi_vnf_p7_config_t *p7_config = get_p7_vnf_config();
|
||||
|
||||
ul_tti_req->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!!
|
||||
ul_tti_req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST;
|
||||
|
||||
// int retval = nfapi_vnf_p7_ul_tti_req(p7_config, ul_tti_req);
|
||||
int retval = p7_config->send_p7_msg((vnf_p7_t *)p7_config, &ul_tti_req->header);
|
||||
int retval = p7_config->send_p7_msg(get_p7_vnf(), &ul_tti_req->header);
|
||||
|
||||
if (retval != 0) {
|
||||
LOG_E(PHY, "%s() Problem sending retval:%d\n", __FUNCTION__, retval);
|
||||
@@ -598,11 +605,11 @@ int oai_fapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req)
|
||||
|
||||
int oai_fapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req)
|
||||
{
|
||||
nfapi_vnf_p7_config_t *p7_config = (((vnf_info *)vnf_config->user_data)->p7_vnfs[0].config);
|
||||
nfapi_vnf_p7_config_t *p7_config = get_p7_vnf_config();
|
||||
ul_dci_req->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!!
|
||||
ul_dci_req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST;
|
||||
// int retval = nfapi_vnf_p7_ul_dci_req(p7_config, ul_dci_req);
|
||||
int retval = p7_config->send_p7_msg((vnf_p7_t *)p7_config, &ul_dci_req->header);
|
||||
int retval = p7_config->send_p7_msg(get_p7_vnf(), &ul_dci_req->header);
|
||||
if (retval != 0) {
|
||||
LOG_E(PHY, "%s() Problem sending retval:%d\n", __FUNCTION__, retval);
|
||||
} else {
|
||||
@@ -613,12 +620,12 @@ int oai_fapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req)
|
||||
|
||||
int oai_fapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req)
|
||||
{
|
||||
nfapi_vnf_p7_config_t *p7_config = (((vnf_info *)vnf_config->user_data)->p7_vnfs[0].config);
|
||||
nfapi_vnf_p7_config_t *p7_config = get_p7_vnf_config();
|
||||
tx_data_req->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!!
|
||||
tx_data_req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST;
|
||||
// LOG_D(PHY, "[VNF] %s() TX_REQ sfn_sf:%d number_of_pdus:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(tx_data_req->SFN),
|
||||
// tx_data_req->Number_of_PDUs); int retval = nfapi_vnf_p7_tx_data_req(p7_config, tx_data_req);
|
||||
int retval = p7_config->send_p7_msg((vnf_p7_t *)p7_config, &tx_data_req->header);
|
||||
int retval = p7_config->send_p7_msg(get_p7_vnf(), &tx_data_req->header);
|
||||
if (retval != 0) {
|
||||
LOG_E(PHY, "%s() Problem sending retval:%d\n", __FUNCTION__, retval);
|
||||
} else {
|
||||
@@ -630,10 +637,10 @@ int oai_fapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req)
|
||||
|
||||
int oai_fapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req)
|
||||
{
|
||||
nfapi_vnf_p7_config_t *p7_config = (((vnf_info *)vnf_config->user_data)->p7_vnfs[0].config);
|
||||
nfapi_vnf_p7_config_t *p7_config = get_p7_vnf_config();
|
||||
dl_config_req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST;
|
||||
dl_config_req->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!!
|
||||
int retval = p7_config->send_p7_msg((vnf_p7_t *)p7_config, &dl_config_req->header);
|
||||
int retval = p7_config->send_p7_msg(get_p7_vnf(), &dl_config_req->header);
|
||||
dl_config_req->dl_tti_request_body.nPDUs = 0;
|
||||
dl_config_req->dl_tti_request_body.nGroup = 0;
|
||||
|
||||
@@ -644,9 +651,9 @@ int oai_fapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req)
|
||||
}
|
||||
|
||||
int oai_fapi_send_end_request(int cell, uint32_t frame, uint32_t slot){
|
||||
nfapi_vnf_p7_config_t *p7_config = (((vnf_info *)vnf_config->user_data)->p7_vnfs[0].config);
|
||||
nfapi_vnf_p7_config_t *p7_config = get_p7_vnf_config();
|
||||
nfapi_nr_slot_indication_scf_t nr_slot_resp = {.header.message_id = 0x8F, .sfn = frame, .slot = slot};
|
||||
int retval = p7_config->send_p7_msg((vnf_p7_t *)p7_config, &nr_slot_resp.header);
|
||||
int retval = p7_config->send_p7_msg(get_p7_vnf(), &nr_slot_resp.header);
|
||||
if (retval != 0) {
|
||||
LOG_E(PHY, "%s() Problem sending retval:%d\n", __FUNCTION__, retval);
|
||||
}
|
||||
|
||||
@@ -56,11 +56,13 @@ bool aerial_send_P7_msg_with_data(void *packedBuf,
|
||||
void *dataBuf,
|
||||
uint32_t dataLength,
|
||||
nfapi_nr_p7_message_header_t *header);
|
||||
void set_config(nfapi_vnf_config_t *conf);
|
||||
|
||||
int nvIPC_Init(nvipc_params_t nvipc_params_s);
|
||||
int oai_fapi_send_end_request(int cell_id, uint32_t frame, uint32_t slot);
|
||||
int oai_fapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req);
|
||||
int oai_fapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req);
|
||||
int oai_fapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req);
|
||||
int oai_fapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req);
|
||||
void nvIPC_Stop();
|
||||
void nvIPC_send_stop_request();
|
||||
#endif // OPENAIRINTERFACE_FAPI_NVIPC_H
|
||||
|
||||
@@ -1780,6 +1780,35 @@ int nr_start_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nf
|
||||
return 0;
|
||||
}
|
||||
|
||||
void stop_nr_nfapi_pnf()
|
||||
{
|
||||
#ifdef ENABLE_WLS
|
||||
wls_fapi_nr_pnf_stop();
|
||||
#endif
|
||||
#ifdef ENABLE_SOCKET
|
||||
socket_nfapi_nr_pnf_stop();
|
||||
#endif
|
||||
}
|
||||
static bool has_sent_stop_ind = false;
|
||||
int nr_stop_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nfapi_nr_stop_request_scf_t *req)
|
||||
{
|
||||
if (has_sent_stop_ind) {
|
||||
// STOP.indication already sent, nothing to do
|
||||
return 0;
|
||||
}
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "Send STOP.indication\n");
|
||||
nfapi_nr_stop_indication_scf_t resp = {.header.message_id = NFAPI_NR_PHY_MSG_TYPE_STOP_INDICATION,
|
||||
.header.phy_id = req->header.phy_id};
|
||||
nfapi_nr_stop_indication(config, &resp);
|
||||
has_sent_stop_ind = true;
|
||||
#ifdef ENABLE_WLS
|
||||
wls_pnf_close(pnf_p5_init_and_receive_pthread);
|
||||
#endif
|
||||
// raise the SIGTERM to simulate CTRL+C
|
||||
raise(SIGTERM);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int measurement_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nfapi_measurement_request_t *req) {
|
||||
nfapi_measurement_response_t resp;
|
||||
memset(&resp, 0, sizeof(resp));
|
||||
@@ -2135,6 +2164,7 @@ void configure_nr_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_add
|
||||
config->nr_param_req = &nr_param_request;
|
||||
config->nr_config_req = &nr_config_request;
|
||||
config->nr_start_req = &nr_start_request;
|
||||
config->nr_stop_req = &nr_stop_request;
|
||||
config->rssi_req = &rssi_request;
|
||||
config->broadcast_detect_req = &broadcast_detect_request;
|
||||
config->system_information_schedule_req = &system_information_schedule_request;
|
||||
@@ -2285,7 +2315,7 @@ void handle_nr_slot_ind(uint16_t sfn, uint16_t slot, NR_Sched_Rsp_t *sched_resp)
|
||||
#ifndef ENABLE_WLS
|
||||
int slot_ahead = 2 << mu;
|
||||
#else
|
||||
int slot_ahead = 1;
|
||||
int slot_ahead = 1 << mu;
|
||||
#endif
|
||||
uint16_t sfn_tx = sfn;
|
||||
uint16_t slot_tx = slot;
|
||||
|
||||
@@ -38,5 +38,5 @@ int oai_nfapi_nr_crc_indication(nfapi_nr_crc_indication_t *ind);
|
||||
int oai_nfapi_nr_srs_indication(nfapi_nr_srs_indication_t *ind);
|
||||
int oai_nfapi_nr_uci_indication(nfapi_nr_uci_indication_t *ind);
|
||||
int oai_nfapi_nr_rach_indication(nfapi_nr_rach_indication_t *ind);
|
||||
|
||||
void stop_nr_nfapi_pnf();
|
||||
#endif /* NFAPI_PNF_H_ */
|
||||
|
||||
@@ -70,10 +70,25 @@
|
||||
#endif
|
||||
|
||||
#define TEST
|
||||
|
||||
static nfapi_vnf_config_t *config;
|
||||
extern RAN_CONTEXT_t RC;
|
||||
extern UL_RCC_IND_t UL_RCC_INFO;
|
||||
|
||||
nfapi_vnf_config_t * get_config()
|
||||
{
|
||||
return config;
|
||||
}
|
||||
vnf_p7_t *get_p7_vnf()
|
||||
{
|
||||
vnf_info *vnf = config->user_data;
|
||||
return (vnf_p7_t *)vnf->p7_vnfs->config;
|
||||
}
|
||||
|
||||
nfapi_vnf_p7_config_t *get_p7_vnf_config()
|
||||
{
|
||||
return &get_p7_vnf()->_public;
|
||||
}
|
||||
|
||||
int vnf_pack_vendor_extension_tlv(void *ve, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *codec) {
|
||||
//NFAPI_TRACE(NFAPI_TRACE_INFO, "vnf_pack_vendor_extension_tlv\n");
|
||||
nfapi_tl_t *tlv = (nfapi_tl_t *)ve;
|
||||
@@ -1251,7 +1266,6 @@ void *configure_nr_p7_vnf(void *ptr)
|
||||
p7_vnf->config->hdr_unpack_func = &fapi_nr_p7_message_header_unpack;
|
||||
p7_vnf->config->pack_func = &fapi_nr_p7_message_pack;
|
||||
p7_vnf->config->send_p7_msg = &wls_vnf_nr_send_p7_message;
|
||||
wls_vnf_set_p7_config(p7_vnf->config);
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_SOCKET
|
||||
@@ -1645,32 +1659,86 @@ void vnf_start_thread(void *ptr) {
|
||||
nfapi_vnf_start((nfapi_vnf_config_t *)ptr);
|
||||
}
|
||||
|
||||
static vnf_info vnf;
|
||||
static bool has_stop_ind = false;
|
||||
static bool waiting_stop_ind = false;
|
||||
int nr_stop_ind_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_nr_stop_indication_scf_t *resp)
|
||||
{
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Received NFAPI_STOP_IND idx:%d phy_id:%d\n", p5_idx, resp->header.phy_id);
|
||||
has_stop_ind = true;
|
||||
#ifdef ENABLE_AERIAL
|
||||
nvIPC_Stop();
|
||||
#endif
|
||||
#ifdef ENABLE_SOCKET
|
||||
nfapi_vnf_p7_stop(get_p7_vnf_config());
|
||||
#endif
|
||||
#ifdef ENABLE_WLS
|
||||
wls_vnf_stop();
|
||||
#endif
|
||||
if (!waiting_stop_ind) {
|
||||
// hasn't been initialized yet, means the PNF stopped before the VNF did
|
||||
// raise a SIGINT to stop the VNF
|
||||
raise(SIGINT);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void stop_nr_nfapi_vnf()
|
||||
{
|
||||
if (has_stop_ind) {
|
||||
// If it got here with the STOP.indication flag already set, it means it was triggered by the PNF,
|
||||
// no need to send a STOP.request
|
||||
return;
|
||||
}
|
||||
#ifdef ENABLE_WLS
|
||||
wls_vnf_send_stop_request();
|
||||
#endif
|
||||
#ifdef ENABLE_AERIAL
|
||||
nvIPC_send_stop_request();
|
||||
#endif
|
||||
#ifdef ENABLE_SOCKET
|
||||
socket_nfapi_send_stop_request((vnf_t *)config);
|
||||
#endif
|
||||
waiting_stop_ind = true;
|
||||
uint64_t counter = 0;
|
||||
vnf_p7_t *p7_vnf = get_p7_vnf();
|
||||
while (p7_vnf->terminate == 0 && counter < 50) {
|
||||
NFAPI_TRACE(NFAPI_TRACE_DEBUG, "Not terminated yet, counter %ld\n", counter);
|
||||
usleep(1000);
|
||||
counter++;
|
||||
}
|
||||
if (p7_vnf->terminate == 0) {
|
||||
NFAPI_TRACE(NFAPI_TRACE_ERROR, "STOP.indication timed out, exiting\n");
|
||||
nfapi_nr_stop_indication_scf_t msg = {.header.message_id = NFAPI_NR_PHY_MSG_TYPE_STOP_INDICATION, .header.phy_id = 0};
|
||||
config->nr_stop_ind(config, 0, &msg);
|
||||
} else {
|
||||
NFAPI_TRACE(NFAPI_TRACE_DEBUG, "Terminated, exiting\n");
|
||||
}
|
||||
}
|
||||
|
||||
void configure_nr_nfapi_vnf(eth_params_t params)
|
||||
{
|
||||
#ifndef ENABLE_AERIAL
|
||||
nfapi_setmode(NFAPI_MODE_VNF);
|
||||
#endif
|
||||
memset(&vnf, 0, sizeof(vnf));
|
||||
memset(vnf.p7_vnfs, 0, sizeof(vnf.p7_vnfs));
|
||||
vnf.p7_vnfs[0].timing_window = 30;
|
||||
vnf.p7_vnfs[0].periodic_timing_enabled = 0;
|
||||
vnf.p7_vnfs[0].aperiodic_timing_enabled = 0;
|
||||
vnf.p7_vnfs[0].periodic_timing_period = 1;
|
||||
vnf.p7_vnfs[0].config = nfapi_vnf_p7_config_create();
|
||||
vnf_info *vnf = calloc(1, sizeof(vnf_info));
|
||||
memset(vnf->p7_vnfs, 0, sizeof(vnf->p7_vnfs));
|
||||
vnf->p7_vnfs[0].timing_window = 30;
|
||||
vnf->p7_vnfs[0].periodic_timing_enabled = 0;
|
||||
vnf->p7_vnfs[0].aperiodic_timing_enabled = 0;
|
||||
vnf->p7_vnfs[0].periodic_timing_period = 1;
|
||||
vnf->p7_vnfs[0].config = nfapi_vnf_p7_config_create();
|
||||
#ifndef ENABLE_AERIAL
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO,
|
||||
"[VNF] %s() vnf.p7_vnfs[0].config:%p VNF ADDRESS:%s:%d\n",
|
||||
"[VNF] %s() vnf->p7_vnfs[0].config:%p VNF ADDRESS:%s:%d\n",
|
||||
__FUNCTION__,
|
||||
vnf.p7_vnfs[0].config,
|
||||
vnf->p7_vnfs[0].config,
|
||||
params.my_addr,
|
||||
params.my_portc);
|
||||
strcpy(vnf.p7_vnfs[0].local_addr, params.my_addr);
|
||||
vnf.p7_vnfs[0].local_port = params.my_portd;
|
||||
strcpy(vnf->p7_vnfs[0].local_addr, params.my_addr);
|
||||
vnf->p7_vnfs[0].local_port = params.my_portd;
|
||||
#endif
|
||||
vnf.p7_vnfs[0].mac = (mac_t *)malloc(sizeof(mac_t));
|
||||
nfapi_vnf_config_t *config = nfapi_vnf_config_create();
|
||||
vnf->p7_vnfs[0].mac = malloc(sizeof(mac_t));
|
||||
config = nfapi_vnf_config_create();
|
||||
config->malloc = malloc;
|
||||
config->free = free;
|
||||
config->vnf_p5_port = params.my_portc;
|
||||
@@ -1688,9 +1756,10 @@ void configure_nr_nfapi_vnf(eth_params_t params)
|
||||
config->nr_param_resp = &nr_param_resp_cb;
|
||||
config->nr_config_resp = &nr_config_resp_cb;
|
||||
config->nr_start_resp = &nr_start_resp_cb;
|
||||
config->nr_stop_ind = &nr_stop_ind_cb;
|
||||
config->nr_error_ind = &nr_error_ind_cb;
|
||||
config->vendor_ext = &vendor_nr_ext_cb;
|
||||
config->user_data = &vnf;
|
||||
config->user_data = vnf;
|
||||
// To allow custom vendor extentions to be added to nfapi
|
||||
config->codec_config.unpack_vendor_extension_tlv = &vnf_nr_unpack_vendor_extension_tlv;
|
||||
config->codec_config.pack_vendor_extension_tlv = &vnf_nr_pack_vendor_extension_tlv;
|
||||
@@ -1727,7 +1796,6 @@ void configure_nr_nfapi_vnf(eth_params_t params)
|
||||
config->hdr_unpack_func = &fapi_nr_message_header_unpack;
|
||||
config->pack_func = &fapi_nr_p5_message_pack;
|
||||
config->send_p5_msg = &aerial_nr_send_p5_message;
|
||||
set_config(config);
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Created VNF NFAPI start thread %s\n", __FUNCTION__);
|
||||
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);
|
||||
@@ -1736,7 +1804,6 @@ void configure_nr_nfapi_vnf(eth_params_t params)
|
||||
pnf->connected = 1;
|
||||
// Add needed parameters
|
||||
|
||||
vnf_info *vnf = (vnf_info *)(config->user_data);
|
||||
pnf_info *pnf_info = vnf->pnfs;
|
||||
|
||||
for (int i = 0; i < 1; ++i) {
|
||||
@@ -1773,18 +1840,23 @@ void configure_nr_nfapi_vnf(eth_params_t params)
|
||||
|
||||
void configure_nfapi_vnf(char *vnf_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port) {
|
||||
nfapi_setmode(NFAPI_MODE_VNF);
|
||||
memset(&vnf, 0, sizeof(vnf));
|
||||
memset(vnf.p7_vnfs, 0, sizeof(vnf.p7_vnfs));
|
||||
vnf.p7_vnfs[0].timing_window = 32;
|
||||
vnf.p7_vnfs[0].periodic_timing_enabled = 1;
|
||||
vnf.p7_vnfs[0].aperiodic_timing_enabled = 0;
|
||||
vnf.p7_vnfs[0].periodic_timing_period = 10;
|
||||
vnf.p7_vnfs[0].config = nfapi_vnf_p7_config_create();
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] %s() vnf.p7_vnfs[0].config:%p VNF ADDRESS:%s:%d\n", __FUNCTION__, vnf.p7_vnfs[0].config, vnf_addr, vnf_p5_port);
|
||||
strcpy(vnf.p7_vnfs[0].local_addr, vnf_addr);
|
||||
vnf.p7_vnfs[0].local_port = vnf_p7_port;
|
||||
vnf.p7_vnfs[0].mac = (mac_t *)malloc(sizeof(mac_t));
|
||||
nfapi_vnf_config_t *config = nfapi_vnf_config_create();
|
||||
vnf_info *vnf = calloc(1, sizeof(vnf_info));
|
||||
memset(vnf->p7_vnfs, 0, sizeof(vnf->p7_vnfs));
|
||||
vnf->p7_vnfs[0].timing_window = 32;
|
||||
vnf->p7_vnfs[0].periodic_timing_enabled = 1;
|
||||
vnf->p7_vnfs[0].aperiodic_timing_enabled = 0;
|
||||
vnf->p7_vnfs[0].periodic_timing_period = 10;
|
||||
vnf->p7_vnfs[0].config = nfapi_vnf_p7_config_create();
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO,
|
||||
"[VNF] %s() vnf.p7_vnfs[0].config:%p VNF ADDRESS:%s:%d\n",
|
||||
__FUNCTION__,
|
||||
vnf->p7_vnfs[0].config,
|
||||
vnf_addr,
|
||||
vnf_p5_port);
|
||||
strcpy(vnf->p7_vnfs[0].local_addr, vnf_addr);
|
||||
vnf->p7_vnfs[0].local_port = vnf_p7_port;
|
||||
vnf->p7_vnfs[0].mac = malloc(sizeof(mac_t));
|
||||
config = nfapi_vnf_config_create();
|
||||
config->malloc = malloc;
|
||||
config->free = free;
|
||||
config->vnf_p5_port = vnf_p5_port;
|
||||
@@ -1803,7 +1875,7 @@ void configure_nfapi_vnf(char *vnf_addr, int vnf_p5_port, char *pnf_ip_addr, int
|
||||
config->config_resp = &config_resp_cb;
|
||||
config->start_resp = &start_resp_cb;
|
||||
config->vendor_ext = &vendor_ext_cb;
|
||||
config->user_data = &vnf;
|
||||
config->user_data = vnf;
|
||||
// To allow custom vendor extentions to be added to nfapi
|
||||
config->codec_config.unpack_vendor_extension_tlv = &vnf_unpack_vendor_extension_tlv;
|
||||
config->codec_config.pack_vendor_extension_tlv = &vnf_pack_vendor_extension_tlv;
|
||||
@@ -1820,7 +1892,7 @@ void configure_nfapi_vnf(char *vnf_addr, int vnf_p5_port, char *pnf_ip_addr, int
|
||||
}
|
||||
|
||||
int oai_nfapi_dl_config_req(nfapi_dl_config_request_t *dl_config_req) {
|
||||
nfapi_vnf_p7_config_t *p7_config = vnf.p7_vnfs[0].config;
|
||||
nfapi_vnf_p7_config_t *p7_config = get_p7_vnf_config();
|
||||
dl_config_req->header.phy_id = 1; // HACK TODO FIXME - need to pass this around!!!!
|
||||
dl_config_req->header.message_id = NFAPI_DL_CONFIG_REQUEST;
|
||||
LOG_D(PHY, "[VNF] %s() DL_CONFIG_REQ sfn_sf:%d_%d number_of_pdus:%d\n", __FUNCTION__,
|
||||
@@ -1856,7 +1928,7 @@ int oai_nfapi_dl_config_req(nfapi_dl_config_request_t *dl_config_req) {
|
||||
int oai_nfapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req)
|
||||
{
|
||||
LOG_D(NR_PHY, "Entering oai_nfapi_nr_dl_config_req sfn:%d,slot:%d\n", dl_config_req->SFN, dl_config_req->Slot);
|
||||
nfapi_vnf_p7_config_t *p7_config = vnf.p7_vnfs[0].config;
|
||||
nfapi_vnf_p7_config_t *p7_config = get_p7_vnf_config();
|
||||
dl_config_req->header.message_id= NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST;
|
||||
dl_config_req->header.phy_id = 1; // HACK TODO FIXME - need to pass this around!!!!
|
||||
|
||||
@@ -1875,7 +1947,7 @@ int oai_nfapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req)
|
||||
int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req)
|
||||
{
|
||||
LOG_D(NR_PHY, "Entering oai_nfapi_nr_tx_data_req sfn:%d,slot:%d\n", tx_data_req->SFN, tx_data_req->Slot);
|
||||
nfapi_vnf_p7_config_t *p7_config = vnf.p7_vnfs[0].config;
|
||||
nfapi_vnf_p7_config_t *p7_config = get_p7_vnf_config();
|
||||
tx_data_req->header.phy_id = 1; // HACK TODO FIXME - need to pass this around!!!!
|
||||
tx_data_req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST;
|
||||
//LOG_D(PHY, "[VNF] %s() TX_REQ sfn_sf:%d number_of_pdus:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(tx_req->sfn_sf), tx_req->tx_request_body.number_of_pdus);
|
||||
@@ -1892,7 +1964,7 @@ int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req)
|
||||
|
||||
int oai_nfapi_tx_req(nfapi_tx_request_t *tx_req)
|
||||
{
|
||||
nfapi_vnf_p7_config_t *p7_config = vnf.p7_vnfs[0].config;
|
||||
nfapi_vnf_p7_config_t *p7_config = get_p7_vnf_config();
|
||||
tx_req->header.phy_id = 1; // HACK TODO FIXME - need to pass this around!!!!
|
||||
tx_req->header.message_id = NFAPI_TX_REQUEST;
|
||||
//LOG_D(PHY, "[VNF] %s() TX_REQ sfn_sf:%d number_of_pdus:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(tx_req->sfn_sf), tx_req->tx_request_body.number_of_pdus);
|
||||
@@ -1908,7 +1980,7 @@ int oai_nfapi_tx_req(nfapi_tx_request_t *tx_req)
|
||||
}
|
||||
|
||||
int oai_nfapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req) {
|
||||
nfapi_vnf_p7_config_t *p7_config = vnf.p7_vnfs[0].config;
|
||||
nfapi_vnf_p7_config_t *p7_config = get_p7_vnf_config();
|
||||
ul_dci_req->header.phy_id = 1; // HACK TODO FIXME - need to pass this around!!!!
|
||||
ul_dci_req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST;
|
||||
//LOG_D(PHY, "[VNF] %s() HI_DCI0_REQ sfn_sf:%d dci:%d hi:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(hi_dci0_req->sfn_sf), hi_dci0_req->hi_dci0_request_body.number_of_dci, hi_dci0_req->hi_dci0_request_body.number_of_hi);
|
||||
@@ -1924,7 +1996,7 @@ int oai_nfapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req) {
|
||||
}
|
||||
|
||||
int oai_nfapi_hi_dci0_req(nfapi_hi_dci0_request_t *hi_dci0_req) {
|
||||
nfapi_vnf_p7_config_t *p7_config = vnf.p7_vnfs[0].config;
|
||||
nfapi_vnf_p7_config_t *p7_config = get_p7_vnf_config();
|
||||
hi_dci0_req->header.phy_id = 1; // HACK TODO FIXME - need to pass this around!!!!
|
||||
hi_dci0_req->header.message_id = NFAPI_HI_DCI0_REQUEST;
|
||||
//LOG_D(PHY, "[VNF] %s() HI_DCI0_REQ sfn_sf:%d dci:%d hi:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(hi_dci0_req->sfn_sf), hi_dci0_req->hi_dci0_request_body.number_of_dci, hi_dci0_req->hi_dci0_request_body.number_of_hi);
|
||||
@@ -1960,7 +2032,7 @@ static void remove_ul_config_req_pdu(int index, nfapi_ul_config_request_t *ul_co
|
||||
}
|
||||
|
||||
int oai_nfapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req) {
|
||||
nfapi_vnf_p7_config_t *p7_config = vnf.p7_vnfs[0].config;
|
||||
nfapi_vnf_p7_config_t *p7_config = get_p7_vnf_config();
|
||||
|
||||
ul_tti_req->header.phy_id = 1; // HACK TODO FIXME - need to pass this around!!!!
|
||||
ul_tti_req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST;
|
||||
@@ -1980,7 +2052,7 @@ int oai_nfapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req) {
|
||||
}
|
||||
|
||||
int oai_nfapi_ul_config_req(nfapi_ul_config_request_t *ul_config_req) {
|
||||
nfapi_vnf_p7_config_t *p7_config = vnf.p7_vnfs[0].config;
|
||||
nfapi_vnf_p7_config_t *p7_config = get_p7_vnf_config();
|
||||
ul_config_req->header.phy_id = 1; // HACK TODO FIXME - need to pass this around!!!!
|
||||
ul_config_req->header.message_id = NFAPI_UL_CONFIG_REQUEST;
|
||||
//LOG_D(PHY, "[VNF] %s() header message_id:%02x\n", __FUNCTION__, ul_config_req->header.message_id);
|
||||
@@ -2040,7 +2112,7 @@ int oai_nfapi_ul_config_req(nfapi_ul_config_request_t *ul_config_req) {
|
||||
int oai_nfapi_ue_release_req(nfapi_ue_release_request_t *release_req){
|
||||
if(release_req->ue_release_request_body.number_of_TLVs <= 0)
|
||||
return 0;
|
||||
nfapi_vnf_p7_config_t *p7_config = vnf.p7_vnfs[0].config;
|
||||
nfapi_vnf_p7_config_t *p7_config = get_p7_vnf_config();
|
||||
|
||||
release_req->header.phy_id = 1; // HACK TODO FIXME - need to pass this around!!!!
|
||||
release_req->header.message_id = NFAPI_UE_RELEASE_REQUEST;
|
||||
|
||||
@@ -148,5 +148,8 @@ typedef struct {
|
||||
|
||||
void configure_nfapi_vnf(char *vnf_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port);
|
||||
void configure_nr_nfapi_vnf(eth_params_t params);
|
||||
|
||||
void stop_nr_nfapi_vnf();
|
||||
nfapi_vnf_config_t *get_config();
|
||||
vnf_p7_t *get_p7_vnf();
|
||||
nfapi_vnf_p7_config_t *get_p7_vnf_config();
|
||||
#endif /* NFAPI_VNF_H_ */
|
||||
|
||||
@@ -36,4 +36,5 @@ bool pnf_nr_send_p5_message(pnf_t *pnf, nfapi_nr_p4_p5_message_header_t *msg, ui
|
||||
bool pnf_nr_send_p7_message(pnf_p7_t* pnf_p7, nfapi_nr_p7_message_header_t* header, uint32_t msg_len);
|
||||
void *pnf_start_p5_thread(void *ptr);
|
||||
void *pnf_nr_p7_thread_start(void *ptr);
|
||||
void socket_nfapi_nr_pnf_stop();
|
||||
#endif // SOCKET_PNF_H
|
||||
|
||||
@@ -31,4 +31,5 @@ bool vnf_nr_send_p5_msg(vnf_t *vnf, uint16_t p5_idx, nfapi_nr_p4_p5_message_head
|
||||
bool vnf_nr_send_p7_msg(vnf_p7_t *vnf_p7, nfapi_nr_p7_message_header_t* header);
|
||||
void vnf_start_p5_thread(void* ptr);
|
||||
void* vnf_nr_start_p7_thread(void* ptr);
|
||||
void socket_nfapi_send_stop_request(vnf_t *vnf);
|
||||
#endif // SOCKET_VNF_H
|
||||
|
||||
@@ -20,6 +20,15 @@
|
||||
*/
|
||||
#include "socket_pnf.h"
|
||||
#include "nfapi.h"
|
||||
static nfapi_pnf_config_t *config;
|
||||
void socket_nfapi_nr_pnf_stop()
|
||||
{
|
||||
AssertFatal(config->nr_stop_req, "STOP.request Handler should be set!");
|
||||
nfapi_nr_stop_request_scf_t req = {0};
|
||||
req.header.phy_id = 0;
|
||||
req.header.message_id = NFAPI_NR_PHY_MSG_TYPE_PNF_STOP_REQUEST;
|
||||
config->nr_stop_req(config, 0, &req);
|
||||
}
|
||||
|
||||
bool pnf_nr_send_p5_message(pnf_t *pnf, nfapi_nr_p4_p5_message_header_t *msg, uint32_t msg_len)
|
||||
{
|
||||
@@ -148,7 +157,7 @@ bool pnf_nr_send_p7_message(pnf_p7_t *pnf_p7, nfapi_nr_p7_message_header_t *head
|
||||
void *pnf_start_p5_thread(void *ptr)
|
||||
{
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] IN PNF NFAPI start thread %s\n", __FUNCTION__);
|
||||
nfapi_pnf_config_t *config = (nfapi_pnf_config_t *)ptr;
|
||||
config = (nfapi_pnf_config_t *)ptr;
|
||||
struct sched_param sp;
|
||||
sp.sched_priority = 20;
|
||||
pthread_setschedparam(pthread_self(), SCHED_FIFO, &sp);
|
||||
|
||||
@@ -20,9 +20,26 @@
|
||||
*/
|
||||
#include "socket_vnf.h"
|
||||
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "nfapi.h"
|
||||
#include "nfapi_vnf.h"
|
||||
#include <common/platform_constants.h>
|
||||
#include "nfapi/oai_integration/vendor_ext.h" //TODO: Remove this include when removing the Aerial transport stuff
|
||||
|
||||
|
||||
void socket_stop_nfapi_p5_p7()
|
||||
{
|
||||
get_p7_vnf()->terminate = 1;
|
||||
get_config()->pnf_disconnect_indication = NULL;
|
||||
}
|
||||
|
||||
void socket_nfapi_send_stop_request(vnf_t *vnf)
|
||||
{
|
||||
nfapi_nr_stop_request_scf_t req = {.header.message_id = NFAPI_NR_PHY_MSG_TYPE_STOP_REQUEST, .header.phy_id = 0};
|
||||
nfapi_nr_vnf_stop_req(&vnf->_public, 0, &req);
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "Sent NFAPI STOP.request\n");
|
||||
}
|
||||
|
||||
static bool send_p5_msg(vnf_t *vnf, nfapi_vnf_pnf_info_t *pnf, const void *msg, int len, uint8_t stream)
|
||||
{
|
||||
int result = socket_send_p5_msg(vnf->sctp, pnf->p5_sock, &pnf->p5_pnf_sockaddr, msg, len, stream);
|
||||
@@ -279,7 +296,6 @@ static int nfapi_nr_vnf_p5_start(nfapi_vnf_config_t *config)
|
||||
// Verify that config is not null
|
||||
if (config == 0)
|
||||
return -1;
|
||||
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "%s()\n", __FUNCTION__);
|
||||
|
||||
int p5ListenSock, p5Sock;
|
||||
@@ -293,7 +309,7 @@ static int nfapi_nr_vnf_p5_start(nfapi_vnf_config_t *config)
|
||||
struct sctp_initmsg initMsg = {0};
|
||||
int noDelay;
|
||||
|
||||
vnf_t *vnf = (vnf_t *)(config);
|
||||
vnf_t *vnf = (vnf_t *)(get_config());
|
||||
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "Starting P5 VNF connection on port %u\n", config->vnf_p5_port);
|
||||
|
||||
@@ -747,8 +763,8 @@ static int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t *config)
|
||||
return -1;
|
||||
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "%s()\n", __FUNCTION__);
|
||||
|
||||
vnf_p7_t *vnf_p7 = (vnf_p7_t *)config;
|
||||
vnf_p7_t *vnf_p7 = get_p7_vnf();
|
||||
vnf_p7 = (vnf_p7_t *)config;
|
||||
|
||||
// Create p7 receive udp port
|
||||
// todo : this needs updating for Ipv6
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include "wls_lib.h"
|
||||
#include "nfapi/open-nFAPI/fapi/inc/nr_fapi_p5_utils.h"
|
||||
#include "nfapi/open-nFAPI/fapi/inc/nr_fapi_p7_utils.h"
|
||||
|
||||
|
||||
@@ -30,4 +30,6 @@ bool wls_pnf_nr_send_p7_message(pnf_p7_t* pnf_p7,nfapi_nr_p7_message_header_t *m
|
||||
void *wls_fapi_pnf_nr_start_thread(void *ptr);
|
||||
int wls_fapi_nr_pnf_start();
|
||||
void wls_pnf_set_p7_config(void *p7_config);
|
||||
void wls_fapi_nr_pnf_stop();
|
||||
void wls_pnf_close(pthread_t p5_thread);
|
||||
#endif // OPENAIRINTERFACE_WLS_PNF_H
|
||||
|
||||
@@ -27,7 +27,8 @@
|
||||
|
||||
void *wls_fapi_vnf_nr_start_thread(void *ptr);
|
||||
int wls_fapi_nr_vnf_start();
|
||||
void wls_vnf_set_p7_config(void *p7_config);
|
||||
bool wls_vnf_nr_send_p5_message(vnf_t *vnf,uint16_t p5_idx, nfapi_nr_p4_p5_message_header_t* msg, uint32_t msg_len);
|
||||
bool wls_vnf_nr_send_p7_message(vnf_p7_t* vnf_p7,nfapi_nr_p7_message_header_t* msg);
|
||||
void wls_vnf_send_stop_request();
|
||||
void wls_vnf_stop();
|
||||
#endif //OPENAIRINTERFACE_WLS_VNF_H
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
*/
|
||||
|
||||
#include "wls_common.h"
|
||||
|
||||
#include "wls_lib.h"
|
||||
void fill_fapi_list_elem(p_fapi_api_queue_elem_t currElem, p_fapi_api_queue_elem_t nextElem, const uint8_t msgType, const uint8_t numMsgInBlock, const uint32_t alignOffset)
|
||||
{
|
||||
currElem->msg_type = msgType;
|
||||
@@ -90,9 +90,19 @@ uint8_t wls_send_fapi_msg(PWLS_MAC_CTX pWls, const uint16_t message_id, const in
|
||||
{
|
||||
int num_avail_blocks = WLS_NumBlocks(pWls->hWls);
|
||||
NFAPI_TRACE(NFAPI_TRACE_DEBUG,"num_avail_blocks is %d\n", num_avail_blocks);
|
||||
int counter = 0;
|
||||
while (num_avail_blocks < 2) {
|
||||
num_avail_blocks = WLS_NumBlocks(pWls->hWls);
|
||||
NFAPI_TRACE(NFAPI_TRACE_DEBUG,"num_avail_blocks is %d\n", num_avail_blocks);
|
||||
if (message_id == NFAPI_NR_PHY_MSG_TYPE_STOP_INDICATION) {
|
||||
// In the case of the STOP.indication, it can happen that this is called after the VNF stopped
|
||||
// For example, if it crashed for some reason, in that case, implement a timeout and return
|
||||
usleep(10 * 1000);
|
||||
counter++;
|
||||
if (counter == 10) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* get PA blocks for header and msg */
|
||||
uint64_t pa_hdr = dequeueBlock(pWls);
|
||||
|
||||
@@ -29,9 +29,10 @@
|
||||
#include <pnf_p7.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include "wls_lib.h"
|
||||
#include "pnf.h"
|
||||
#include "nr_nfapi_p7.h"
|
||||
#include "nr_fapi_p5.h"
|
||||
#include "nfapi/open-nFAPI/fapi/inc/nr_fapi_p7_utils.h"
|
||||
|
||||
// A copy of the PNF P7 config is needed for the message processing thread, in other transport mechanisms where P7 is handled in a
|
||||
// different thread, the config is passed to it upon the thread creation
|
||||
@@ -65,6 +66,28 @@ void *wls_fapi_pnf_nr_start_thread(void *ptr)
|
||||
return (void *)0;
|
||||
}
|
||||
|
||||
void wls_pnf_close(pthread_t p5_thread)
|
||||
{
|
||||
_this->terminate = 1;
|
||||
WLS_WakeUp(wls_mac_get_ctx()->hWls);
|
||||
pthread_join(p5_thread, NULL);
|
||||
if (WLS_Close(wls_mac_get_ctx()->hWls) != 0) {
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] WLS_CLose call failed...\n");
|
||||
} else {
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] WLS_CLose called successfully...\n");
|
||||
}
|
||||
rte_eal_cleanup();
|
||||
}
|
||||
|
||||
void wls_fapi_nr_pnf_stop()
|
||||
{
|
||||
AssertFatal(cfg->nr_stop_req, "STOP.request Handler should be set!");
|
||||
nfapi_nr_stop_request_scf_t req = {0};
|
||||
req.header.phy_id = 0;
|
||||
req.header.message_id = NFAPI_NR_PHY_MSG_TYPE_STOP_REQUEST;
|
||||
cfg->nr_stop_req(cfg, 0, &req);
|
||||
}
|
||||
|
||||
int wls_fapi_nr_pnf_start()
|
||||
{
|
||||
int64_t ret;
|
||||
@@ -194,6 +217,9 @@ bool wls_pnf_nr_send_p7_message(pnf_p7_t *pnf_p7, nfapi_nr_p7_message_header_t *
|
||||
NFAPI_TRACE(NFAPI_TRACE_DEBUG, "num_avail_blocks is %d\n", num_avail_blocks);
|
||||
while (num_avail_blocks < 2) {
|
||||
num_avail_blocks = WLS_NumBlocks(pWls->hWls);
|
||||
if (_this->terminate) {
|
||||
return false;
|
||||
}
|
||||
NFAPI_TRACE(NFAPI_TRACE_DEBUG, "num_avail_blocks is %d\n", num_avail_blocks);
|
||||
}
|
||||
/* get PA blocks for header and msg */
|
||||
@@ -254,7 +280,7 @@ void phy_mac_recv()
|
||||
bool to_return = false;
|
||||
while (_this->terminate == 0) {
|
||||
int numMsgToGet = WLS_Wait(pWls->hWls);
|
||||
if (numMsgToGet == 0) {
|
||||
if (numMsgToGet == 0 || _this->terminate) {
|
||||
continue;
|
||||
}
|
||||
uint64_t PAs[numMsgToGet];
|
||||
@@ -279,6 +305,11 @@ void phy_mac_recv()
|
||||
}
|
||||
}
|
||||
}
|
||||
// A STOP.indication might have been processed, which set's terminate to 1
|
||||
// don't return pages in that case
|
||||
if (_this->terminate) {
|
||||
break;
|
||||
}
|
||||
if (to_return) {
|
||||
// We only return the pages to be enqueued in case we're using the OAI VNF,
|
||||
// The Radisys O-DU handles enqueueing the blocks differently, and also doesn't handle receiving a single block
|
||||
|
||||
@@ -21,26 +21,23 @@
|
||||
#include "wls_vnf.h"
|
||||
|
||||
#include "vnf_p7.h"
|
||||
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "wls_lib.h"
|
||||
#include <rte_eal.h>
|
||||
#include <rte_string_fns.h>
|
||||
#include <rte_common.h>
|
||||
#include <rte_lcore.h>
|
||||
#include <rte_debug.h>
|
||||
#include <nr_fapi_p5.h>
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include <rte_errno.h>
|
||||
#include <unistd.h>
|
||||
#include <common/platform_constants.h>
|
||||
#include <sys/wait.h>
|
||||
#include "nfapi_vnf.h"
|
||||
|
||||
static nfapi_vnf_config_t *config;
|
||||
static WLS_MAC_CTX wls_mac_iface;
|
||||
vnf_t *_vnf = NULL;
|
||||
// A copy of the VNF P7 config is needed for the message processing thread, in other transport mechanisms where P7 is handled in a
|
||||
// different thread, the config is passed to it upon the thread creation
|
||||
nfapi_vnf_p7_config_t *wls_vnf_p7_config = NULL;
|
||||
|
||||
void wls_vnf_set_p7_config(void *p7_config)
|
||||
{
|
||||
wls_vnf_p7_config = (nfapi_vnf_p7_config_t *)p7_config;
|
||||
}
|
||||
|
||||
static PWLS_MAC_CTX wls_mac_get_ctx(void)
|
||||
{
|
||||
@@ -99,17 +96,54 @@ static bool wls_mac_create_mem_array(PWLS_MAC_MEM_SRUCT pMemArray, void *pMemArr
|
||||
return true;
|
||||
}
|
||||
|
||||
void mac_dpdk_init()
|
||||
bool primary_process_running(int argc, char *argv[])
|
||||
{
|
||||
char *my_argv[] = {"OAI_VNF", "-c3", "--proc-type=auto", "--file-prefix", WLS_DEV_NAME, "--iova-mode=pa"};
|
||||
printf("\nCalling rte_eal_init: ");
|
||||
for (unsigned long i = 0; i < RTE_DIM(my_argv); i++) {
|
||||
printf("%s ", my_argv[i]);
|
||||
}
|
||||
printf("\n");
|
||||
// If the PNF was stopped normally, this is enough, as the mp_socket file does not exist
|
||||
if (access("/var/run/dpdk/" WLS_DEV_NAME "/mp_socket", W_OK | R_OK) != 0)
|
||||
return false;
|
||||
|
||||
if (rte_eal_init(RTE_DIM(my_argv), my_argv) < 0)
|
||||
rte_panic("\nCannot init EAL\n");
|
||||
// If we run rte_eal_init before the primary process is running, it will result in a 'Connection Refused' error in the logs, but
|
||||
// the call itself will succeed ( retval not -1 )
|
||||
//
|
||||
// We can use rte_eal_primary_proc_alive to determine if the primary process is running, the issue is that since the init had a
|
||||
// refused connection, if we try to open WLS after rte_eal_primary_proc_alive reports that the primary is running, it will fail,
|
||||
// since rte_eal_init failed to connect to the primary process, and we can't call rte_eal_init in the same process more than once,
|
||||
// or it will result in an EALREADY error
|
||||
//
|
||||
// Given this, a new process is created that calls rte_eal_init and checks whether the primary process is running, exiting
|
||||
// right after and reporting to our VNF the primary status
|
||||
//
|
||||
// When the VNF receives the status from the forked process that the
|
||||
// primary process is running, it then calls rte_eal_init, which at this point we know will be successful, and continue to open
|
||||
// the WLS instance
|
||||
pid_t pid = fork();
|
||||
if (pid == 0) {
|
||||
// We set the log level to emergency , effectively disabling logs in the child process
|
||||
// This prevents too many logs being printed out to the terminal while we wait for the primary process to be available
|
||||
rte_log_set_global_level(RTE_LOG_EMERG);
|
||||
AssertFatal(rte_eal_init(argc, argv) != -1, "rte_eal_init() failed\n");
|
||||
int status = rte_eal_primary_proc_alive(NULL) == 0;
|
||||
rte_eal_cleanup();
|
||||
_exit(status);
|
||||
}
|
||||
int status;
|
||||
waitpid(pid, &status, 0);
|
||||
return WIFEXITED(status) && WEXITSTATUS(status) == 0;
|
||||
}
|
||||
|
||||
bool mac_dpdk_init()
|
||||
{
|
||||
char *my_argv[] = {"OAI_VNF", "-c3", "--proc-type=secondary", "--file-prefix", WLS_DEV_NAME, "--iova-mode=pa"};
|
||||
NFAPI_TRACE(NFAPI_TRACE_DEBUG, "\nCalling rte_eal_init: ");
|
||||
for (int i = 0; i < RTE_DIM(my_argv); i++) {
|
||||
NFAPI_TRACE(NFAPI_TRACE_DEBUG, "%s ", my_argv[i]);
|
||||
}
|
||||
NFAPI_TRACE(NFAPI_TRACE_DEBUG, "\n");
|
||||
while (!primary_process_running(RTE_DIM(my_argv), my_argv)) {
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "DPDK primary process not available yet, retrying in 1 second...\n");
|
||||
sleep(1);
|
||||
}
|
||||
return rte_eal_init(RTE_DIM(my_argv), my_argv) >= 0;
|
||||
}
|
||||
|
||||
static uint32_t wls_mac_alloc_mem_array(PWLS_MAC_MEM_SRUCT pMemArray, void **ppBlock)
|
||||
@@ -258,7 +292,7 @@ for(int i = 0 ; i< pWls->nTotalBlocks; i++){
|
||||
void* pMsg = wls_mac_alloc_buffer(pWls, 0, i);
|
||||
/* Enqueue all blocks */
|
||||
nBlocks += WLS_EnqueueBlock(pWls->hWls, WLS_VA2PA(pWls->hWls, pMsg));
|
||||
}
|
||||
}
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "\nAllocated %d Blocks \n", nBlocks);
|
||||
return true;
|
||||
}
|
||||
@@ -274,6 +308,33 @@ static int vnf_wls_init()
|
||||
return 1;
|
||||
}
|
||||
|
||||
void wls_vnf_stop()
|
||||
{
|
||||
vnf_p7_t *p7_vnf = get_p7_vnf();
|
||||
_vnf->terminate = 1;
|
||||
p7_vnf->terminate = 1;
|
||||
rte_eal_cleanup();
|
||||
}
|
||||
|
||||
void wls_vnf_send_stop_request()
|
||||
{
|
||||
PWLS_MAC_CTX pWls = wls_mac_get_ctx();
|
||||
nfapi_nr_stop_request_scf_t req = {.header.message_id = NFAPI_NR_PHY_MSG_TYPE_STOP_REQUEST, .header.phy_id = 0};
|
||||
vnf_p7_t *p7_vnf = get_p7_vnf();
|
||||
nfapi_vnf_config_t * config = get_config();
|
||||
if (p7_vnf == NULL || pWls->hWls == NULL) {
|
||||
nfapi_nr_stop_indication_scf_t msg;
|
||||
msg.header.message_id = NFAPI_NR_PHY_MSG_TYPE_STOP_INDICATION;
|
||||
msg.header.phy_id = 0;
|
||||
config->nr_stop_ind(config, 0, &msg);
|
||||
return;
|
||||
}
|
||||
|
||||
if (pWls->hWls != NULL) {
|
||||
nfapi_nr_vnf_stop_req(config, 0, &req);
|
||||
}
|
||||
}
|
||||
|
||||
void *wls_fapi_vnf_nr_start_thread(void *ptr)
|
||||
{
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] IN WLS PNF NFAPI start thread %s\n", __FUNCTION__);
|
||||
@@ -294,11 +355,11 @@ static void procPhyMessages(uint32_t msg_size, void *msg_buf, uint16_t msg_id)
|
||||
case NFAPI_NR_PHY_MSG_TYPE_CONFIG_RESPONSE:
|
||||
case NFAPI_NR_PHY_MSG_TYPE_START_RESPONSE:
|
||||
case NFAPI_NR_PHY_MSG_TYPE_STOP_INDICATION:
|
||||
vnf_nr_handle_p4_p5_message(msg_buf, msg_size, 0, config);
|
||||
vnf_nr_handle_p4_p5_message(msg_buf, msg_size, 0, get_config());
|
||||
break;
|
||||
|
||||
case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST ... NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION: {
|
||||
vnf_nr_handle_p7_message(msg_buf, msg_size + NFAPI_NR_P7_HEADER_LENGTH, (vnf_p7_t *)wls_vnf_p7_config);
|
||||
vnf_nr_handle_p7_message(msg_buf, msg_size + NFAPI_NR_P7_HEADER_LENGTH, get_p7_vnf());
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -308,6 +369,7 @@ static void procPhyMessages(uint32_t msg_size, void *msg_buf, uint16_t msg_id)
|
||||
|
||||
int wls_fapi_nr_vnf_start(nfapi_vnf_config_t *cfg)
|
||||
{
|
||||
nfapi_vnf_config_t * config = get_config();
|
||||
config = cfg;
|
||||
|
||||
if (config == 0) {
|
||||
@@ -333,7 +395,7 @@ int wls_fapi_nr_vnf_start(nfapi_vnf_config_t *cfg)
|
||||
PWLS_MAC_CTX pWls = wls_mac_get_ctx();
|
||||
while (_vnf->terminate == 0) {
|
||||
int numMsgToGet = WLS_Wait(pWls->hWls);
|
||||
if (numMsgToGet == 0) {
|
||||
if (numMsgToGet == 0 || _vnf->terminate) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -351,6 +413,9 @@ int wls_fapi_nr_vnf_start(nfapi_vnf_config_t *cfg)
|
||||
procPhyMessages(len, (void *)(msg + 1), msg->msg_type);
|
||||
}
|
||||
}
|
||||
if (_vnf->terminate) {
|
||||
break;
|
||||
}
|
||||
for (int i = 0; i < pa_idx; i++) {
|
||||
if (WLS_EnqueueBlock(pWls->hWls, PAs[i]) == -1) {
|
||||
NFAPI_TRACE(NFAPI_TRACE_DEBUG, "Error in WLS_EnqueueBlock for block %lu\n", PAs[i]);
|
||||
@@ -403,7 +468,7 @@ bool wls_vnf_nr_send_p7_message(vnf_p7_t *vnf_p7, nfapi_nr_p7_message_header_t *
|
||||
AssertFatal(fapiMsgElem, "WLS_PA2VA failed for fapiMsgElem\n");
|
||||
//memcpy((uint8_t *)(fapiMsgElem + 1), message, packed_len + NFAPI_HEADER_LENGTH);
|
||||
const uint8_t wls_header[] = {1, 0}; // num_messages , opaque_handle
|
||||
|
||||
|
||||
fill_fapi_list_elem(headerElem, fapiMsgElem, FAPI_VENDOR_MSG_HEADER_IND, 1, 2);
|
||||
memcpy((uint8_t *)(headerElem + 1), wls_header, 2);
|
||||
int packed_len = ((nfapi_vnf_p7_config_t *)vnf_p7)->pack_func(msg, (fapiMsgElem + 1), NFAPI_MAX_PACKED_MESSAGE_SIZE, NULL);
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "PHY/impl_defs_top.h"
|
||||
#include "PHY/impl_defs_nr.h"
|
||||
#include "common/utils/nr/nr_common.h"
|
||||
#include "executables/position_interface.h"
|
||||
|
||||
#define NFAPI_UE_MAX_NUM_CB 8
|
||||
#define NFAPI_MAX_NUM_UL_PDU 255
|
||||
@@ -562,18 +563,26 @@ typedef struct {
|
||||
} fapi_nr_ta_command_pdu;
|
||||
|
||||
typedef struct {
|
||||
int epoch_hfn;
|
||||
int epoch_sfn;
|
||||
int epoch_subframe;
|
||||
|
||||
// orbital angular velocity in rad/ms
|
||||
double omega;
|
||||
// satellite position at epoch time
|
||||
position_t pos_sat_0;
|
||||
// satellite position at 90° orbit
|
||||
position_t pos_sat_90;
|
||||
|
||||
// N_common_ta_adj represents common round-trip-time between gNB and SAT received in SIB19 (ms)
|
||||
double N_common_ta_adj;
|
||||
// drift rate of common ta in µs/s
|
||||
double N_common_ta_drift;
|
||||
// change rate of common ta drift in µs/s²
|
||||
double N_common_ta_drift_variant;
|
||||
|
||||
// cell scheduling offset expressed in terms of 15kHz SCS
|
||||
long cell_specific_k_offset;
|
||||
|
||||
// ntn_total_time_advance_ms represents the complete round-trip-time between gNB and UE via SAT
|
||||
double ntn_total_time_advance_ms;
|
||||
// drift rate of ntn_total_time_advance_ms in µs/s
|
||||
double ntn_total_time_advance_drift;
|
||||
// change rate of ntn_total_time_advance_ms drift in µs/s²
|
||||
double ntn_total_time_advance_drift_variant;
|
||||
} fapi_nr_dl_ntn_config_command_pdu;
|
||||
|
||||
typedef struct {
|
||||
@@ -697,7 +706,6 @@ typedef struct
|
||||
uint8_t restricted_set_config;//PRACH restricted set config Value: 0: unrestricted 1: restricted set type A 2: restricted set type B
|
||||
uint8_t num_prach_fd_occasions;//Corresponds to the parameter 𝑀 in [38.211, sec 6.3.3.2] which equals the higher layer parameter msg1FDM Value: 1,2,4,8
|
||||
fapi_nr_num_prach_fd_occasions_t* num_prach_fd_occasions_list;
|
||||
uint8_t ssb_per_rach;//SSB-per-RACH-occasion Value: 0: 1/8 1:1/4, 2:1/2 3:1 4:2 5:4, 6:8 7:16
|
||||
uint8_t prach_multiple_carriers_in_a_band;//0 = disabled 1 = enabled
|
||||
uint8_t root_seq_computed; // flag set and used only in PHY to indicate if table is computed with this config
|
||||
|
||||
|
||||
@@ -1254,6 +1254,10 @@ uint8_t pack_nr_p5_message_body(nfapi_nr_p4_p5_message_header_t *header,
|
||||
result = pack_stop_request(header, ppWritePackedMsg, end, config);
|
||||
break;
|
||||
|
||||
case NFAPI_NR_PHY_MSG_TYPE_STOP_INDICATION:
|
||||
result = pack_nr_stop_indication(header, ppWritePackedMsg, end, config);
|
||||
break;
|
||||
|
||||
case NFAPI_NR_PHY_MSG_TYPE_STOP_RESPONSE:
|
||||
result = pack_stop_response(header, ppWritePackedMsg, end, config);
|
||||
break;
|
||||
@@ -2447,6 +2451,10 @@ bool nfapi_nr_p5_message_unpack(void *pMessageBuf,
|
||||
result = unpack_stop_request(&pReadPackedMessage, end, pMessageHeader, config);
|
||||
break;
|
||||
|
||||
case NFAPI_NR_PHY_MSG_TYPE_STOP_INDICATION:
|
||||
result = unpack_nr_stop_indication(&pReadPackedMessage, end, pMessageHeader, config);
|
||||
break;
|
||||
|
||||
case NFAPI_NR_PHY_MSG_TYPE_STOP_RESPONSE:
|
||||
result = unpack_stop_response(&pReadPackedMessage, end, pMessageHeader, config);
|
||||
break;
|
||||
|
||||
@@ -497,6 +497,14 @@ int nfapi_nr_pnf_start_resp(nfapi_pnf_config_t* config, nfapi_nr_start_response_
|
||||
*/
|
||||
int nfapi_pnf_stop_resp(nfapi_pnf_config_t* config, nfapi_stop_response_t* resp);
|
||||
|
||||
/*! Send the STOP.indication
|
||||
* \param config A pointer to a pnf configuration
|
||||
* \param resp A pointer to the message structure
|
||||
* \return 0 for success, -1 for failure
|
||||
*
|
||||
*/
|
||||
int nfapi_nr_stop_indication(nfapi_pnf_config_t* config, nfapi_nr_stop_indication_scf_t* resp);
|
||||
|
||||
/*! Send the MEASUREMENT.response
|
||||
* \param config A pointer to a pnf configuraiton
|
||||
* \param resp A pointer to the message structure
|
||||
|
||||
@@ -387,6 +387,18 @@ int nfapi_pnf_stop_resp(nfapi_pnf_config_t* config, nfapi_stop_response_t* resp)
|
||||
return pnf_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_stop_response_t));
|
||||
}
|
||||
|
||||
int nfapi_nr_stop_indication(nfapi_pnf_config_t* config, nfapi_nr_stop_indication_scf_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);
|
||||
AssertFatal(config->send_p5_msg, "Function pointer must be configured|");
|
||||
return config->send_p5_msg(_this, &(resp->header), sizeof(nfapi_nr_stop_indication_scf_t));
|
||||
}
|
||||
|
||||
int nfapi_pnf_measurement_resp(nfapi_pnf_config_t* config, nfapi_measurement_response_t* resp)
|
||||
{
|
||||
if (config == NULL || resp == NULL)
|
||||
|
||||
@@ -728,34 +728,19 @@ int nr_pnf_p7_get_msgs(pnf_p7_t* pnf_p7,
|
||||
ret_dl_tti->SFN = sfn;
|
||||
ret_dl_tti->Slot = slot;
|
||||
ret_dl_tti->dl_tti_request_body.nPDUs = 0;
|
||||
nfapi_nr_dl_tti_request_t* dl_tti_req = &tx_slot_buffer->dl_tti_req;
|
||||
if (dl_tti_req->SFN == sfn && dl_tti_req->Slot == slot) {
|
||||
copy_dl_tti_request(dl_tti_req, ret_dl_tti);
|
||||
tx_slot_buffer->dl_tti_req.SFN = -1;
|
||||
tx_slot_buffer->dl_tti_req.Slot = -1;
|
||||
}
|
||||
|
||||
ret_tx_data->SFN = sfn;
|
||||
ret_tx_data->Slot = slot;
|
||||
ret_tx_data->Number_of_PDUs = 0;
|
||||
nfapi_nr_dl_tti_request_t* dl_tti_req = &tx_slot_buffer->dl_tti_req;
|
||||
nfapi_nr_tx_data_request_t* txd = &tx_slot_buffer->tx_data_req;
|
||||
if (dl_tti_req->SFN == sfn && dl_tti_req->Slot == slot && txd->SFN == sfn && txd->Slot == slot) {
|
||||
nfapi_nr_dl_tti_request_body_t* p_tti = &dl_tti_req->dl_tti_request_body;
|
||||
int ret_idx = 0;
|
||||
for (int i = 0; i < p_tti->nPDUs; ++i) {
|
||||
int tx_index = p_tti->dl_tti_pdu_list[i].pdsch_pdu.pdsch_pdu_rel15.pduIndex - 1;
|
||||
if (tx_index >= txd->Number_of_PDUs) {
|
||||
NFAPI_TRACE(NFAPI_TRACE_ERROR,
|
||||
"%4d.%2d no corresponding tx_data.request for dl_tti.request index %d, dropping\n",
|
||||
sfn,
|
||||
slot,
|
||||
tx_index);
|
||||
continue;
|
||||
}
|
||||
ret_dl_tti->dl_tti_request_body.dl_tti_pdu_list[ret_idx] = p_tti->dl_tti_pdu_list[i];
|
||||
// TODO avoid huge copy
|
||||
ret_tx_data->pdu_list[ret_idx] = txd->pdu_list[i];
|
||||
ret_idx++;
|
||||
}
|
||||
ret_dl_tti->dl_tti_request_body.nPDUs = ret_idx;
|
||||
ret_tx_data->Number_of_PDUs = ret_idx;
|
||||
|
||||
tx_slot_buffer->dl_tti_req.SFN = -1;
|
||||
tx_slot_buffer->dl_tti_req.Slot = -1;
|
||||
if (txd->SFN == sfn && txd->Slot == slot) {
|
||||
copy_tx_data_request(txd, ret_tx_data);
|
||||
tx_slot_buffer->tx_data_req.SFN = -1;
|
||||
tx_slot_buffer->tx_data_req.Slot = -1;
|
||||
}
|
||||
@@ -764,10 +749,7 @@ int nr_pnf_p7_get_msgs(pnf_p7_t* pnf_p7,
|
||||
ret_ul_tti->Slot = slot;
|
||||
ret_ul_tti->n_pdus = 0;
|
||||
if (tx_slot_buffer->ul_tti_req.SFN == sfn && tx_slot_buffer->ul_tti_req.Slot == slot) {
|
||||
nfapi_nr_ul_tti_request_t* p = &tx_slot_buffer->ul_tti_req;
|
||||
ret_ul_tti->n_pdus = p->n_pdus;
|
||||
for (int i = 0; i < p->n_pdus; ++i)
|
||||
ret_ul_tti->pdus_list[i] = p->pdus_list[i];
|
||||
copy_ul_tti_request(&tx_slot_buffer->ul_tti_req, ret_ul_tti);
|
||||
tx_slot_buffer->ul_tti_req.SFN = -1;
|
||||
tx_slot_buffer->ul_tti_req.Slot = -1;
|
||||
}
|
||||
@@ -776,10 +758,7 @@ int nr_pnf_p7_get_msgs(pnf_p7_t* pnf_p7,
|
||||
ret_ul_dci->Slot = slot;
|
||||
ret_ul_dci->numPdus = 0;
|
||||
if (tx_slot_buffer->ul_dci_req.SFN == sfn && tx_slot_buffer->ul_dci_req.Slot == slot) {
|
||||
nfapi_nr_ul_dci_request_t* p = &tx_slot_buffer->ul_dci_req;
|
||||
ret_ul_dci->numPdus = p->numPdus;
|
||||
for (int i = 0; i < p->numPdus; ++i)
|
||||
ret_ul_dci->ul_dci_pdu_list[i] = p->ul_dci_pdu_list[i];
|
||||
copy_ul_dci_request(&tx_slot_buffer->ul_dci_req, ret_ul_dci);
|
||||
tx_slot_buffer->ul_dci_req.SFN = -1;
|
||||
tx_slot_buffer->ul_dci_req.Slot = -1;
|
||||
}
|
||||
|
||||
@@ -268,8 +268,8 @@ int nfapi_pnf_p7_nr_rx_data_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_rx_data_
|
||||
|
||||
pnf_p7_t* _this = (pnf_p7_t*)(config);
|
||||
AssertFatal(_this->_public.send_p7_msg, "Function pointer must be configured|");
|
||||
int ret = _this->_public.send_p7_msg(_this, (nfapi_nr_p7_message_header_t*)ind, sizeof(nfapi_nr_rx_data_indication_t));
|
||||
if (ret == 0) {
|
||||
bool ret = _this->_public.send_p7_msg(_this, (nfapi_nr_p7_message_header_t*)ind, sizeof(nfapi_nr_rx_data_indication_t));
|
||||
if (ret) {
|
||||
for (int i = 0; i < ind->number_of_pdus; ++i)
|
||||
_this->nr_stats.ul.bytes += ind->pdu_list[i].pdu_length;
|
||||
}
|
||||
|
||||
@@ -210,6 +210,24 @@ typedef struct nfapi_vnf_config
|
||||
int (*pnf_start_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_start_response_t* resp);
|
||||
int (*pnf_nr_start_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_pnf_start_response_t* resp);
|
||||
|
||||
/*! A callback for the STOP.indication
|
||||
* \param config A pointer to the vnf configuration
|
||||
* \param p5_idx The p5 index used to indicate a particular pnf p5 connection
|
||||
* \param ind A data structure for the decoded STOP.indication This will
|
||||
* have been allocated on the stack.
|
||||
* \return not currently used.
|
||||
*
|
||||
* The STOP.indication contains the result of the STOP.request
|
||||
*
|
||||
*
|
||||
* ind may contain pointers to dynamically allocated sub structures
|
||||
* such as the vendor_extention. The dynamically allocated structure will
|
||||
* be deallocated on return. If the client wishes to 'keep' the structures
|
||||
* then the substructure pointers should be set to 0 and then the client should
|
||||
* use the codec_config.deallocate function to release it at a future point
|
||||
*/
|
||||
int (*nr_stop_ind)(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_stop_indication_scf_t* ind);
|
||||
|
||||
/*! A callback for the PNF_STOP.resp
|
||||
* \param config A pointer to the vnf configuration
|
||||
* \param p5_idx The p5 index used to indicate a particular pnf p5 connection
|
||||
@@ -640,6 +658,7 @@ int nfapi_nr_vnf_start_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_star
|
||||
* \return 0 means success, -1 failure
|
||||
*/
|
||||
int nfapi_vnf_stop_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_stop_request_t* req);
|
||||
int nfapi_nr_vnf_stop_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_stop_request_scf_t* req);
|
||||
|
||||
/*! Send the MEASUREMENT.request
|
||||
* \param config A pointer to a vnf config
|
||||
|
||||
@@ -665,6 +665,30 @@ void vnf_nr_handle_error_indication(void *pRecvMsg, int recvMsgLen, nfapi_vnf_co
|
||||
}
|
||||
}
|
||||
|
||||
void vnf_nr_handle_stop_indication(void* pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx)
|
||||
{
|
||||
// ensure it's valid
|
||||
if (pRecvMsg == NULL || config == NULL) {
|
||||
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
|
||||
} else {
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "Received STOP.indication\n");
|
||||
|
||||
nfapi_nr_stop_indication_scf_t msg;
|
||||
|
||||
// unpack the message
|
||||
if (config->unpack_func(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config)) {
|
||||
if (config->nr_stop_ind) {
|
||||
(config->nr_stop_ind)(config, p5_idx, &msg);
|
||||
}
|
||||
} else {
|
||||
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
// make sure to release any dynamic part of the message
|
||||
if (msg.vendor_extension)
|
||||
config->codec_config.deallocate(msg.vendor_extension);
|
||||
}
|
||||
}
|
||||
|
||||
void vnf_handle_stop_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx)
|
||||
{
|
||||
@@ -1172,6 +1196,10 @@ void vnf_nr_handle_p4_p5_message(void *pRecvMsg, int recvMsgLen, int p5_idx, nfa
|
||||
vnf_handle_stop_response(pRecvMsg, recvMsgLen, config, p5_idx);
|
||||
break;
|
||||
|
||||
case NFAPI_NR_PHY_MSG_TYPE_STOP_INDICATION:
|
||||
vnf_nr_handle_stop_indication(pRecvMsg, recvMsgLen, config, p5_idx);
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
if(messageHeader.message_id >= NFAPI_VENDOR_EXT_MSG_MIN &&
|
||||
|
||||
@@ -665,6 +665,18 @@ int nfapi_vnf_stop_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_stop_reques
|
||||
|
||||
return vnf_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_stop_request_t));
|
||||
}
|
||||
|
||||
int nfapi_nr_vnf_stop_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_stop_request_scf_t* req)
|
||||
{
|
||||
if (config == 0 || req == 0)
|
||||
return -1;
|
||||
|
||||
vnf_t* _this = (vnf_t*)(config);
|
||||
AssertFatal(config->send_p5_msg, "Function pointer must be configured\n");
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Sending NFAPI STOP.request\n");
|
||||
return config->send_p5_msg(_this, p5_idx, &req->header, sizeof(nfapi_nr_stop_request_scf_t));
|
||||
}
|
||||
|
||||
int nfapi_vnf_measurement_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_measurement_request_t* req)
|
||||
{
|
||||
if(config == 0 || req == 0)
|
||||
|
||||
@@ -3,3 +3,6 @@ add_subdirectory(TOOLS)
|
||||
add_subdirectory(NR_TRANSPORT)
|
||||
add_subdirectory(CODING)
|
||||
add_subdirectory(MODULATION)
|
||||
if (ENABLE_TESTS)
|
||||
add_subdirectory(INIT/tests)
|
||||
endif()
|
||||
@@ -438,7 +438,7 @@ int main(int argc, char *argv[])
|
||||
int n_trials = 1;
|
||||
double SNR_step = 0.1;
|
||||
|
||||
randominit(0);
|
||||
randominit();
|
||||
int test_uncoded = 0;
|
||||
n_iter_stats_t dec_iter[400] = {0};
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ void lte_param_init(unsigned char N_tx, unsigned char N_rx,unsigned char transmi
|
||||
PHY_vars_UE = malloc(sizeof(PHY_VARS_UE));
|
||||
mac_xface = malloc(sizeof(MAC_xface));
|
||||
|
||||
randominit(0);
|
||||
randominit();
|
||||
set_taus_seed(0);
|
||||
|
||||
lte_frame_parms = &(PHY_vars_eNB->lte_frame_parms);
|
||||
@@ -367,7 +367,7 @@ int main(int argc, char *argv[])
|
||||
int num_pdcch_symbols = 1;
|
||||
int subframe = 6;
|
||||
|
||||
randominit(0);
|
||||
randominit();
|
||||
logInit();
|
||||
lte_param_init(1,1,1,0,0,3);
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ void lte_param_init(unsigned char N_tx, unsigned char N_rx)
|
||||
PHY_config = malloc(sizeof(PHY_CONFIG));
|
||||
mac_xface = malloc(sizeof(MAC_xface));
|
||||
|
||||
randominit(0);
|
||||
randominit();
|
||||
set_taus_seed(0);
|
||||
|
||||
lte_frame_parms = &(PHY_config->lte_frame_parms);
|
||||
@@ -241,8 +241,7 @@ int main(int argc, char *argv[])
|
||||
PHY_vars = malloc(sizeof(PHY_VARS));
|
||||
mac_xface = malloc(sizeof(MAC_xface));
|
||||
|
||||
|
||||
randominit(0);
|
||||
randominit();
|
||||
set_taus_seed(0);
|
||||
|
||||
ccodelte_init();
|
||||
|
||||
@@ -125,7 +125,7 @@ int main(int argc, char *argv[])
|
||||
cpu_meas_enabled = 1;
|
||||
reset_meas(&timeEncoder);
|
||||
reset_meas(&timeDecoder);
|
||||
randominit(0);
|
||||
randominit();
|
||||
crcTableInit();
|
||||
|
||||
if (polarMessageType == 0) { // PBCH
|
||||
|
||||
@@ -13,7 +13,7 @@ int main(int argc, char *argv[])
|
||||
cpu_meas_enabled = 1;
|
||||
reset_meas(&timeEncoder);
|
||||
reset_meas(&timeDecoder);
|
||||
randominit(0);
|
||||
randominit();
|
||||
|
||||
int ret = 1;
|
||||
int arguments, iterations = 1000, messageLength = 11;
|
||||
|
||||
@@ -77,7 +77,7 @@ void lte_param_init(PHY_VARS_eNB **eNBp,
|
||||
eNB->RU_list[0] = ru;
|
||||
ru->num_eNB=1;
|
||||
srand(0);
|
||||
randominit(0);
|
||||
randominit();
|
||||
set_taus_seed(0);
|
||||
frame_parms = &(eNB->frame_parms);
|
||||
frame_parms->N_RB_DL = N_RB_DL; //50 for 10MHz and 25 for 5 MHz
|
||||
|
||||
@@ -259,33 +259,116 @@ uint32_t get_samples_per_slot(int slot, const NR_DL_FRAME_PARMS *fp)
|
||||
return samp_count;
|
||||
}
|
||||
|
||||
uint32_t get_slot_from_timestamp(openair0_timestamp timestamp_rx, const NR_DL_FRAME_PARMS *fp)
|
||||
uint32_t get_samples_symbol_duration(const NR_DL_FRAME_PARMS *fp, int slot, int start_symbol, int num_symbols)
|
||||
{
|
||||
uint32_t slot_idx = 0;
|
||||
int samples_till_the_slot = fp->get_samples_per_slot(slot_idx,fp)-1;
|
||||
timestamp_rx = timestamp_rx%fp->samples_per_frame;
|
||||
int end_symbol = start_symbol + num_symbols - 1;
|
||||
AssertFatal(start_symbol <= end_symbol && start_symbol >= 0 && end_symbol < fp->symbols_per_slot,
|
||||
"Symbol range is invalid start_symbol %d, num_symbols %d symbols_per_slot %d\n",
|
||||
start_symbol,
|
||||
num_symbols,
|
||||
fp->symbols_per_slot);
|
||||
if (num_symbols == fp->symbols_per_slot) {
|
||||
return get_samples_per_slot(slot, fp);
|
||||
}
|
||||
uint32_t num_samples = 0;
|
||||
int num_symbols_added = 0;
|
||||
|
||||
while (timestamp_rx > samples_till_the_slot) {
|
||||
slot_idx++;
|
||||
samples_till_the_slot += fp->get_samples_per_slot(slot_idx,fp);
|
||||
}
|
||||
return slot_idx;
|
||||
// Handle symbols with different nb_prefix_samples0
|
||||
if (fp->numerology_index == 0) {
|
||||
// Add symbol 0
|
||||
if (start_symbol == 0) {
|
||||
num_samples += fp->nb_prefix_samples0 + fp->ofdm_symbol_size;
|
||||
num_symbols_added++;
|
||||
}
|
||||
// Add symbol 7
|
||||
if (start_symbol <= 7 && end_symbol >= 7) {
|
||||
num_samples += fp->nb_prefix_samples0 + fp->ofdm_symbol_size;
|
||||
num_symbols_added++;
|
||||
}
|
||||
} else {
|
||||
// Add first symbol
|
||||
if (start_symbol == 0) {
|
||||
num_samples += (slot % (fp->slots_per_subframe / 2)) ? fp->nb_prefix_samples : fp->nb_prefix_samples0;
|
||||
num_samples += fp->ofdm_symbol_size;
|
||||
num_symbols_added++;
|
||||
}
|
||||
}
|
||||
|
||||
int num_symbols_left = max(0, num_symbols - num_symbols_added);
|
||||
num_samples += num_symbols_left * (fp->nb_prefix_samples + fp->ofdm_symbol_size);
|
||||
return num_samples;
|
||||
}
|
||||
|
||||
uint32_t get_samples_slot_timestamp(int slot, const NR_DL_FRAME_PARMS *fp, unsigned int sl_ahead)
|
||||
uint32_t get_samples_symbol_timestamp(const NR_DL_FRAME_PARMS *fp, int slot, int symbol)
|
||||
{
|
||||
uint32_t samp_count = 0;
|
||||
|
||||
if(!sl_ahead) {
|
||||
for(unsigned int idx_slot = 0; idx_slot < slot; idx_slot++)
|
||||
samp_count += fp->get_samples_per_slot(idx_slot, fp);
|
||||
} else {
|
||||
for (unsigned int idx_slot = slot; idx_slot < slot + sl_ahead; idx_slot++)
|
||||
samp_count += fp->get_samples_per_slot(idx_slot, fp);
|
||||
if (symbol == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return get_samples_symbol_duration(fp, slot, 0, symbol);
|
||||
}
|
||||
|
||||
uint32_t get_slot_from_timestamp(openair0_timestamp timestamp_rx, const NR_DL_FRAME_PARMS *fp)
|
||||
{
|
||||
timestamp_rx = timestamp_rx % fp->samples_per_frame;
|
||||
if (timestamp_rx < fp->samples_per_slot0)
|
||||
return 0;
|
||||
|
||||
if (fp->numerology_index == 0)
|
||||
return timestamp_rx / fp->samples_per_subframe;
|
||||
|
||||
const unsigned int num_half_sf = timestamp_rx / (fp->samples_per_subframe / 2);
|
||||
const unsigned int slot_per_half_sf = fp->slots_per_subframe / 2;
|
||||
|
||||
uint32_t slot_count = num_half_sf * slot_per_half_sf;
|
||||
int samp_idx = num_half_sf * (fp->samples_per_subframe / 2) - 1;
|
||||
|
||||
// Remaining samples
|
||||
if (samp_idx < timestamp_rx) {
|
||||
slot_count++;
|
||||
samp_idx += fp->samples_per_slot0; // First slot of half subframe
|
||||
}
|
||||
if (samp_idx < timestamp_rx) {
|
||||
const unsigned int rem_samples = timestamp_rx - samp_idx;
|
||||
const unsigned int num_slots = ceil((double)rem_samples / fp->samples_per_slotN0);
|
||||
slot_count += num_slots;
|
||||
}
|
||||
|
||||
return slot_count - 1;
|
||||
}
|
||||
|
||||
uint32_t get_samples_slot_timestamp(const NR_DL_FRAME_PARMS *fp, unsigned int slot)
|
||||
{
|
||||
if (slot == 0)
|
||||
return 0;
|
||||
|
||||
if (fp->numerology_index == 0)
|
||||
return slot * fp->samples_per_subframe;
|
||||
|
||||
uint32_t samp_count = 0;
|
||||
// Number of half subframes
|
||||
const unsigned int num_half_sf = slot / (fp->slots_per_subframe / 2);
|
||||
samp_count += num_half_sf * fp->samples_per_subframe / 2;
|
||||
|
||||
// Remaining slots
|
||||
unsigned int rem_slots = slot % (fp->slots_per_subframe / 2);
|
||||
if (rem_slots > 0) {
|
||||
samp_count += fp->samples_per_slot0; // First slot of the last half subframe
|
||||
rem_slots--;
|
||||
}
|
||||
samp_count += rem_slots * fp->samples_per_slotN0; // Remaining slots of the last half subframe
|
||||
|
||||
return samp_count;
|
||||
}
|
||||
|
||||
uint32_t get_samples_slot_duration(const NR_DL_FRAME_PARMS *fp, unsigned int start_slot, unsigned int num_slots)
|
||||
{
|
||||
if (start_slot == 0 && num_slots == 0)
|
||||
return 0;
|
||||
|
||||
return (get_samples_slot_timestamp(fp, start_slot + num_slots) - get_samples_slot_timestamp(fp, start_slot));
|
||||
}
|
||||
|
||||
void nr_init_frame_parms(nfapi_nr_config_request_scf_t* cfg, NR_DL_FRAME_PARMS *fp)
|
||||
{
|
||||
|
||||
@@ -319,12 +402,11 @@ void nr_init_frame_parms(nfapi_nr_config_request_scf_t* cfg, NR_DL_FRAME_PARMS *
|
||||
fp->samples_per_frame_wCP = 10 * fp->samples_per_subframe_wCP;
|
||||
fp->samples_per_slot_wCP = fp->symbols_per_slot*fp->ofdm_symbol_size;
|
||||
fp->samples_per_slotN0 = (fp->nb_prefix_samples + fp->ofdm_symbol_size) * fp->symbols_per_slot;
|
||||
fp->samples_per_slot0 = fp->nb_prefix_samples0 + ((fp->symbols_per_slot-1)*fp->nb_prefix_samples) + (fp->symbols_per_slot*fp->ofdm_symbol_size);
|
||||
fp->samples_per_subframe = (fp->nb_prefix_samples0 + fp->ofdm_symbol_size) * 2 +
|
||||
(fp->nb_prefix_samples + fp->ofdm_symbol_size) * (fp->symbols_per_slot * fp->slots_per_subframe - 2);
|
||||
fp->get_samples_per_slot = &get_samples_per_slot;
|
||||
fp->get_samples_slot_timestamp = &get_samples_slot_timestamp;
|
||||
fp->get_slot_from_timestamp = &get_slot_from_timestamp;
|
||||
fp->samples_per_subframe = (fp->nb_prefix_samples0 + fp->ofdm_symbol_size) * 2
|
||||
+ (fp->nb_prefix_samples + fp->ofdm_symbol_size) * (fp->symbols_per_slot * fp->slots_per_subframe - 2);
|
||||
fp->samples_per_slot0 = fp->numerology_index == 0 ? fp->samples_per_subframe
|
||||
: fp->nb_prefix_samples0 + ((fp->symbols_per_slot - 1) * fp->nb_prefix_samples)
|
||||
+ (fp->symbols_per_slot * fp->ofdm_symbol_size);
|
||||
fp->samples_per_frame = 10 * fp->samples_per_subframe;
|
||||
fp->freq_range = get_freq_range_from_freq(fp->dl_CarrierFreq);
|
||||
|
||||
@@ -402,11 +484,11 @@ int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *fp,
|
||||
fp->samples_per_frame_wCP = 10 * fp->samples_per_subframe_wCP;
|
||||
fp->samples_per_slot_wCP = fp->symbols_per_slot*fp->ofdm_symbol_size;
|
||||
fp->samples_per_slotN0 = (fp->nb_prefix_samples + fp->ofdm_symbol_size) * fp->symbols_per_slot;
|
||||
fp->samples_per_slot0 = fp->nb_prefix_samples0 + ((fp->symbols_per_slot-1)*fp->nb_prefix_samples) + (fp->symbols_per_slot*fp->ofdm_symbol_size);
|
||||
fp->samples_per_subframe = (fp->nb_prefix_samples0 + fp->ofdm_symbol_size) * 2 +
|
||||
(fp->nb_prefix_samples + fp->ofdm_symbol_size) * (fp->symbols_per_slot * fp->slots_per_subframe - 2);
|
||||
fp->get_samples_per_slot = &get_samples_per_slot;
|
||||
fp->get_samples_slot_timestamp = &get_samples_slot_timestamp;
|
||||
fp->samples_per_subframe = (fp->nb_prefix_samples0 + fp->ofdm_symbol_size) * 2
|
||||
+ (fp->nb_prefix_samples + fp->ofdm_symbol_size) * (fp->symbols_per_slot * fp->slots_per_subframe - 2);
|
||||
fp->samples_per_slot0 = fp->numerology_index == 0 ? fp->samples_per_subframe
|
||||
: fp->nb_prefix_samples0 + ((fp->symbols_per_slot - 1) * fp->nb_prefix_samples)
|
||||
+ (fp->symbols_per_slot * fp->ofdm_symbol_size);
|
||||
fp->samples_per_frame = 10 * fp->samples_per_subframe;
|
||||
fp->freq_range = get_freq_range_from_freq(fp->dl_CarrierFreq);
|
||||
|
||||
@@ -460,11 +542,14 @@ void nr_init_frame_parms_ue_sa(NR_DL_FRAME_PARMS *frame_parms, uint64_t downlink
|
||||
frame_parms->samples_per_frame_wCP = 10 * frame_parms->samples_per_subframe_wCP;
|
||||
frame_parms->samples_per_slot_wCP = frame_parms->symbols_per_slot*frame_parms->ofdm_symbol_size;
|
||||
frame_parms->samples_per_slotN0 = (frame_parms->nb_prefix_samples + frame_parms->ofdm_symbol_size) * frame_parms->symbols_per_slot;
|
||||
frame_parms->samples_per_slot0 = frame_parms->nb_prefix_samples0 + ((frame_parms->symbols_per_slot-1)*frame_parms->nb_prefix_samples) + (frame_parms->symbols_per_slot*frame_parms->ofdm_symbol_size);
|
||||
frame_parms->samples_per_subframe = (frame_parms->nb_prefix_samples0 + frame_parms->ofdm_symbol_size) * 2 +
|
||||
(frame_parms->nb_prefix_samples + frame_parms->ofdm_symbol_size) * (frame_parms->symbols_per_slot * frame_parms->slots_per_subframe - 2);
|
||||
frame_parms->get_samples_per_slot = &get_samples_per_slot;
|
||||
frame_parms->get_samples_slot_timestamp = &get_samples_slot_timestamp;
|
||||
frame_parms->samples_per_subframe = (frame_parms->nb_prefix_samples0 + frame_parms->ofdm_symbol_size) * 2
|
||||
+ (frame_parms->nb_prefix_samples + frame_parms->ofdm_symbol_size)
|
||||
* (frame_parms->symbols_per_slot * frame_parms->slots_per_subframe - 2);
|
||||
frame_parms->samples_per_slot0 = frame_parms->numerology_index == 0
|
||||
? frame_parms->samples_per_subframe
|
||||
: frame_parms->nb_prefix_samples0
|
||||
+ ((frame_parms->symbols_per_slot - 1) * frame_parms->nb_prefix_samples)
|
||||
+ (frame_parms->symbols_per_slot * frame_parms->ofdm_symbol_size);
|
||||
frame_parms->samples_per_frame = 10 * frame_parms->samples_per_subframe;
|
||||
|
||||
LOG_W(PHY, "samples_per_subframe %d/per second %d, wCP %d\n", frame_parms->samples_per_subframe, 1000*frame_parms->samples_per_subframe, frame_parms->samples_per_subframe_wCP);
|
||||
@@ -560,12 +645,11 @@ int nr_init_frame_parms_ue_sl(NR_DL_FRAME_PARMS *fp,
|
||||
fp->samples_per_frame_wCP = 10 * fp->samples_per_subframe_wCP;
|
||||
fp->samples_per_slot_wCP = fp->symbols_per_slot * fp->ofdm_symbol_size;
|
||||
fp->samples_per_slotN0 = (fp->nb_prefix_samples + fp->ofdm_symbol_size) * fp->symbols_per_slot;
|
||||
fp->samples_per_slot0 =
|
||||
fp->nb_prefix_samples0 + ((fp->symbols_per_slot - 1) * fp->nb_prefix_samples) + (fp->symbols_per_slot * fp->ofdm_symbol_size);
|
||||
fp->samples_per_subframe = (fp->nb_prefix_samples0 + fp->ofdm_symbol_size) * 2
|
||||
+ (fp->nb_prefix_samples + fp->ofdm_symbol_size) * (fp->symbols_per_slot * fp->slots_per_subframe - 2);
|
||||
fp->get_samples_per_slot = &get_samples_per_slot;
|
||||
fp->get_samples_slot_timestamp = &get_samples_slot_timestamp;
|
||||
fp->samples_per_slot0 = fp->numerology_index == 0 ? fp->samples_per_subframe
|
||||
: fp->nb_prefix_samples0 + ((fp->symbols_per_slot - 1) * fp->nb_prefix_samples)
|
||||
+ (fp->symbols_per_slot * fp->ofdm_symbol_size);
|
||||
fp->samples_per_frame = 10 * fp->samples_per_subframe;
|
||||
fp->freq_range = get_freq_range_from_freq(fp->sl_CarrierFreq);
|
||||
|
||||
|
||||
@@ -55,10 +55,11 @@ void free_nr_ue_ul_harq(NR_UL_UE_HARQ_t harq_list[NR_MAX_ULSCH_HARQ_PROCESSES],
|
||||
|
||||
void phy_init_nr_top(PHY_VARS_NR_UE *ue);
|
||||
void phy_term_nr_top(void);
|
||||
#ifndef __cplusplus
|
||||
void init_delay_table(uint16_t ofdm_symbol_size,
|
||||
int max_delay_comp,
|
||||
int max_ofdm_symbol_size,
|
||||
c16_t delay_table[][max_ofdm_symbol_size]);
|
||||
|
||||
#endif
|
||||
void sl_ue_phy_init(PHY_VARS_NR_UE *UE);
|
||||
#endif
|
||||
|
||||
2
openair1/PHY/INIT/tests/CMakeLists.txt
Normal file
2
openair1/PHY/INIT/tests/CMakeLists.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
add_executable(test_nr_frame_params test_nr_frame_params.cpp)
|
||||
target_link_libraries(test_nr_frame_params PRIVATE LOG minimal_lib PHY_NR -lm GTest::gtest)
|
||||
177
openair1/PHY/INIT/tests/test_nr_frame_params.cpp
Normal file
177
openair1/PHY/INIT/tests/test_nr_frame_params.cpp
Normal file
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
* 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 "gtest/gtest.h"
|
||||
extern "C" {
|
||||
#include <stdlib.h>
|
||||
#include "openair1/PHY/defs_nr_common.h"
|
||||
#include "openair1/PHY/INIT/nr_phy_init.h"
|
||||
|
||||
static softmodem_params_t softmodem_params;
|
||||
softmodem_params_t *get_softmodem_params(void)
|
||||
{
|
||||
return &softmodem_params;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t ref_get_samples_slot_timestamp(NR_DL_FRAME_PARMS *fp, unsigned int slot)
|
||||
{
|
||||
uint32_t samp_count = 0;
|
||||
for (unsigned int i = 0; i < slot; i++) {
|
||||
samp_count += get_samples_per_slot(i, fp);
|
||||
}
|
||||
return samp_count;
|
||||
}
|
||||
|
||||
uint32_t ref_get_slot_from_timestamp(openair0_timestamp ts, NR_DL_FRAME_PARMS *fp)
|
||||
{
|
||||
uint32_t slot_idx = 0;
|
||||
int samples_till_the_slot = get_samples_per_slot(slot_idx, fp) - 1;
|
||||
ts = ts % fp->samples_per_frame;
|
||||
|
||||
while (ts > samples_till_the_slot) {
|
||||
slot_idx++;
|
||||
samples_till_the_slot += get_samples_per_slot(slot_idx, fp);
|
||||
}
|
||||
return slot_idx;
|
||||
}
|
||||
|
||||
void test_coherence_symbol_api(NR_DL_FRAME_PARMS *fp)
|
||||
{
|
||||
EXPECT_EQ(get_samples_symbol_timestamp(fp, 0, 0), get_samples_slot_timestamp(fp, 0));
|
||||
|
||||
for (int slot = 0; slot < 4; slot++) {
|
||||
EXPECT_EQ(get_samples_symbol_duration(fp, slot, 0, fp->symbols_per_slot) + get_samples_slot_timestamp(fp, slot),
|
||||
get_samples_slot_timestamp(fp, slot + 1));
|
||||
}
|
||||
|
||||
for (int symbol = 0; symbol < fp->symbols_per_slot - 1; symbol++) {
|
||||
EXPECT_EQ(get_samples_symbol_timestamp(fp, 0, symbol + 1) - get_samples_symbol_timestamp(fp, 0, symbol),
|
||||
get_samples_symbol_duration(fp, 0, symbol, 1));
|
||||
}
|
||||
}
|
||||
|
||||
void test_coherence_slot_api(NR_DL_FRAME_PARMS *fp)
|
||||
{
|
||||
for (unsigned int slot = 0; slot < fp->slots_per_frame; slot++) {
|
||||
EXPECT_EQ(get_samples_slot_timestamp(fp, slot), ref_get_samples_slot_timestamp(fp, slot));
|
||||
}
|
||||
|
||||
openair0_timestamp ts = get_samples_per_slot(0, fp);
|
||||
// When timestamp is the last sample of the slot
|
||||
EXPECT_EQ(get_slot_from_timestamp(ts - 1, fp), 0);
|
||||
for (unsigned int slot = 0; slot < fp->slots_per_frame; slot++) {
|
||||
// When timestamp is the first sample of the slot
|
||||
ts = ref_get_samples_slot_timestamp(fp, slot);
|
||||
EXPECT_EQ(get_slot_from_timestamp(ts, fp), slot);
|
||||
// When timestamp is anywhere in the slot
|
||||
ts += (rand() % fp->samples_per_slotN0);
|
||||
EXPECT_EQ(get_slot_from_timestamp(ts, fp), slot);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(nr_frame_params, test_mu_3)
|
||||
{
|
||||
NR_DL_FRAME_PARMS fp;
|
||||
int mu = NR_MU_3;
|
||||
memset(&fp, 0, sizeof(fp));
|
||||
nfapi_nr_config_request_scf_t cfg;
|
||||
cfg.carrier_config.num_rx_ant.value = 4;
|
||||
cfg.carrier_config.num_tx_ant.value = 4;
|
||||
cfg.carrier_config.dl_grid_size[mu].value = 66;
|
||||
cfg.carrier_config.ul_grid_size[mu].value = 66;
|
||||
cfg.cell_config.frame_duplex_type.value = TDD;
|
||||
cfg.ssb_config.scs_common.value = mu;
|
||||
fp.dl_CarrierFreq = 27524520000;
|
||||
fp.nr_band = 261;
|
||||
nr_init_frame_parms(&cfg, &fp);
|
||||
nr_dump_frame_parms(&fp);
|
||||
test_coherence_symbol_api(&fp);
|
||||
test_coherence_slot_api(&fp);
|
||||
}
|
||||
|
||||
TEST(nr_frame_params, test_mu_2)
|
||||
{
|
||||
NR_DL_FRAME_PARMS fp;
|
||||
int mu = NR_MU_2;
|
||||
memset(&fp, 0, sizeof(fp));
|
||||
nfapi_nr_config_request_scf_t cfg;
|
||||
cfg.carrier_config.num_rx_ant.value = 4;
|
||||
cfg.carrier_config.num_tx_ant.value = 4;
|
||||
cfg.carrier_config.dl_grid_size[mu].value = 51;
|
||||
cfg.carrier_config.ul_grid_size[mu].value = 51;
|
||||
cfg.cell_config.frame_duplex_type.value = TDD;
|
||||
cfg.ssb_config.scs_common.value = mu;
|
||||
fp.dl_CarrierFreq = 27524520000;
|
||||
fp.nr_band = 261;
|
||||
nr_init_frame_parms(&cfg, &fp);
|
||||
nr_dump_frame_parms(&fp);
|
||||
test_coherence_symbol_api(&fp);
|
||||
test_coherence_slot_api(&fp);
|
||||
}
|
||||
|
||||
TEST(nr_frame_params, test_mu_1)
|
||||
{
|
||||
NR_DL_FRAME_PARMS fp;
|
||||
int mu = NR_MU_1;
|
||||
memset(&fp, 0, sizeof(fp));
|
||||
nfapi_nr_config_request_scf_t cfg;
|
||||
cfg.carrier_config.num_rx_ant.value = 4;
|
||||
cfg.carrier_config.num_tx_ant.value = 4;
|
||||
cfg.carrier_config.dl_grid_size[mu].value = 106;
|
||||
cfg.carrier_config.ul_grid_size[mu].value = 106;
|
||||
cfg.cell_config.frame_duplex_type.value = TDD;
|
||||
cfg.ssb_config.scs_common.value = mu;
|
||||
fp.dl_CarrierFreq = 3600000000;
|
||||
fp.nr_band = 78;
|
||||
nr_init_frame_parms(&cfg, &fp);
|
||||
nr_dump_frame_parms(&fp);
|
||||
test_coherence_symbol_api(&fp);
|
||||
test_coherence_slot_api(&fp);
|
||||
}
|
||||
|
||||
TEST(nr_frame_params, test_mu_0)
|
||||
{
|
||||
int mu = NR_MU_0;
|
||||
NR_DL_FRAME_PARMS fp;
|
||||
memset(&fp, 0, sizeof(fp));
|
||||
nfapi_nr_config_request_scf_t cfg;
|
||||
cfg.carrier_config.num_rx_ant.value = 4;
|
||||
cfg.carrier_config.num_tx_ant.value = 4;
|
||||
cfg.carrier_config.dl_grid_size[mu].value = 216;
|
||||
cfg.carrier_config.ul_grid_size[mu].value = 216;
|
||||
cfg.cell_config.frame_duplex_type.value = TDD;
|
||||
cfg.ssb_config.scs_common.value = mu;
|
||||
fp.dl_CarrierFreq = 2600000000;
|
||||
fp.nr_band = 38;
|
||||
nr_init_frame_parms(&cfg, &fp);
|
||||
nr_dump_frame_parms(&fp);
|
||||
test_coherence_symbol_api(&fp);
|
||||
test_coherence_slot_api(&fp);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
uniqCfg = load_configmodule(argc, argv, CONFIG_ENABLECMDLINEONLY);
|
||||
logInit();
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
@@ -80,7 +80,7 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue,
|
||||
// For Sidelink 16 frames worth of samples is processed to find SSB, for 5G-NR 2.
|
||||
const unsigned int total_samples = (is_sl) ? 16 * frame_parms->samples_per_frame : 2 * frame_parms->samples_per_frame;
|
||||
|
||||
unsigned int rx_offset = frame_parms->get_samples_slot_timestamp(slot, frame_parms, 0);
|
||||
unsigned int rx_offset = get_samples_slot_timestamp(frame_parms, slot);
|
||||
const unsigned int abs_symbol = slot * frame_parms->symbols_per_slot + symbol;
|
||||
for (int idx_symb = slot * frame_parms->symbols_per_slot; idx_symb <= abs_symbol; idx_symb++)
|
||||
rx_offset += (idx_symb % (0x7 << frame_parms->numerology_index)) ? nb_prefix_samples : nb_prefix_samples0;
|
||||
@@ -150,7 +150,7 @@ int nr_slot_fep_ul(NR_DL_FRAME_PARMS *frame_parms,
|
||||
int32_t tmp_dft_in[8192] __attribute__ ((aligned (32)));
|
||||
|
||||
// offset of first OFDM symbol
|
||||
unsigned int rxdata_offset = frame_parms->get_samples_slot_timestamp(Ns,frame_parms,0);
|
||||
unsigned int rxdata_offset = get_samples_slot_timestamp(frame_parms, Ns);
|
||||
unsigned int abs_symbol = Ns * frame_parms->symbols_per_slot + symbol;
|
||||
for (int idx_symb = Ns*frame_parms->symbols_per_slot; idx_symb <= abs_symbol; idx_symb++)
|
||||
rxdata_offset += (idx_symb%(0x7<<frame_parms->numerology_index)) ? nb_prefix_samples : nb_prefix_samples0;
|
||||
|
||||
@@ -362,7 +362,7 @@ static void rx_nr_prach_ru_internal(prach_item_t *p,
|
||||
// Fixme: slot or slot makes no sense ???
|
||||
int slot2 = p->prach_sequence_length ? p->slot : p->slot;
|
||||
int idx = aa + beam_id * p->nb_rx;
|
||||
c16_t *prach = (c16_t *)&rxdata[idx][fp->get_samples_slot_timestamp(slot2, fp, 0) + sample_offset_slot - N_TA_offset];
|
||||
c16_t *prach = (c16_t *)&rxdata[idx][get_samples_slot_timestamp(fp, slot2) + sample_offset_slot - N_TA_offset];
|
||||
|
||||
// do DFT
|
||||
c16_t *prach2 = prach + Ncp;
|
||||
|
||||
@@ -324,7 +324,7 @@ nr_initial_sync_t sl_nr_slss_search(PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc,
|
||||
|
||||
int32_t sync_pos = -1; // sync_pos_frame = -1;
|
||||
int32_t metric_tdd_ncp = 0;
|
||||
uint8_t phase_tdd_ncp;
|
||||
uint8_t phase_tdd_ncp = 0;
|
||||
double im, re;
|
||||
int ret = -1;
|
||||
uint16_t rx_slss_id = 65535;
|
||||
|
||||
@@ -70,6 +70,7 @@ void math_dft(cd_t *in, cd_t *out, int len)
|
||||
int main(void)
|
||||
{
|
||||
int ret = 0;
|
||||
randominit();
|
||||
load_dftslib();
|
||||
c16_t *d16 = malloc16(12 * dftFtab[sizeofArray(dftFtab) - 1].size * sizeof(*d16));
|
||||
c16_t *o16 = malloc16(12 * dftFtab[sizeofArray(dftFtab) - 1].size * sizeof(*d16));
|
||||
|
||||
@@ -467,7 +467,8 @@ typedef struct PHY_VARS_NR_UE_s {
|
||||
|
||||
/// Timing Advance updates variables
|
||||
/// Timing advance update computed from the TA command signalled from gNB
|
||||
int timing_advance;
|
||||
int timing_advance; /// corresponds to N_TA
|
||||
int timing_advance_ntn; /// corresponds to N_common_TA_adj + N_UE_TA_adj
|
||||
int N_TA_offset; ///timing offset used in TDD
|
||||
int ta_frame;
|
||||
int ta_slot;
|
||||
@@ -538,11 +539,14 @@ typedef struct {
|
||||
/// NR slot index within frame_rx [0 .. slots_per_frame - 1] to act upon for transmission
|
||||
int nr_slot_rx;
|
||||
int tx_slot_type;
|
||||
//#endif
|
||||
/// frame to act upon for transmission
|
||||
int frame_tx;
|
||||
/// frame to act upon for reception
|
||||
int frame_rx;
|
||||
/// hyper frame number to act upon for transmission
|
||||
int hfn_tx;
|
||||
/// hyper frame number to act upon for reception
|
||||
int hfn_rx;
|
||||
} UE_nr_rxtx_proc_t;
|
||||
|
||||
typedef struct {
|
||||
|
||||
@@ -165,11 +165,6 @@ void init_prach_list(prach_list_t *);
|
||||
|
||||
typedef struct NR_DL_FRAME_PARMS NR_DL_FRAME_PARMS;
|
||||
|
||||
typedef uint32_t (*get_samples_per_slot_t)(int slot, const NR_DL_FRAME_PARMS *fp);
|
||||
typedef uint32_t (*get_slot_from_timestamp_t)(openair0_timestamp timestamp_rx, const NR_DL_FRAME_PARMS *fp);
|
||||
|
||||
typedef uint32_t (*get_samples_slot_timestamp_t)(int slot, const NR_DL_FRAME_PARMS *fp, unsigned int sl_ahead);
|
||||
|
||||
struct NR_DL_FRAME_PARMS {
|
||||
/// frequency range
|
||||
frequency_range_t freq_range;
|
||||
@@ -225,12 +220,6 @@ struct NR_DL_FRAME_PARMS {
|
||||
uint16_t slots_per_frame;
|
||||
/// Number of samples in a subframe
|
||||
uint32_t samples_per_subframe;
|
||||
/// Number of samples in current slot
|
||||
get_samples_per_slot_t get_samples_per_slot;
|
||||
/// slot calculation from timestamp
|
||||
get_slot_from_timestamp_t get_slot_from_timestamp;
|
||||
/// Number of samples before slot
|
||||
get_samples_slot_timestamp_t get_samples_slot_timestamp;
|
||||
/// Number of samples in 0th and center slot of a subframe
|
||||
uint32_t samples_per_slot0;
|
||||
/// Number of samples in other slots of the subframe
|
||||
@@ -336,4 +325,17 @@ typedef struct {
|
||||
#define KHz (1000UL)
|
||||
#define MHz (1000*KHz)
|
||||
|
||||
// Get symbol duration within slot in samples
|
||||
uint32_t get_samples_symbol_duration(const NR_DL_FRAME_PARMS *fp, int slot, int start_symbol, int num_symbols);
|
||||
// Get timestamp of symbol within slot in samples
|
||||
uint32_t get_samples_symbol_timestamp(const NR_DL_FRAME_PARMS *fp, int slot, int symbol);
|
||||
// Get slot duration between two slot
|
||||
uint32_t get_samples_slot_duration(const NR_DL_FRAME_PARMS *fp, unsigned int start_slot, unsigned int num_slots);
|
||||
// Get timestamp of slot from start of frame
|
||||
uint32_t get_samples_slot_timestamp(const NR_DL_FRAME_PARMS *fp, unsigned int slot);
|
||||
// Get slot from timestamp
|
||||
uint32_t get_slot_from_timestamp(openair0_timestamp timestamp_rx, const NR_DL_FRAME_PARMS *fp);
|
||||
// Get number of samples in the slot
|
||||
uint32_t get_samples_per_slot(int slot, const NR_DL_FRAME_PARMS *fp);
|
||||
|
||||
#endif
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user