mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-18 15:10:29 +00:00
Compare commits
24 Commits
sl-eurecom
...
sl-eurecom
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
439bcdf9f8 | ||
|
|
4d21f2fd3e | ||
|
|
bcac6783da | ||
|
|
f35a75baa2 | ||
|
|
ef201f1419 | ||
|
|
eb38ab0a56 | ||
|
|
26700cbb18 | ||
|
|
bbaf90c64d | ||
|
|
5c0497c92a | ||
|
|
13c035ef77 | ||
|
|
9c9e50391e | ||
|
|
801886c8d9 | ||
|
|
a957cc7b59 | ||
|
|
6eba4d2abe | ||
|
|
82af5bb27b | ||
|
|
7d0119efa6 | ||
|
|
c67c11b380 | ||
|
|
92c5b04cdb | ||
|
|
ad6e003ad3 | ||
|
|
0a1d4ba709 | ||
|
|
9ae927b862 | ||
|
|
fd54152a53 | ||
|
|
d01693b901 | ||
|
|
cf65d02fd4 |
376
README.md
376
README.md
@@ -1,74 +1,330 @@
|
||||
<h1 align="center">
|
||||
<a href="https://openairinterface.org/"><img src="https://openairinterface.org/wp-content/uploads/2015/06/cropped-oai_final_logo.png" alt="OAI" width="550"></a>
|
||||
</h1>
|
||||
# OAI-SL-MultiUE-Broker
|
||||
|
||||
<p align="center">
|
||||
<a href="https://gitlab.eurecom.fr/oai/openairinterface5g/-/blob/master/LICENSE"><img src="https://img.shields.io/badge/license-OAI--Public--V1.1-blue" alt="License"></a>
|
||||
<a href="https://releases.ubuntu.com/18.04/"><img src="https://img.shields.io/badge/OS-Ubuntu18-Green" alt="Supported OS Ubuntu 18"></a>
|
||||
<a href="https://releases.ubuntu.com/20.04/"><img src="https://img.shields.io/badge/OS-Ubuntu20-Green" alt="Supported OS Ubuntu 20"></a>
|
||||
<a href="https://releases.ubuntu.com/22.04/"><img src="https://img.shields.io/badge/OS-Ubuntu22-Green" alt="Supported OS Ubuntu 22"></a>
|
||||
<a href="https://www.redhat.com/en/technologies/linux-platforms/enterprise-linux"><img src="https://img.shields.io/badge/OS-RHEL8-Green" alt="Supported OS RHEL8"></a>
|
||||
<a href="https://www.redhat.com/en/technologies/linux-platforms/enterprise-linux"><img src="https://img.shields.io/badge/OS-RHEL9-Green" alt="Supported OS RELH9"></a>
|
||||
<a href="https://getfedora.org/en/workstation/"><img src="https://img.shields.io/badge/OS-Fedore37-Green" alt="Supported OS Fedora 37"></a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://jenkins-oai.eurecom.fr/job/RAN-Container-Parent/"><img src="https://img.shields.io/jenkins/build?jobUrl=https%3A%2F%2Fjenkins-oai.eurecom.fr%2Fjob%2FRAN-Container-Parent%2F&label=build%20Images"></a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://hub.docker.com/r/oaisoftwarealliance/oai-gnb"><img alt="Docker Pulls" src="https://img.shields.io/docker/pulls/oaisoftwarealliance/oai-gnb?label=gNB%20docker%20pulls"></a>
|
||||
<a href="https://hub.docker.com/r/oaisoftwarealliance/oai-nr-ue"><img alt="Docker Pulls" src="https://img.shields.io/docker/pulls/oaisoftwarealliance/oai-nr-ue?label=NR-UE%20docker%20pulls"></a>
|
||||
<a href="https://hub.docker.com/r/oaisoftwarealliance/oai-enb"><img alt="Docker Pulls" src="https://img.shields.io/docker/pulls/oaisoftwarealliance/oai-enb?label=eNB%20docker%20pulls"></a>
|
||||
<a href="https://hub.docker.com/r/oaisoftwarealliance/oai-lte-ue"><img alt="Docker Pulls" src="https://img.shields.io/docker/pulls/oaisoftwarealliance/oai-lte-ue?label=LTE-UE%20docker%20pulls"></a>
|
||||
</p>
|
||||
## RFSim Broker based Multiple UEs Test
|
||||
|
||||
# OpenAirInterface License #
|
||||
This part test is based on ‘sl-eurecom4’ branch on openairinterface5g.
|
||||
(https://gitlab.eurecom.fr/oai/openairinterface5g.git)
|
||||
|
||||
* [OAI License Model](http://www.openairinterface.org/?page_id=101)
|
||||
* [OAI License v1.1 on our website](http://www.openairinterface.org/?page_id=698)
|
||||
|
||||
It is distributed under **OAI Public License V1.1**.
|
||||
|
||||
The license information is distributed under [LICENSE](LICENSE) file in the same directory.
|
||||
|
||||
Please see [NOTICE](NOTICE.md) file for third party software that is included in the sources.
|
||||
|
||||
# Where to Start #
|
||||
|
||||
* [General overview of documentation](./doc/README.md)
|
||||
* [The implemented features](./doc/FEATURE_SET.md)
|
||||
* [How to build](./doc/BUILD.md)
|
||||
* [How to run the modems](./doc/RUNMODEM.md)
|
||||
|
||||
Not all information is available in a central place, and information for
|
||||
specific sub-systems might be available in the corresponding sub-directories.
|
||||
To find all READMEs, this command might be handy:
|
||||
## To start
|
||||
|
||||
First go to the correct repository :
|
||||
```
|
||||
find . -iname "readme*"
|
||||
cd openairinterface5g/cmake_targets
|
||||
```
|
||||
To install zeroMQ :
|
||||
```
|
||||
apt-get install libzmq3-dev
|
||||
```
|
||||
Then start compilation :
|
||||
```
|
||||
sudo ./build_oai --nrUE -w SIMU --cmake-opt -DENABLE_T_TRACER=OFF
|
||||
```
|
||||
Or, to start a clean start compilation, do the clean up first then compile :
|
||||
```
|
||||
sudo ./build_oai -c -C
|
||||
|
||||
sudo ./build_oai -I --cmake-opt -DENABLE_T_TRACER=OFF
|
||||
```
|
||||
Now we need to create three UEs through namespaces:
|
||||
```
|
||||
cd openairinterface5g/cmake_targets
|
||||
sudo ./multi-ue.sh -c1 -c2 -c3
|
||||
```
|
||||
* It is likely the new system would face the ASN.1 error, which is due to the wrong version of ASN.1. To fix it, please do the following:
|
||||
|
||||
* Remove the current wrong version :
|
||||
```
|
||||
sudo rm -rf /opt/asn1c
|
||||
sudo rm -rf /tmp/asn1c
|
||||
```
|
||||
* Clone and checkout the exact same commit:
|
||||
```
|
||||
cd /tmp
|
||||
git clone https://github.com/mouse07410/asn1c.git
|
||||
cd asn1c
|
||||
git checkout 657f5790
|
||||
```
|
||||
* Build and install the correct version :
|
||||
```
|
||||
git submodule update --init --recursive
|
||||
autoreconf -iv
|
||||
./configure --prefix=/opt/asn1c
|
||||
make -j$(nproc)
|
||||
sudo make install
|
||||
```
|
||||
* Then recompile. Do remember to delete the wrong /ran_build files :
|
||||
```
|
||||
cd ~/OAI-SL-Broker/openairinterface5g/cmake_targets
|
||||
rm -rf ran_build
|
||||
sudo ./build_oai --nrUE -w SIMU --cmake-opt -DENABLE_T_TRACER=OFF
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
## Start RFSim for Multiple UEs through Broker
|
||||
|
||||
|
||||
### Launch Broker (outside namespace):
|
||||
```
|
||||
cd ran_build/build/
|
||||
./broker
|
||||
```
|
||||
|
||||
# RAN repository structure #
|
||||
### Launch SYNC-REF (namespace 1):
|
||||
```
|
||||
sudo ./multi-ue.sh -o1
|
||||
cd ran_build/build/
|
||||
sudo RFSIMULATOR=server ./nr-uesoftmodem --rfsim -O ../../../targets/PROJECTS/NR-SIDELINK/CONF/sl_sync_ref.conf --sl-mode 2 --sa --sync-ref --brokerip 10.201.1.100
|
||||
```
|
||||
|
||||
The OpenAirInterface (OAI) software is composed of the following parts:
|
||||
### Launch UE2 (namespace 2):
|
||||
```
|
||||
sudo ./multi-ue.sh -o2
|
||||
cd ran_build/build/
|
||||
sudo ./nr-uesoftmodem --rfsim -O ../../../targets/PROJECTS/NR-SIDELINK/CONF/ue1.conf --sl-mode 2 --sa --brokerip 10.202.1.100 --device_id 1 | sudo tee $HOME/sl-oai-release4/rat-selection/logs/sl.log
|
||||
```
|
||||
|
||||
### Launch UE3 (namespace 3):
|
||||
```
|
||||
sudo ./multi-ue.sh -o3
|
||||
cd ran_build/build/
|
||||
sudo ./nr-uesoftmodem --rfsim -O ../../../targets/PROJECTS/NR-SIDELINK/CONF/ue2.conf --sl-mode 2 --sa --brokerip 10.203.1.100 --device_id 2 | sudo tee $HOME/sl-oai-release4/rat-selection/logs/sl.log
|
||||
```
|
||||
|
||||
Optional : You can now quickly check the connection to sync-ref from two UEs :
|
||||
```
|
||||
ping -I oaitun_ue2 10.0.0.1
|
||||
ping -I oaitun_ue3 10.0.0.1
|
||||
```
|
||||
|
||||
Note: when restart the simulation, you might need to kill everything first by the following command :
|
||||
```
|
||||
sudo pkill -f nr-uesoftmodem
|
||||
sudo pkill -f broker
|
||||
sudo pkill -f rfsimulator
|
||||
```
|
||||
|
||||
## Monitor route with Babel and Wireshark
|
||||
You might need to first install Babel onto the local machine
|
||||
|
||||
```
|
||||
openairinterface5g
|
||||
├── charts
|
||||
├── ci-scripts : Meta-scripts used by the OSA CI process. Contains also configuration files used day-to-day by CI.
|
||||
├── CMakeLists.txt : Top-level CMakeLists.txt for building
|
||||
├── cmake_targets : Build utilities to compile (simulation, emulation and real-time platforms), and generated build files.
|
||||
├── common : Some common OAI utilities, some other tools can be found at openair2/UTILS.
|
||||
├── doc : Documentation
|
||||
├── docker : Dockerfiles to build for Ubuntu and RHEL
|
||||
├── executables : Top-level executable source files (gNB, eNB, ...)
|
||||
├── maketags : Script to generate emacs tags.
|
||||
├── nfapi : (n)FAPI code for MAC-PHY interface
|
||||
├── openair1 : 3GPP LTE Rel-10/12 PHY layer / 3GPP NR Rel-15 layer. A local Readme file provides more details.
|
||||
├── openair2 : 3GPP LTE Rel-10 RLC/MAC/PDCP/RRC/X2AP + LTE Rel-14 M2AP implementation. Also 3GPP NR Rel-15 RLC/MAC/PDCP/RRC/X2AP.
|
||||
├── openair3 : 3GPP LTE Rel10 for S1AP, NAS GTPV1-U for both ENB and UE.
|
||||
├── openshift : OpenShift helm charts for some deployment options of OAI
|
||||
├── radio : Drivers for various radios such as USRP, AW2S, RFsim, ...
|
||||
└── targets : Some configuration files; only historical relevance, and might be deleted in the future
|
||||
sudo apt update
|
||||
sudo apt install babeld
|
||||
```
|
||||
|
||||
### Launch SYNC-REF (namespace 1):
|
||||
First go into the correct namespace :
|
||||
```
|
||||
sudo ./multi-ue.sh -o1
|
||||
```
|
||||
|
||||
In order to have a readable address at the logside, we'll hardcode the IP address through following command, so sync-ref will be translate as 'fe80::1/64'
|
||||
```
|
||||
sudo ip netns exec ue1 ip -6 addr add fe80::1/64 dev oaitun_ue1 nodad
|
||||
```
|
||||
Then launch Babel on sync-ref :
|
||||
```
|
||||
ip netns exec ue1 bash -lc '
|
||||
set -e
|
||||
cat > /tmp/babeld-ue1.conf <<EOF
|
||||
interface oaitun_ue1
|
||||
redistribute local deny
|
||||
pid-file /tmp/babeld-ue1.pid
|
||||
EOF
|
||||
babeld -d 1 -c /tmp/babeld-ue1.conf
|
||||
'
|
||||
```
|
||||
For now, as no other UE is connected, sync-ref will simply print its local id.
|
||||
|
||||
### Launch UE2 (namespace 2):
|
||||
First go into the correct namespace :
|
||||
```
|
||||
sudo ./multi-ue.sh -o2
|
||||
```
|
||||
|
||||
To make it easier to observe, UE2 will be allocated address as 'fe80::2/64' by following command :
|
||||
```
|
||||
sudo ip netns exec ue2 ip -6 addr add fe80::2/64 dev oaitun_ue2 nodad
|
||||
```
|
||||
Then launch Babel on UE2 :
|
||||
```
|
||||
ip netns exec ue2 bash -lc '
|
||||
set -e
|
||||
cat > /tmp/babeld-ue2.conf <<EOF
|
||||
interface oaitun_ue2
|
||||
redistribute local deny
|
||||
pid-file /tmp/babeld-ue2.pid
|
||||
EOF
|
||||
babeld -d 1 -c /tmp/babeld-ue2.conf
|
||||
'
|
||||
```
|
||||
|
||||
### Launch UE3 (namespace 3):
|
||||
First go into the correct namespace :
|
||||
```
|
||||
sudo ./multi-ue.sh -o3
|
||||
```
|
||||
|
||||
UE3 will be allocated address as 'fe80::3/64'
|
||||
```
|
||||
sudo ip netns exec ue3 ip -6 addr add fe80::3/64 dev oaitun_ue3 nodad
|
||||
|
||||
```
|
||||
Then launch Babel on UE3 :
|
||||
```
|
||||
ip netns exec ue3 bash -lc '
|
||||
set -e
|
||||
cat > /tmp/babeld-ue3.conf <<EOF
|
||||
interface oaitun_ue3
|
||||
redistribute local deny
|
||||
pid-file /tmp/babeld-ue3.pid
|
||||
EOF
|
||||
babeld -d 1 -c /tmp/babeld-ue3.conf
|
||||
'
|
||||
|
||||
```
|
||||
|
||||
Note : On babel, it will show neighbour connection with 'Neighbour ... rxcost 96 txcost 65535...', when it's 96, it means perfect connection, 65535 means a bad connection, if the connection is bad when generating the UE3, try to kill and restart again.
|
||||
|
||||
### Wireshark monitor
|
||||
Within the each namespace, you can start wireshark with filter on each node to check the Babel messages (example as for sync-ref, please update the oaitun_ueX name for each UE):
|
||||
```
|
||||
sudo wireshark -i oaitun_ue1 -k &
|
||||
```
|
||||
You should be able to see 'Babel Hello' message, and 'Babel Hello ihu'. ihu representing 'I hear you'.
|
||||
When there are two UEs connecting to sync-ref at the same time, you should be able to see 'Babel Hello ihu ihu'
|
||||
|
||||
|
||||
## Enable TAP in RFSim for Multiple UEs
|
||||
This part is to switch from default TUN to TAP.
|
||||
The baseline is, by default, system is running through TUN. In order to enable TAP, when you run each node simply add a flag at the begining: " OAI_TUNTAP_MODE=tap".
|
||||
|
||||
Optional : To disable the TAP (in case of an uncleaned restart...), do the following :
|
||||
```
|
||||
unset OAI_TUNTAP_MODE
|
||||
```
|
||||
### Launch Broker (outside namespace):
|
||||
```
|
||||
cd ran_build/build/
|
||||
./broker
|
||||
```
|
||||
### Launch SYNC-REF (namespace 1):
|
||||
```
|
||||
sudo ./multi-ue.sh -o1
|
||||
cd ran_build/build/
|
||||
sudo OAI_TUNTAP_MODE=tap RFSIMULATOR=server ./nr-uesoftmodem --rfsim -O ../../../targets/PROJECTS/NR-SIDELINK/CONF/sl_sync_ref.conf --sl-mode 2 --sa --sync-ref --brokerip 10.201.1.100
|
||||
```
|
||||
|
||||
### Launch UE2 (namespace 2):
|
||||
```
|
||||
sudo ./multi-ue.sh -o2
|
||||
cd ran_build/build/
|
||||
sudo OAI_TUNTAP_MODE=tap ./nr-uesoftmodem --rfsim -O ../../../targets/PROJECTS/NR-SIDELINK/CONF/ue1.conf --sl-mode 2 --sa --brokerip 10.202.1.100 --device_id 1 | sudo tee $HOME/sl-oai-release4/rat-selection/logs/sl.log
|
||||
```
|
||||
|
||||
### Launch UE3 (namespace 3):
|
||||
```
|
||||
sudo ./multi-ue.sh -o3
|
||||
cd ran_build/build/
|
||||
sudo OAI_TUNTAP_MODE=tap ./nr-uesoftmodem --rfsim -O ../../../targets/PROJECTS/NR-SIDELINK/CONF/ue2.conf --sl-mode 2 --sa --brokerip 10.203.1.100 --device_id 2 | sudo tee $HOME/sl-oai-release4/rat-selection/logs/sl.log
|
||||
```
|
||||
|
||||
## Check connection with Batman
|
||||
|
||||
### Start Batman on sync-ref (namespace 1):
|
||||
```
|
||||
sudo ./multi-ue.sh -o1
|
||||
ip link set oaitun_ue1 address 02:00:00:00:00:01
|
||||
sudo batctl if add oaitun_ue1
|
||||
```
|
||||
|
||||
### Start Batman on UE2 (namespace 2):
|
||||
```
|
||||
sudo ./multi-ue.sh -o2
|
||||
ip link set oaitun_ue2 address 02:00:00:00:00:02
|
||||
sudo batctl if add oaitun_ue2
|
||||
```
|
||||
|
||||
|
||||
### Start Batman on UE3 (namespace 3):
|
||||
```
|
||||
sudo ./multi-ue.sh -o3
|
||||
ip link set oaitun_ue3 address 02:00:00:00:00:03
|
||||
sudo batctl if add oaitun_ue3
|
||||
```
|
||||
### Batman command
|
||||
To check the neighbour :
|
||||
```
|
||||
batctl n
|
||||
```
|
||||
To check the routing table :
|
||||
```
|
||||
batctl o
|
||||
```
|
||||
|
||||
### Start wireshark with filter
|
||||
You can check the current packets exchange with wireshark, please update the name 'oaitun_ueX' accordingly.
|
||||
```
|
||||
wireshark -k -i oaitun_ueX -Y "eth.type == 0x4305"
|
||||
```
|
||||
|
||||
## HW with TAP
|
||||
Similarly, we can start the HW with TAP with the following command
|
||||
|
||||
### Launch SYNC-REF (machine 1):
|
||||
```
|
||||
cd ran_build/build/
|
||||
sudo OAI_TUNTAP_MODE=tap ./nr-uesoftmodem -O ../../../targets/PROJECTS/NR-SIDELINK/CONF/sl_sync_ref.conf --sa -E --sl-mode 2 --sync-ref --usrp-args "type=b200,master_clock_rate=46.08e6,enable_gps=true" --ue-txgain 10 --ue-rxgain 100 --thread-pool -1,-1,-1,-1 --clock-source 2 --time-source 2
|
||||
```
|
||||
|
||||
### Launch UE2 (machine 2):
|
||||
```
|
||||
cd ran_build/build/
|
||||
sudo OAI_TUNTAP_MODE=tap ./nr-uesoftmodem -O ../../../targets/PROJECTS/NR-SIDELINK/CONF/ue1.conf --sa -E --sl-mode 2 --usrp-args "type=b200,master_clock_rate=46.08e6,enable_gps=true" --ue-txgain 10 --ue-rxgain 100 --thread-pool -1,-1,-1,-1 --clock-source 2 --time-source 2
|
||||
```
|
||||
|
||||
### Launch UE3 (machine 3):
|
||||
```
|
||||
cd ran_build/build/
|
||||
sudo OAI_TUNTAP_MODE=tap ./nr-uesoftmodem -O ../../../targets/PROJECTS/NR-SIDELINK/CONF/ue2.conf --sa -E --sl-mode 2 --usrp-args "type=b200,master_clock_rate=46.08e6,enable_gps=true" --ue-txgain 10 --ue-rxgain 100 --thread-pool -1,-1,-1,-1 --clock-source 2 --time-source 2
|
||||
```
|
||||
|
||||
## More UEs generated with TAP
|
||||
The newest update enables to generate more than 2 UEs along with one sync-ref. The following is an example of 3 UEs.
|
||||
One would, first, need to create a new .conf file in openairinterface5g/targets/PROJECTS/NR-SIDELINK/, second, in file /openairinterface5g/openair2/LAYER2/NR_MAC_UE/mac_defs.h, the parameter of "#define CUR_SL_UE_CONNECTIONS" need to be updated to match the max number of UEs(Exclusive of sync-ref, this value is limited to 6 though)
|
||||
### Launch Broker (outside namespace):
|
||||
```
|
||||
cd ran_build/build/
|
||||
./broker
|
||||
```
|
||||
### Launch SYNC-REF (namespace 1):
|
||||
```
|
||||
sudo ./multi-ue.sh -o1
|
||||
cd ran_build/build/
|
||||
sudo OAI_TUNTAP_MODE=tap RFSIMULATOR=server ./nr-uesoftmodem --rfsim -O ../../../targets/PROJECTS/NR-SIDELINK/CONF/sl_sync_ref.conf --sl-mode 2 --sa --sync-ref --brokerip 10.201.1.100 --thread-pool -1,-1
|
||||
```
|
||||
|
||||
### Launch UE2 (namespace 2):
|
||||
```
|
||||
sudo ./multi-ue.sh -o2
|
||||
cd ran_build/build/
|
||||
sudo OAI_TUNTAP_MODE=tap ./nr-uesoftmodem --rfsim -O ../../../targets/PROJECTS/NR-SIDELINK/CONF/ue1.conf --sl-mode 2 --sa --brokerip 10.202.1.100 --device_id 1 --thread-pool -1,-1 | sudo tee $HOME/sl-oai-release4/rat-selection/logs/sl.log
|
||||
```
|
||||
|
||||
### Launch UE3 (namespace 3):
|
||||
```
|
||||
sudo ./multi-ue.sh -o3
|
||||
cd ran_build/build/
|
||||
sudo OAI_TUNTAP_MODE=tap ./nr-uesoftmodem --rfsim -O ../../../targets/PROJECTS/NR-SIDELINK/CONF/ue2.conf --sl-mode 2 --sa --brokerip 10.203.1.100 --device_id 2 --thread-pool -1,-1 | sudo tee $HOME/sl-oai-release4/rat-selection/logs/sl.log
|
||||
```
|
||||
|
||||
### Launch UE4 (namespace 4):
|
||||
```
|
||||
sudo ./multi-ue.sh -o4
|
||||
cd ran_build/build/
|
||||
sudo OAI_TUNTAP_MODE=tap ./nr-uesoftmodem --rfsim -O ../../../targets/PROJECTS/NR-SIDELINK/CONF/ue3.conf --sl-mode 2 --sa --brokerip 10.204.1.100 --device_id 3 --thread-pool -1,-1 | sudo tee $HOME/sl-oai-release4/rat-selection/logs/sl.log
|
||||
```
|
||||
|
||||
1
cmake_targets/babeld
Submodule
1
cmake_targets/babeld
Submodule
Submodule cmake_targets/babeld added at 950992f282
@@ -280,7 +280,7 @@ function main() {
|
||||
;;
|
||||
"SIMU")
|
||||
HW="OAI_"$2
|
||||
TARGET_LIST="$TARGET_LIST rfsimulator"
|
||||
TARGET_LIST="$TARGET_LIST rfsimulator broker"
|
||||
CMAKE_CMD="$CMAKE_CMD -DOAI_$2=ON"
|
||||
;;
|
||||
"AW2SORI")
|
||||
@@ -479,7 +479,7 @@ function main() {
|
||||
# add some default libraries that should always be built
|
||||
# for eNB, gNB, UEs, simulators
|
||||
if [[ $gNB == 1 || $eNB == 1 || $UE == 1 || $nrUE == 1 || $SIMUS_PHY == 1 || $RU == 1 ]]; then
|
||||
TARGET_LIST="$TARGET_LIST params_libconfig coding rfsimulator dfts"
|
||||
TARGET_LIST="$TARGET_LIST params_libconfig coding rfsimulator dfts broker"
|
||||
fi
|
||||
|
||||
mkdir -p $DIR/$BUILD_DIR/build
|
||||
|
||||
67
cmake_targets/multi-ue.sh
Executable file
67
cmake_targets/multi-ue.sh
Executable file
@@ -0,0 +1,67 @@
|
||||
#!/bin/bash
|
||||
|
||||
ue_id=-1
|
||||
|
||||
create_namespace() {
|
||||
ue_id=$1
|
||||
local name="ue$ue_id"
|
||||
echo "creating namespace for UE ID ${ue_id} name ${name}"
|
||||
ip netns add $name
|
||||
ip link add v-eth$ue_id type veth peer name v-ue$ue_id
|
||||
ip link set v-ue$ue_id netns $name
|
||||
BASE_IP=$((200+ue_id))
|
||||
ip addr add 10.$BASE_IP.1.100/24 dev v-eth$ue_id
|
||||
ip link set v-eth$ue_id up
|
||||
iptables -t nat -A POSTROUTING -s 10.$BASE_IP.1.0/255.255.255.0 -o lo -j MASQUERADE
|
||||
iptables -A FORWARD -i lo -o v-eth$ue_id -j ACCEPT
|
||||
iptables -A FORWARD -o lo -i v-eth$ue_id -j ACCEPT
|
||||
ip netns exec $name ip link set dev lo up
|
||||
ip netns exec $name ip addr add 10.$BASE_IP.1.$ue_id/24 dev v-ue$ue_id
|
||||
ip netns exec $name ip link set v-ue$ue_id up
|
||||
}
|
||||
|
||||
delete_namespace() {
|
||||
local ue_id=$1
|
||||
local name="ue$ue_id"
|
||||
echo "deleting namespace for UE ID ${ue_id} name ${name}"
|
||||
ip link delete v-eth$ue_id
|
||||
ip netns delete $name
|
||||
}
|
||||
|
||||
list_namespaces() {
|
||||
ip netns list
|
||||
}
|
||||
|
||||
open_namespace() {
|
||||
if [[ $ue_id -lt 1 ]]; then echo "error: no last UE processed"; exit 1; fi
|
||||
local name="ue$ue_id"
|
||||
echo "opening shell in namespace ${name}"
|
||||
echo "type 'ip netns exec $name bash' in additional terminals"
|
||||
ip netns exec $name bash
|
||||
}
|
||||
|
||||
usage () {
|
||||
echo "$1 -c <num>: create namespace \"ue<num>\""
|
||||
echo "$1 -d <num>: delete namespace \"ue<num>\""
|
||||
echo "$1 -e : execute shell in last processed namespace"
|
||||
echo "$1 -l : list namespaces"
|
||||
echo "$1 -o <num>: open shell in namespace \"ue<num>\""
|
||||
}
|
||||
|
||||
prog_name=$(basename $0)
|
||||
|
||||
if [[ $(id -u) -ne 0 ]] ; then echo "Please run as root"; exit 1; fi
|
||||
if [[ $# -eq 0 ]]; then echo "error: no parameters given"; usage $prog_name; exit 1; fi
|
||||
|
||||
while getopts c:d:ehlo: cmd
|
||||
do
|
||||
case "${cmd}" in
|
||||
c) create_namespace ${OPTARG};;
|
||||
d) delete_namespace ${OPTARG};;
|
||||
e) open_namespace; exit;;
|
||||
h) usage ${prog_name}; exit;;
|
||||
l) list_namespaces;;
|
||||
o) ue_id=${OPTARG}; open_namespace;;
|
||||
/?) echo "Invalid option"; usage ${prog_name}; exit;;
|
||||
esac
|
||||
done
|
||||
49
doc/JSUC.md
Normal file
49
doc/JSUC.md
Normal file
@@ -0,0 +1,49 @@
|
||||
# Joint sidelink and Uu communication (JSUC)
|
||||
This tutorial will discuss the setup for a hybrid communication mode using sidelink and Uu.
|
||||
|
||||
## Setup
|
||||
The idea is to have 4 UEs, two running sidelink and two running normal mode. A logical UE (UE A and UE B) supporting hybrid communication mode is represented by 2 UEs, one running sidelink and the other running normal mode.
|
||||
|
||||

|
||||
|
||||
The following repos will be used for each technology:
|
||||
- Uu: `mkdir normal-mode`, `cd normal-mode` then clone `https://github.com/beraoudabdelkhalek/rfsim-Uu-metrics`
|
||||
- Sidelink: `mkdir sidelink`, `cd sidelink` then clone `https://gitlab.eurecom.fr/oai/openairinterface5g` and `git checkout sl-eurecom4`
|
||||
|
||||
- Build both projects, and build the telnet server for each project `./build_oai --build-lib telnetsrv`
|
||||
- Run the OAI core network.
|
||||
- Create 4 namespaces: `sudo ~/normal-mode/rfsim-Uu-metrics/tools/script/multi-ue.sh -c x` where x is from 1-4
|
||||
- Run the gNB executable on the host using the project inside the `normal-mode` directory:
|
||||
```sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf --gNBs.[0].min_rxtxtime 6 --rfsim --rfsimulator.options chanmod --telnetsrv```
|
||||
- Run the broker on the host using the project inside `sidelink` directory.
|
||||
- Run UE 1 in NS 1 (normal mode) using `normal-mode` directory:
|
||||
`sudo ~/normal-mode/rfsim-Uu-metrics/tools/script/multi-ue.sh -o 1`
|
||||
|
||||
```sudo ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --rfsim --rfsimulator.serveraddr 10.201.1.100 --uicc0.imsi 001010000000001 -O ../../../ci-scripts/conf_files/nrue.uicc.conf --rfsimulator.options chanmod --telnetsrv --telnetsrv.listenport 9091```
|
||||
|
||||
- Run UE 2 in NS 2 (sidelink mode) using `sidelink` directory:
|
||||
`sudo ~/normal-mode/rfsim-Uu-metrics/tools/script/multi-ue.sh -o 2`
|
||||
|
||||
```sudo RFSIMULATOR=server ./nr-uesoftmodem --rfsim -O ../../../targets/PROJECTS/NR-SIDELINK/CONF/sl_sync_ref.conf --sl-mode 2 --sa --sync-ref --brokerip 10.202.1.100```
|
||||
|
||||
- Run UE 3 in NS 3 (sidelink mode) using `sidelink` directory:
|
||||
`sudo ~/normal-mode/rfsim-Uu-metrics/tools/script/multi-ue.sh -o 3`
|
||||
|
||||
```sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem --rfsim -O ../../../targets/PROJECTS/NR-SIDELINK/CONF/sl_ue1.conf --sl-mode 2 --sa --brokerip 10.203.1.100 --device_id 1```
|
||||
|
||||
- Run UE 4 in NS 4 (normal mode) using `normal-mode` directory:
|
||||
`sudo ~/normal-mode/rfsim-Uu-metrics/tools/script/multi-ue.sh -o 4`
|
||||
|
||||
```sudo ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --rfsim --rfsimulator.serveraddr 10.204.1.100 --uicc0.imsi 001010000000002 -O ../../../ci-scripts/conf_files/nrue.uicc.conf --rfsimulator.options chanmod --telnetsrv --telnetsrv.listenport 9091```
|
||||
|
||||
## Connectivity test
|
||||
|
||||
### Uu Connectivity:
|
||||
From UE 1 ping UE 4:
|
||||
- `sudo ~/normal-mode/rfsim-Uu-metrics/tools/script/multi-ue.sh -o 1`
|
||||
- `ping 10.0.0.3`
|
||||
|
||||
### Sidelink Connectivity:
|
||||
From UE 2 ping UE 3:
|
||||
- `sudo ~/normal-mode/rfsim-Uu-metrics/tools/script/multi-ue.sh -o 2`
|
||||
- `ping 10.0.0.2`
|
||||
BIN
doc/images/hybrid_communication_setup.png
Executable file
BIN
doc/images/hybrid_communication_setup.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 48 KiB |
@@ -169,7 +169,7 @@ extern void *udp_eNB_task(void *args_p);
|
||||
|
||||
int transmission_mode=1;
|
||||
int emulate_rf = 0;
|
||||
int numerology = 0;
|
||||
int numerology = 1; //Jin change to 1
|
||||
|
||||
|
||||
static char *parallel_config = NULL;
|
||||
|
||||
@@ -118,6 +118,8 @@ static int tx_max_power[MAX_NUM_CCs] = {0};
|
||||
int single_thread_flag = 1;
|
||||
int tddflag = 0;
|
||||
int vcdflag = 0;
|
||||
int sl_nas_enabled = 0; //SLC Flag
|
||||
|
||||
|
||||
double rx_gain_off = 0.0;
|
||||
char *usrp_args = NULL;
|
||||
@@ -449,7 +451,6 @@ int main( int argc, char **argv ) {
|
||||
// get options and fill parameters from configuration file
|
||||
|
||||
get_options (); //Command-line options specific for NRUE
|
||||
|
||||
get_common_options(SOFTMODEM_5GUE_BIT);
|
||||
CONFIG_CLEARRTFLAG(CONFIG_NOEXITONHELP);
|
||||
#if T_TRACER
|
||||
@@ -549,7 +550,17 @@ int main( int argc, char **argv ) {
|
||||
|
||||
if (UE[CC_id]->sl_mode) {
|
||||
AssertFatal(UE[CC_id]->sl_mode == 2, "Only Sidelink mode 2 supported. Mode 1 not yet supported\n");
|
||||
nr_UE_configure_Sidelink(0, get_nrUE_params()->sync_ref, &ueinfo);
|
||||
// starting the sockets between the PC5 Controller and the RRC and the PDCP
|
||||
//nr_rrc_pc5_control_socket_init();
|
||||
if (sl_nas_enabled) {
|
||||
nr_rrc_pc5_control_socket_init();
|
||||
LOG_I(RRC, "[SL-NAS] PC5 controller socket started\n");
|
||||
} else {
|
||||
LOG_I(RRC, "[SL-NAS] PC5 controller socket not started\n");
|
||||
}
|
||||
nr_pdcp_pc5_signaling_socket_init();
|
||||
//
|
||||
nr_UE_configure_Sidelink(0, get_nrUE_params()->sync_ref, &ueinfo);
|
||||
DevAssert(mac->if_module != NULL && mac->if_module->sl_phy_config_request != NULL);
|
||||
sl_nr_ue_phy_params_t *sl_phy = &UE[CC_id]->SL_UE_PHY_PARAMS;
|
||||
mac->if_module->sl_phy_config_request(&mac->SL_MAC_PARAMS->sl_phy_config);
|
||||
|
||||
@@ -70,6 +70,7 @@ typedef struct ueinfo {
|
||||
{"ue-timing-correction-disable", CONFIG_HLP_DISABLETIMECORR, PARAMFLAG_BOOL, .iptr=&(nrUE_params.no_timing_correction), .defintval=0, TYPE_INT, 0}, \
|
||||
{"SLC", CONFIG_HLP_SLF, 0, .u64ptr=&(sidelink_frequency[0][0]), .defuintval=2600000000,TYPE_UINT64,0}, \
|
||||
{"sync-ref", CONFIG_HLP_SL_SYNCSOURCEUE, PARAMFLAG_BOOL, .uptr=&(nrUE_params.sync_ref), .defuintval=0, TYPE_UINT32, 0}, \
|
||||
{"sl-nas", "Enable SL-NAS PC5 controller socket\n", PARAMFLAG_BOOL, .iptr=&sl_nas_enabled, .defintval=0, TYPE_INT, 0}, \
|
||||
{"mcs", CONFIG_HLP_SL_MAX_MCS, 0, .u8ptr=&(nrUE_params.mcs), .defintval=9, TYPE_UINT8, 0}, \
|
||||
{"snr", CONFIG_HLP_SL_SNR, 0, .dblptr=&(nrUE_params.snr), .defdblval=0.0, TYPE_DOUBLE, 0}, \
|
||||
}
|
||||
@@ -113,4 +114,6 @@ extern void start_oai_nrue_threads(void);
|
||||
void *UE_thread(void *arg);
|
||||
void init_nr_ue_vars(PHY_VARS_NR_UE *ue, uint8_t UE_id, uint8_t abstraction_flag);
|
||||
void init_nrUE_standalone_thread(int ue_idx);
|
||||
|
||||
extern int sl_nas_enabled; //SLC Flag
|
||||
#endif
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include "fapi_nr_ue_interface.h"
|
||||
|
||||
#define SL_NR_RX_CONFIG_LIST_NUM 1
|
||||
#define SL_NR_TX_CONFIG_LIST_NUM 1
|
||||
#define SL_NR_TX_CONFIG_LIST_NUM 1 //Jin original 1, change to 2
|
||||
#define SL_NR_RX_IND_MAX_PDU 2
|
||||
#define SL_NR_SCI_IND_MAX_PDU 2
|
||||
#define SL_NR_MAX_PSCCH_SCI_LENGTH_IN_BYTES 8
|
||||
|
||||
@@ -44,9 +44,10 @@
|
||||
// 10*log10(pow(2,30))
|
||||
#define pow_2_30_dB 90
|
||||
|
||||
//#define DEBUG_CSI_PRINTS // To enable CSI SNR debug logs
|
||||
// #define DEBUG_CSI_PRINTS // To enable CSI SNR debug logs
|
||||
extern short nr_qpsk_mod_table[8];
|
||||
//#define NR_CSIRS_DEBUG
|
||||
// #define NR_CSIRS_DEBUG
|
||||
#define METRICS
|
||||
//#define NR_CSIIM_DEBUG
|
||||
|
||||
void nr_det_A_MF_2x2(int32_t *a_mf_00,
|
||||
@@ -235,7 +236,7 @@ int nr_get_csi_rs_signal(const PHY_VARS_NR_UE *ue,
|
||||
int dataF_offset = get_softmodem_params()->sl_mode == 2 ? 0 : proc->nr_slot_rx * ue->frame_parms.samples_per_slot_wCP;
|
||||
uint16_t port_tx = s+j_cdm[cdm_id]*CDM_group_size;
|
||||
c16_t *tx_csi_rs_signal = (c16_t*)&nr_csi_info->csi_rs_generated_signal[port_tx][symbol_offset+dataF_offset];
|
||||
LOG_I(NR_PHY, "l,k (%2d,%4d) |\tport_tx %d (%4d,%4d)\tant_rx %d (%4d,%4d)\n",
|
||||
LOG_D(NR_PHY, "l,k (%2d,%4d) |\tport_tx %d (%4d,%4d)\tant_rx %d (%4d,%4d)\n",
|
||||
symb,
|
||||
k,
|
||||
port_tx+3000,
|
||||
@@ -257,7 +258,7 @@ int nr_get_csi_rs_signal(const PHY_VARS_NR_UE *ue,
|
||||
*rsrp_dBm = dB_fixed(*rsrp) + 30 - pow_2_30_dB
|
||||
- ((int)openair0_cfg[0].rx_gain[0] - (int)openair0_cfg[0].rx_gain_offset[0]) - dB_fixed(ue->frame_parms.ofdm_symbol_size);
|
||||
|
||||
#ifdef NR_CSIRS_DEBUG
|
||||
#ifdef METRICS
|
||||
LOG_I(NR_PHY, "RSRP = %i (%i dBm)\n", *rsrp, *rsrp_dBm);
|
||||
#endif
|
||||
|
||||
@@ -359,19 +360,19 @@ int nr_csi_rs_channel_estimation(const PHY_VARS_NR_UE *ue,
|
||||
continue;
|
||||
}
|
||||
for(int k = 0; k<frame_parms->ofdm_symbol_size; k++) {
|
||||
LOG_I(NR_PHY, "l,k (%2d,%4d) | ", symb, k);
|
||||
LOG_D(NR_PHY, "l,k (%2d,%4d) | ", symb, k);
|
||||
for(uint16_t port_tx = 0; port_tx<N_ports; port_tx++) {
|
||||
uint64_t symbol_offset = symb*frame_parms->ofdm_symbol_size;
|
||||
c16_t *tx_csi_rs_signal = (c16_t*)&csi_rs_generated_signal[port_tx][symbol_offset+dataF_offset];
|
||||
c16_t *rx_csi_rs_signal = (c16_t*)&csi_rs_received_signal[ant_rx][symbol_offset];
|
||||
c16_t *csi_rs_ls_estimated_channel16 = (c16_t*)&csi_rs_ls_estimated_channel[ant_rx][port_tx][0];
|
||||
printf("port_tx %d --> ant_rx %d, tx (%4d,%4d), rx (%4d,%4d), ls (%4d,%4d) | ",
|
||||
port_tx+3000, ant_rx,
|
||||
tx_csi_rs_signal[k].r, tx_csi_rs_signal[k].i,
|
||||
rx_csi_rs_signal[k].r, rx_csi_rs_signal[k].i,
|
||||
csi_rs_ls_estimated_channel16[k].r, csi_rs_ls_estimated_channel16[k].i);
|
||||
// printf("port_tx %d --> ant_rx %d, tx (%4d,%4d), rx (%4d,%4d), ls (%4d,%4d) | ",
|
||||
// port_tx+3000, ant_rx,
|
||||
// tx_csi_rs_signal[k].r, tx_csi_rs_signal[k].i,
|
||||
// rx_csi_rs_signal[k].r, rx_csi_rs_signal[k].i,
|
||||
// csi_rs_ls_estimated_channel16[k].r, csi_rs_ls_estimated_channel16[k].i);
|
||||
}
|
||||
printf("\n");
|
||||
// printf("\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -434,18 +435,18 @@ int nr_csi_rs_channel_estimation(const PHY_VARS_NR_UE *ue,
|
||||
int rb = k >= frame_parms->first_carrier_offset ?
|
||||
(k - frame_parms->first_carrier_offset)/NR_NB_SC_PER_RB :
|
||||
(k + frame_parms->ofdm_symbol_size - frame_parms->first_carrier_offset)/NR_NB_SC_PER_RB;
|
||||
LOG_I(NR_PHY, "(k = %4d) |\t", k);
|
||||
LOG_D(NR_PHY, "(k = %4d) |\t", k);
|
||||
for(uint16_t port_tx = 0; port_tx<N_ports; port_tx++) {
|
||||
c16_t *csi_rs_ls_estimated_channel16 = (c16_t*)&csi_rs_ls_estimated_channel[ant_rx][port_tx][0];
|
||||
c16_t *csi_rs_estimated_channel16 = (c16_t *)&csi_rs_estimated_channel_freq[ant_rx][port_tx][mem_offset];
|
||||
printf("Channel port_tx %d --> ant_rx %d : ls (%4d,%4d), int (%4d,%4d), noise (%4d,%4d) | ",
|
||||
port_tx+3000, ant_rx,
|
||||
csi_rs_ls_estimated_channel16[k].r, csi_rs_ls_estimated_channel16[k].i,
|
||||
csi_rs_estimated_channel16[k].r, csi_rs_estimated_channel16[k].i,
|
||||
rb >= csirs_config_pdu->start_rb+csirs_config_pdu->nr_of_rbs ? 0 : noise_real[ant_rx][port_tx][rb-csirs_config_pdu->start_rb],
|
||||
rb >= csirs_config_pdu->start_rb+csirs_config_pdu->nr_of_rbs ? 0 : noise_imag[ant_rx][port_tx][rb-csirs_config_pdu->start_rb]);
|
||||
// printf("Channel port_tx %d --> ant_rx %d : ls (%4d,%4d), int (%4d,%4d), noise (%4d,%4d) | ",
|
||||
// port_tx+3000, ant_rx,
|
||||
// csi_rs_ls_estimated_channel16[k].r, csi_rs_ls_estimated_channel16[k].i,
|
||||
// csi_rs_estimated_channel16[k].r, csi_rs_estimated_channel16[k].i,
|
||||
// rb >= csirs_config_pdu->start_rb+csirs_config_pdu->nr_of_rbs ? 0 : noise_real[ant_rx][port_tx][rb-csirs_config_pdu->start_rb],
|
||||
// rb >= csirs_config_pdu->start_rb+csirs_config_pdu->nr_of_rbs ? 0 : noise_imag[ant_rx][port_tx][rb-csirs_config_pdu->start_rb]);
|
||||
}
|
||||
printf("\n");
|
||||
// printf("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1087,11 +1088,11 @@ void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, c16_t
|
||||
if (get_softmodem_params()->sl_mode == 2) {
|
||||
nr_csi_rs_cqi_estimation_sl(sl_sinr_dB, &cqi);
|
||||
get_nrUE_params()->snr = sl_sinr_dB;
|
||||
LOG_D(NR_PHY, "Rx CSI-RS %4d.%2d sl_sinr %i rsrp %d dBm cqi %d\n",
|
||||
LOG_I(NR_PHY, "Rx CSI-RS %4d.%2d sl_sinr %i rsrp %d dBm cqi %d\n",
|
||||
proc->frame_rx, proc->nr_slot_rx, sl_sinr_dB, rsrp_dBm, cqi);
|
||||
} else {
|
||||
nr_csi_rs_cqi_estimation(precoded_sinr_dB, &cqi);
|
||||
LOG_D(NR_PHY, "Rx %4d.%2d snr %u rsrp %d dBm cqi %d\n",
|
||||
LOG_I(NR_PHY, "Rx %4d.%2d snr %u rsrp %d dBm cqi %d\n",
|
||||
proc->frame_rx, proc->nr_slot_rx, precoded_sinr_dB, rsrp_dBm, cqi);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
#include <linux/if.h>
|
||||
#include <linux/if_tun.h>
|
||||
#include "common/openairinterface5g_limits.h"
|
||||
|
||||
|
||||
#include "pdcp.h"
|
||||
#include <executables/nr-uesoftmodem.h>
|
||||
|
||||
@@ -66,7 +66,24 @@ struct msghdr nas_msg_rx;
|
||||
|
||||
#define GRAAL_NETLINK_ID 31
|
||||
|
||||
static int tun_alloc(char *dev) {
|
||||
//Jin add for TAP
|
||||
typedef enum {
|
||||
OAI_TUNTAP_TUN = 0,
|
||||
OAI_TUNTAP_TAP = 1
|
||||
} oai_tuntap_mode_t;
|
||||
|
||||
static oai_tuntap_mode_t oai_get_tuntap_mode(void)
|
||||
{
|
||||
// Default: TUN (keeps your current behaviour)
|
||||
const char *s = getenv("OAI_TUNTAP_MODE"); // set to "tap" to enable TAP
|
||||
if (s && !strcasecmp(s, "tap"))
|
||||
return OAI_TUNTAP_TAP;
|
||||
return OAI_TUNTAP_TUN;
|
||||
}
|
||||
//Jin TAP end
|
||||
|
||||
//static int tun_alloc(char *dev) { //Jin origin
|
||||
static int tun_alloc(char *dev, oai_tuntap_mode_t mode) { //Jin replace TAP
|
||||
struct ifreq ifr;
|
||||
int fd, err;
|
||||
|
||||
@@ -81,7 +98,8 @@ static int tun_alloc(char *dev) {
|
||||
*
|
||||
* IFF_NO_PI - Do not provide packet information
|
||||
*/
|
||||
ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
|
||||
//ifr.ifr_flags = IFF_TUN | IFF_NO_PI; //Jin origin
|
||||
ifr.ifr_flags = ((mode == OAI_TUNTAP_TAP) ? IFF_TAP : IFF_TUN) | IFF_NO_PI; //Jin replace TAP
|
||||
|
||||
if( *dev )
|
||||
strncpy(ifr.ifr_name, dev, sizeof(ifr.ifr_name)-1);
|
||||
@@ -106,14 +124,19 @@ int netlink_init_mbms_tun(char *ifprefix, int id) {//for UE, id = 1, 2, ...,
|
||||
else {
|
||||
sprintf(ifname, "oaitun_%.3s1", ifprefix); // added "1": for historical reasons
|
||||
}
|
||||
nas_sock_mbms_fd = tun_alloc(ifname);
|
||||
// nas_sock_mbms_fd = tun_alloc(ifname); //Jin origin
|
||||
oai_tuntap_mode_t mode = oai_get_tuntap_mode(); //Jin TAP
|
||||
nas_sock_mbms_fd = tun_alloc(ifname, mode); //Jin add TAP
|
||||
|
||||
if (nas_sock_mbms_fd == -1) {
|
||||
printf("[NETLINK] Error opening mbms socket %s (%d:%s)\n",ifname,errno, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf("[NETLINK]Opened socket %s with fd %d\n",ifname,nas_sock_mbms_fd);
|
||||
//printf("[NETLINK]Opened socket %s with fd %d\n",ifname,nas_sock_mbms_fd); //Jin origin
|
||||
printf("[Jin TAP TAP NETLINK]%s Opened socket %s with fd %d\n", //Jin have a look at TAP
|
||||
(mode == OAI_TUNTAP_TAP) ? "TAP" : "TUN",
|
||||
ifname, nas_sock_mbms_fd);
|
||||
ret = fcntl(nas_sock_mbms_fd,F_SETFL,O_NONBLOCK);
|
||||
|
||||
if (ret == -1) {
|
||||
@@ -136,14 +159,18 @@ int netlink_init_mbms_tun(char *ifprefix, int id) {//for UE, id = 1, 2, ...,
|
||||
int netlink_init_tun(char *ifprefix, int num_if, int id) {//for UE, id = 1, 2, ...,
|
||||
int ret;
|
||||
char ifname[64];
|
||||
oai_tuntap_mode_t mode = oai_get_tuntap_mode(); //Jin add TAP
|
||||
|
||||
int begx = (id == 0) ? 0 : id - 1;
|
||||
int endx = (id == 0) ? num_if : id;
|
||||
int index;
|
||||
for (int i = begx; i < endx; i++) {
|
||||
sprintf(ifname, "oaitun_%.3s%d", ifprefix, i+1);
|
||||
index = get_softmodem_params()->sl_mode ? 0 : i;
|
||||
nas_sock_fd[index] = tun_alloc(ifname);
|
||||
//index = get_softmodem_params()->sl_mode ? 0 : i; //Jin origin
|
||||
index = i; //Jin replace so TAP has different endpoints for multiple UES
|
||||
//nas_sock_fd[index] = tun_alloc(ifname); //Jin origin
|
||||
oai_tuntap_mode_t mode = oai_get_tuntap_mode(); //Jin add TAP
|
||||
nas_sock_fd[index] = tun_alloc(ifname, mode); //Jin add TAP
|
||||
|
||||
if (nas_sock_fd[index] == -1) {
|
||||
LOG_E(PDCP, "TUN: Error opening socket %s (%d:%s)\n", ifname, errno, strerror(errno));
|
||||
@@ -152,6 +179,9 @@ int netlink_init_tun(char *ifprefix, int num_if, int id) {//for UE, id = 1, 2, .
|
||||
|
||||
LOG_I(PDCP, "TUN: Opened socket %s with fd nas_sock_fd[%d]=%d\n",
|
||||
ifname, index, nas_sock_fd[index]);
|
||||
LOG_D(PDCP, "JIN LOG TAP !!!!!!!!!! %s: Opened socket %s with fd nas_sock_fd[%d]=%d\n",
|
||||
(mode == OAI_TUNTAP_TAP) ? "TAP" : "TUN",
|
||||
ifname, index, nas_sock_fd[index]);
|
||||
ret = fcntl(nas_sock_fd[index], F_SETFL, O_NONBLOCK);
|
||||
|
||||
if (ret == -1) {
|
||||
@@ -227,4 +257,4 @@ void netlink_cleanup(void)
|
||||
{
|
||||
free(nas_nlh_tx);
|
||||
nas_nlh_tx = NULL;
|
||||
}
|
||||
}
|
||||
@@ -528,7 +528,8 @@ ue_send_sdu(module_id_t module_idP,
|
||||
(char *)payload_ptr,
|
||||
rx_lengths[i],
|
||||
1,
|
||||
NULL);
|
||||
NULL,
|
||||
0,0); //Jin add last two
|
||||
} else if ((rx_lcids[i] < NB_RB_MAX) && (rx_lcids[i] > DCCH1 )) {
|
||||
LOG_D(MAC,"[UE %d] Frame %d : DLSCH -> DL-DTCH%d (eNB %d, %d bytes)\n", module_idP, frameP,rx_lcids[i], eNB_index,rx_lengths[i]);
|
||||
#if defined(ENABLE_MAC_PAYLOAD_DEBUG)
|
||||
@@ -547,7 +548,8 @@ ue_send_sdu(module_id_t module_idP,
|
||||
MBMS_FLAG_NO,
|
||||
rx_lcids[i],
|
||||
(char *) payload_ptr, rx_lengths[i], 1,
|
||||
NULL);
|
||||
NULL,
|
||||
0,0); //Jin add last two
|
||||
} else {
|
||||
LOG_E(MAC, "[UE %d] Frame %d : unknown LCID %d (eNB %d)\n",
|
||||
module_idP, frameP, rx_lcids[i], eNB_index);
|
||||
@@ -780,7 +782,8 @@ ue_send_mch_sdu(module_id_t module_idP, uint8_t CC_id, frame_t frameP,
|
||||
(char *)payload_ptr,
|
||||
rx_lengths[i],
|
||||
1,
|
||||
NULL);
|
||||
NULL,
|
||||
0,0); //Jin add last two
|
||||
}
|
||||
} else {
|
||||
LOG_W(MAC,
|
||||
@@ -852,7 +855,8 @@ void ue_send_sl_sdu(module_id_t module_idP,
|
||||
rlc_sdu,
|
||||
rlc_sdu_len,
|
||||
1,
|
||||
NULL);
|
||||
NULL,
|
||||
0,0); //Jin add last two
|
||||
} else { //SL_DISCOVERY
|
||||
uint16_t len = sdu_len;
|
||||
LOG_I( MAC, "SL DISCOVERY \n");
|
||||
|
||||
@@ -527,10 +527,23 @@ int nr_rrc_mac_config_req_sl_preconfig(module_id_t module_id,
|
||||
NR_TDD_UL_DL_Pattern_t *tdd = &sl_mac->sl_TDD_config->pattern1;
|
||||
const int n_ul_slots_period = tdd ? tdd->nrofUplinkSlots + (tdd->nrofUplinkSymbols > 0 ? 1 : 0) : nr_slots_frame;
|
||||
uint16_t num_subch = sl_get_num_subch(mac->sl_tx_res_pool);
|
||||
mac->sl_info.list[0]->UE_sched_ctrl.sched_psfch = calloc(n_ul_slots_period * num_subch, sizeof(SL_sched_feedback_t));
|
||||
mac->sl_info.list[0]->UE_sched_ctrl.sched_psfch->feedback_frame = -1;
|
||||
mac->sl_info.list[0]->UE_sched_ctrl.sched_psfch->feedback_slot = -1;
|
||||
//Jin replace hardcode list, to support multiple UES.
|
||||
//mac->sl_info.list[0]->UE_sched_ctrl.sched_psfch = calloc(n_ul_slots_period * num_subch, sizeof(SL_sched_feedback_t));
|
||||
//mac->sl_info.list[0]->UE_sched_ctrl.sched_psfch->feedback_frame = -1;
|
||||
//mac->sl_info.list[0]->UE_sched_ctrl.sched_psfch->feedback_slot = -1;
|
||||
/****************** Jin replacement ****************************** */
|
||||
SL_UE_iterator(mac->sl_info.list, UE) {
|
||||
const int n = sl_num_slsch_feedbacks(mac);
|
||||
UE->UE_sched_ctrl.sched_psfch = calloc(n, sizeof(SL_sched_feedback_t));
|
||||
for (int i = 0; i < n; i++) {
|
||||
UE->UE_sched_ctrl.sched_psfch = calloc(n_ul_slots_period * num_subch, sizeof(SL_sched_feedback_t));
|
||||
UE->UE_sched_ctrl.sched_psfch->feedback_frame = -1;
|
||||
UE->UE_sched_ctrl.sched_psfch->feedback_slot = -1;
|
||||
}
|
||||
}
|
||||
/************************************************ */
|
||||
|
||||
|
||||
int nr_slots_period = nr_slots_frame;
|
||||
int nr_ulstart_slot = 0;
|
||||
if (tdd) {
|
||||
@@ -744,9 +757,22 @@ void nr_rrc_mac_config_req_sl_mib(module_id_t module_id,
|
||||
|
||||
const int n_ul_slots_period = tdd ? tdd->nrofUplinkSlots + (tdd->nrofUplinkSymbols > 0 ? 1 : 0) : nr_slots_frame;
|
||||
uint16_t num_subch = sl_get_num_subch(mac->sl_tx_res_pool);
|
||||
mac->sl_info.list[0]->UE_sched_ctrl.sched_psfch = calloc(n_ul_slots_period * num_subch, sizeof(SL_sched_feedback_t));
|
||||
mac->sl_info.list[0]->UE_sched_ctrl.sched_psfch->feedback_frame = -1;
|
||||
mac->sl_info.list[0]->UE_sched_ctrl.sched_psfch->feedback_slot = -1;
|
||||
//Jin replace hardcode list, to support multiple UES.
|
||||
//mac->sl_info.list[0]->UE_sched_ctrl.sched_psfch = calloc(n_ul_slots_period * num_subch, sizeof(SL_sched_feedback_t)); //Jin
|
||||
//mac->sl_info.list[0]->UE_sched_ctrl.sched_psfch->feedback_frame = -1;
|
||||
//mac->sl_info.list[0]->UE_sched_ctrl.sched_psfch->feedback_slot = -1;
|
||||
/****************** Jin replacement ****************************** */
|
||||
SL_UE_iterator(mac->sl_info.list, UE) {
|
||||
const int n = sl_num_slsch_feedbacks(mac);
|
||||
UE->UE_sched_ctrl.sched_psfch = calloc(n, sizeof(SL_sched_feedback_t));
|
||||
for (int i = 0; i < n; i++) {
|
||||
UE->UE_sched_ctrl.sched_psfch = calloc(n_ul_slots_period * num_subch, sizeof(SL_sched_feedback_t));
|
||||
UE->UE_sched_ctrl.sched_psfch->feedback_frame = -1;
|
||||
UE->UE_sched_ctrl.sched_psfch->feedback_slot = -1;
|
||||
}
|
||||
}
|
||||
/************************************************ */
|
||||
|
||||
|
||||
LOG_I(MAC, "SIDELINK CONFIGs: tdd config period:%d, mu:%ld, DLslots:%ld,ULslots:%ld Mixedslotsym DL:UL %ld:%ld\n",
|
||||
sl_config->tdd_table.tdd_period, sl_mac->sl_TDD_config->referenceSubcarrierSpacing,
|
||||
|
||||
@@ -537,7 +537,8 @@ typedef struct {
|
||||
} NR_SL_UE_sched_ctrl_t;
|
||||
|
||||
#define MAX_SL_UE_CONNECTIONS 8
|
||||
#define CUR_SL_UE_CONNECTIONS 1
|
||||
//#define CUR_SL_UE_CONNECTIONS 1
|
||||
#define CUR_SL_UE_CONNECTIONS 2 //jin : increase for X No.of.UEs
|
||||
|
||||
#define MAX_SL_CSI_REPORTCONFIG MAX_SL_UE_CONNECTIONS
|
||||
|
||||
|
||||
@@ -78,7 +78,9 @@ extern void mac_rlc_data_ind(const module_id_t module_idP,
|
||||
char *buffer_pP,
|
||||
const tb_size_t tb_sizeP,
|
||||
num_tb_t num_tbP,
|
||||
crc_t *crcs_pP);
|
||||
crc_t *crcs_pP,
|
||||
const uint32_t sourceL2Id, // jin add
|
||||
const uint32_t destinationL2Id); // jin add
|
||||
|
||||
extern const char *rnti_types[];
|
||||
extern const char *dci_formats[];
|
||||
|
||||
@@ -91,10 +91,24 @@ void handle_nr_ue_sl_harq(module_id_t mod_id,
|
||||
{
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id);
|
||||
NR_UE_SL_SCHED_LOCK(&mac->sl_sched_lock);
|
||||
NR_SL_UE_info_t **UE_SL_temp = (NR_SL_UE_info_t **)&mac->sl_info.list, *UE;
|
||||
// TODO: update for multiple UEs
|
||||
UE=*(UE_SL_temp);
|
||||
//NR_SL_UE_info_t **UE_SL_temp = (NR_SL_UE_info_t **)&mac->sl_info.list, *UE; //Jin replace
|
||||
// TODO: update for multiple UEs !!!Jin fix here!
|
||||
//UE=*(UE_SL_temp); //Jin replace
|
||||
//uint8_t num_ack_rcvd = rx_slsch_pdu->num_acks_rcvd; //Jin replace
|
||||
|
||||
/***********Jin add for multiple UEs ***********/
|
||||
// IMPORTANT: src_id must be host-order here.
|
||||
NR_SL_UE_info_t *UE = find_UE(mac, src_id);
|
||||
LOG_I(NR_MAC, "%s: JIN debug &&&&&&&&&&&&&&&& me=%u src_id=%u\n", __FUNCTION__, mac->src_id, src_id);
|
||||
if (!UE) {
|
||||
LOG_W(NR_MAC, "%s: unknown peer src_id=%u (me=%u)\n",
|
||||
__FUNCTION__, src_id, mac->src_id);
|
||||
NR_UE_SL_SCHED_UNLOCK(&mac->sl_sched_lock);
|
||||
return;
|
||||
}
|
||||
uint8_t num_ack_rcvd = rx_slsch_pdu->num_acks_rcvd;
|
||||
/**************Jin end ********* */
|
||||
|
||||
|
||||
NR_SL_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
|
||||
NR_UE_sl_harq_t **matched_harqs = (NR_UE_sl_harq_t **) calloc(sched_ctrl->feedback_sl_harq.len, sizeof(NR_UE_sl_harq_t *));
|
||||
@@ -212,8 +226,30 @@ void nr_schedule_slsch(NR_UE_MAC_INST_t *mac, int frameP, int slotP, nr_sci_pdu_
|
||||
uint16_t *slsch_pdu_length_max, NR_UE_sl_harq_t *cur_harq,
|
||||
mac_rlc_status_resp_t *rlc_status,
|
||||
sl_resource_info_t *resource) {
|
||||
uid_t dest_id = UE->uid;
|
||||
NR_SL_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
|
||||
//uid_t dest_id = UE->uid;//Jin problem : hardcoded as 1 for all UEs
|
||||
/* ----------------------------Jin replacement:--------- */
|
||||
uid_t dest_id = 0;
|
||||
const uint16_t src = mac->src_id;
|
||||
|
||||
if (src == 0) {
|
||||
// alternate between 1 and 2 deterministically using (frame,slot)
|
||||
sl_nr_ue_mac_params_t *sl_mac_params = mac->SL_MAC_PARAMS;
|
||||
const int mu = sl_mac_params->sl_phy_config.sl_config_req.sl_bwp_config.sl_scs;
|
||||
const int spf = nr_slots_per_frame[mu];
|
||||
const int64_t abs = (int64_t)frameP * spf + slotP; // use the function's frame/slot variables
|
||||
dest_id = (abs & 1) ? 2 : 1;
|
||||
} else {
|
||||
dest_id = 0;
|
||||
}
|
||||
|
||||
// Optional: sanity log (remove once stable)
|
||||
LOG_D(NR_MAC, "[SL-TX] src_id=%u -> dest_id=%u (frame=%d slot=%d)\n",
|
||||
src, dest_id, frameP, slotP);
|
||||
/* ------------------------------------------------------ */
|
||||
|
||||
|
||||
|
||||
NR_SL_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
|
||||
const NR_mac_dir_stats_t *stats = &UE->mac_sl_stats.sl;
|
||||
NR_sched_pssch_t *sched_pssch = &sched_ctrl->sched_pssch;
|
||||
sl_nr_ue_mac_params_t *sl_mac = mac->SL_MAC_PARAMS;
|
||||
@@ -310,7 +346,17 @@ void nr_schedule_slsch(NR_UE_MAC_INST_t *mac, int frameP, int slotP, nr_sci_pdu_
|
||||
uint16_t num_subch = sl_get_num_subch(mac->sl_tx_res_pool);
|
||||
bool is_feedback_slot = false;
|
||||
for (int i = 0; i < (n_ul_slots_period * num_subch); i++) {
|
||||
SL_sched_feedback_t *sched_psfch = &mac->sl_info.list[0]->UE_sched_ctrl.sched_psfch[i];
|
||||
//SL_sched_feedback_t *sched_psfch = &mac->sl_info.list[0]->UE_sched_ctrl.sched_psfch[i]; //Jin replace
|
||||
//Jin implementation to repalce info.list
|
||||
NR_SL_UE_info_t *peer = find_UE(mac, dest_id);
|
||||
if (!peer || !peer->UE_sched_ctrl.sched_psfch) {
|
||||
LOG_W(NR_MAC, "PSSCH/PSFCH: no peer or no sched_psfch for dest_id=%d\n", dest_id);
|
||||
continue; // or return depending on context
|
||||
}
|
||||
SL_sched_feedback_t *sched_psfch = &peer->UE_sched_ctrl.sched_psfch[i];
|
||||
//Jin end
|
||||
|
||||
|
||||
if (slotP == sched_psfch->feedback_slot) {
|
||||
LOG_D(NR_MAC, "%4d.%2d i = %d sched_psfch %p feedback slot %d\n", frameP, slotP, i, sched_psfch, sched_psfch->feedback_slot);
|
||||
is_feedback_slot = true;
|
||||
@@ -349,8 +395,24 @@ void nr_schedule_slsch(NR_UE_MAC_INST_t *mac, int frameP, int slotP, nr_sci_pdu_
|
||||
sci2_pdu->ndi = cur_harq->ndi;
|
||||
sci2_pdu->rv_index = nr_rv_round_map[cur_harq->round % 4];
|
||||
sci2_pdu->source_id = mac->src_id;
|
||||
/* --- JIN: sync-ref should reply to the UE that sent the last SCI2 --- */
|
||||
if (mac->src_id == 0) { // sync-ref
|
||||
const uint16_t last_rx_src = mac->sci_pdu_rx.source_id; // decoded in nr_ue_process_sci2_indication_pdu
|
||||
if (last_rx_src != 0 && last_rx_src != mac->src_id) {
|
||||
dest_id = last_rx_src;
|
||||
}
|
||||
LOG_D(NR_MAC,
|
||||
"[JIN][SL-TX-DEST] sync-ref me=%u choose DST=%u (last_rx_src=%u)\n",
|
||||
mac->src_id, dest_id, last_rx_src);
|
||||
}
|
||||
/* --- end JIN --- */
|
||||
|
||||
|
||||
sci2_pdu->dest_id = dest_id;
|
||||
sci2_pdu->harq_feedback = cur_harq->is_waiting;
|
||||
|
||||
//LOG_D(NR_MAC, "[Jin Jin !!!!! slsch define sci2] SCI2 SRC=%d DST=%d\n",sci2_pdu->source_id ,sci2_pdu->dest_id );//Jin debug fixed srcID problem
|
||||
|
||||
LOG_D(NR_MAC, "%4d.%2d Comparing Setting harq_feedback %d bytes_in_buffer %d sl_harq_pid %d\n", frameP, slotP, sci2_pdu->harq_feedback, rlc_status->bytes_in_buffer, cur_harq ? cur_harq->sl_harq_pid : 0);
|
||||
sci2_pdu->cast_type = 1;
|
||||
if (format2 == NR_SL_SCI_FORMAT_2C || format2 == NR_SL_SCI_FORMAT_2A) {
|
||||
@@ -388,7 +450,7 @@ SL_CSI_Report_t* set_nr_ue_sl_csi_meas_periodicity(const NR_TDD_UL_DL_Pattern_t
|
||||
uint8_t n_slots_frame = nr_slots_per_frame[mu];
|
||||
const int n_ul_slots_period = tdd ? tdd->nrofUplinkSlots + (tdd->nrofUplinkSymbols > 0 ? 1 : 0) : n_slots_frame;
|
||||
const int nr_slots_period = tdd ? n_slots_frame / get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity) : n_slots_frame;
|
||||
const int ideal_period = (CUR_SL_UE_CONNECTIONS * nr_slots_period) / n_ul_slots_period;
|
||||
const int ideal_period = (CUR_SL_UE_CONNECTIONS * nr_slots_period) / n_ul_slots_period; //Jin replace
|
||||
const int first_ul_slot_period = tdd ? get_first_ul_slot(tdd->nrofDownlinkSlots, tdd->nrofDownlinkSymbols, tdd->nrofUplinkSymbols) : 0;
|
||||
const int idx = (uid << 1) + is_rsrp;
|
||||
SL_CSI_Report_t *csi_report = &sched_ctrl->sched_csi_report;
|
||||
|
||||
@@ -160,6 +160,7 @@ static uint8_t nr_extract_dci_info(NR_UE_MAC_INST_t *mac,
|
||||
|
||||
void nr_ue_init_mac(module_id_t module_idP, ueinfo_t* ueinfo)
|
||||
{
|
||||
|
||||
LOG_I(NR_MAC, "[UE%d] Applying default macMainConfig\n", module_idP);
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(module_idP);
|
||||
nr_ue_mac_default_configs(mac);
|
||||
@@ -185,11 +186,11 @@ void nr_ue_init_mac(module_id_t module_idP, ueinfo_t* ueinfo)
|
||||
AssertFatal((get_nrUE_params()->mcs >= 0 && get_nrUE_params()->mcs <= 28), "MCS must be 1 to 28!!!");
|
||||
int k = 0;
|
||||
for (int i = 0; i < CUR_SL_UE_CONNECTIONS + 1; i++) {
|
||||
if (mac->src_id == i)
|
||||
if (mac->src_id == i)
|
||||
continue;
|
||||
mac->sl_info.list[k] = calloc(1, sizeof(NR_SL_UE_info_t));
|
||||
mac->sl_info.list[k]->uid = i;
|
||||
NR_SL_UE_sched_ctrl_t *UE_sched_ctrl = &mac->sl_info.list[k]->UE_sched_ctrl;
|
||||
NR_SL_UE_sched_ctrl_t *UE_sched_ctrl = &mac->sl_info.list[k]->UE_sched_ctrl;
|
||||
UE_sched_ctrl->rx_csi_report.RI = 0;
|
||||
UE_sched_ctrl->rx_csi_report.CQI = 0;
|
||||
UE_sched_ctrl->sl_max_mcs = get_nrUE_params()->mcs;
|
||||
@@ -200,6 +201,12 @@ void nr_ue_init_mac(module_id_t module_idP, ueinfo_t* ueinfo)
|
||||
create_nr_list(&UE_sched_ctrl->retrans_sl_harq, 16);
|
||||
k++;
|
||||
}
|
||||
mac->sl_info.list[k] = NULL; //Jin add, renew for new UES
|
||||
|
||||
if (ueinfo != NULL) {
|
||||
mac->src_id = ueinfo->srcid;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void nr_ue_mac_default_configs(NR_UE_MAC_INST_t *mac)
|
||||
@@ -3734,7 +3741,8 @@ void nr_ue_process_mac_pdu(nr_downlink_indication_t *dl_info,
|
||||
(char *)(pduP + mac_subheader_len),
|
||||
mac_len,
|
||||
1,
|
||||
NULL);
|
||||
NULL,
|
||||
0,0);//Jin add last 2
|
||||
break;
|
||||
default:
|
||||
LOG_W(MAC, "unknown lcid %02x\n", rx_lcid);
|
||||
|
||||
@@ -599,7 +599,7 @@ void configure_psfch_params_tx(int module_idP,
|
||||
sl_nr_rx_indication_t *rx_ind,
|
||||
int pdu_id)
|
||||
{
|
||||
// TODO: May need to update in case of multiple UEs
|
||||
// TODO: May need to update in case of multiple UEs !!!!Jin!!!
|
||||
const uint8_t psfch_periods[] = {0,1,2,4};
|
||||
NR_SL_PSFCH_Config_r16_t *sl_psfch_config = mac->sl_tx_res_pool->sl_PSFCH_Config_r16->choice.setup;
|
||||
long psfch_period = (sl_psfch_config->sl_PSFCH_Period_r16)
|
||||
@@ -754,7 +754,10 @@ int16_t get_feedback_slot(long psfch_period, uint16_t slot) {
|
||||
|
||||
int nr_ue_sl_acknack_scheduling(NR_UE_MAC_INST_t *mac, sl_nr_rx_indication_t *rx_ind,
|
||||
long psfch_period, uint16_t frame, uint16_t slot, const int nr_slots_frame) {
|
||||
// TODO: needs to be updated for multi-subchannels
|
||||
LOG_I(NR_MAC,//Jin add
|
||||
"[JIN DEBUG SL ACKNAKC SL-RX-IND] me=%u rx_ind sfn=%u slot=%u num_pdus=%u\n",
|
||||
mac->src_id, rx_ind->sfn, rx_ind->slot, rx_ind->number_pdus);
|
||||
// TODO: needs to be updated for multi-subchannels Jin : ?????
|
||||
int psfch_frame, psfch_slot;
|
||||
sl_nr_ue_mac_params_t *sl_mac = mac->SL_MAC_PARAMS;
|
||||
NR_TDD_UL_DL_Pattern_t *tdd = &sl_mac->sl_TDD_config->pattern1;
|
||||
@@ -765,7 +768,17 @@ int nr_ue_sl_acknack_scheduling(NR_UE_MAC_INST_t *mac, sl_nr_rx_indication_t *rx
|
||||
|
||||
psfch_slot = get_feedback_slot(psfch_period, slot);
|
||||
const int psfch_index = get_psfch_index(rx_ind->sfn, rx_ind->slot, nr_slots_frame, tdd, n_ul_buf_max_size);
|
||||
NR_SL_UE_sched_ctrl_t *sched_ctrl = &mac->sl_info.list[0]->UE_sched_ctrl;
|
||||
//NR_SL_UE_sched_ctrl_t *sched_ctrl = &mac->sl_info.list[0]->UE_sched_ctrl; //Jin replace
|
||||
//Jin patch
|
||||
const uint16_t peer_id = mac->sci_pdu_rx.source_id;
|
||||
NR_SL_UE_info_t *peer = find_UE(mac, peer_id);
|
||||
if (!peer || !peer->UE_sched_ctrl.sched_psfch) {
|
||||
LOG_W(NR_MAC, "%s: no peer or sched_psfch for peer_id=%u\n", __FUNCTION__, peer_id);
|
||||
return -1;
|
||||
}
|
||||
NR_SL_UE_sched_ctrl_t *sched_ctrl = &peer->UE_sched_ctrl;
|
||||
//Jin end
|
||||
|
||||
SL_sched_feedback_t *curr_psfch = &sched_ctrl->sched_psfch[psfch_index];
|
||||
psfch_frame = frame;
|
||||
frameslot_t fs;
|
||||
@@ -800,7 +813,32 @@ void fill_psfch_params_tx(NR_UE_MAC_INST_t *mac, sl_nr_rx_indication_t *rx_ind,
|
||||
|
||||
NR_SL_BWP_Generic_r16_t *sl_bwp = mac->sl_bwp->sl_BWP_Generic_r16;
|
||||
|
||||
SL_sched_feedback_t *sched_psfch = &mac->sl_info.list[0]->UE_sched_ctrl.sched_psfch[psfch_index];
|
||||
//SL_sched_feedback_t *sched_psfch = &mac->sl_info.list[0]->UE_sched_ctrl.sched_psfch[psfch_index]; //Jin replace
|
||||
//Jin replace
|
||||
|
||||
const uint16_t peer_id = mac->sci_pdu_rx.source_id;
|
||||
NR_SL_UE_info_t *peer = find_UE(mac, peer_id);
|
||||
if (!peer) {
|
||||
LOG_W(NR_MAC, "%s: no peer struct for source_id=%u (psfch_index=%d)\n",
|
||||
__FUNCTION__, peer_id, psfch_index);
|
||||
return;
|
||||
}
|
||||
if (!peer->UE_sched_ctrl.sched_psfch) {
|
||||
LOG_W(NR_MAC, "%s: peer_id=%u has NULL sched_psfch\n",
|
||||
__FUNCTION__, peer_id);
|
||||
return;
|
||||
}
|
||||
const int n = sl_num_slsch_feedbacks(mac);
|
||||
if (psfch_index < 0 || psfch_index >= n) {
|
||||
LOG_W(NR_MAC, "%s: psfch_index=%d out of range (n=%d) peer_id=%u\n",
|
||||
__FUNCTION__, psfch_index, n, peer_id);
|
||||
return;
|
||||
}
|
||||
SL_sched_feedback_t *sched_psfch = &peer->UE_sched_ctrl.sched_psfch[psfch_index];
|
||||
//jIN END
|
||||
|
||||
|
||||
|
||||
LOG_D(NR_MAC, "psfch_period %ld, feedback frame:slot %d:%d, frame:slot %d:%d, harq feedback %d psfch_index %d\n",
|
||||
psfch_period,
|
||||
sched_psfch->feedback_frame,
|
||||
@@ -884,12 +922,16 @@ void update_harq_lists(NR_UE_MAC_INST_t *mac, frame_t frame, sub_frame_t slot, N
|
||||
remove_nr_list(&sched_ctrl->feedback_sl_harq, cur);
|
||||
harq->feedback_slot = -1;
|
||||
harq->is_waiting = false;
|
||||
|
||||
//Jin disactive
|
||||
/*
|
||||
if (harq->round >= HARQ_ROUND_MAX - 1) {
|
||||
abort_nr_ue_sl_harq(mac, cur, UE);
|
||||
} else {
|
||||
add_tail_nr_list(&sched_ctrl->retrans_sl_harq, cur);
|
||||
harq->round++;
|
||||
}
|
||||
*/
|
||||
}
|
||||
cur = sched_ctrl->feedback_sl_harq.next[cur];
|
||||
}
|
||||
@@ -919,7 +961,8 @@ void configure_psfch_params_rx(int module_idP,
|
||||
SL_UE_iterator(UE_info->list, UE) {
|
||||
NR_SL_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
|
||||
NR_UE_sl_harq_t **matched_harqs = (NR_UE_sl_harq_t **) calloc(sched_ctrl->feedback_sl_harq.len, sizeof(NR_UE_sl_harq_t *));
|
||||
int matched_sz = find_current_slot_harqs(frame, slot, sched_ctrl, matched_harqs);
|
||||
//int matched_sz = find_current_slot_harqs(frame, slot, sched_ctrl, matched_harqs);
|
||||
int matched_sz = 0; //Jin desable SCI also
|
||||
LOG_D(NR_MAC, "%s matched_sz %d\n", __FUNCTION__, matched_sz);
|
||||
rx_config->sl_rx_config_list[0].num_psfch_pdus = 0;
|
||||
for (int i = 0; i < matched_sz; i++) {
|
||||
@@ -990,37 +1033,68 @@ uint8_t sl_num_slsch_feedbacks(NR_UE_MAC_INST_t *mac) {
|
||||
}
|
||||
|
||||
bool is_feedback_scheduled(NR_UE_MAC_INST_t *mac, int frameP,int slotP) {
|
||||
for (int i = 0; i < sl_num_slsch_feedbacks(mac); i++) {
|
||||
SL_sched_feedback_t *sched_psfch = &mac->sl_info.list[0]->UE_sched_ctrl.sched_psfch[i];
|
||||
LOG_D(NR_MAC, "frame.slot %4d.%2d, harq_feedback %d\n", frameP, slotP, sched_psfch->harq_feedback);
|
||||
if (frameP == sched_psfch->feedback_frame && slotP == sched_psfch->feedback_slot && sched_psfch->harq_feedback) {
|
||||
return true;
|
||||
|
||||
|
||||
//for (int i = 0; i < sl_num_slsch_feedbacks(mac); i++) { //Jin replace
|
||||
// SL_sched_feedback_t *sched_psfch = &mac->sl_info.list[0]->UE_sched_ctrl.sched_psfch[i]; //JIn replace
|
||||
|
||||
//Jin replace the loop begining
|
||||
const int n = sl_num_slsch_feedbacks(mac);
|
||||
|
||||
//NR_SL_UE_info_t *UE = NULL; // required by some SL_UE_iterator macro variants
|
||||
SL_UE_iterator(mac->sl_info.list, UE) {
|
||||
SL_sched_feedback_t *arr = UE->UE_sched_ctrl.sched_psfch;
|
||||
if (!arr)
|
||||
continue;
|
||||
for (int i = 0; i < n; i++) {
|
||||
SL_sched_feedback_t *sched_psfch = &arr[i];
|
||||
//Jin end
|
||||
|
||||
LOG_D(NR_MAC, "frame.slot %4d.%2d, harq_feedback %d\n", frameP, slotP, sched_psfch->harq_feedback);
|
||||
if (frameP == sched_psfch->feedback_frame && slotP == sched_psfch->feedback_slot && sched_psfch->harq_feedback) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void reset_sched_psfch(NR_UE_MAC_INST_t *mac, int frameP,int slotP) {
|
||||
//for (int i = 0; i < sl_num_slsch_feedbacks(mac); i++) { //Jin replace
|
||||
//SL_sched_feedback_t *sched_psfch = &mac->sl_info.list[0]->UE_sched_ctrl.sched_psfch[i]; //jin replace
|
||||
//Jin replace whole loop beginning
|
||||
const int n = sl_num_slsch_feedbacks(mac);
|
||||
SL_UE_iterator(mac->sl_info.list, UE) {
|
||||
|
||||
for (int i = 0; i < sl_num_slsch_feedbacks(mac); i++) {
|
||||
SL_sched_feedback_t *sched_psfch = &mac->sl_info.list[0]->UE_sched_ctrl.sched_psfch[i];
|
||||
if (frameP == sched_psfch->feedback_frame && slotP == sched_psfch->feedback_slot) {
|
||||
sched_psfch->feedback_frame = -1;
|
||||
sched_psfch->feedback_slot = -1;
|
||||
sched_psfch->harq_feedback = 0;
|
||||
SL_sched_feedback_t *arr = UE->UE_sched_ctrl.sched_psfch;
|
||||
if (!arr)
|
||||
continue;
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
SL_sched_feedback_t *sched_psfch = &arr[i];
|
||||
//Jin end
|
||||
|
||||
if (frameP == sched_psfch->feedback_frame && slotP == sched_psfch->feedback_slot) {
|
||||
sched_psfch->feedback_frame = -1;
|
||||
sched_psfch->feedback_slot = -1;
|
||||
sched_psfch->harq_feedback = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void nr_ue_process_mac_sl_pdu(int module_idP,
|
||||
sl_nr_rx_indication_t *rx_ind,
|
||||
int pdu_id)
|
||||
{
|
||||
{
|
||||
int8_t pdu_type = (rx_ind->rx_indication_body + pdu_id)->pdu_type;
|
||||
sl_nr_slsch_pdu_t *rx_slsch_pdu = &(rx_ind->rx_indication_body + pdu_id)->rx_slsch_pdu;
|
||||
uint8_t *pduP = rx_slsch_pdu->pdu;
|
||||
int32_t pdu_len = (int32_t)rx_slsch_pdu->pdu_length;
|
||||
uint8_t done = 0;
|
||||
|
||||
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(module_idP);
|
||||
int frame = rx_ind->sfn;
|
||||
int slot = rx_ind->slot;
|
||||
@@ -1028,6 +1102,50 @@ void nr_ue_process_mac_sl_pdu(int module_idP,
|
||||
return;
|
||||
}
|
||||
|
||||
// ---------------- Jin DEBUG: dump first bytes and scan for LCID=4 ----------------
|
||||
//LOG_I(NR_MAC, "[SL-RX-DBG] me=%u pdu_len=%d pdu_type=%d frame=%d slot=%d\n",
|
||||
// mac->src_id, pdu_len, pdu_type, frame, slot);
|
||||
|
||||
if (pdu_len >= 16) {
|
||||
//LOG_I(NR_MAC,
|
||||
// "[SL-RX-DBG] pdu@0 first16: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
|
||||
// pduP[0], pduP[1], pduP[2], pduP[3], pduP[4], pduP[5], pduP[6], pduP[7],
|
||||
// pduP[8], pduP[9], pduP[10], pduP[11], pduP[12], pduP[13], pduP[14], pduP[15]);
|
||||
if (pdu_len >= 5) {
|
||||
uint8_t lcid_off4 = ((NR_MAC_SUBHEADER_FIXED *)(pduP + 4))->LCID;
|
||||
// LOG_I(NR_MAC, "[SL-RX-DBG] LCID at off=4 is %u (byte=%02x)\n", lcid_off4, pduP[4]);
|
||||
}
|
||||
|
||||
|
||||
} else if (pdu_len > 0) {
|
||||
// print up to 8 bytes if small
|
||||
int n = pdu_len < 8 ? pdu_len : 8;
|
||||
//LOG_I(NR_MAC, "[SL-RX-DBG] pdu@0 first%d:", n);
|
||||
for (int i = 0; i < n; i++) {
|
||||
// LOG_I(NR_MAC, " %02x", pduP[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Scan offsets 0..15: where does the parser "see" LCID=4?
|
||||
int max_scan = pdu_len < 256 ? pdu_len : 256;
|
||||
for (int off = 0; off < max_scan; off++) {
|
||||
uint8_t lcid = ((NR_MAC_SUBHEADER_FIXED *)(pduP + off))->LCID;
|
||||
if (lcid == 4) {
|
||||
// LOG_I(NR_MAC, "[SL-RX-DBG] FOUND LCID=4 at off=%d (byte=%02x)\n", off, pduP[off]);
|
||||
if (pdu_len - off >= 16) {
|
||||
// LOG_I(NR_MAC,
|
||||
// "[SL-RX-DBG] pdu@off first16: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
|
||||
// pduP[off+0], pduP[off+1], pduP[off+2], pduP[off+3],
|
||||
// pduP[off+4], pduP[off+5], pduP[off+6], pduP[off+7],
|
||||
// pduP[off+8], pduP[off+9], pduP[off+10], pduP[off+11],
|
||||
// pduP[off+12], pduP[off+13], pduP[off+14], pduP[off+15]);
|
||||
}
|
||||
}
|
||||
}
|
||||
// ---------------- end Jin DEBUG ----------------
|
||||
|
||||
|
||||
|
||||
NR_SLSCH_MAC_SUBHEADER_FIXED *sl_sch_subheader = (NR_SLSCH_MAC_SUBHEADER_FIXED *) pduP;
|
||||
uint8_t psfch_period = 0;
|
||||
if (mac->sl_tx_res_pool->sl_PSFCH_Config_r16 &&
|
||||
@@ -1083,13 +1201,30 @@ void nr_ue_process_mac_sl_pdu(int module_idP,
|
||||
tx_slot);
|
||||
}
|
||||
|
||||
LOG_D(NR_MAC, "In %s : processing PDU %d (with length %d) of %d total number of PDUs...\n", __FUNCTION__, pdu_id, pdu_len, rx_ind->number_pdus);
|
||||
LOG_D(NR_PHY, "%4d.%2d Rx V %d R %d SRC %d DST %d\n", frame, slot, sl_sch_subheader->V, sl_sch_subheader->R, sl_sch_subheader->SRC, sl_sch_subheader->DST);
|
||||
LOG_I(NR_MAC, "In %s : processing PDU %d (with length %d) of %d total number of PDUs...\n", __FUNCTION__, pdu_id, pdu_len, rx_ind->number_pdus);
|
||||
LOG_I(NR_PHY, "%4d.%2d Rx V %d R %d SRC %d DST %d\n", frame, slot, sl_sch_subheader->V, sl_sch_subheader->R, sl_sch_subheader->SRC, sl_sch_subheader->DST);
|
||||
pduP += sizeof(*sl_sch_subheader);
|
||||
pdu_len -= sizeof(*sl_sch_subheader);
|
||||
|
||||
|
||||
|
||||
if (frame % 20 == 0)
|
||||
LOG_D(NR_PHY, "%4d.%2d Rx V %d R %d SRC %d DST %d\n", frame, slot, sl_sch_subheader->V, sl_sch_subheader->R, sl_sch_subheader->SRC, sl_sch_subheader->DST);
|
||||
while (!done && pdu_len > 0) {
|
||||
|
||||
//JIN: Filter packets not meant for this UE
|
||||
uint16_t my_id = mac->src_id;
|
||||
uint16_t dst_id = sl_sch_subheader->DST;
|
||||
// Accept if: (1) unicast to me, OR (2) broadcast/multicast
|
||||
bool for_me = (dst_id == my_id) || (dst_id >= 0xFF00); // Adjust broadcast range as needed
|
||||
if (!for_me) {
|
||||
LOG_D(NR_MAC, "[SL-RX-FILTER] Ignoring packet: DST=%u but my_id=%u\n",
|
||||
dst_id, my_id);
|
||||
return; // Not for me, ignore it
|
||||
}
|
||||
//JIN END
|
||||
|
||||
|
||||
while (!done && pdu_len > 0) {
|
||||
uint16_t mac_len = 0x0000;
|
||||
uint16_t mac_subheader_len = 0x0001; // default to fixed-length subheader = 1-oct
|
||||
uint8_t rx_lcid = ((NR_MAC_SUBHEADER_FIXED *)(pduP))->LCID;
|
||||
@@ -1100,19 +1235,68 @@ void nr_ue_process_mac_sl_pdu(int module_idP,
|
||||
if (!get_mac_len(pduP, pdu_len, &mac_len, &mac_subheader_len))
|
||||
return;
|
||||
LOG_D(NR_MAC, "%4d.%2d : SLSCH -> LCID %d %d bytes with subheader %d\n", frame, slot, rx_lcid, mac_len, mac_subheader_len);
|
||||
// Jin Debug: ICMP sequence tracker
|
||||
// -------------------------------
|
||||
/*
|
||||
uint8_t *sdu = (uint8_t *)(pduP + mac_subheader_len);
|
||||
uint32_t sdu_len = mac_len;
|
||||
|
||||
if (sdu_len >= 34) { // Enough bytes for IPv4 + ICMP
|
||||
uint8_t *iph = sdu;
|
||||
|
||||
// IPv4 check: version = 4
|
||||
if ((iph[0] >> 4) == 4) {
|
||||
uint8_t ihl = (iph[0] & 0x0F) * 4;
|
||||
uint8_t protocol = iph[9];
|
||||
|
||||
if (protocol == 1 && sdu_len >= ihl + 8) { // ICMP
|
||||
uint8_t *icmph = iph + ihl;
|
||||
|
||||
uint8_t type = icmph[0];
|
||||
uint8_t code = icmph[1];
|
||||
uint16_t seq = (icmph[6] << 8) | icmph[7];
|
||||
|
||||
LOG_I(NR_MAC,
|
||||
"Jin ^^^^^^^^ [ICMP-RX] frame=%d slot=%d seq=%u type=%u code=%u\n",
|
||||
frame, slot, seq, type, code);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
// -------------------------------
|
||||
|
||||
|
||||
|
||||
LOG_I(NR_MAC, "[Jin !!!!!!!!! SL-RX->RLC] me=%u sl_hdr_SRC=%u sl_hdr_DST=%u rx_lcid=%u frame=%d slot=%d\n",
|
||||
mac->src_id, sl_sch_subheader->SRC, sl_sch_subheader->DST, rx_lcid, frame, slot);
|
||||
|
||||
|
||||
mac_rlc_data_ind(module_idP,
|
||||
mac->src_id,
|
||||
mac->src_id, //Jin origin
|
||||
// sl_sch_subheader->SRC, //Jin replace support multiple UEs
|
||||
0,
|
||||
frame,
|
||||
ENB_FLAG_NO,
|
||||
MBMS_FLAG_NO,
|
||||
rx_lcid,
|
||||
rx_lcid,
|
||||
(char *)(pduP + mac_subheader_len),
|
||||
mac_len,
|
||||
1,
|
||||
NULL);
|
||||
NULL,
|
||||
sl_sch_subheader->SRC, // NEW: sourceL2Id
|
||||
sl_sch_subheader->DST); // NEW: destinationL2Id
|
||||
//Jin log
|
||||
LOG_I(NR_MAC,
|
||||
"[Jin-Log check rx at pdu SL-RX-SLSCH] srcID_ME=%u sci_src=%u sci_dst=%u lcid=%u mac_len=%u frame=%u slot=%u\n",
|
||||
//mac->src_id, //jin origin
|
||||
sl_sch_subheader->SRC,//Jin update log
|
||||
mac->sci_pdu_rx.source_id,
|
||||
mac->sci_pdu_rx.dest_id,
|
||||
rx_lcid,
|
||||
mac_len,
|
||||
frame,
|
||||
slot);
|
||||
break;
|
||||
|
||||
case SL_SCH_LCID_SL_CSI_REPORT:
|
||||
{
|
||||
NR_MAC_SUBHEADER_FIXED* sub_pdu_header = (NR_MAC_SUBHEADER_FIXED*) pduP;
|
||||
|
||||
@@ -31,10 +31,11 @@
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include <arpa/inet.h> //Jin add
|
||||
/* exe */
|
||||
#include <common/utils/nr/nr_common.h>
|
||||
|
||||
#include <inttypes.h>//JIn add
|
||||
#include "mac_defs.h"
|
||||
/* PHY */
|
||||
#include "openair1/PHY/impl_defs_top.h"
|
||||
|
||||
@@ -44,6 +45,7 @@
|
||||
#include "NR_MAC_UE/mac_proto.h"
|
||||
#include "NR_MAC_UE/mac_extern.h"
|
||||
#include "NR_MAC_UE/nr_ue_sci.h"
|
||||
|
||||
/* utils */
|
||||
#include "assertions.h"
|
||||
#include "oai_asn1.h"
|
||||
@@ -55,6 +57,11 @@
|
||||
#include "LAYER2/NR_MAC_COMMON/nr_mac_extern.h"
|
||||
#include "LAYER2/RLC/rlc.h"
|
||||
|
||||
#include "RRC/NR_UE/rrc_defs.h"
|
||||
extern NR_SL_SchedulerConfig_t nr_sl_scheduler_config;
|
||||
|
||||
|
||||
|
||||
extern const int pscch_tda[2];
|
||||
extern const int pscch_rb_table[5];
|
||||
//#define SRS_DEBUG
|
||||
@@ -2982,7 +2989,7 @@ uint8_t nr_ue_get_sdu(module_id_t module_idP,
|
||||
//mac_ce_p->phr_ce_len = 0;
|
||||
//mac_ce_p->phr_header_len = 0;
|
||||
|
||||
uint8_t lcid = 0;
|
||||
uint8_t lcid = 0;
|
||||
uint16_t sdu_length = 0;
|
||||
uint16_t num_sdus = 0;
|
||||
mac_ce_p->sdu_length_total = 0;
|
||||
@@ -3285,6 +3292,7 @@ uint8_t sl_determine_if_SSB_slot(uint16_t frame, uint16_t slot, uint16_t slots_p
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void nr_store_slsch_buffer(NR_UE_MAC_INST_t *mac, frame_t frame, sub_frame_t slot) {
|
||||
|
||||
NR_SL_UEs_t *UE_info = &mac->sl_info;
|
||||
@@ -3293,9 +3301,9 @@ static void nr_store_slsch_buffer(NR_UE_MAC_INST_t *mac, frame_t frame, sub_fram
|
||||
sched_ctrl->num_total_bytes = 0;
|
||||
sched_ctrl->sl_pdus_total = 0;
|
||||
|
||||
const int lcid = 4;
|
||||
sched_ctrl->rlc_status[lcid] = mac_rlc_status_ind(0, mac->src_id, 0, frame, slot, ENB_FLAG_NO, MBMS_FLAG_NO, 4, 0, 0);
|
||||
|
||||
const int lcid = 4; //Jin : origin 4, test 1
|
||||
sched_ctrl->rlc_status[lcid] = mac_rlc_status_ind(0, mac->src_id, 0, frame, slot, ENB_FLAG_NO, MBMS_FLAG_NO, lcid, 0, 0);
|
||||
|
||||
if (sched_ctrl->rlc_status[lcid].bytes_in_buffer == 0)
|
||||
continue;
|
||||
|
||||
@@ -3432,6 +3440,8 @@ bool nr_ue_sl_pssch_scheduler(NR_UE_MAC_INST_t *mac,
|
||||
uint16_t frame = sl_ind->frame_tx;
|
||||
int feedback_frame, feedback_slot;
|
||||
int lcid = 4;
|
||||
|
||||
|
||||
int sdu_length = 0;
|
||||
uint16_t sdu_length_total = 0;
|
||||
uint8_t total_mac_pdu_header_len = 0;
|
||||
@@ -3445,15 +3455,14 @@ bool nr_ue_sl_pssch_scheduler(NR_UE_MAC_INST_t *mac,
|
||||
}
|
||||
if (sl_ind->slot_type != SIDELINK_SLOT_TYPE_TX) return is_resource_allocated;
|
||||
|
||||
if (slot > 9 && get_nrUE_params()->sync_ref) return is_resource_allocated;
|
||||
|
||||
if (slot < 10 && !get_nrUE_params()->sync_ref) return is_resource_allocated;
|
||||
if (slot > 9 && get_nrUE_params()->sync_ref) return is_resource_allocated;
|
||||
if (slot < 10 && !get_nrUE_params()->sync_ref) return is_resource_allocated;
|
||||
|
||||
LOG_D(NR_MAC,"[UE%d] SL-PSSCH SCHEDULER: Frame:SLOT %d:%d, slot_type:%d\n",
|
||||
sl_ind->module_id, frame, slot,sl_ind->slot_type);
|
||||
|
||||
uint16_t slsch_pdu_length_max;
|
||||
tx_config->tx_config_list[0].tx_pscch_pssch_config_pdu.slsch_payload = mac->slsch_payload;
|
||||
//tx_config->tx_config_list[0].tx_pscch_pssch_config_pdu.slsch_payload = mac->slsch_payload; //Jin comment for now, wrong
|
||||
|
||||
NR_SL_UEs_t *UE_info = &mac->sl_info;
|
||||
|
||||
@@ -3461,10 +3470,102 @@ bool nr_ue_sl_pssch_scheduler(NR_UE_MAC_INST_t *mac,
|
||||
LOG_D(NR_MAC, "UE list is empty\n");
|
||||
return is_resource_allocated;
|
||||
}
|
||||
|
||||
|
||||
//Jin new add replace previous tx_conf_list[0]
|
||||
tx_config->number_pdus = 0;
|
||||
tx_config->sfn = frame;
|
||||
tx_config->slot = slot;
|
||||
//jin end
|
||||
|
||||
preprocess(mac, frame, slot, &feedback_frame, &feedback_slot, sl_bwp, configured_PSFCH);
|
||||
|
||||
/* ---------------- Jin TDMA: minimal, deterministic, slot-parity 2UES+syncref----- ------ */
|
||||
/*
|
||||
uint16_t chosen_uid = 0;
|
||||
|
||||
if (get_nrUE_params()->sync_ref) {
|
||||
//UE0 transmits in slots 0..9, alternate destination by slot parity
|
||||
chosen_uid = (slot & 1) ? 2 : 1; //odd->UE2, even->UE1
|
||||
} else {
|
||||
const uint16_t owner_uid = (slot & 1) ? 2 : 1; //odd->UE2, even->UE1
|
||||
if (mac->src_id != owner_uid)
|
||||
return false; // not my TX slot
|
||||
chosen_uid = 0; //always send uplink to sync-ref
|
||||
}
|
||||
|
||||
LOG_D(NR_MAC, "[SL-TDMA-20] me=%u frame=%u slot=%u chosen_uid=%u\n",
|
||||
mac->src_id, frame, slot, chosen_uid);
|
||||
*/
|
||||
/* ---------------- end Jin TDMA ---------------- */
|
||||
/* ---------------- Jin TDMA: round-robin, N-UE generalised ---------------- */
|
||||
|
||||
uint16_t chosen_uid = 0;
|
||||
const int num_peers = CUR_SL_UE_CONNECTIONS; // peers per UE = total_UEs - 1
|
||||
|
||||
if (get_nrUE_params()->sync_ref) {
|
||||
// Sync-ref (uid=0) cycles through all non-zero peer UIDs round-robin
|
||||
// Each peer gets one slot in a repeating window of num_peers slots
|
||||
chosen_uid = (slot % num_peers) + 1; // gives 1..num_peers
|
||||
} else {
|
||||
//Non-sync-ref UEs: each owns one slot per window of num_peers slots.
|
||||
// src_id is 1-based (1..num_peers), so own slot index = src_id - 1
|
||||
const int own_slot_in_window = (int)mac->src_id - 1;
|
||||
if ((slot % num_peers) != own_slot_in_window)
|
||||
return false; //not my TX slot
|
||||
chosen_uid = 0; // always send uplink to sync-ref
|
||||
}
|
||||
|
||||
LOG_D(NR_MAC, "[SL-TDMA-20] me=%u frame=%u slot=%u chosen_uid=%u num_peers=%d\n",
|
||||
mac->src_id, frame, slot, chosen_uid, num_peers);
|
||||
|
||||
/* ---------------- end Jin TDMA ---------------- */
|
||||
/* ---------------- Jin TDMA Hardcoded : parameters push from SLC---------------- */
|
||||
/*
|
||||
uint16_t chosen_uid = 0;
|
||||
const int num_peers = CUR_SL_UE_CONNECTIONS;
|
||||
|
||||
if (get_nrUE_params()->sync_ref) {
|
||||
// sync-ref cycles through all peer UIDs regardless
|
||||
chosen_uid = (slot % num_peers) + 1;
|
||||
} else {
|
||||
int own_slot_in_window;
|
||||
uint8_t my_ue_id = (uint8_t)(mac->src_id - 1); // 0-based
|
||||
|
||||
if (nr_sl_scheduler_config.valid &&
|
||||
nr_sl_scheduler_config.action == 1 &&
|
||||
my_ue_id < MAX_UE_NR_CAPABILITY_SIZE) {
|
||||
// SLC_C has assigned a slot for this UE
|
||||
own_slot_in_window = nr_sl_scheduler_config.sfid[my_ue_id];
|
||||
LOG_D(NR_MAC, "[SLC_C] UE%d using dynamic slot %d\n",
|
||||
my_ue_id, own_slot_in_window);
|
||||
} else {
|
||||
// fallback: UE id == slot index
|
||||
own_slot_in_window = (int)mac->src_id - 1;
|
||||
LOG_D(NR_MAC, "[SLC_C] UE%d using default slot %d\n",
|
||||
my_ue_id, own_slot_in_window);
|
||||
}
|
||||
|
||||
if ((slot % num_peers) != own_slot_in_window)
|
||||
return false;
|
||||
chosen_uid = 0;
|
||||
}
|
||||
*/
|
||||
/* ---------------- end Jin TDMA push from SLC---------------- */
|
||||
|
||||
|
||||
SL_UE_iterator(UE_info->list, UE) {
|
||||
//Jin apply previous defined tdma slots
|
||||
if (UE->uid != chosen_uid)
|
||||
continue;
|
||||
// Ensure SCI2 destination matches the peer we are scheduling
|
||||
mac->sci2_pdu.source_id = mac->src_id;
|
||||
mac->sci2_pdu.dest_id = UE->uid;
|
||||
//Jin end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
NR_mac_dir_stats_t *sl_mac_stats = &UE->mac_sl_stats.sl;
|
||||
NR_SL_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
|
||||
sl_mac_stats->current_bytes = 0;
|
||||
@@ -3472,9 +3573,20 @@ bool nr_ue_sl_pssch_scheduler(NR_UE_MAC_INST_t *mac,
|
||||
NR_sched_pssch_t *sched_pssch = &sched_ctrl->sched_pssch;
|
||||
int8_t harq_id = sched_pssch->sl_harq_pid;
|
||||
|
||||
/*
|
||||
LOG_I(NR_MAC,//jin log
|
||||
"[PSSCH-OPP-Jin] frame=%d slot=%d slot_type=%d sync_ref=%d rbSize=%d\n",
|
||||
frame, slot, sl_ind->slot_type, get_nrUE_params()->sync_ref,
|
||||
sched_pssch->rbSize);*/
|
||||
|
||||
if (sched_pssch->rbSize <= 0)
|
||||
continue;
|
||||
|
||||
//Jin add
|
||||
const int pdu_idx = tx_config->number_pdus;
|
||||
AssertFatal(pdu_idx < 8,
|
||||
"tx_config_list overflow: pdu_idx=%d\n", pdu_idx);
|
||||
|
||||
NR_UE_sl_harq_t *cur_harq = NULL;
|
||||
|
||||
if (harq_id < 0) {
|
||||
@@ -3496,6 +3608,8 @@ bool nr_ue_sl_pssch_scheduler(NR_UE_MAC_INST_t *mac,
|
||||
cur_harq = &sched_ctrl->sl_harq_processes[harq_id];
|
||||
DevAssert(!cur_harq->is_waiting);
|
||||
/* retransmission or bytes to send */
|
||||
//Jin disable retx
|
||||
/*
|
||||
if (configured_PSFCH && ((cur_harq->round != 0) || (sched_ctrl->num_total_bytes > 0))) {
|
||||
cur_harq->feedback_slot = feedback_slot;
|
||||
cur_harq->feedback_frame = feedback_frame;
|
||||
@@ -3506,6 +3620,25 @@ bool nr_ue_sl_pssch_scheduler(NR_UE_MAC_INST_t *mac,
|
||||
else
|
||||
add_tail_nr_list(&sched_ctrl->available_sl_harq, harq_id);
|
||||
cur_harq->sl_harq_pid = harq_id;
|
||||
*/ //Jin end
|
||||
|
||||
//Jin disable harq
|
||||
cur_harq->feedback_slot = -1;
|
||||
cur_harq->feedback_frame = -1;
|
||||
cur_harq->is_waiting = false;
|
||||
|
||||
add_tail_nr_list(&sched_ctrl->available_sl_harq, harq_id);
|
||||
|
||||
cur_harq->sl_harq_pid = harq_id;
|
||||
|
||||
/*LOG_I(NR_MAC,
|
||||
"[SL-HARQ-TRACE] SET PID=%d waiting=%d round=%d feedback=%d.%d (tx=%d.%d)\n",
|
||||
harq_id, cur_harq->is_waiting, cur_harq->round,
|
||||
cur_harq->feedback_frame, cur_harq->feedback_slot,
|
||||
frame, slot);8?
|
||||
// --------------------------------------------------------------
|
||||
|
||||
|
||||
/*
|
||||
The encoder checks for a change in ndi value everytime, since sci2 changes with every transmission,
|
||||
we oscillate the ndi value so the encoder treats the data as new data everytime.
|
||||
@@ -3515,6 +3648,8 @@ bool nr_ue_sl_pssch_scheduler(NR_UE_MAC_INST_t *mac,
|
||||
nr_schedule_slsch(mac, frame, slot, &mac->sci1_pdu, &mac->sci2_pdu, NR_SL_SCI_FORMAT_2A,
|
||||
UE, &slsch_pdu_length_max, cur_harq, &sched_ctrl->rlc_status[lcid], resource);
|
||||
|
||||
//Jin comment
|
||||
/*
|
||||
*config_type = SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH;
|
||||
tx_config->number_pdus = 1;
|
||||
tx_config->sfn = frame;
|
||||
@@ -3532,6 +3667,27 @@ bool nr_ue_sl_pssch_scheduler(NR_UE_MAC_INST_t *mac,
|
||||
slot,
|
||||
resource);
|
||||
sl_nr_tx_config_pscch_pssch_pdu_t *pscch_pssch_pdu = &tx_config->tx_config_list[0].tx_pscch_pssch_config_pdu;
|
||||
*/
|
||||
//Jin comment end, replace by following
|
||||
*config_type = SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH;
|
||||
tx_config->tx_config_list[pdu_idx].pdu_type = *config_type;
|
||||
fill_pssch_pscch_pdu(sl_mac_params,
|
||||
&tx_config->tx_config_list[pdu_idx].tx_pscch_pssch_config_pdu,
|
||||
sl_bwp,
|
||||
sl_res_pool,
|
||||
&mac->sci1_pdu,
|
||||
&mac->sci2_pdu,
|
||||
slsch_pdu_length_max,
|
||||
NR_SL_SCI_FORMAT_1A,
|
||||
NR_SL_SCI_FORMAT_2A,
|
||||
slot,
|
||||
resource);
|
||||
sl_nr_tx_config_pscch_pssch_pdu_t *pscch_pssch_pdu =
|
||||
&tx_config->tx_config_list[pdu_idx].tx_pscch_pssch_config_pdu;
|
||||
/* We have now reserved one entry */
|
||||
tx_config->number_pdus = pdu_idx + 1;
|
||||
//Jin replacement end. apply our defined pdu_idx instead of list[0]
|
||||
|
||||
sched_pssch->R = pscch_pssch_pdu->target_coderate;
|
||||
sched_pssch->tb_size = pscch_pssch_pdu->tb_size;
|
||||
sched_pssch->sl_harq_pid = mac->sci2_pdu.harq_pid;
|
||||
@@ -3579,20 +3735,46 @@ bool nr_ue_sl_pssch_scheduler(NR_UE_MAC_INST_t *mac,
|
||||
sl_mac_stats->total_rbs += sched_pssch->rbSize;
|
||||
|
||||
|
||||
int buflen = tx_config->tx_config_list[0].tx_pscch_pssch_config_pdu.tb_size;
|
||||
//int buflen = tx_config->tx_config_list[0].tx_pscch_pssch_config_pdu.tb_size; // Jin origin replaced
|
||||
int buflen = tx_config->tx_config_list[pdu_idx].tx_pscch_pssch_config_pdu.tb_size; //Jin replace
|
||||
|
||||
LOG_D(NR_MAC, "[UE%d] Initial TTI-%d:%d TX PSCCH_PSSCH REQ TBS %d\n", sl_ind->module_id, frame, slot, buflen);
|
||||
|
||||
uint8_t *pdu = (uint8_t *) cur_harq->transportBlock;
|
||||
int buflen_remain = buflen;
|
||||
uint8_t *base = pdu;//Jin add
|
||||
uint8_t *mac_pdu_base = pdu; //Jin add fix header problem
|
||||
|
||||
NR_SLSCH_MAC_SUBHEADER_FIXED *sl_sch_subheader = (NR_SLSCH_MAC_SUBHEADER_FIXED *) pdu;
|
||||
sl_sch_subheader->V = 0;
|
||||
sl_sch_subheader->R = 0;
|
||||
/* --- JIN: fix for wrong DST in SL-SCH subheader (sync-ref only) --- */
|
||||
/*
|
||||
if (mac->src_id == 0) { // sync-ref
|
||||
const uint16_t last_rx_src = mac->sci_pdu_rx.source_id; // last decoded SCI2 source
|
||||
const uint16_t cur_dst = mac->sci2_pdu.dest_id;
|
||||
|
||||
LOG_I(NR_MAC,
|
||||
"[JIN][SL-SCH-HDR] pre: me=%u sci2_pdu SRC=%u DST=%u last_rx_src=%u\n",
|
||||
mac->src_id, mac->sci2_pdu.source_id, cur_dst, last_rx_src);
|
||||
|
||||
if (last_rx_src != 0 && last_rx_src != mac->src_id && cur_dst != last_rx_src) {
|
||||
mac->sci2_pdu.dest_id = last_rx_src;
|
||||
LOG_I(NR_MAC,
|
||||
"[JIN][SL-SCH-HDR] override DST -> %u\n",
|
||||
mac->sci2_pdu.dest_id);
|
||||
}
|
||||
}
|
||||
*/
|
||||
/* --- end JIN --- */
|
||||
sl_sch_subheader->SRC = mac->sci2_pdu.source_id;
|
||||
sl_sch_subheader->DST = mac->sci2_pdu.dest_id;
|
||||
sl_sch_subheader->DST = mac->sci2_pdu.dest_id; //sci_pdu->source_id jin this is as 2, but here is written as 1...
|
||||
LOG_D(NR_MAC, "[Jin Jin !!!!!SL-TX] About to TX: SCI2 SRC=%d DST=%d\n",sl_sch_subheader->SRC,sl_sch_subheader->DST);//Jin debug fixed srcID problem
|
||||
pdu += sizeof(NR_SLSCH_MAC_SUBHEADER_FIXED);
|
||||
LOG_D(NR_MAC, "%4d.%2d Tx V %d, R %d, SRC %d, DST %d\n", frame, slot, sl_sch_subheader->V, sl_sch_subheader->R, sl_sch_subheader->SRC, sl_sch_subheader->DST);
|
||||
|
||||
|
||||
|
||||
buflen_remain -= sizeof(NR_SLSCH_MAC_SUBHEADER_FIXED);
|
||||
LOG_D(NR_MAC, "buflen_remain after adding SL_SCH_MAC_SUBHEADER_FIXED %d\n", buflen_remain);
|
||||
const uint8_t sh_size = sizeof(NR_MAC_SUBHEADER_LONG);
|
||||
@@ -3606,7 +3788,8 @@ bool nr_ue_sl_pssch_scheduler(NR_UE_MAC_INST_t *mac,
|
||||
NR_MAC_SUBHEADER_LONG *header = (NR_MAC_SUBHEADER_LONG *) pdu;
|
||||
pdu += sh_size;
|
||||
buflen_remain -= sh_size;
|
||||
const rlc_buffer_occupancy_t ndata = min(sched_ctrl->rlc_status[lcid].bytes_in_buffer, buflen_remain);
|
||||
//const rlc_buffer_occupancy_t ndata = min(sched_ctrl->rlc_status[lcid].bytes_in_buffer, buflen_remain);
|
||||
const rlc_buffer_occupancy_t ndata = buflen_remain;//Jin allow max
|
||||
|
||||
start_meas(&mac->rlc_data_req);
|
||||
|
||||
@@ -3639,6 +3822,16 @@ bool nr_ue_sl_pssch_scheduler(NR_UE_MAC_INST_t *mac,
|
||||
lcid,
|
||||
buflen);
|
||||
|
||||
//Jin Log
|
||||
LOG_I(NR_MAC,
|
||||
"[SL-MAC nr_ue_scheduler.c] TX SDU LCID=%d LEN=%d frame=%d slot=%d SRC=%d DST=%d\n",
|
||||
lcid, sdu_length, frame, slot,
|
||||
sl_sch_subheader->SRC, sl_sch_subheader->DST);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
header->R = 0;
|
||||
header->F = 1;
|
||||
header->LCID = lcid;
|
||||
@@ -3656,6 +3849,12 @@ bool nr_ue_sl_pssch_scheduler(NR_UE_MAC_INST_t *mac,
|
||||
LOG_D(NR_MAC, "In %s: no data to transmit for RB with LCID 0x%02x\n", __FUNCTION__, lcid);
|
||||
break;
|
||||
}
|
||||
//Jin log
|
||||
LOG_D(NR_MAC, "[SL-TX-DBG] TB base first16: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
|
||||
base[0], base[1], base[2], base[3],
|
||||
base[4], base[5], base[6], base[7],
|
||||
base[8], base[9], base[10], base[11],
|
||||
base[12], base[13], base[14], base[15]);
|
||||
}
|
||||
|
||||
if (buflen_remain > 0) {
|
||||
@@ -3673,6 +3872,7 @@ bool nr_ue_sl_pssch_scheduler(NR_UE_MAC_INST_t *mac,
|
||||
pdu += mac_ce_p->tot_mac_ce_len;
|
||||
LOG_D(NR_PHY, "buflen_remain %d, sdu_length_total %d, total_mac_pdu_header_len %d, adding tot_mac_ce_len %d, \n", buflen_remain, mac_ce_p->sdu_length_total, mac_ce_p->total_mac_pdu_header_len, mac_ce_p->tot_mac_ce_len);
|
||||
}
|
||||
int used = buflen - buflen_remain;//Jin calculate the actual used bytes. fix header problem.
|
||||
}
|
||||
}
|
||||
uint8_t sizeof_csi_report = (sizeof(NR_MAC_SUBHEADER_FIXED) + sizeof(nr_sl_csi_report_t));
|
||||
@@ -3736,8 +3936,20 @@ bool nr_ue_sl_pssch_scheduler(NR_UE_MAC_INST_t *mac,
|
||||
cur_harq->sched_pssch = *sched_pssch;
|
||||
} // end of initial transmission
|
||||
|
||||
const uint32_t TBS = pscch_pssch_pdu->tb_size;
|
||||
memcpy(pscch_pssch_pdu->slsch_payload, cur_harq->transportBlock, TBS);
|
||||
//const uint32_t TBS = pscch_pssch_pdu->tb_size; //Jin replace : origin
|
||||
//memcpy(pscch_pssch_pdu->slsch_payload, cur_harq->transportBlock, TBS);//Jin replace : origin
|
||||
pscch_pssch_pdu->slsch_payload = cur_harq->transportBlock;//Jin replace
|
||||
pscch_pssch_pdu->slsch_payload_length = pscch_pssch_pdu->tb_size;//Jin replace : remove memcpy
|
||||
uint8_t *b = pscch_pssch_pdu->slsch_payload; //Jin replace add log
|
||||
LOG_D(NR_MAC,//jin log
|
||||
"[Jin debug !!!! SL-TX-PDU] me=%u peer_uid=%u idx=%d frame=%d slot=%d tb=%p len=%u first8: "
|
||||
"%02x %02x %02x %02x %02x %02x %02x %02x\n",
|
||||
mac->src_id, UE->uid, pdu_idx, frame, slot,
|
||||
b, pscch_pssch_pdu->slsch_payload_length,
|
||||
b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]);
|
||||
|
||||
|
||||
|
||||
// mark UE as scheduled
|
||||
sched_pssch->rbSize = 0;
|
||||
is_resource_allocated = true;
|
||||
@@ -3913,8 +4125,10 @@ void nr_ue_sidelink_scheduler(nr_sidelink_indication_t *sl_ind) {
|
||||
nr_scheduled_response_t scheduled_response;
|
||||
memset(&scheduled_response,0, sizeof(nr_scheduled_response_t));
|
||||
|
||||
|
||||
uint8_t tti_action = 0, is_psbch_slot = 0;
|
||||
|
||||
|
||||
|
||||
// Check if PSBCH slot and PSBCH should be transmitted or Received
|
||||
is_psbch_slot = nr_ue_sl_psbch_scheduler(sl_ind, sl_mac, &rx_config, &tx_config, &tti_action);
|
||||
|
||||
@@ -3926,6 +4140,7 @@ void nr_ue_sidelink_scheduler(nr_sidelink_indication_t *sl_ind) {
|
||||
if (((1<<slot_mod_period) % mask) == 0) tx_allowed=0;
|
||||
}
|
||||
|
||||
|
||||
frameslot_t frame_slot;
|
||||
frame_slot.frame = frame;
|
||||
frame_slot.slot = slot;
|
||||
@@ -3981,16 +4196,23 @@ void nr_ue_sidelink_scheduler(nr_sidelink_indication_t *sl_ind) {
|
||||
if (mac->sl_rx_res_pool && mac->sl_rx_res_pool->ext1 && mac->sl_rx_res_pool->ext1->sl_TimeResource_r16) {
|
||||
int sl_rx_period = 8*mac->sl_rx_res_pool->ext1->sl_TimeResource_r16->size - mac->sl_rx_res_pool->ext1->sl_TimeResource_r16->bits_unused;
|
||||
int slot_mod_period = sl_ind->slot_rx%sl_rx_period;
|
||||
uint8_t mask = mac->sl_rx_res_pool->ext1->sl_TimeResource_r16->buf[slot_mod_period>>3];
|
||||
if (((1<<slot_mod_period) % mask) == 0) rx_allowed=false;
|
||||
|
||||
//uint8_t mask = mac->sl_rx_res_pool->ext1->sl_TimeResource_r16->buf[slot_mod_period>>3];
|
||||
//if (((1<<slot_mod_period) % mask) == 0) rx_allowed=false;
|
||||
}
|
||||
if (sl_ind->slot_type==SIDELINK_SLOT_TYPE_TX || sl_ind->phy_data==NULL) rx_allowed=false;
|
||||
//Jin test following to bypss tx allowed
|
||||
// if (sl_ind->phy_data != NULL && sl_ind->slot_type != SIDELINK_SLOT_TYPE_TX) {
|
||||
// rx_allowed = true; // bypass only bitmap gating
|
||||
//}
|
||||
//tx_allowed = true;
|
||||
|
||||
static uint16_t prev_slot = 0;
|
||||
NR_SL_PSFCH_Config_r16_t *sl_psfch_config = mac->sl_tx_res_pool->sl_PSFCH_Config_r16 ? mac->sl_tx_res_pool->sl_PSFCH_Config_r16->choice.setup : NULL;
|
||||
const uint8_t psfch_periods[] = {0,1,2,4};
|
||||
long psfch_period = (sl_psfch_config && sl_psfch_config->sl_PSFCH_Period_r16)
|
||||
? psfch_periods[*sl_psfch_config->sl_PSFCH_Period_r16] : 0;
|
||||
|
||||
|
||||
if ((prev_slot != slot) && rx_allowed && !is_psbch_slot) {
|
||||
frameslot_t fs;
|
||||
fs.frame = frame;
|
||||
@@ -4008,10 +4230,12 @@ void nr_ue_sidelink_scheduler(nr_sidelink_indication_t *sl_ind) {
|
||||
if (resource && mac->is_synced && !is_psbch_slot && tx_allowed && sl_ind->slot_type == SIDELINK_SLOT_TYPE_TX) {
|
||||
//Check if reserved slot or a sidelink resource configured in Rx/Tx resource pool timeresource bitmap
|
||||
bool is_resource_allocated = nr_ue_sl_pssch_scheduler(mac, sl_ind, mac->sl_bwp, mac->sl_tx_res_pool, &tx_config, resource, &tti_action);
|
||||
|
||||
if (is_resource_allocated && mac->sci2_pdu.csi_req) {
|
||||
nr_ue_sl_csi_rs_scheduler(mac, mu, mac->sl_bwp, &tx_config, NULL, &tti_action);
|
||||
LOG_D(NR_MAC, "%4d.%2d Scheduling CSI-RS\n", frame, slot);
|
||||
}
|
||||
/* JIN_DISABLE_HARQ_FEEDBACK
|
||||
bool is_feedback_slot = mac->sl_tx_res_pool->sl_PSFCH_Config_r16 ? is_feedback_scheduled(mac, frame, slot) : false;
|
||||
if (is_resource_allocated && is_feedback_slot && mac->sl_tx_res_pool->sl_PSFCH_Config_r16->choice.setup) {
|
||||
if (is_feedback_slot) {
|
||||
@@ -4019,6 +4243,7 @@ void nr_ue_sidelink_scheduler(nr_sidelink_indication_t *sl_ind) {
|
||||
reset_sched_psfch(mac, frame, slot);
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
if (((slot % 20) == 6) && ((frame % 100) == 0)) {
|
||||
@@ -4051,6 +4276,53 @@ void nr_ue_sidelink_scheduler(nr_sidelink_indication_t *sl_ind) {
|
||||
LOG_D(NR_MAC, "Inserting transmit history data: %4d.%2d\n", frame_slot.frame, frame_slot.slot);
|
||||
push_back(&mac->sl_transmit_history, &frame_slot);
|
||||
}
|
||||
// --- JIN: robust TX logging: find PSCCH+PSSCH entry by pdu_type (NOT index 0) ---
|
||||
if (tti_action == SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH_PSFCH ||
|
||||
tti_action == SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH ||
|
||||
tti_action == SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH_CSI_RS) {
|
||||
|
||||
int found = 0;
|
||||
for (int i = 0; i < tx_config.number_pdus; i++) {
|
||||
uint8_t t = tx_config.tx_config_list[i].pdu_type;
|
||||
|
||||
LOG_D(NR_MAC,
|
||||
"[SL-TX-LIST] me=%u frame=%d slot=%d i=%d pdu_type=%u\n",
|
||||
mac->src_id, frame, slot, i, t);
|
||||
|
||||
if (t == SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH_PSFCH ||
|
||||
t == SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH ||
|
||||
t == SL_NR_CONFIG_TYPE_TX_PSCCH_PSSCH_CSI_RS) {
|
||||
|
||||
sl_nr_tx_config_pscch_pssch_pdu_t *p =
|
||||
&tx_config.tx_config_list[i].tx_pscch_pssch_config_pdu;
|
||||
|
||||
found = 1;
|
||||
|
||||
if (p->slsch_payload && p->slsch_payload_length >= 8) {
|
||||
uint8_t *b = p->slsch_payload;
|
||||
LOG_D(NR_MAC,
|
||||
"[SL-TX-FINAL] me=%u frame=%d slot=%d idx=%d slsch_len=%u tb_size=%u first8: "
|
||||
"%02x %02x %02x %02x %02x %02x %02x %02x\n",
|
||||
mac->src_id, frame, slot, i,
|
||||
p->slsch_payload_length, p->tb_size,
|
||||
b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]);
|
||||
} else {
|
||||
LOG_W(NR_MAC,
|
||||
"[SL-TX-FINAL] me=%u frame=%d slot=%d idx=%d slsch_payload missing/short "
|
||||
"(ptr=%p len=%u tb_size=%u)\n",
|
||||
mac->src_id, frame, slot, i,
|
||||
p->slsch_payload, p->slsch_payload_length, p->tb_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
LOG_W(NR_MAC,
|
||||
"[SL-TX-FINAL] me=%u frame=%d slot=%d no PSCCH+PSSCH PDU found (number_pdus=%u)\n",
|
||||
mac->src_id, frame, slot, tx_config.number_pdus);
|
||||
}
|
||||
}
|
||||
// --- Jin end
|
||||
if ((mac->if_module != NULL) && (mac->if_module->scheduled_response != NULL))
|
||||
mac->if_module->scheduled_response(&scheduled_response);
|
||||
}
|
||||
@@ -4081,7 +4353,19 @@ void nr_ue_sl_psfch_scheduler(NR_UE_MAC_INST_t *mac,
|
||||
sl_nr_tx_rx_config_psfch_pdu_t *psfch_pdu_list = tx_config->tx_config_list[0].tx_pscch_pssch_config_pdu.psfch_pdu_list;
|
||||
int k = 0;
|
||||
for (int i = 0; i < (n_ul_slots_period * num_subch); i++) {
|
||||
SL_sched_feedback_t *sched_psfch = &mac->sl_info.list[0]->UE_sched_ctrl.sched_psfch[i];
|
||||
// SL_sched_feedback_t *sched_psfch = &mac->sl_info.list[0]->UE_sched_ctrl.sched_psfch[i]; //Jin replace
|
||||
//Jin replace
|
||||
NR_SL_UE_info_t *UE = NULL;
|
||||
uint16_t peer_id = UE->uid;
|
||||
NR_SL_UE_info_t *peer = find_UE(mac, peer_id);
|
||||
if (!peer || !peer->UE_sched_ctrl.sched_psfch) {
|
||||
LOG_W(NR_MAC, "TX sched: no peer/sched_psfch for dest_id=%d\n", peer_id);
|
||||
continue;
|
||||
}
|
||||
SL_sched_feedback_t *sched_psfch = &peer->UE_sched_ctrl.sched_psfch[i];
|
||||
//Jin end
|
||||
|
||||
|
||||
LOG_D(NR_MAC,"frame.slot: feedback %4d.%2d, current (%4d.%2d)\n",
|
||||
sched_psfch->feedback_frame, sched_psfch->feedback_slot, frame, slot);
|
||||
if (sched_psfch->feedback_slot == slot && sched_psfch->feedback_frame == frame) {
|
||||
@@ -4310,6 +4594,8 @@ bool slot_has_psfch(NR_UE_MAC_INST_t *mac, BIT_STRING_t *phy_sl_bitmap, uint64_t
|
||||
}
|
||||
|
||||
void validate_selected_sl_slot(bool tx, bool rx, NR_TDD_UL_DL_ConfigCommon_t *conf, frameslot_t frame_slot) {
|
||||
//Jin disactive these part, since we installed TDD manually.
|
||||
/*
|
||||
AssertFatal(conf->pattern1.nrofUplinkSlots == 4 && conf->pattern1.nrofDownlinkSlots == 6,
|
||||
"Invalid configuration set. Please update the nrofUplinkSlots to 4 and nrofDownlinkSlots to 6.\n");
|
||||
if (get_nrUE_params()->sync_ref) {
|
||||
@@ -4337,6 +4623,7 @@ void validate_selected_sl_slot(bool tx, bool rx, NR_TDD_UL_DL_ConfigCommon_t *co
|
||||
conf->pattern1.nrofUplinkSlots, conf->pattern1.nrofDownlinkSlots);
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
bool is_sl_slot(NR_UE_MAC_INST_t *mac, BIT_STRING_t *phy_sl_bitmap, uint16_t phy_map_sz, uint64_t abs_slot) {
|
||||
|
||||
@@ -864,6 +864,7 @@ int nr_ue_process_sci2_indication_pdu(NR_UE_MAC_INST_t *mac, module_id_t mod_id,
|
||||
sci->sci_format_type,sci->Nid,sci->subch_index,sci->sci_payloadlen,*(unsigned long long*)sci->sci_payloadBits);
|
||||
AssertFatal(sci->sci_format_type == SL_SCI_FORMAT_2_ON_PSSCH, "need to have format 2 here only\n");
|
||||
extract_pssch_sci_pdu((uint64_t *)sci->sci_payloadBits, sci->sci_payloadlen,sl_bwp, sl_res_pool, sci_pdu);
|
||||
|
||||
LOG_D(NR_MAC,"SCI2A: harq_pid %d ndi %d RV %d SRC %x DST %x HARQ_FB %d Cast %d CSI_Req %d\n", sci_pdu->harq_pid,sci_pdu->ndi,sci_pdu->rv_index,sci_pdu->source_id,sci_pdu->dest_id,sci_pdu->harq_feedback,sci_pdu->cast_type,sci_pdu->csi_req);
|
||||
// send schedule response
|
||||
|
||||
|
||||
@@ -218,7 +218,7 @@ tbs_size_t mac_rlc_data_req (const module_id_t, const rnti_t, con
|
||||
* \param[in] crcs Array of CRC decoding.
|
||||
*/
|
||||
void mac_rlc_data_ind (const module_id_t, const rnti_t, const eNB_index_t,const frame_t, const eNB_flag_t, const MBMS_flag_t, logical_chan_id_t, char *, tb_size_t, num_tb_t,
|
||||
crc_t * );
|
||||
crc_t * , uint32_t sourceL2Id, uint32_t destinationL2Id); //jin add srcid and destid
|
||||
|
||||
/*! \fn mac_rlc_status_resp_t mac_rlc_status_ind (const module_id_t mod_idP, const rnti_t rntiP, const frame_t frameP, const sub_frame_t subframeP, const eNB_flag_t eNB_flagP, const MBMS_flag_t MBMS_flagP, logical_chan_id_t rb_idP)
|
||||
* \brief Interface with MAC layer, request and set the number of bytes scheduled for transmission by the RLC instance corresponding to the radio bearer identifier.
|
||||
|
||||
@@ -126,10 +126,12 @@ static void nr_pdcp_entity_recv_pdu(nr_pdcp_entity_t *entity,
|
||||
|
||||
if (rcvd_count < entity->rx_deliv
|
||||
|| nr_pdcp_sdu_in_list(entity->rx_list, rcvd_count)) {
|
||||
LOG_W(PDCP, "discard NR PDU rcvd_count=%d, entity->rx_deliv %d,sdu_in_list %d\n", rcvd_count,entity->rx_deliv,nr_pdcp_sdu_in_list(entity->rx_list,rcvd_count));
|
||||
//LOG_W(PDCP, "discard NR PDU rcvd_count=%d, entity->rx_deliv %d,sdu_in_list %d\n", rcvd_count,entity->rx_deliv,nr_pdcp_sdu_in_list(entity->rx_list,rcvd_count));
|
||||
LOG_W(PDCP,
|
||||
"[JIN DEBUG DEBUG *********** DELETE LATER !!!!! PDCP-RX] entity=%p rb_id=%d rx_deliv=%u rcvd_sn=%d rcvd_count=%u size=%d\n",
|
||||
entity, entity->rb_id, entity->rx_deliv, rcvd_sn, rcvd_count, size);
|
||||
entity->stats.rxpdu_dd_pkts++;
|
||||
entity->stats.rxpdu_dd_bytes += size;
|
||||
|
||||
entity->stats.rxpdu_dd_bytes += size;
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -144,6 +146,7 @@ static void nr_pdcp_entity_recv_pdu(nr_pdcp_entity_t *entity,
|
||||
entity->rx_next = rcvd_count + 1;
|
||||
}
|
||||
|
||||
|
||||
/* TODO(?): out of order delivery */
|
||||
|
||||
if (rcvd_count == entity->rx_deliv) {
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
#include "NR_CellGroupConfig.h"
|
||||
#include "openair2/RRC/NR/nr_rrc_proto.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#include <poll.h>
|
||||
/* from OAI */
|
||||
#include "oai_asn1.h"
|
||||
#include "nr_pdcp_oai_api.h"
|
||||
@@ -42,11 +42,72 @@
|
||||
#include "gnb_config.h"
|
||||
#include "executables/softmodem-common.h"
|
||||
|
||||
#include <netinet/ip.h>
|
||||
|
||||
|
||||
#define TODO do { \
|
||||
printf("%s:%d:%s: todo\n", __FILE__, __LINE__, __FUNCTION__); \
|
||||
exit(1); \
|
||||
} while (0)
|
||||
|
||||
// SL PC5-S Controller
|
||||
int pdcp_pc5_sockfd;
|
||||
//struct sockaddr_in prose_ctrl_addr;
|
||||
struct sockaddr_in prose_pdcp_addr;
|
||||
struct sockaddr_in pdcp_sin;
|
||||
// end
|
||||
|
||||
//Jin add to support bearer creation : SL QoS mapping table - populated by SLC_C via bearer creation
|
||||
#define SL_QOS_MAX_MAPS 16
|
||||
|
||||
typedef struct {
|
||||
uint8_t tos;
|
||||
uint8_t qfi;
|
||||
bool valid;
|
||||
} sl_qos_entry_t;
|
||||
|
||||
static sl_qos_entry_t sl_qos_table[SL_QOS_MAX_MAPS] = {0};
|
||||
static pthread_mutex_t sl_qos_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
void sl_add_qos_map(uint8_t tos, uint8_t qfi) {
|
||||
pthread_mutex_lock(&sl_qos_mutex);
|
||||
// check if already exists - update it
|
||||
for (int i = 0; i < SL_QOS_MAX_MAPS; i++) {
|
||||
if (sl_qos_table[i].valid && sl_qos_table[i].tos == tos) {
|
||||
sl_qos_table[i].qfi = qfi;
|
||||
LOG_I(PDCP, "[SL-QOS-MAP] Updated TOS=0x%02x → QFI=%d\n", tos, qfi);
|
||||
pthread_mutex_unlock(&sl_qos_mutex);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// add new entry
|
||||
for (int i = 0; i < SL_QOS_MAX_MAPS; i++) {
|
||||
if (!sl_qos_table[i].valid) {
|
||||
sl_qos_table[i].tos = tos;
|
||||
sl_qos_table[i].qfi = qfi;
|
||||
sl_qos_table[i].valid = true;
|
||||
LOG_I(PDCP, "[SL-QOS-MAP] Added TOS=0x%02x → QFI=%d\n", tos, qfi);
|
||||
pthread_mutex_unlock(&sl_qos_mutex);
|
||||
return;
|
||||
}
|
||||
}
|
||||
LOG_E(PDCP, "[SL-QOS-MAP] Table full, cannot add TOS=0x%02x\n", tos);
|
||||
pthread_mutex_unlock(&sl_qos_mutex);
|
||||
}
|
||||
static uint8_t sl_lookup_qfi(uint8_t tos) {
|
||||
pthread_mutex_lock(&sl_qos_mutex);
|
||||
for (int i = 0; i < SL_QOS_MAX_MAPS; i++) {
|
||||
if (sl_qos_table[i].valid && sl_qos_table[i].tos == tos) {
|
||||
uint8_t qfi = sl_qos_table[i].qfi;
|
||||
pthread_mutex_unlock(&sl_qos_mutex);
|
||||
return qfi;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&sl_qos_mutex);
|
||||
return 1; // default bearer
|
||||
}
|
||||
//Jin bearer adding end
|
||||
|
||||
|
||||
static nr_pdcp_ue_manager_t *nr_pdcp_ue_manager;
|
||||
|
||||
/* TODO: handle time a bit more properly */
|
||||
@@ -106,6 +167,9 @@ typedef struct {
|
||||
|
||||
static rlc_data_req_queue q;
|
||||
|
||||
|
||||
static NR_SL_RadioBearerConfig_r16_t *g_sl_rb_cfg = NULL; //Jin add quick for multiple UEs RB
|
||||
|
||||
static void *rlc_data_req_thread(void *_)
|
||||
{
|
||||
int i;
|
||||
@@ -225,6 +289,8 @@ typedef struct {
|
||||
rb_id_t rb_id;
|
||||
sdu_size_t sdu_buffer_size;
|
||||
mem_block_t *sdu_buffer;
|
||||
uint32_t srcID; // JIN : Source L2 ID
|
||||
uint32_t dstID; // jin: Destination L2 ID
|
||||
} pdcp_data_ind_queue_item;
|
||||
|
||||
#define PDCP_DATA_IND_QUEUE_SIZE 10000
|
||||
@@ -245,14 +311,18 @@ static void do_pdcp_data_ind(
|
||||
const MBMS_flag_t MBMS_flagP,
|
||||
const rb_id_t rb_id,
|
||||
const sdu_size_t sdu_buffer_size,
|
||||
mem_block_t *const sdu_buffer)
|
||||
mem_block_t *const sdu_buffer,
|
||||
const uint32_t srcID, // JIN
|
||||
const uint32_t dstID) // JIN
|
||||
{
|
||||
nr_pdcp_ue_t *ue;
|
||||
nr_pdcp_entity_t *rb;
|
||||
ue_id_t rntiMaybeUEid = ctxt_pP->rntiMaybeUEid;
|
||||
ue_id_t peer_ue_id = ctxt_pP->rntiMaybeUEid; // This is the PEER's ID from RLC
|
||||
LOG_I(PDCP, "[DEBUG-THEORY] rntiMaybeUEid=0x%lx (this should be PEER's ID in sidelink)\n",
|
||||
peer_ue_id);
|
||||
ue_id_t local_ue_id;
|
||||
|
||||
if (ctxt_pP->module_id != 0 ||
|
||||
//ctxt_pP->enb_flag != 1 ||
|
||||
ctxt_pP->instance != 0 ||
|
||||
ctxt_pP->eNB_index != 0 ||
|
||||
ctxt_pP->brOption != 0) {
|
||||
@@ -261,28 +331,95 @@ static void do_pdcp_data_ind(
|
||||
}
|
||||
|
||||
if (ctxt_pP->enb_flag)
|
||||
T(T_ENB_PDCP_UL, T_INT(ctxt_pP->module_id), T_INT(rntiMaybeUEid), T_INT(rb_id), T_INT(sdu_buffer_size));
|
||||
T(T_ENB_PDCP_UL, T_INT(ctxt_pP->module_id), T_INT(peer_ue_id), T_INT(rb_id), T_INT(sdu_buffer_size));
|
||||
|
||||
nr_pdcp_manager_lock(nr_pdcp_ue_manager);
|
||||
ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, rntiMaybeUEid);
|
||||
|
||||
// JIN ADD: In sidelink, we need to find the LOCAL UE, not the peer
|
||||
// The dstID is the local UE's L2 ID (destination of the packet)
|
||||
if (dstID != 0) {
|
||||
// Sidelink mode: dstID is the local UE
|
||||
local_ue_id = dstID;
|
||||
LOG_D(PDCP, "[SL-RX] Packet from peer=0x%x to local_ue=0x%x rb_id=%ld size=%d\n",
|
||||
peer_ue_id, local_ue_id, rb_id, sdu_buffer_size);
|
||||
} else {
|
||||
// Legacy mode: rntiMaybeUEid is the local UE
|
||||
local_ue_id = peer_ue_id;
|
||||
peer_ue_id = 0; // No peer in legacy mode
|
||||
LOG_D(PDCP, "[LEGACY-RX] local_ue=0x%lx rb_id=%ld size=%d\n",
|
||||
local_ue_id, rb_id, sdu_buffer_size);
|
||||
}
|
||||
|
||||
ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, local_ue_id);
|
||||
|
||||
if (srb_flagP == 1) {
|
||||
// SRBs: use traditional lookup (no peer-specific entities for control plane)
|
||||
if (rb_id < 1 || rb_id > 2)
|
||||
rb = NULL;
|
||||
else
|
||||
rb = ue->srb[rb_id - 1];
|
||||
} else {
|
||||
if (rb_id < 1 || rb_id > MAX_DRBS_PER_UE)
|
||||
rb = NULL;
|
||||
else
|
||||
rb = ue->drb[rb_id - 1];
|
||||
// jin: use peer-aware lookup in sidelink mode
|
||||
if (peer_ue_id != 0) {
|
||||
rb = nr_pdcp_ue_get_peer_drb_entity(ue, peer_ue_id, rb_id);
|
||||
|
||||
if (rb == NULL) {
|
||||
// Auto-create peer entity by cloning the shared entity's configuration
|
||||
nr_pdcp_entity_t *template = ue->drb[rb_id - 1];
|
||||
|
||||
if (template != NULL) {
|
||||
LOG_I(PDCP, "[SL-AUTO-CREATE] Creating peer PDCP entity: local_ue=0x%lx peer=0x%lx rb_id=%ld\n",
|
||||
local_ue_id, peer_ue_id, rb_id);
|
||||
// Create new entity with same configuration as template
|
||||
nr_pdcp_entity_t *new_entity = new_nr_pdcp_entity(
|
||||
template->type,
|
||||
template->is_gnb,
|
||||
template->rb_id,
|
||||
template->pdusession_id,
|
||||
template->has_sdap_rx,
|
||||
template->has_sdap_tx,
|
||||
template->deliver_sdu,
|
||||
template->deliver_sdu_data,
|
||||
template->deliver_pdu,
|
||||
template->deliver_pdu_data,
|
||||
template->sn_size,
|
||||
template->t_reordering,
|
||||
template->discard_timer,
|
||||
template->ciphering_algorithm,
|
||||
template->integrity_algorithm,
|
||||
template->ciphering_key,
|
||||
template->integrity_key
|
||||
);
|
||||
|
||||
// Add to peer context
|
||||
nr_pdcp_ue_add_peer_drb_pdcp_entity(ue, peer_ue_id, rb_id, new_entity);
|
||||
rb = new_entity;
|
||||
|
||||
LOG_I(PDCP, "[SL-AUTO-CREATE] Successfully created peer entity %p for peer=0x%lx\n",
|
||||
rb, peer_ue_id);
|
||||
} else {
|
||||
LOG_E(PDCP, "[SL-AUTO-CREATE] Cannot create peer entity, template DRB is NULL! local_ue=0x%lx rb_id=%ld\n",
|
||||
local_ue_id, rb_id);
|
||||
rb = NULL;
|
||||
}
|
||||
} else {
|
||||
LOG_D(PDCP, "[SL-RX] Using existing peer entity %p for local_ue=0x%lx peer=0x%lx rb_id=%ld\n",
|
||||
rb, local_ue_id, peer_ue_id, rb_id);
|
||||
}
|
||||
} else {
|
||||
// Legacy: use shared entity
|
||||
if (rb_id < 1 || rb_id > MAX_DRBS_PER_UE)
|
||||
rb = NULL;
|
||||
else
|
||||
rb = ue->drb[rb_id - 1];
|
||||
}
|
||||
}
|
||||
|
||||
if (rb != NULL) {
|
||||
rb->recv_pdu(rb, (char *)sdu_buffer->data, sdu_buffer_size);
|
||||
} else {
|
||||
LOG_E(PDCP, "%s:%d:%s: no RB found (rb_id %ld, srb_flag %d)\n",
|
||||
__FILE__, __LINE__, __FUNCTION__, rb_id, srb_flagP);
|
||||
LOG_E(PDCP, "%s:%d:%s: no RB found (local_ue_id=0x%lx, peer_ue_id=0x%lx, rb_id=%ld, srb_flag=%d)\n",
|
||||
__FILE__, __LINE__, __FUNCTION__, local_ue_id, peer_ue_id, rb_id, srb_flagP);
|
||||
}
|
||||
|
||||
nr_pdcp_manager_unlock(nr_pdcp_ue_manager);
|
||||
@@ -307,7 +444,9 @@ static void *pdcp_data_ind_thread(void *_)
|
||||
pq.q[i].MBMS_flagP,
|
||||
pq.q[i].rb_id,
|
||||
pq.q[i].sdu_buffer_size,
|
||||
pq.q[i].sdu_buffer);
|
||||
pq.q[i].sdu_buffer,
|
||||
pq.q[i].srcID, // JIN ADD
|
||||
pq.q[i].dstID); // JIN ADD
|
||||
|
||||
if (pthread_mutex_lock(&pq.m) != 0) abort();
|
||||
|
||||
@@ -338,7 +477,9 @@ static void enqueue_pdcp_data_ind(
|
||||
const MBMS_flag_t MBMS_flagP,
|
||||
const rb_id_t rb_id,
|
||||
const sdu_size_t sdu_buffer_size,
|
||||
mem_block_t *const sdu_buffer)
|
||||
mem_block_t *const sdu_buffer,
|
||||
const uint32_t srcID, // JIN ADD
|
||||
const uint32_t dstID) // JIN ADD
|
||||
{
|
||||
int i;
|
||||
int logged = 0;
|
||||
@@ -361,6 +502,8 @@ static void enqueue_pdcp_data_ind(
|
||||
pq.q[i].rb_id = rb_id;
|
||||
pq.q[i].sdu_buffer_size = sdu_buffer_size;
|
||||
pq.q[i].sdu_buffer = sdu_buffer;
|
||||
pq.q[i].srcID = srcID; // Jin add
|
||||
pq.q[i].dstID = dstID; // Jin add
|
||||
|
||||
if (pthread_cond_signal(&pq.c) != 0) abort();
|
||||
if (pthread_mutex_unlock(&pq.m) != 0) abort();
|
||||
@@ -375,12 +518,17 @@ bool pdcp_data_ind(const protocol_ctxt_t *const ctxt_pP,
|
||||
const uint32_t *const srcID,
|
||||
const uint32_t *const dstID)
|
||||
{
|
||||
uint32_t src = (srcID != NULL) ? *srcID : 0; // Jin get the pointer
|
||||
uint32_t dst = (dstID != NULL) ? *dstID : 0; // Jin get the pointer
|
||||
|
||||
enqueue_pdcp_data_ind(ctxt_pP,
|
||||
srb_flagP,
|
||||
MBMS_flagP,
|
||||
rb_id,
|
||||
sdu_buffer_size,
|
||||
sdu_buffer);
|
||||
sdu_buffer,
|
||||
src, // jin add
|
||||
dst); // jin add
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -399,12 +547,32 @@ static void reblock_tun_socket(void)
|
||||
extern int nas_sock_fd[];
|
||||
int f;
|
||||
|
||||
|
||||
/**********Jin origin comment ***
|
||||
f = fcntl(nas_sock_fd[0], F_GETFL, 0);
|
||||
f &= ~(O_NONBLOCK);
|
||||
if (fcntl(nas_sock_fd[0], F_SETFL, f) == -1) {
|
||||
LOG_E(PDCP, "reblock_tun_socket failed\n");
|
||||
exit(1);
|
||||
}
|
||||
*********** Jin end ***/
|
||||
|
||||
//Jin TAP : multiple tun/tap FDs can exist.
|
||||
for (int i = 0; i < (MAX_MOBILES_PER_ENB * 2); i++) {
|
||||
if (nas_sock_fd[i] <= 0)
|
||||
continue;
|
||||
f = fcntl(nas_sock_fd[i], F_GETFL, 0);
|
||||
if (f == -1)
|
||||
continue;
|
||||
f &= ~(O_NONBLOCK);
|
||||
if (fcntl(nas_sock_fd[i], F_SETFL, f) == -1) {
|
||||
LOG_E(PDCP, "reblock_tun_socket failed for nas_sock_fd[%d]\n", i);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
//Jin end
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void *enb_tun_read_thread(void *_)
|
||||
@@ -463,7 +631,20 @@ static void *ue_tun_read_thread(void *_)
|
||||
int rb_id = 1;
|
||||
pthread_setname_np( pthread_self(),"ue_tun_read");
|
||||
LOG_I(PDCP,"ue_tun_read_thread created on core %d\n",sched_getcpu());
|
||||
|
||||
//Jin add : borrow from ENB to control UE number
|
||||
struct pollfd pfd[MAX_MOBILES_PER_ENB * 2];
|
||||
memset(pfd, 0, sizeof(pfd));
|
||||
for (int i = 0; i < (MAX_MOBILES_PER_ENB * 2); i++) {
|
||||
pfd[i].fd = nas_sock_fd[i];
|
||||
pfd[i].events = POLLIN;
|
||||
}
|
||||
//JIn end
|
||||
|
||||
|
||||
while (1) {
|
||||
//Jin origin comment follwoing :
|
||||
/*
|
||||
len = read(nas_sock_fd[0], &rx_buf, NL_MAX_PAYLOAD);
|
||||
if (len == -1) {
|
||||
LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
@@ -492,6 +673,75 @@ static void *ue_tun_read_thread(void *_)
|
||||
extern uint8_t nas_pduid;
|
||||
|
||||
sdap_data_req(&ctxt, rntiMaybeUEid, SRB_FLAG_NO, rb_id, RLC_MUI_UNDEFINED, RLC_SDU_CONFIRM_NO, len, (unsigned char *)rx_buf, PDCP_TRANSMISSION_MODE_DATA, NULL, NULL, nas_qfi, dc, nas_pduid);
|
||||
*/ //Jin comment end
|
||||
|
||||
//Jin add new : to support multiple UE under TAP
|
||||
int rc = poll(pfd, (MAX_MOBILES_PER_ENB * 2), 100);
|
||||
if (rc <= 0)
|
||||
continue;
|
||||
|
||||
// get a UE id that PDCP actually knows about
|
||||
ue_id_t rntiMaybeUEid;
|
||||
nr_pdcp_manager_lock(nr_pdcp_ue_manager);
|
||||
const bool has_ue = nr_pdcp_get_first_ue_id(nr_pdcp_ue_manager, &rntiMaybeUEid);
|
||||
nr_pdcp_manager_unlock(nr_pdcp_ue_manager);
|
||||
if (!has_ue)
|
||||
continue;
|
||||
|
||||
for (int i = 0; i < (MAX_MOBILES_PER_ENB * 2); i++) {
|
||||
if (nas_sock_fd[i] <= 0)
|
||||
continue;
|
||||
|
||||
if (pfd[i].fd != nas_sock_fd[i])
|
||||
pfd[i].fd = nas_sock_fd[i];
|
||||
|
||||
if (!(pfd[i].revents & POLLIN))
|
||||
continue;
|
||||
|
||||
int len = read(pfd[i].fd, rx_buf, NL_MAX_PAYLOAD);
|
||||
if (len <= 0)
|
||||
continue;
|
||||
|
||||
LOG_I(PDCP, "JIN TUN: ue_tun_read_thread: nas_sock_fd[%d] read %d bytes -> ue_id=%d\n",
|
||||
i, len, (int)rntiMaybeUEid);
|
||||
|
||||
// Keep UE context consistent (do NOT invent ue_id from i)
|
||||
ctxt.module_id = 0;
|
||||
ctxt.enb_flag = 0;
|
||||
ctxt.instance = 0;
|
||||
ctxt.frame = 0;
|
||||
ctxt.subframe = 0;
|
||||
ctxt.eNB_index = 0;
|
||||
ctxt.brOption = 0;
|
||||
ctxt.rntiMaybeUEid = rntiMaybeUEid;
|
||||
|
||||
bool dc = SDAP_HDR_UL_DATA_PDU;
|
||||
|
||||
uint8_t pkt_qfi = 1; // default
|
||||
/*
|
||||
uint8_t pkt_pduid = 0;
|
||||
if (len >= 20) { // has IP header
|
||||
struct iphdr *iph = (struct iphdr *)rx_buf;
|
||||
uint8_t slcu_hdr = iph->tos >> 2;
|
||||
pkt_qfi = (slcu_hdr >> 3) & 0x07;
|
||||
if (pkt_qfi == 0) pkt_qfi = 1; // fallback to default bearer
|
||||
LOG_I(PDCP, "JIN CHECK TOS TOS !!!!!!!! [TOS-QFI] tos=0x%02x extracted_qfi=%d\n", iph->tos, pkt_qfi);
|
||||
}*/
|
||||
if (len >= 20) {
|
||||
struct iphdr *iph = (struct iphdr *)rx_buf;
|
||||
uint8_t raw_tos = iph->tos;
|
||||
pkt_qfi = sl_lookup_qfi(raw_tos);
|
||||
LOG_I(PDCP, "[TOS-QFI] raw_tos=0x%02x → pkt_qfi=%d\n", raw_tos, pkt_qfi);
|
||||
}
|
||||
|
||||
sdap_data_req(&ctxt, rntiMaybeUEid, SRB_FLAG_NO, rb_id,
|
||||
RLC_MUI_UNDEFINED, RLC_SDU_CONFIRM_NO,
|
||||
len, (unsigned char *)rx_buf,
|
||||
PDCP_TRANSMISSION_MODE_DATA,
|
||||
NULL, NULL, pkt_qfi, dc, 0);
|
||||
}
|
||||
//Jin end
|
||||
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@@ -608,7 +858,7 @@ uint64_t nr_pdcp_module_init(uint64_t _pdcp_optmask, int id)
|
||||
//Add --nr-ip-over-lte option check for next line
|
||||
if (IS_SOFTMODEM_NOS1){
|
||||
nas_config(1, 1, !get_softmodem_params()->nsa ? 2 : 3, ifsuffix_ue);
|
||||
set_qfi_pduid(7, 10);
|
||||
set_qfi_pduid(7, 10);
|
||||
}
|
||||
LOG_I(PDCP, "UE pdcp will use tun interface\n");
|
||||
start_pdcp_tun_ue();
|
||||
@@ -630,14 +880,15 @@ uint64_t nr_pdcp_module_init(uint64_t _pdcp_optmask, int id)
|
||||
static void deliver_sdu_drb(void *_ue, nr_pdcp_entity_t *entity,
|
||||
char *buf, int size)
|
||||
{
|
||||
LOG_I(PDCP, "[JIN-RX-DELIVER]!!!!! size=%d rb_id=%d ue=%lu\n", size, (int)entity->rb_id, ((nr_pdcp_ue_t*)_ue)->rntiMaybeUEid);
|
||||
nr_pdcp_ue_t *ue = _ue;
|
||||
int rb_id;
|
||||
int i;
|
||||
|
||||
|
||||
if (IS_SOFTMODEM_NOS1 || UE_NAS_USE_TUN) {
|
||||
LOG_D(PDCP, "IP packet received with size %d, to be sent to SDAP interface, UE ID/RNTI: %ld\n", size, ue->rntiMaybeUEid);
|
||||
sdap_data_ind(entity->rb_id, entity->is_gnb, entity->has_sdap_rx, entity->pdusession_id, ue->rntiMaybeUEid, buf, size);
|
||||
}
|
||||
}
|
||||
else{
|
||||
for (i = 0; i < MAX_DRBS_PER_UE; i++) {
|
||||
if (entity == ue->drb[i]) {
|
||||
@@ -895,6 +1146,7 @@ void add_drb_sl(ue_id_t srcid, NR_SL_RadioBearerConfig_r16_t *s, int ciphering_a
|
||||
AssertFatal(s->sl_PDCP_Config_r16 != NULL, "SL PDCP config is not there!\n");
|
||||
int slrb_id = s->slrb_Uu_ConfigIndex_r16;
|
||||
int sn_size = decode_sn_size_ul(*s->sl_PDCP_Config_r16->sl_PDCP_SN_Size_r16);
|
||||
LOG_I(PDCP, "JIN CHECK !!!! !!! !!! Sn-size [SL-DRB] srcid=%lu slrb_id=%d sn_size=%d\n", srcid, slrb_id, sn_size);
|
||||
int discard_timer = decode_discard_timer_sl(*s->sl_PDCP_Config_r16->sl_DiscardTimer_r16);
|
||||
|
||||
// these 3 are configured differently in Sidelink
|
||||
@@ -906,20 +1158,28 @@ void add_drb_sl(ue_id_t srcid, NR_SL_RadioBearerConfig_r16_t *s, int ciphering_a
|
||||
bool has_sdap = s->sl_SDAP_Config_r16 && s->sl_SDAP_Config_r16->sl_SDAP_Header_r16 == NR_SL_SDAP_Config_r16__sl_SDAP_Header_r16_present;
|
||||
bool is_sdap_DefaultRB = s->sl_SDAP_Config_r16 && s->sl_SDAP_Config_r16->sl_DefaultRB_r16 == true ? true : false;
|
||||
/* TODO(?): accept different UL and DL SN sizes? */
|
||||
uint8_t mappedQFIs2AddCount = 0;
|
||||
NR_QFI_t *mappedQFIs2Add = NULL;
|
||||
if (has_sdap &&
|
||||
s->sl_SDAP_Config_r16->sl_MappedQoS_Flows_r16 != NULL &&
|
||||
s->sl_SDAP_Config_r16->sl_MappedQoS_Flows_r16->choice.sl_MappedQoS_FlowsList_r16 != NULL) {
|
||||
mappedQFIs2AddCount = s->sl_SDAP_Config_r16->sl_MappedQoS_Flows_r16
|
||||
->choice.sl_MappedQoS_FlowsList_r16->list.count;
|
||||
mappedQFIs2Add = calloc(mappedQFIs2AddCount, sizeof(*mappedQFIs2Add));
|
||||
LOG_D(SDAP, "Captured mappedQoS_FlowsToAdd from RRC: count %d\n", mappedQFIs2AddCount);
|
||||
|
||||
uint8_t mappedQFIs2AddCount = s->sl_SDAP_Config_r16->sl_MappedQoS_Flows_r16->choice.sl_MappedQoS_FlowsList_r16->list.count;
|
||||
NR_QFI_t *mappedQFIs2Add = calloc(mappedQFIs2AddCount, sizeof(*mappedQFIs2Add));
|
||||
LOG_D(SDAP, "Captured mappedQoS_FlowsToAdd from RRC: count %d\n", mappedQFIs2AddCount);
|
||||
|
||||
long standardized_PQI = 0;
|
||||
for (int i = 0; i < mappedQFIs2AddCount; i++) {
|
||||
standardized_PQI = s->sl_SDAP_Config_r16->sl_MappedQoS_Flows_r16->choice.sl_MappedQoS_FlowsList_r16->list.array[i]->sl_PQI_r16->choice.sl_StandardizedPQI_r16;
|
||||
if (standardized_PQI < 64)
|
||||
mappedQFIs2Add[i] = standardized_PQI;
|
||||
long standardized_PQI = 0;
|
||||
for (int i = 0; i < mappedQFIs2AddCount; i++) {
|
||||
standardized_PQI = s->sl_SDAP_Config_r16->sl_MappedQoS_Flows_r16
|
||||
->choice.sl_MappedQoS_FlowsList_r16->list.array[i]
|
||||
->sl_PQI_r16->choice.sl_StandardizedPQI_r16;
|
||||
if (standardized_PQI < 64)
|
||||
mappedQFIs2Add[i] = standardized_PQI;
|
||||
}
|
||||
}
|
||||
|
||||
nr_pdcp_manager_lock(nr_pdcp_ue_manager);
|
||||
nr_pdcp_ue_t *ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, srcid);
|
||||
nr_pdcp_ue_t *ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, srcid);
|
||||
if (ue->drb[slrb_id-1] != NULL) {
|
||||
LOG_W(PDCP, "%s:%d:%s: warning DRB %d already exist for UE ID/RNTI %ld, do nothing\n", __FILE__, __LINE__, __FUNCTION__, slrb_id, srcid);
|
||||
} else {
|
||||
@@ -1155,7 +1415,7 @@ bool nr_pdcp_data_req_drb(protocol_ctxt_t *ctxt_pP,
|
||||
if (rb_id < 1 || rb_id > MAX_DRBS_PER_UE)
|
||||
rb = NULL;
|
||||
else
|
||||
rb = ue->drb[rb_id - 1];
|
||||
rb = ue->drb[rb_id - 1];
|
||||
|
||||
if (rb == NULL) {
|
||||
LOG_E(PDCP, "%s:%d:%s: no DRB found (ue_id %ld, rb_id %ld)\n", __FILE__, __LINE__, __FUNCTION__, ue_id, rb_id);
|
||||
@@ -1284,3 +1544,134 @@ const bool nr_pdcp_get_statistics(ue_id_t ue_id, int srb_flag, int rb_id, nr_pdc
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//
|
||||
// NR_PC5 extensions for PC5S
|
||||
//
|
||||
|
||||
// Signaling socket between the PC5 Controller and PDCP for PC5-S traffic
|
||||
void
|
||||
nr_pdcp_pc5_signaling_socket_init() {
|
||||
|
||||
pthread_attr_t attr;
|
||||
struct sched_param sched_param;
|
||||
int optval; // flag value for setsockopt
|
||||
//int n; // message byte size
|
||||
//create PDCP socket
|
||||
pdcp_pc5_sockfd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
|
||||
if (pdcp_pc5_sockfd < 0) {
|
||||
LOG_E(PDCP,"[pdcp_pc5_socket_init] Error opening socket %d (%d:%s)\n",pdcp_pc5_sockfd,errno, strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
optval = 1;
|
||||
setsockopt(pdcp_pc5_sockfd, SOL_SOCKET, SO_REUSEADDR,
|
||||
(const void *)&optval, sizeof(int));
|
||||
//fcntl(pdcp_pc5_sockfd,F_SETFL,O_NONBLOCK);
|
||||
bzero((char *) &pdcp_sin, sizeof(pdcp_sin));
|
||||
pdcp_sin.sin_family = AF_INET;
|
||||
pdcp_sin.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
pdcp_sin.sin_port = htons(NR_PDCP_SOCKET_PORT_NO);
|
||||
|
||||
// associate the parent socket with a port
|
||||
if (bind(pdcp_pc5_sockfd, (struct sockaddr *) &pdcp_sin,
|
||||
sizeof(pdcp_sin)) < 0) {
|
||||
LOG_E(PDCP,"[pdcp_pc5_socket_init] ERROR: Failed on binding the socket\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
//create thread to listen to incoming packets
|
||||
if (pthread_attr_init(&attr) != 0) {
|
||||
LOG_E(RRC, "[pdcp_signaling_socket_init] Failed to initialize pthread attribute for PC5_CTL -> PDCP communication (%d:%s)\n",
|
||||
errno, strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
sched_param.sched_priority = 10;
|
||||
pthread_attr_setschedpolicy(&attr, SCHED_RR);
|
||||
pthread_attr_setschedparam(&attr, &sched_param);
|
||||
pthread_t nr_pdcp_control_socket_thread;
|
||||
|
||||
if (pthread_create(&nr_pdcp_control_socket_thread, &attr, nr_pdcp_control_socket_thread_fct, NULL) != 0) {
|
||||
LOG_E(PDCP, "[nr_pdcp_control_socket_init]Failed to create new thread for NR_PDCP/PC5_CTL communication (%d:%s)\n",
|
||||
errno, strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
pthread_setname_np( nr_pdcp_control_socket_thread, "NR_PDCP/NR_PC5 Control Socket" );
|
||||
|
||||
}
|
||||
|
||||
// Signaling socket thread to listen to the PC5-S port
|
||||
void *nr_pdcp_control_socket_thread_fct (void *arg) {
|
||||
|
||||
//pdcp_t *pdcp_p = NULL;
|
||||
int bytes_received;
|
||||
nr_sidelink_pc5s_element *sl_pc5s_msg_send = NULL;
|
||||
nr_pc5s_header_t *pc5s_header = NULL;
|
||||
rb_id_t rab_id = 0;
|
||||
char receive_buf[MAX_MESSAGE_SIZE];
|
||||
char send_buf[MAX_MESSAGE_SIZE];
|
||||
|
||||
while (1) {
|
||||
LOG_I(RRC,"Listening to incoming connection from PC5 Controller \n");
|
||||
|
||||
// receive a message from PC5 Controller
|
||||
memset(receive_buf, 0, sizeof(receive_buf));
|
||||
socklen_t prose_addr_len = sizeof(prose_pdcp_addr);
|
||||
bytes_received = recvfrom(pdcp_pc5_sockfd, receive_buf, sizeof(receive_buf), MAX_MESSAGE_SIZE,
|
||||
(struct sockaddr *) &prose_pdcp_addr, &prose_addr_len);
|
||||
if (bytes_received == -1) {
|
||||
LOG_E(PDCP, "%s(%d). recvfrom failed. %s\n", __FUNCTION__, __LINE__, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
if (bytes_received == 0) {
|
||||
LOG_E(PDCP, "%s(%d). EOF pdcp_pc5_sockfd.\n", __FUNCTION__, __LINE__);
|
||||
}
|
||||
if (bytes_received > sizeof(receive_buf)) {
|
||||
LOG_E(PDCP, "%s(%d). Message truncated. %d\n", __FUNCTION__, __LINE__, bytes_received);
|
||||
return 0;
|
||||
}
|
||||
if (bytes_received > 0) {
|
||||
pc5s_header = calloc(1, sizeof(nr_pc5s_header_t));
|
||||
memcpy((void *)pc5s_header, (void *)receive_buf, sizeof(nr_pc5s_header_t));
|
||||
|
||||
|
||||
switch(pc5s_header->traffic_type) {
|
||||
case TRAFFIC_PC5S_SESSION_INIT :
|
||||
//send reply to NR_PC5 Controller
|
||||
LOG_D(PDCP,"Received a request to open PDCP socket and establish a new PDCP session ... send response to PC5 Controller \n");
|
||||
memset(send_buf, 0, sizeof(send_buf));
|
||||
sl_pc5s_msg_send = calloc(1, sizeof(nr_sidelink_pc5s_element));
|
||||
sl_pc5s_msg_send->pc5s_header.traffic_type = TRAFFIC_PC5S_SESSION_INIT;
|
||||
sl_pc5s_msg_send->pc5sPrimitive.status = 1;
|
||||
memcpy(send_buf, sl_pc5s_msg_send, sizeof(nr_sidelink_pc5s_element));
|
||||
int prose_addr_len = sizeof(prose_pdcp_addr);
|
||||
int bytes_sent = sendto(pdcp_pc5_sockfd, send_buf, sizeof(nr_sidelink_pc5s_element), 0,
|
||||
(struct sockaddr *) &prose_pdcp_addr, prose_addr_len);
|
||||
free (sl_pc5s_msg_send);
|
||||
|
||||
if (bytes_sent < 0) {
|
||||
LOG_E(PDCP, "ERROR: Failed to send to PC5 Controller \n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
break;
|
||||
|
||||
case TRAFFIC_PC5S_SIGNALLING: /* PC5-S message -> send to other UE */
|
||||
//LOG_I(PDCP, "[PDCP] pc5s_header->rb_id = %ld\n", pc5s_header->rb_id);
|
||||
LOG_D(PDCP, "pc5s message type %d, unsupported yet \n", pc5s_header->traffic_type);
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_D(PDCP, "pc5s message type %d, unknown...\n", pc5s_header->traffic_type);
|
||||
break;
|
||||
} /* end of switch */
|
||||
}/* end of bytes_received > 0 */
|
||||
} /* end of while loop */
|
||||
if (pc5s_header != NULL) {
|
||||
free(pc5s_header);
|
||||
pc5s_header = NULL;
|
||||
}
|
||||
return 0;
|
||||
} /* pdcp_fifo_read_input_sdus_frompc5s */
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
void nr_pdcp_layer_init(void);
|
||||
uint64_t nr_pdcp_module_init(uint64_t _pdcp_optmask, int id);
|
||||
|
||||
void sl_add_qos_map(uint8_t tos, uint8_t qfi); //Jin add
|
||||
|
||||
void du_rlc_data_req(const protocol_ctxt_t *const ctxt_pP,
|
||||
const srb_flag_t srb_flagP,
|
||||
const MBMS_flag_t MBMS_flagP,
|
||||
@@ -110,4 +112,35 @@ const bool nr_pdcp_get_statistics(ue_id_t ue_id, int srb_flag, int rb_id, nr_pdc
|
||||
|
||||
void add_drb_sl(ue_id_t srcid, NR_SL_RadioBearerConfig_r16_t *s, int ciphering_algorithm, int integrity_algorithm, unsigned char *ciphering_key, unsigned char *integrity_key);
|
||||
|
||||
// NR_PC5 extensions for PC5S
|
||||
#define NR_PDCP_SOCKET_PORT_NO 9999 //temporary value
|
||||
#define NR_PC5_SIGNALLING_PAYLOAD_SIZE 100 //should be updated with a correct value
|
||||
|
||||
void nr_pdcp_pc5_signaling_socket_init(void);
|
||||
void *nr_pdcp_control_socket_thread_fct (void*);
|
||||
|
||||
typedef struct {
|
||||
rb_id_t rb_id;
|
||||
sdu_size_t data_size;
|
||||
signed int inst;
|
||||
ip_traffic_type_t traffic_type;
|
||||
uint32_t sourceL2Id;
|
||||
uint32_t destinationL2Id;
|
||||
} __attribute__((__packed__)) nr_pc5s_header_t;
|
||||
|
||||
//new PC5S-message
|
||||
typedef struct {
|
||||
unsigned char bytes[NR_PC5_SIGNALLING_PAYLOAD_SIZE];
|
||||
} __attribute__((__packed__)) NR_PC5SignallingMessage ;
|
||||
|
||||
//example of PC5-S messages
|
||||
typedef struct {
|
||||
nr_pc5s_header_t pc5s_header;
|
||||
union {
|
||||
uint8_t status;
|
||||
NR_PC5SignallingMessage pc5_signalling_message;
|
||||
} pc5sPrimitive;
|
||||
} __attribute__((__packed__)) nr_sidelink_pc5s_element;
|
||||
|
||||
|
||||
#endif /* NR_PDCP_OAI_API_H */
|
||||
|
||||
@@ -132,6 +132,23 @@ void nr_pdcp_manager_remove_ue(nr_pdcp_ue_manager_t *_m, ue_id_t rntiMaybeUEid)
|
||||
if (ue->drb[j] != NULL)
|
||||
ue->drb[j]->delete_entity(ue->drb[j]);
|
||||
|
||||
//Jin add: Clean up peer contexts
|
||||
for (i = 0; i < ue->sl_peer_count; i++) {
|
||||
nr_pdcp_peer_context_t *peer_ctx = ue->sl_peers[i];
|
||||
for (j = 0; j < MAX_DRBS_PER_UE; j++) {
|
||||
if (peer_ctx->drb[j] != NULL) {
|
||||
peer_ctx->drb[j]->delete_entity(peer_ctx->drb[j]);
|
||||
}
|
||||
}
|
||||
free(peer_ctx);
|
||||
}
|
||||
if (ue->sl_peers != NULL) {
|
||||
free(ue->sl_peers);
|
||||
}
|
||||
//Jin end
|
||||
|
||||
|
||||
|
||||
free(ue);
|
||||
|
||||
m->ue_count--;
|
||||
@@ -210,3 +227,94 @@ bool nr_pdcp_get_first_ue_id(nr_pdcp_ue_manager_t *_m, ue_id_t *ret)
|
||||
*ret = m->ue_list[0]->rntiMaybeUEid;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//Jin add following for peer multi UES
|
||||
/* must be called with lock acquired */
|
||||
nr_pdcp_peer_context_t *nr_pdcp_ue_get_peer_context(
|
||||
nr_pdcp_ue_t *ue,
|
||||
ue_id_t peer_ue_id)
|
||||
{
|
||||
int i;
|
||||
|
||||
// Search for existing peer context
|
||||
for (i = 0; i < ue->sl_peer_count; i++) {
|
||||
if (ue->sl_peers[i]->peer_ue_id == peer_ue_id) {
|
||||
return ue->sl_peers[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Create new peer context
|
||||
LOG_D(PDCP, "Creating new peer context for UE 0x%"PRIx64" with peer 0x%"PRIx64"\n",
|
||||
ue->rntiMaybeUEid, peer_ue_id);
|
||||
|
||||
ue->sl_peer_count++;
|
||||
ue->sl_peers = realloc(ue->sl_peers,
|
||||
sizeof(nr_pdcp_peer_context_t *) * ue->sl_peer_count);
|
||||
if (ue->sl_peers == NULL) {
|
||||
LOG_E(PDCP, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ue->sl_peers[ue->sl_peer_count - 1] = calloc(1, sizeof(nr_pdcp_peer_context_t));
|
||||
if (ue->sl_peers[ue->sl_peer_count - 1] == NULL) {
|
||||
LOG_E(PDCP, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ue->sl_peers[ue->sl_peer_count - 1]->peer_ue_id = peer_ue_id;
|
||||
|
||||
return ue->sl_peers[ue->sl_peer_count - 1];
|
||||
}
|
||||
|
||||
/* must be called with lock acquired */
|
||||
void nr_pdcp_ue_add_peer_drb_pdcp_entity(
|
||||
nr_pdcp_ue_t *ue,
|
||||
ue_id_t peer_ue_id,
|
||||
int drb_id,
|
||||
nr_pdcp_entity_t *entity)
|
||||
{
|
||||
if (drb_id < 1 || drb_id > MAX_DRBS_PER_UE) {
|
||||
LOG_E(PDCP, "%s:%d:%s: fatal, bad drb id\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
nr_pdcp_peer_context_t *peer_ctx = nr_pdcp_ue_get_peer_context(ue, peer_ue_id);
|
||||
|
||||
drb_id--;
|
||||
|
||||
if (peer_ctx->drb[drb_id] != NULL) {
|
||||
LOG_W(PDCP, "%s:%d:%s: warning, peer drb already present (ue=0x%"PRIx64", peer=0x%"PRIx64", drb=%d), replacing\n",
|
||||
__FILE__, __LINE__, __FUNCTION__, ue->rntiMaybeUEid, peer_ue_id, drb_id + 1);
|
||||
peer_ctx->drb[drb_id]->delete_entity(peer_ctx->drb[drb_id]);
|
||||
}
|
||||
|
||||
peer_ctx->drb[drb_id] = entity;
|
||||
|
||||
LOG_D(PDCP, "Added peer DRB entity: local_ue=0x%"PRIx64" peer_ue=0x%"PRIx64" drb_id=%d\n",
|
||||
ue->rntiMaybeUEid, peer_ue_id, drb_id + 1);
|
||||
}
|
||||
|
||||
/* must be called with lock acquired */
|
||||
nr_pdcp_entity_t *nr_pdcp_ue_get_peer_drb_entity(
|
||||
nr_pdcp_ue_t *ue,
|
||||
ue_id_t peer_ue_id,
|
||||
int drb_id)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (drb_id < 1 || drb_id > MAX_DRBS_PER_UE) {
|
||||
LOG_E(PDCP, "%s:%d:%s: fatal, bad drb id\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Search for peer context
|
||||
for (i = 0; i < ue->sl_peer_count; i++) {
|
||||
if (ue->sl_peers[i]->peer_ue_id == peer_ue_id) {
|
||||
return ue->sl_peers[i]->drb[drb_id - 1];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL; // Peer context not found
|
||||
}
|
||||
//JIn end
|
||||
|
||||
@@ -28,12 +28,46 @@
|
||||
|
||||
typedef void nr_pdcp_ue_manager_t;
|
||||
|
||||
typedef struct nr_pdcp_peer_context_t nr_pdcp_peer_context_t; //Jin add
|
||||
|
||||
typedef struct nr_pdcp_ue_t {
|
||||
ue_id_t rntiMaybeUEid;
|
||||
nr_pdcp_entity_t *srb[3];
|
||||
nr_pdcp_entity_t *drb[MAX_DRBS_PER_UE];
|
||||
|
||||
// Jin add multi UES
|
||||
nr_pdcp_peer_context_t **sl_peers; // Array of pointers to peer contexts
|
||||
int sl_peer_count; // Number of active peers
|
||||
} nr_pdcp_ue_t;
|
||||
|
||||
// JIN ADD : Per-peer PDCP context for sidelink
|
||||
struct nr_pdcp_peer_context_t {
|
||||
ue_id_t peer_ue_id; // The peer UE's L2 ID
|
||||
nr_pdcp_entity_t *drb[MAX_DRBS_PER_UE]; // PDCP entities for this peer
|
||||
};
|
||||
|
||||
/***********************************************************************/
|
||||
/* sidelink peer management functions */
|
||||
/***********************************************************************/
|
||||
// Get or create peer context for a given peer UE ID
|
||||
nr_pdcp_peer_context_t *nr_pdcp_ue_get_peer_context(
|
||||
nr_pdcp_ue_t *ue,
|
||||
ue_id_t peer_ue_id);
|
||||
|
||||
// Add DRB PDCP entity for a specific peer
|
||||
void nr_pdcp_ue_add_peer_drb_pdcp_entity(
|
||||
nr_pdcp_ue_t *ue,
|
||||
ue_id_t peer_ue_id,
|
||||
int drb_id,
|
||||
nr_pdcp_entity_t *entity);
|
||||
|
||||
// Get DRB PDCP entity for a specific peer
|
||||
nr_pdcp_entity_t *nr_pdcp_ue_get_peer_drb_entity(
|
||||
nr_pdcp_ue_t *ue,
|
||||
ue_id_t peer_ue_id,
|
||||
int drb_id);
|
||||
|
||||
|
||||
/***********************************************************************/
|
||||
/* manager functions */
|
||||
/***********************************************************************/
|
||||
|
||||
@@ -65,7 +65,9 @@ void mac_rlc_data_ind (
|
||||
char *buffer_pP,
|
||||
const tb_size_t tb_sizeP,
|
||||
num_tb_t num_tbP,
|
||||
crc_t *crcs_pP)
|
||||
crc_t *crcs_pP,
|
||||
const uint32_t sourceL2Id, // JIN : Source L2 ID for sidelink
|
||||
const uint32_t destinationL2Id) // JIN: Destination L2 ID for sidelink
|
||||
{
|
||||
nr_rlc_ue_t *ue;
|
||||
nr_rlc_entity_t *rb;
|
||||
@@ -85,6 +87,12 @@ void mac_rlc_data_ind (
|
||||
if(ue == NULL)
|
||||
LOG_I(RLC, "RLC instance for the given UE was not found \n");
|
||||
|
||||
// JIN: Store L2 IDs for sidelink (used when delivering to PDCP)
|
||||
ue->sl_rx_src_l2id = sourceL2Id;
|
||||
ue->sl_rx_dst_l2id = destinationL2Id;
|
||||
// END JIN
|
||||
|
||||
|
||||
switch (channel_idP) {
|
||||
case 0: rb = ue->srb0; break;
|
||||
case 1 ... 3: rb = ue->srb[channel_idP - 1]; break;
|
||||
@@ -427,8 +435,9 @@ rb_found:
|
||||
|
||||
/* used fields? */
|
||||
ctx.module_id = 0;
|
||||
ctx.rntiMaybeUEid = ue->rnti;
|
||||
|
||||
//ctx.rntiMaybeUEid = ue->rnti;
|
||||
ctx.rntiMaybeUEid = ue->sl_rx_src_l2id;
|
||||
|
||||
is_enb = nr_rlc_manager_get_enb_flag(nr_rlc_ue_manager);
|
||||
ctx.enb_flag = is_enb;
|
||||
|
||||
@@ -484,7 +493,14 @@ rb_found:
|
||||
}
|
||||
memcpy(memblock->data, buf, size);
|
||||
LOG_D(PDCP, "Calling PDCP layer from RLC in %s\n", __FUNCTION__);
|
||||
if (!pdcp_data_ind(&ctx, is_srb, 0, rb_id, size, memblock, NULL, NULL)) {
|
||||
|
||||
// JIN: Pass L2 IDs to PDCP
|
||||
uint32_t src = ue->sl_rx_src_l2id;
|
||||
uint32_t dst = ue->sl_rx_dst_l2id;
|
||||
|
||||
//if (!pdcp_data_ind(&ctx, is_srb, 0, rb_id, size, memblock, NULL, NULL)) {
|
||||
if (!pdcp_data_ind(&ctx, is_srb, 0, rb_id, size, memblock,
|
||||
(src != 0) ? &src : NULL, (dst != 0) ? &dst : NULL)) { // Jin add pass ID if availble
|
||||
LOG_E(RLC, "%s:%d:%s: ERROR: pdcp_data_ind failed\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
/* what to do in case of failure? for the moment: nothing */
|
||||
}
|
||||
|
||||
@@ -33,6 +33,10 @@ typedef struct nr_rlc_ue_t {
|
||||
nr_rlc_entity_t *srb0;
|
||||
nr_rlc_entity_t *srb[3];
|
||||
nr_rlc_entity_t *drb[MAX_DRBS_PER_UE];
|
||||
// JIN: Sidelink L2 IDs (set by MAC layer before calling mac_rlc_data_ind)
|
||||
uint32_t sl_rx_src_l2id; // Source L2 ID of received packet
|
||||
uint32_t sl_rx_dst_l2id; // Destination L2 ID of received packet
|
||||
|
||||
} nr_rlc_ue_t;
|
||||
|
||||
/***********************************************************************/
|
||||
|
||||
3
openair2/RRC/NAS/nas_sock_fd.h
Normal file
3
openair2/RRC/NAS/nas_sock_fd.h
Normal file
@@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
#include "openair2/RRC/NAS/nas_config.h" // MAX_MOBILES_PER_ENB
|
||||
extern int nas_sock_fd[MAX_MOBILES_PER_ENB*2];
|
||||
@@ -75,6 +75,36 @@
|
||||
|
||||
#include "nr_nas_msg_sim.h"
|
||||
|
||||
#include "openair2/SDAP/nr_sdap/nr_sdap.h"
|
||||
#include "openair2/SDAP/nr_sdap/nr_sdap_entity.h"
|
||||
|
||||
//Gate SLC Flag here
|
||||
#include "executables/nr-uesoftmodem.h"
|
||||
extern int sl_nas_enabled;
|
||||
|
||||
// for NR_PC5 Controller
|
||||
int ctrl_sock_fd;
|
||||
#define BUFSIZE 4096 //Jin enlarge bufsize 1024 origin
|
||||
struct sockaddr_in prose_ctl_addr;
|
||||
int slrb_id;
|
||||
//int send_ue_information = 0;
|
||||
NR_SL_UE_STATE_t On_Off_Net = NR_UE_STATE_OFF_NETWORK;
|
||||
// end
|
||||
|
||||
NR_SL_SchedulerConfig_t nr_sl_scheduler_config = {
|
||||
.sfid = {0, 1, 2, 3, 4, 5, 6, 7}, //JinN: UE per slot, now it's 8 max, need to be updated for more
|
||||
.action = 1,
|
||||
.valid = 0 // not yet overridden by SLC_C
|
||||
};
|
||||
|
||||
//Jin add for resourcePool
|
||||
NR_SL_RpoolConfig_t nr_sl_rpool_config[MAX_SL_POOLS] = {
|
||||
[0] = { .start_rb = 0, .rb_number = 50, .num_subchannel = 1, .valid = 0 },
|
||||
[1] = { .start_rb = 0, .rb_number = 0, .num_subchannel = 0, .valid = 0 },
|
||||
};
|
||||
uint8_t nr_sl_ue_pool_assignment[MAX_SL_UE] = {0}; /* all UEs on pool 0 */
|
||||
|
||||
|
||||
NR_UE_RRC_INST_t *NR_UE_rrc_inst;
|
||||
/* NAS Attach request with IMSI */
|
||||
static const char nr_nas_attach_req_imsi[] = {
|
||||
@@ -2538,3 +2568,580 @@ void nr_ue_rrc_timer_trigger(int module_id, int frame, int slot, int gnb_id)
|
||||
LOG_D(NR_RRC, "RRC timer trigger: frame %d slot %d \n", frame, slot);
|
||||
itti_send_msg_to_task(TASK_RRC_NRUE, GNB_MODULE_ID_TO_INSTANCE(module_id), message_p);
|
||||
}
|
||||
|
||||
/* control socket for PC5 Controller (and futur O-RAN-like agent control)
|
||||
*
|
||||
*/
|
||||
|
||||
//--------------------------------------------------------
|
||||
void
|
||||
nr_rrc_pc5_control_socket_init() {
|
||||
struct sockaddr_in rrc_ctrl_socket_addr;
|
||||
pthread_attr_t attr;
|
||||
struct sched_param sched_param;
|
||||
int optval; // flag value for setsockopt
|
||||
//int n; // message byte size
|
||||
// create the control socket
|
||||
ctrl_sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
|
||||
if (ctrl_sock_fd == -1) {
|
||||
LOG_E(RRC,"[rrc_control_socket_init]: Error opening socket %d (%d:%s)\n",ctrl_sock_fd,errno, strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// if (ctrl_sock_fd < 0)
|
||||
// error("ERROR: Failed on opening socket");
|
||||
optval = 1;
|
||||
setsockopt(ctrl_sock_fd, SOL_SOCKET, SO_REUSEADDR,
|
||||
(const void *)&optval , sizeof(int));
|
||||
//build the server's address
|
||||
bzero((char *) &rrc_ctrl_socket_addr, sizeof(rrc_ctrl_socket_addr));
|
||||
rrc_ctrl_socket_addr.sin_family = AF_INET;
|
||||
rrc_ctrl_socket_addr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
rrc_ctrl_socket_addr.sin_port = htons(NR_CONTROL_SOCKET_PORT_NO);
|
||||
|
||||
// associate the parent socket with a port
|
||||
if (bind(ctrl_sock_fd, (struct sockaddr *) &rrc_ctrl_socket_addr,
|
||||
sizeof(rrc_ctrl_socket_addr)) < 0) {
|
||||
LOG_E(RRC,"[rrc_control_socket_init] ERROR: Failed on binding the socket\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
//create thread to listen to incoming packets
|
||||
if (pthread_attr_init(&attr) != 0) {
|
||||
LOG_E(RRC, "[rrc_control_socket_init]Failed to initialize pthread attribute for PC5_CTL -> RRC communication (%d:%s)\n",
|
||||
errno, strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
sched_param.sched_priority = 10;
|
||||
pthread_attr_setschedpolicy(&attr, SCHED_RR);
|
||||
pthread_attr_setschedparam(&attr, &sched_param);
|
||||
pthread_t nr_rrc_control_socket_thread;
|
||||
|
||||
if (pthread_create(&nr_rrc_control_socket_thread, &attr, nr_rrc_control_socket_thread_fct, NULL) != 0) {
|
||||
LOG_E(RRC, "[nr_rrc_control_socket_init]Failed to create new thread for NR_RRC/NR_PC5_CTL communication (%d:%s)\n",
|
||||
errno, strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
pthread_setname_np( nr_rrc_control_socket_thread, "NR_RRC/NR_PC5 Control Socket" );
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------
|
||||
void *nr_rrc_control_socket_thread_fct(void *arg)
|
||||
{
|
||||
|
||||
unsigned int prose_addr_len;
|
||||
char send_buf[BUFSIZE];
|
||||
char receive_buf[BUFSIZE];
|
||||
int n;
|
||||
struct nr_sidelink_ctrl_element *sl_ctrl_msg_recv = NULL;
|
||||
struct nr_sidelink_ctrl_element *sl_ctrl_msg_send = NULL;
|
||||
uint32_t sourceL2Id, groupL2Id, destinationL2Id;
|
||||
module_id_t module_id = 0; //hardcoded for testing only
|
||||
uint8_t type;
|
||||
//NR_UE_RRC_INST_t *rrc = &NR_UE_rrc_inst[module_id];
|
||||
//protocol_ctxt_t ctxt;
|
||||
//struct NR_RLC_Config *DRB_rlc_config = NULL;
|
||||
//struct NR_PDCP_Config *DRB_pdcp_config = NULL;
|
||||
//struct NR_PDCP_Config__rlc_UM *PDCP_rlc_UM = NULL;
|
||||
//struct NR_LogicalChannelConfig *DRB_lchan_config = NULL;
|
||||
//struct NR_LogicalChannelConfig__ul_SpecificParameters *DRB_ul_SpecificParameters = NULL;
|
||||
//long *logicalchannelgroup_drb = NULL;
|
||||
int j = 0;
|
||||
int i = 0;
|
||||
int slrb_id =0;
|
||||
//LTE_DRB_Identity_t drb_id = 0;
|
||||
//LTE_DRB_ToReleaseList_t* drb2release_list = NULL;
|
||||
|
||||
//from the main program, listen for the incoming messages from control socket (PC5 Controller)
|
||||
prose_addr_len = sizeof(prose_ctl_addr);
|
||||
//int enable_notification = 1;
|
||||
|
||||
LOG_I(RRC,"NR UE SL state: %d \n", On_Off_Net);
|
||||
while (1) {
|
||||
LOG_I(RRC,"Listening to incoming connection from PC5 Controller \n");
|
||||
// receive a message from PC5 Controller
|
||||
memset(receive_buf, 0, BUFSIZE);
|
||||
n = recvfrom(ctrl_sock_fd, receive_buf, BUFSIZE, 0,
|
||||
(struct sockaddr *) &prose_ctl_addr, (socklen_t *)&prose_addr_len);
|
||||
if (n < 0){
|
||||
LOG_E(RRC, "ERROR: Failed to receive from PC5 Controller \n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
//TODO: should store the address of PC5 Controller [NR_UE_rrc_inst] to be able to send UE state notification to the Controller
|
||||
|
||||
sl_ctrl_msg_recv = calloc(1, sizeof(struct nr_sidelink_ctrl_element));
|
||||
memcpy((void *)sl_ctrl_msg_recv, (void *)receive_buf, sizeof(struct nr_sidelink_ctrl_element));
|
||||
|
||||
//process the message
|
||||
switch (sl_ctrl_msg_recv->type) {
|
||||
case NR_SESSION_INIT_REQ:
|
||||
if (LOG_DEBUGFLAG(DEBUG_CTRLSOCKET)){
|
||||
LOG_I(RRC,"Received NR_SessionInitializationRequest on socket from PC5 Controller (msg type: %d)\n", sl_ctrl_msg_recv->type);
|
||||
}
|
||||
|
||||
//TODO: get SL_UE_STATE from lower layer
|
||||
LOG_I(RRC,"Send UEStateInformation to PC5 Controller \n");
|
||||
memset(send_buf, 0, BUFSIZE);
|
||||
|
||||
sl_ctrl_msg_send = calloc(1, sizeof(struct nr_sidelink_ctrl_element));
|
||||
sl_ctrl_msg_send->type = NR_UE_STATUS_INFO;
|
||||
sl_ctrl_msg_send->nr_sidelinkPrimitive.ue_state = On_Off_Net;
|
||||
memcpy((void *)send_buf, (void *)sl_ctrl_msg_send, sizeof(struct nr_sidelink_ctrl_element));
|
||||
free(sl_ctrl_msg_send);
|
||||
|
||||
prose_addr_len = sizeof(prose_ctl_addr);
|
||||
n = sendto(ctrl_sock_fd, (char *)send_buf, sizeof(struct nr_sidelink_ctrl_element), 0, (struct sockaddr *)&prose_ctl_addr, prose_addr_len);
|
||||
if (n < 0) {
|
||||
LOG_E(RRC, "ERROR: Failed to send to PC5 Controller \n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (LOG_DEBUGFLAG(DEBUG_CTRLSOCKET)){
|
||||
struct nr_sidelink_ctrl_element *ptr_ctrl_msg = NULL;
|
||||
ptr_ctrl_msg = (struct nr_sidelink_ctrl_element *) send_buf;
|
||||
LOG_UI(RRC,"[UEStateInformation] msg type: %d\n",ptr_ctrl_msg->type);
|
||||
LOG_UI(RRC,"[UEStateInformation] UE state: %d\n",ptr_ctrl_msg->nr_sidelinkPrimitive.ue_state);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case NR_GROUP_COMMUNICATION_ESTABLISH_REQ:
|
||||
sourceL2Id = sl_ctrl_msg_recv->nr_sidelinkPrimitive.group_comm_establish_req.sourceL2Id;
|
||||
groupL2Id = sl_ctrl_msg_recv->nr_sidelinkPrimitive.group_comm_establish_req.groupL2Id;
|
||||
int group_comm_rbid = 0;
|
||||
|
||||
if (LOG_DEBUGFLAG(DEBUG_CTRLSOCKET)){
|
||||
LOG_I(RRC,"[GroupCommunicationEstablishReq] Received on socket from PC5 Controller (msg type: %d)\n",sl_ctrl_msg_recv->type);
|
||||
LOG_I(RRC,"[GroupCommunicationEstablishReq] source Id: 0x%08x\n",sl_ctrl_msg_recv->nr_sidelinkPrimitive.group_comm_establish_req.sourceL2Id);
|
||||
LOG_I(RRC,"[GroupCommunicationEstablishReq] group Id: 0x%08x\n",sl_ctrl_msg_recv->nr_sidelinkPrimitive.group_comm_establish_req.groupL2Id);
|
||||
LOG_I(RRC,"[GroupCommunicationEstablishReq] group IP Address: " IPV4_ADDR "\n",IPV4_ADDR_FORMAT(sl_ctrl_msg_recv->nr_sidelinkPrimitive.group_comm_establish_req.groupIpAddress));
|
||||
}
|
||||
|
||||
LOG_I(RRC,"Send GroupCommunicationEstablishResp to PC5 CTL\n");
|
||||
LOG_I(RRC,"[GroupCommunicationEstablishResponse] msg type: %d\n",NR_GROUP_COMMUNICATION_ESTABLISH_RSP);
|
||||
LOG_I(RRC,"[GroupCommunicationEstablishResponse] slrb_id: %d\n",group_comm_rbid);
|
||||
memset(send_buf, 0, BUFSIZE);
|
||||
sl_ctrl_msg_send = calloc(1, sizeof(struct nr_sidelink_ctrl_element));
|
||||
sl_ctrl_msg_send->type = NR_GROUP_COMMUNICATION_ESTABLISH_RSP;
|
||||
sl_ctrl_msg_send->nr_sidelinkPrimitive.slrb_id = group_comm_rbid; //slrb_id
|
||||
|
||||
memcpy((void *)send_buf, (void *)sl_ctrl_msg_send, sizeof(struct nr_sidelink_ctrl_element));
|
||||
free(sl_ctrl_msg_send);
|
||||
|
||||
prose_addr_len = sizeof(prose_ctl_addr);
|
||||
n = sendto(ctrl_sock_fd, (char *)send_buf, sizeof(struct nr_sidelink_ctrl_element), 0, (struct sockaddr *)&prose_ctl_addr, prose_addr_len);
|
||||
if (n < 0){
|
||||
LOG_E(RRC, "ERROR: Failed to send to PC5 CTL\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case NR_GROUP_COMMUNICATION_RELEASE_REQ:
|
||||
printf("-----------------------------------\n");
|
||||
if (LOG_DEBUGFLAG(DEBUG_CTRLSOCKET)){
|
||||
LOG_I(RRC,"[NR_GroupCommunicationReleaseRequest] Received on socket from PC5 Controller (msg type: %d)\n",sl_ctrl_msg_recv->type);
|
||||
LOG_I(RRC,"[NR_GroupCommunicationReleaseRequest] Slrb Id: %i\n",sl_ctrl_msg_recv->nr_sidelinkPrimitive.slrb_id);
|
||||
}
|
||||
//reset groupL2ID from MAC LAYER
|
||||
//UE_rrc_inst[module_id].groupL2Id = 0x00000000;
|
||||
//sourceL2Id = UE_rrc_inst[module_id].sourceL2Id;
|
||||
|
||||
LOG_I(RRC,"Send NR_GroupCommunicationReleaseResponse to PC5 CTL \n");
|
||||
memset(send_buf, 0, BUFSIZE);
|
||||
|
||||
sl_ctrl_msg_send = calloc(1, sizeof(struct nr_sidelink_ctrl_element));
|
||||
sl_ctrl_msg_send->type = NR_GROUP_COMMUNICATION_RELEASE_RSP;
|
||||
sl_ctrl_msg_send->nr_sidelinkPrimitive.group_comm_release_rsp = NR_GROUP_COMMUNICATION_RELEASE_OK;
|
||||
|
||||
memcpy((void *)send_buf, (void *)sl_ctrl_msg_send, sizeof(struct nr_sidelink_ctrl_element));
|
||||
free(sl_ctrl_msg_send);
|
||||
|
||||
prose_addr_len = sizeof(prose_ctl_addr);
|
||||
n = sendto(ctrl_sock_fd, (char *)send_buf, sizeof(struct nr_sidelink_ctrl_element), 0, (struct sockaddr *)&prose_ctl_addr, prose_addr_len);
|
||||
if (n < 0){
|
||||
LOG_E(RRC, "ERROR: Failed to send to PC5 CTL \n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case NR_DIRECT_COMMUNICATION_ESTABLISH_REQ:
|
||||
sourceL2Id = sl_ctrl_msg_recv->nr_sidelinkPrimitive.direct_comm_establish_req.sourceL2Id;
|
||||
destinationL2Id = sl_ctrl_msg_recv->nr_sidelinkPrimitive.direct_comm_establish_req.destinationL2Id;
|
||||
int direct_comm_rbid = 0;
|
||||
|
||||
if (LOG_DEBUGFLAG(DEBUG_CTRLSOCKET)){
|
||||
LOG_I(RRC,"[NR_DirectCommunicationEstablishReq] Received on socket from PC5 Controller (msg type: %d)\n",sl_ctrl_msg_recv->type);
|
||||
LOG_I(RRC,"[NR_DirectCommunicationEstablishReq] source Id: 0x%08x\n",sl_ctrl_msg_recv->nr_sidelinkPrimitive.group_comm_establish_req.sourceL2Id);
|
||||
LOG_I(RRC,"[NR_DirectCommunicationEstablishReq] destination Id: 0x%08x\n",sl_ctrl_msg_recv->nr_sidelinkPrimitive.group_comm_establish_req.groupL2Id);
|
||||
}
|
||||
|
||||
|
||||
#ifdef DEBUG_CTRL_SOCKET
|
||||
LOG_I(RRC,"Send DirectCommunicationEstablishResp to PC5 CTL\n");
|
||||
LOG_I(RRC,"[NR_DirectCommunicationEstablishResponse] msg type: %d\n",NR_DIRECT_COMMUNICATION_ESTABLISH_RSP);
|
||||
LOG_I(RRC,"[NR_DirectCommunicationEstablishResponse] slrb_id: %d\n",direct_comm_rbid);
|
||||
#endif
|
||||
|
||||
memset(send_buf, 0, BUFSIZE);
|
||||
sl_ctrl_msg_send = calloc(1, sizeof(struct nr_sidelink_ctrl_element));
|
||||
sl_ctrl_msg_send->type = NR_DIRECT_COMMUNICATION_ESTABLISH_RSP;
|
||||
sl_ctrl_msg_send->nr_sidelinkPrimitive.slrb_id = direct_comm_rbid; //slrb_id
|
||||
|
||||
memcpy((void *)send_buf, (void *)sl_ctrl_msg_send, sizeof(struct nr_sidelink_ctrl_element));
|
||||
free(sl_ctrl_msg_send);
|
||||
|
||||
prose_addr_len = sizeof(prose_ctl_addr);
|
||||
n = sendto(ctrl_sock_fd, (char *)send_buf, sizeof(struct nr_sidelink_ctrl_element), 0, (struct sockaddr *)&prose_ctl_addr, prose_addr_len);
|
||||
if (n < 0){
|
||||
LOG_E(RRC, "ERROR: Failed to send to PC5 Controller \n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case NR_DIRECT_COMMUNICATION_RELEASE_REQ:
|
||||
printf("-----------------------------------\n");
|
||||
#ifdef DEBUG_CTRL_SOCKET
|
||||
LOG_I(RRC,"[NR_DirectCommunicationReleaseRequest] Received on socket from PC5 Controller (msg type: %d)\n",sl_ctrl_msg_recv->type);
|
||||
LOG_I(RRC,"[NR_DirectCommunicationReleaseRequest] Slrb Id: %i\n",sl_ctrl_msg_recv->nr_sidelinkPrimitive.slrb_id);
|
||||
#endif
|
||||
slrb_id = sl_ctrl_msg_recv->nr_sidelinkPrimitive.slrb_id;
|
||||
//reset groupL2ID from MAC LAYER
|
||||
|
||||
LOG_I(RRC,"Send NR_DirectCommunicationReleaseResponse to PC5 Controller \n");
|
||||
memset(send_buf, 0, BUFSIZE);
|
||||
|
||||
sl_ctrl_msg_send = calloc(1, sizeof(struct nr_sidelink_ctrl_element));
|
||||
sl_ctrl_msg_send->type = NR_DIRECT_COMMUNICATION_RELEASE_RSP;
|
||||
sl_ctrl_msg_send->nr_sidelinkPrimitive.direct_comm_release_rsp = NR_DIRECT_COMMUNICATION_RELEASE_OK;
|
||||
|
||||
memcpy((void *)send_buf, (void *)sl_ctrl_msg_send, sizeof(struct nr_sidelink_ctrl_element));
|
||||
free(sl_ctrl_msg_send);
|
||||
|
||||
prose_addr_len = sizeof(prose_ctl_addr);
|
||||
n = sendto(ctrl_sock_fd, (char *)send_buf, sizeof(struct nr_sidelink_ctrl_element), 0, (struct sockaddr *)&prose_ctl_addr, prose_addr_len);
|
||||
if (n < 0){
|
||||
LOG_E(RRC, "ERROR: Failed to send to PC5 Controller \n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case NR_PC5S_ESTABLISH_REQ:
|
||||
type = sl_ctrl_msg_recv->nr_sidelinkPrimitive.pc5s_establish_req.type;
|
||||
sourceL2Id = sl_ctrl_msg_recv->nr_sidelinkPrimitive.pc5s_establish_req.sourceL2Id;
|
||||
int pc5s_rbid = 10; // to update
|
||||
if (LOG_DEBUGFLAG(DEBUG_CTRLSOCKET)){
|
||||
LOG_I(RRC,"[NR_PC5EstablishReq] Received on socket from PC5 Controller (msg type: %d)\n",sl_ctrl_msg_recv->type);
|
||||
LOG_I(RRC,"[NR_PC5EstablishReq] type: %d\n",sl_ctrl_msg_recv->nr_sidelinkPrimitive.pc5s_establish_req.type); //RX/TX
|
||||
LOG_I(RRC,"[NR_PC5EstablishReq] source Id: 0x%08x \n",sl_ctrl_msg_recv->nr_sidelinkPrimitive.pc5s_establish_req.sourceL2Id);
|
||||
}
|
||||
if (type > 0) {
|
||||
destinationL2Id = sl_ctrl_msg_recv->nr_sidelinkPrimitive.pc5s_establish_req.destinationL2Id;
|
||||
if (LOG_DEBUGFLAG(DEBUG_CTRLSOCKET)){
|
||||
LOG_I(RRC,"[NR_PC5EstablishReq] destination Id: 0x%08x \n",sl_ctrl_msg_recv->nr_sidelinkPrimitive.pc5s_establish_req.destinationL2Id);
|
||||
}
|
||||
}
|
||||
|
||||
//store sourceL2Id/destinationL2Id
|
||||
if (type > 0) { //TX
|
||||
} else {//RX
|
||||
}
|
||||
|
||||
// configure lower layers PDCP/MAC/PHY for this communication
|
||||
//Establish a new RBID/LCID for this communication
|
||||
// Establish a SLRB (starting from 8 for now)
|
||||
|
||||
//TX
|
||||
if (type > 0) {
|
||||
} else {//RX
|
||||
//configure MAC with sourceL2Id/groupL2ID
|
||||
}
|
||||
|
||||
LOG_I(RRC,"Send NR_PC5EstablishRsp to PC5 Controller \n");
|
||||
memset(send_buf, 0, BUFSIZE);
|
||||
sl_ctrl_msg_send = calloc(1, sizeof(struct nr_sidelink_ctrl_element));
|
||||
sl_ctrl_msg_send->type = NR_PC5S_ESTABLISH_RSP;
|
||||
//sl_ctrl_msg_send->nr_sidelinkPrimitive.pc5s_establish_rsp.slrbid_lcid28 = pc5s_rbid;
|
||||
//sl_ctrl_msg_send->nr_sidelinkPrimitive.pc5s_establish_rsp.slrbid_lcid29 = pc5s_rbid;
|
||||
//sl_ctrl_msg_send->nr_sidelinkPrimitive.pc5s_establish_rsp.slrbid_lcid30 = pc5s_rbid;
|
||||
|
||||
memcpy((void *)send_buf, (void *)sl_ctrl_msg_send, sizeof(struct nr_sidelink_ctrl_element));
|
||||
free(sl_ctrl_msg_send);
|
||||
|
||||
prose_addr_len = sizeof(prose_ctl_addr);
|
||||
n = sendto(ctrl_sock_fd, (char *)send_buf, sizeof(struct nr_sidelink_ctrl_element), 0, (struct sockaddr *)&prose_ctl_addr, prose_addr_len);
|
||||
|
||||
if (n < 0){
|
||||
LOG_E(RRC, "ERROR: Failed to send to PC5 Controller \n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
break;
|
||||
|
||||
case NR_PC5S_RELEASE_REQ:
|
||||
printf("-----------------------------------\n");
|
||||
#ifdef DEBUG_CTRL_SOCKET
|
||||
LOG_I(RRC,"[NR_PC5SReleaseRequest] Received on socket from PC5 Controller (msg type: %d)\n",sl_ctrl_msg_recv->type);
|
||||
LOG_I(RRC,"[NR_PC5SReleaseRequest] Slrb Id: %i\n",sl_ctrl_msg_recv->nr_sidelinkPrimitive.slrb_id);
|
||||
#endif
|
||||
slrb_id = sl_ctrl_msg_recv->nr_sidelinkPrimitive.slrb_id;
|
||||
//reset groupL2ID from MAC LAYER
|
||||
|
||||
LOG_I(RRC,"Send NR_PC5SReleaseResponse to PC5 Controller \n");
|
||||
memset(send_buf, 0, BUFSIZE);
|
||||
|
||||
sl_ctrl_msg_send = calloc(1, sizeof(struct nr_sidelink_ctrl_element));
|
||||
sl_ctrl_msg_send->type = NR_PC5S_RELEASE_RSP;
|
||||
sl_ctrl_msg_send->nr_sidelinkPrimitive.pc5s_release_rsp = NR_PC5S_RELEASE_OK;
|
||||
|
||||
memcpy((void *)send_buf, (void *)sl_ctrl_msg_send, sizeof(struct nr_sidelink_ctrl_element));
|
||||
free(sl_ctrl_msg_send);
|
||||
|
||||
prose_addr_len = sizeof(prose_ctl_addr);
|
||||
n = sendto(ctrl_sock_fd, (char *)send_buf, sizeof(struct nr_sidelink_ctrl_element), 0, (struct sockaddr *)&prose_ctl_addr, prose_addr_len);
|
||||
if (n < 0){
|
||||
LOG_E(RRC, "ERROR: Failed to send to PC5 Controller \n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
break;
|
||||
|
||||
case NR_PC5_DISCOVERY_MESSAGE:
|
||||
LOG_I(RRC,"[NR_PC5DiscoveryMessage] NOT SUPPORTED YET\n");
|
||||
break;
|
||||
/*
|
||||
case NR_MACReconfigurationRequest:
|
||||
LOG_D(RRC,"[NR_MACReconfigurationRequest] !!!Received a Scheduler Reconfiguration Request\n");
|
||||
memset(send_buf, 0, BUFSIZE);
|
||||
|
||||
sl_ctrl_msg_send = calloc(1, sizeof(struct nr_sidelink_ctrl_element));
|
||||
sl_ctrl_msg_send->type = NR_MACReconfigurationConfirm; // send the OK back to controller
|
||||
sl_ctrl_msg_send->nr_sidelinkPrimitive.pc5_scheduler_config.map.action = sl_ctrl_msg_recv->nr_sidelinkPrimitive.pc5_scheduler_config.map.action;
|
||||
sl_ctrl_msg_send->nr_sidelinkPrimitive.pc5_scheduler_config.map.sfid = sl_ctrl_msg_recv->nr_sidelinkPrimitive.pc5_scheduler_config.map.sfid;
|
||||
//sl_ctrl_msg_send->nr_sidelinkPrimitive.pc5_scheduler_config.map.action = sl_ctrl_msg_recv->pc5_scheduler_config.map.action; // to be updated by 1 (release) in case of failure
|
||||
//sl_ctrl_msg_send->nr_sidelinkPrimitive.pc5_scheduler_config.map.sfid = sl_ctrl_msg_recv->pc5_scheduler_config.map.sfid;// to be updated by the real sfid, in case the expected one is not available
|
||||
memcpy((void *)send_buf, (void *)sl_ctrl_msg_send, sizeof(struct nr_sidelink_ctrl_element));
|
||||
free(sl_ctrl_msg_send);
|
||||
|
||||
prose_addr_len = sizeof(prose_ctl_addr);
|
||||
n = sendto(ctrl_sock_fd, (char *)send_buf, sizeof(struct nr_sidelink_ctrl_element), 0, (struct sockaddr *)&prose_ctl_addr, prose_addr_len);
|
||||
if (n < 0) {
|
||||
LOG_E(RRC, "ERROR: Failed to send to PC5 Controller \n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
break;
|
||||
*/
|
||||
case NR_MACReconfigurationRequest:
|
||||
LOG_I(RRC,"[NR_MACReconfigurationRequest] sfid=%d action=%d\n",
|
||||
sl_ctrl_msg_recv->nr_sidelinkPrimitive.pc5_scheduler_config.map.sfid,
|
||||
sl_ctrl_msg_recv->nr_sidelinkPrimitive.pc5_scheduler_config.map.action);
|
||||
{
|
||||
uint8_t ue_sfid = sl_ctrl_msg_recv->nr_sidelinkPrimitive
|
||||
.pc5_scheduler_config.map.sfid;
|
||||
uint8_t ue_action = sl_ctrl_msg_recv->nr_sidelinkPrimitive
|
||||
.pc5_scheduler_config.map.action;
|
||||
|
||||
// sfid here encodes: upper 4 bits = ue_id, lower 4 bits = slot
|
||||
// e.g. sfid=0x12 means UE1 gets slot 2
|
||||
uint8_t ue_id = (ue_sfid >> 4) & 0x0F;
|
||||
uint8_t slot_id = (ue_sfid) & 0x0F;
|
||||
|
||||
if (ue_id < MAX_UE_NR_CAPABILITY_SIZE) {
|
||||
nr_sl_scheduler_config.sfid[ue_id] = slot_id;
|
||||
nr_sl_scheduler_config.action = ue_action;
|
||||
nr_sl_scheduler_config.valid = 1;
|
||||
LOG_I(RRC,"[SLC_C] UE%d assigned slot %d\n", ue_id, slot_id);
|
||||
} else {
|
||||
LOG_E(RRC,"[SLC_C] ue_id %d out of range\n", ue_id);
|
||||
}
|
||||
}
|
||||
// send Confirm back
|
||||
memset(send_buf, 0, BUFSIZE);
|
||||
sl_ctrl_msg_send = calloc(1, sizeof(struct nr_sidelink_ctrl_element));
|
||||
sl_ctrl_msg_send->type = NR_MACReconfigurationConfirm;
|
||||
sl_ctrl_msg_send->nr_sidelinkPrimitive.pc5_scheduler_config.map.sfid =
|
||||
sl_ctrl_msg_recv->nr_sidelinkPrimitive.pc5_scheduler_config.map.sfid;
|
||||
sl_ctrl_msg_send->nr_sidelinkPrimitive.pc5_scheduler_config.map.action =
|
||||
sl_ctrl_msg_recv->nr_sidelinkPrimitive.pc5_scheduler_config.map.action;
|
||||
memcpy((void *)send_buf, (void *)sl_ctrl_msg_send,
|
||||
sizeof(struct nr_sidelink_ctrl_element));
|
||||
free(sl_ctrl_msg_send);
|
||||
prose_addr_len = sizeof(prose_ctl_addr);
|
||||
n = sendto(ctrl_sock_fd, (char *)send_buf,
|
||||
sizeof(struct nr_sidelink_ctrl_element), 0,
|
||||
(struct sockaddr *)&prose_ctl_addr, prose_addr_len);
|
||||
if (n < 0) {
|
||||
LOG_E(RRC, "ERROR: Failed to send NR_MACReconfigurationConfirm\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
break;
|
||||
|
||||
case NR_RRCReconfigurationRequest:
|
||||
LOG_D(RRC,"!!!! Received a NR_RRCReconfigurationRequest from PC5 Controller \n");
|
||||
|
||||
LOG_D(RRC,"!!!! Send NR_RRCReconfigurationAccept to PC5 Controller \n");
|
||||
memset(send_buf, 0, BUFSIZE);
|
||||
// Send the RRCReconfigurationAccept
|
||||
printf("[RRC] ------------------------------------------------\n");
|
||||
printf("[RRC] Send NR_RRCReconfigurationAccept \n");
|
||||
|
||||
sl_ctrl_msg_send = calloc(1, sizeof(struct nr_sidelink_ctrl_element));
|
||||
sl_ctrl_msg_send->type = NR_RRCReconfigurationAccept; // send the OK back to controller
|
||||
sl_ctrl_msg_send->nr_sidelinkPrimitive.pc5_rrcreconfiguration_rsp = NR_RRC_RECONFIGURATION_OK;
|
||||
memcpy((void *)send_buf, (void *)sl_ctrl_msg_send, sizeof(struct nr_sidelink_ctrl_element));
|
||||
free(sl_ctrl_msg_send);
|
||||
|
||||
prose_addr_len = sizeof(prose_ctl_addr);
|
||||
n = sendto(ctrl_sock_fd, (char *)send_buf, sizeof(struct nr_sidelink_ctrl_element), 0, (struct sockaddr *)&prose_ctl_addr, prose_addr_len);
|
||||
if (n < 0){
|
||||
LOG_E(RRC, "ERROR: Failed to send NR_RRCReconfigurationAccept to PC5 Controller \n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
break;
|
||||
case NR_RRCReconfigurationSetup:
|
||||
LOG_I(RRC,"Received a NR_RRCReconfigurationSetup from PC5 Controller \n");
|
||||
|
||||
// Setup the Radio Bearer
|
||||
struct NR_SL_RadioBearerConfig_r16 *sl_RadioBearerConfig_r16 = calloc(1,sizeof(*sl_RadioBearerConfig_r16));
|
||||
|
||||
//Define received_data
|
||||
struct nr_sidelink_ctrl_element *msg = (struct nr_sidelink_ctrl_element *)receive_buf;
|
||||
NR_RRC_Configuration received_data = msg->nr_sidelinkPrimitive.pc5_rrc_config;
|
||||
uint8_t qfi = sl_ctrl_msg_recv->nr_sidelinkPrimitive.pc5_rrc_config.sl_radioBearerConfig.slrb_Uu_ConfigIndex_r16; //define QFI
|
||||
|
||||
//Jin update TOS for multi bearer
|
||||
uint8_t bearer_tos = 0x00; // default
|
||||
if (qfi == 3) bearer_tos = 0x10;
|
||||
if (qfi == 5) bearer_tos = 0x20;
|
||||
// add more as needed
|
||||
sl_add_qos_map(bearer_tos, qfi);
|
||||
|
||||
|
||||
sl_RadioBearerConfig_r16->slrb_Uu_ConfigIndex_r16 = received_data.sl_radioBearerConfig.slrb_Uu_ConfigIndex_r16;
|
||||
sl_RadioBearerConfig_r16->sl_SDAP_Config_r16 = NULL;
|
||||
sl_RadioBearerConfig_r16->sl_TransRange_r16 = NULL;
|
||||
sl_RadioBearerConfig_r16->sl_PDCP_Config_r16 = calloc(1, sizeof(*sl_RadioBearerConfig_r16->sl_PDCP_Config_r16));
|
||||
|
||||
sl_RadioBearerConfig_r16->sl_PDCP_Config_r16->sl_DiscardTimer_r16 = calloc(1,sizeof(*sl_RadioBearerConfig_r16->sl_PDCP_Config_r16->sl_DiscardTimer_r16));
|
||||
*sl_RadioBearerConfig_r16->sl_PDCP_Config_r16->sl_DiscardTimer_r16 = received_data.sl_radioBearerConfig.sl_PDCP_Config_r16.sl_DiscardTimer_r16;
|
||||
sl_RadioBearerConfig_r16->sl_PDCP_Config_r16->sl_PDCP_SN_Size_r16 = calloc(1,sizeof(*sl_RadioBearerConfig_r16->sl_PDCP_Config_r16->sl_PDCP_SN_Size_r16));
|
||||
*sl_RadioBearerConfig_r16->sl_PDCP_Config_r16->sl_PDCP_SN_Size_r16 = received_data.sl_radioBearerConfig.sl_PDCP_Config_r16.sl_PDCP_SN_Size_r16;
|
||||
sl_RadioBearerConfig_r16->sl_PDCP_Config_r16->sl_OutOfOrderDelivery = NULL;
|
||||
|
||||
// Setup the RLC Radio Bearer
|
||||
struct NR_SL_RLC_BearerConfig_r16 *sl_RLC_BearerConfig_r16 = calloc(1,sizeof(*sl_RLC_BearerConfig_r16));
|
||||
|
||||
sl_RLC_BearerConfig_r16->sl_RLC_BearerConfigIndex_r16 = received_data.sl_RLC_BearerConfig.sl_RLC_BearerConfigIndex_r16;
|
||||
sl_RLC_BearerConfig_r16->sl_ServedRadioBearer_r16 = calloc(1,sizeof(*sl_RLC_BearerConfig_r16->sl_ServedRadioBearer_r16));
|
||||
*sl_RLC_BearerConfig_r16->sl_ServedRadioBearer_r16 = received_data.sl_RLC_BearerConfig.sl_ServedRadioBearer_r16;
|
||||
sl_RLC_BearerConfig_r16->sl_RLC_Config_r16 = calloc(1,sizeof(*sl_RLC_BearerConfig_r16->sl_RLC_Config_r16));
|
||||
sl_RLC_BearerConfig_r16->sl_RLC_Config_r16->present = received_data.sl_RLC_BearerConfig.sl_RLC_Config_r16.present;
|
||||
sl_RLC_BearerConfig_r16->sl_RLC_Config_r16->choice.sl_UM_RLC_r16 = calloc(1,sizeof(*sl_RLC_BearerConfig_r16->sl_RLC_Config_r16->choice.sl_UM_RLC_r16));
|
||||
sl_RLC_BearerConfig_r16->sl_RLC_Config_r16->choice.sl_UM_RLC_r16->sl_SN_FieldLengthUM_r16 = calloc(1, sizeof(*sl_RLC_BearerConfig_r16->sl_RLC_Config_r16->choice.sl_UM_RLC_r16->sl_SN_FieldLengthUM_r16));
|
||||
|
||||
|
||||
*sl_RLC_BearerConfig_r16->sl_RLC_Config_r16->choice.sl_UM_RLC_r16->sl_SN_FieldLengthUM_r16=received_data.sl_RLC_BearerConfig.sl_RLC_Config_r16.sl_SN_FieldLengthUM_r16;
|
||||
// Logical Channel Config for default link
|
||||
sl_RLC_BearerConfig_r16->sl_MAC_LogicalChannelConfig_r16 = calloc(1,sizeof(*sl_RLC_BearerConfig_r16->sl_MAC_LogicalChannelConfig_r16));
|
||||
sl_RLC_BearerConfig_r16->sl_MAC_LogicalChannelConfig_r16->sl_Priority_r16 = received_data.sl_RLC_BearerConfig.sl_MAC_LogicalChannelConfig_r16.sl_Priority_r16;
|
||||
sl_RLC_BearerConfig_r16->sl_MAC_LogicalChannelConfig_r16->sl_PrioritisedBitRate_r16 = received_data.sl_RLC_BearerConfig.sl_MAC_LogicalChannelConfig_r16.sl_PrioritisedBitRate_r16;
|
||||
sl_RLC_BearerConfig_r16->sl_MAC_LogicalChannelConfig_r16->sl_BucketSizeDuration_r16 = received_data.sl_RLC_BearerConfig.sl_MAC_LogicalChannelConfig_r16.sl_BucketSizeDuration_r16;
|
||||
sl_RLC_BearerConfig_r16->sl_MAC_LogicalChannelConfig_r16->sl_ConfiguredGrantType1Allowed_r16 = NULL;
|
||||
sl_RLC_BearerConfig_r16->sl_MAC_LogicalChannelConfig_r16->sl_HARQ_FeedbackEnabled_r16 = calloc(1,sizeof(*sl_RLC_BearerConfig_r16->sl_MAC_LogicalChannelConfig_r16->sl_HARQ_FeedbackEnabled_r16));
|
||||
*sl_RLC_BearerConfig_r16->sl_MAC_LogicalChannelConfig_r16->sl_HARQ_FeedbackEnabled_r16 = received_data.sl_RLC_BearerConfig.sl_MAC_LogicalChannelConfig_r16.sl_HARQ_FeedbackEnabled_r16;
|
||||
sl_RLC_BearerConfig_r16->sl_MAC_LogicalChannelConfig_r16->sl_AllowedCG_List_r16 = NULL;
|
||||
sl_RLC_BearerConfig_r16->sl_MAC_LogicalChannelConfig_r16->sl_AllowedSCS_List_r16 = NULL;
|
||||
sl_RLC_BearerConfig_r16->sl_MAC_LogicalChannelConfig_r16->sl_LogicalChannelGroup_r16 = calloc(1,sizeof(*sl_RLC_BearerConfig_r16->sl_MAC_LogicalChannelConfig_r16->sl_LogicalChannelGroup_r16));
|
||||
*sl_RLC_BearerConfig_r16->sl_MAC_LogicalChannelConfig_r16->sl_LogicalChannelGroup_r16 = received_data.sl_RLC_BearerConfig.sl_MAC_LogicalChannelConfig_r16.sl_LogicalChannelGroup_r16;
|
||||
sl_RLC_BearerConfig_r16->sl_MAC_LogicalChannelConfig_r16->sl_SchedulingRequestId_r16 = NULL;
|
||||
sl_RLC_BearerConfig_r16->sl_MAC_LogicalChannelConfig_r16->sl_LogicalChannelSR_DelayTimerApplied_r16 = NULL;
|
||||
|
||||
// SL RadioBearers
|
||||
add_drb_sl(0, (NR_SL_RadioBearerConfig_r16_t *)sl_RadioBearerConfig_r16, 0, 0, NULL, NULL);
|
||||
//Jin add to update SDAP
|
||||
nr_sdap_entity_t *sdap_entity = nr_sdap_get_entity(module_id, 0);
|
||||
if (sdap_entity) {
|
||||
sdap_entity->qfi2drb_map_update(sdap_entity,
|
||||
qfi, // QFI value (e.g. 2 or 3)
|
||||
qfi, // DRB id = same as QFI
|
||||
true, // has_sdap_rx
|
||||
true); // has_sdap_tx
|
||||
LOG_I(RRC,"[SLC_C] SDAP: QFI=%d mapped to DRB=%d\n", qfi, qfi);
|
||||
} else {
|
||||
LOG_E(RRC,"[S LC_C] SDAP entity not found\n");
|
||||
}
|
||||
|
||||
|
||||
// Configure RLC
|
||||
nr_rlc_add_drb_sl(0, received_data.sl_radioBearerConfig.slrb_Uu_ConfigIndex_r16, (NR_SL_RLC_BearerConfig_r16_t *)sl_RLC_BearerConfig_r16);
|
||||
|
||||
// Done reconfiguration.
|
||||
LOG_I(RRC,"Send NR_RRCReconfigurationConfirm to PC5 Controller \n");
|
||||
memset(send_buf, 0, BUFSIZE);
|
||||
// Send the NR_RRCReconfigurationConfirm
|
||||
printf("[RRC] ------------------------------------------------\n");
|
||||
printf("[RRC] Send NR_RRCReconfigurationConfirm \n");
|
||||
|
||||
sl_ctrl_msg_send = calloc(1, sizeof(struct nr_sidelink_ctrl_element));
|
||||
sl_ctrl_msg_send->type = NR_RRCReconfigurationConfirm; // send the OK back to controller
|
||||
sl_ctrl_msg_send->nr_sidelinkPrimitive.pc5_rrcreconfiguration_rsp = NR_RRC_RECONFIGURATION_OK;
|
||||
memcpy((void *)send_buf, (void *)sl_ctrl_msg_send, sizeof(struct nr_sidelink_ctrl_element));
|
||||
free(sl_ctrl_msg_send);
|
||||
|
||||
prose_addr_len = sizeof(prose_ctl_addr);
|
||||
n = sendto(ctrl_sock_fd, (char *)send_buf, sizeof(struct nr_sidelink_ctrl_element), 0, (struct sockaddr *)&prose_ctl_addr, prose_addr_len);
|
||||
if (n < 0){
|
||||
LOG_E(RRC, "ERROR: Failed to send NR_RRCReconfigurationConfirm to PC5 Controller \n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
break;
|
||||
//Jin add for resourcepool
|
||||
case NR_ResourcePoolReconfigRequest:
|
||||
LOG_I(RRC, "[NR_ResourcePoolReconfigRequest] start_rb=%u rb_number=%u nsc=%u\n",
|
||||
sl_ctrl_msg_recv->nr_sidelinkPrimitive.rpool_config.start_rb,
|
||||
sl_ctrl_msg_recv->nr_sidelinkPrimitive.rpool_config.rb_number,
|
||||
sl_ctrl_msg_recv->nr_sidelinkPrimitive.rpool_config.num_subchannel);
|
||||
{
|
||||
uint8_t idx = 0; /* phase 1: always pool 0 */
|
||||
nr_sl_rpool_config[idx].start_rb = sl_ctrl_msg_recv->nr_sidelinkPrimitive.rpool_config.start_rb;
|
||||
nr_sl_rpool_config[idx].rb_number = sl_ctrl_msg_recv->nr_sidelinkPrimitive.rpool_config.rb_number;
|
||||
nr_sl_rpool_config[idx].num_subchannel = sl_ctrl_msg_recv->nr_sidelinkPrimitive.rpool_config.num_subchannel;
|
||||
nr_sl_rpool_config[idx].valid = 1;
|
||||
LOG_I(RRC, "[SLC] rpool[%u] updated: start=%u rb=%u nsc=%u\n",
|
||||
idx,
|
||||
nr_sl_rpool_config[idx].start_rb,
|
||||
nr_sl_rpool_config[idx].rb_number,
|
||||
nr_sl_rpool_config[idx].num_subchannel);
|
||||
}
|
||||
memset(send_buf, 0, BUFSIZE);
|
||||
sl_ctrl_msg_send = calloc(1, sizeof(struct nr_sidelink_ctrl_element));
|
||||
sl_ctrl_msg_send->type = NR_ResourcePoolReconfigConfirm;
|
||||
sl_ctrl_msg_send->nr_sidelinkPrimitive.rpool_config =
|
||||
sl_ctrl_msg_recv->nr_sidelinkPrimitive.rpool_config;
|
||||
memcpy((void *)send_buf, (void *)sl_ctrl_msg_send,
|
||||
sizeof(struct nr_sidelink_ctrl_element));
|
||||
free(sl_ctrl_msg_send);
|
||||
prose_addr_len = sizeof(prose_ctl_addr);
|
||||
n = sendto(ctrl_sock_fd, (char *)send_buf,
|
||||
sizeof(struct nr_sidelink_ctrl_element), 0,
|
||||
(struct sockaddr *)&prose_ctl_addr, prose_addr_len);
|
||||
if (n < 0) {
|
||||
LOG_E(RRC, "ERROR: Failed to send NR_ResourcePoolReconfigConfirm\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
free (sl_ctrl_msg_recv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -263,5 +263,202 @@ typedef struct NR_UE_RRC_INST_s {
|
||||
|
||||
} NR_UE_RRC_INST_t;
|
||||
|
||||
// NR_PC5 Controller
|
||||
|
||||
//Primitives
|
||||
#define NR_SESSION_INIT_REQ 1
|
||||
#define NR_UE_STATUS_INFO 2
|
||||
#define NR_GROUP_COMMUNICATION_ESTABLISH_REQ 3
|
||||
#define NR_GROUP_COMMUNICATION_ESTABLISH_RSP 4
|
||||
#define NR_DIRECT_COMMUNICATION_ESTABLISH_REQ 5
|
||||
#define NR_DIRECT_COMMUNICATION_ESTABLISH_RSP 6
|
||||
#define NR_GROUP_COMMUNICATION_RELEASE_REQ 7
|
||||
#define NR_GROUP_COMMUNICATION_RELEASE_RSP 8
|
||||
#define NR_DIRECT_COMMUNICATION_RELEASE_REQ 9
|
||||
#define NR_DIRECT_COMMUNICATION_RELEASE_RSP 10
|
||||
#define NR_PC5S_ESTABLISH_REQ 11
|
||||
#define NR_PC5S_ESTABLISH_RSP 12
|
||||
#define NR_PC5_DISCOVERY_MESSAGE 13
|
||||
#define NR_PC5S_RELEASE_REQ 14
|
||||
#define NR_PC5S_RELEASE_RSP 15
|
||||
#define NR_MACReconfigurationRequest 16
|
||||
#define NR_MACReconfigurationConfirm 17
|
||||
#define NR_RRCReconfigurationRequest 18
|
||||
#define NR_RRCReconfigurationAccept 19
|
||||
#define NR_RRCReconfigurationSetup 20
|
||||
#define NR_RRCReconfigurationConfirm 21
|
||||
#define NR_PC5_DISCOVERY_PAYLOAD_SIZE 29
|
||||
#define NR_PC5_SIGNALLING_PAYLOAD_SIZE 100 //should be updated with a correct value
|
||||
//Jin add for Rpool
|
||||
#define NR_ResourcePoolReconfigRequest 22
|
||||
#define NR_ResourcePoolReconfigConfirm 23
|
||||
|
||||
|
||||
//#define DEBUG_CTRL_SOCKET
|
||||
#define NR_CONTROL_SOCKET_PORT_NO 5555
|
||||
|
||||
//#define DEBUG_SCG_CONFIG 1
|
||||
|
||||
typedef enum {
|
||||
NR_UE_STATE_OFF_NETWORK,
|
||||
NR_UE_STATE_ON_NETWORK
|
||||
} NR_SL_UE_STATE_t;
|
||||
|
||||
typedef enum {
|
||||
NR_GROUP_COMMUNICATION_RELEASE_OK = 0,
|
||||
NR_GROUP_COMMUNICATION_RELEASE_FAILURE
|
||||
} NR_Group_Communication_Status_t;
|
||||
|
||||
typedef enum {
|
||||
NR_DIRECT_COMMUNICATION_RELEASE_OK = 0,
|
||||
NR_DIRECT_COMMUNICATION_RELEASE_FAILURE
|
||||
} NR_Direct_Communication_Status_t;
|
||||
|
||||
typedef enum {
|
||||
NR_PC5S_RELEASE_OK = 0,
|
||||
NR_PC5S_RELEASE_FAILURE
|
||||
} NR_PC5S_Release_Status_t;
|
||||
|
||||
struct NR_GroupCommunicationEstablishReq {
|
||||
uint32_t sourceL2Id;
|
||||
uint32_t groupL2Id;
|
||||
uint32_t groupIpAddress;
|
||||
uint8_t pqi;
|
||||
};
|
||||
|
||||
struct NR_GroupCommunicationReleaseReq {
|
||||
uint32_t sourceL2Id;
|
||||
uint32_t groupL2Id;
|
||||
int slrb_id;
|
||||
};
|
||||
|
||||
struct NR_DirectCommunicationEstablishReq {
|
||||
uint32_t sourceL2Id;
|
||||
uint32_t destinationL2Id;
|
||||
uint8_t pqi;
|
||||
};
|
||||
|
||||
struct NR_PC5SEstablishReq {
|
||||
uint8_t type;
|
||||
uint32_t sourceL2Id;
|
||||
uint32_t destinationL2Id;
|
||||
};
|
||||
|
||||
struct NR_PC5SEstablishRsp {
|
||||
uint32_t slrbid_lcid28;
|
||||
uint32_t slrbid_lcid29;
|
||||
uint32_t slrbid_lcid30;
|
||||
};
|
||||
|
||||
//PC5_DISCOVERY MESSAGE
|
||||
typedef struct {
|
||||
unsigned char payload[NR_PC5_DISCOVERY_PAYLOAD_SIZE];
|
||||
uint32_t measuredPower;
|
||||
} __attribute__((__packed__)) NR_PC5DiscoveryMessage ;
|
||||
|
||||
//
|
||||
// Section for the E5 Agent scheduler configuration
|
||||
//
|
||||
|
||||
// UE scheduler configuration
|
||||
typedef struct {
|
||||
uint8_t action; // 0 = add, 1 = release
|
||||
uint8_t sfid; // subframe ID allocated to the UE
|
||||
} NR_RBMapping;
|
||||
|
||||
// message structure to be sent
|
||||
typedef struct {
|
||||
NR_RBMapping map;
|
||||
} NR_Scheduler_Configuration;
|
||||
|
||||
//parameters for scheduler
|
||||
typedef struct {
|
||||
uint8_t sfid[MAX_UE_NR_CAPABILITY_SIZE]; // slot index per UE (indexed by ue_id)
|
||||
uint8_t action; // 1=active, 0=released
|
||||
uint8_t valid; // 1=SLC_C has configured this
|
||||
} NR_SL_SchedulerConfig_t;
|
||||
|
||||
extern NR_SL_SchedulerConfig_t nr_sl_scheduler_config;
|
||||
|
||||
|
||||
//Jin add for resourcepool
|
||||
#define MAX_SL_POOLS 2 /* phase 1 uses index 0 only; index 1 reserved for future slicing */
|
||||
#define MAX_SL_UE 8
|
||||
typedef struct {
|
||||
uint8_t start_rb;
|
||||
uint8_t rb_number;
|
||||
uint8_t num_subchannel;
|
||||
uint8_t valid;
|
||||
} NR_SL_RpoolConfig_t;
|
||||
extern NR_SL_RpoolConfig_t nr_sl_rpool_config[MAX_SL_POOLS];
|
||||
extern uint8_t nr_sl_ue_pool_assignment[MAX_SL_UE];
|
||||
|
||||
|
||||
//
|
||||
// Section of the E5 agent adjusting QoS
|
||||
//
|
||||
|
||||
typedef struct {
|
||||
int sl_DiscardTimer_r16;
|
||||
int sl_PDCP_SN_Size_r16;
|
||||
} Serialized_NR_SL_PDCP_Config_r16;
|
||||
|
||||
typedef struct {
|
||||
int slrb_Uu_ConfigIndex_r16;
|
||||
Serialized_NR_SL_PDCP_Config_r16 sl_PDCP_Config_r16;
|
||||
} Serialized_NR_SL_RadioBearerConfig_r16;
|
||||
|
||||
typedef struct {
|
||||
int present;
|
||||
int sl_SN_FieldLengthUM_r16;
|
||||
} Serialized_NR_SL_RLC_Config_r16;
|
||||
|
||||
typedef struct {
|
||||
int sl_Priority_r16;
|
||||
int sl_PrioritisedBitRate_r16;
|
||||
int sl_BucketSizeDuration_r16;
|
||||
int sl_HARQ_FeedbackEnabled_r16;
|
||||
int sl_LogicalChannelGroup_r16;
|
||||
} Serialized_NR_SL_MAC_LogicalChannelConfig_r16;
|
||||
|
||||
typedef struct {
|
||||
int sl_RLC_BearerConfigIndex_r16;
|
||||
int sl_ServedRadioBearer_r16;
|
||||
Serialized_NR_SL_RLC_Config_r16 sl_RLC_Config_r16;
|
||||
Serialized_NR_SL_MAC_LogicalChannelConfig_r16 sl_MAC_LogicalChannelConfig_r16;
|
||||
} Serialized_NR_SL_RLC_BearerConfig_r16;
|
||||
|
||||
typedef enum {
|
||||
NR_RRC_RECONFIGURATION_OK = 0,
|
||||
NR_RRC_RECONFIGURATION_FAILURE
|
||||
} NR_PC5_RRCReconfiguration_Status_t;
|
||||
|
||||
typedef struct {
|
||||
Serialized_NR_SL_RadioBearerConfig_r16 sl_radioBearerConfig;
|
||||
Serialized_NR_SL_RLC_BearerConfig_r16 sl_RLC_BearerConfig;
|
||||
} NR_RRC_Configuration;
|
||||
|
||||
// end NR_PC5 Controller section
|
||||
|
||||
struct nr_sidelink_ctrl_element {
|
||||
unsigned short type;
|
||||
union {
|
||||
struct NR_GroupCommunicationEstablishReq group_comm_establish_req;
|
||||
struct NR_DirectCommunicationEstablishReq direct_comm_establish_req;
|
||||
NR_Group_Communication_Status_t group_comm_release_rsp;
|
||||
NR_Direct_Communication_Status_t direct_comm_release_rsp;
|
||||
NR_PC5S_Release_Status_t pc5s_release_rsp;
|
||||
NR_SL_UE_STATE_t ue_state;
|
||||
int slrb_id;
|
||||
struct NR_PC5SEstablishReq pc5s_establish_req;
|
||||
struct NR_PC5SEstablishRsp pc5s_establish_rsp;
|
||||
NR_PC5DiscoveryMessage pc5_discovery_message;
|
||||
NR_Scheduler_Configuration pc5_scheduler_config;
|
||||
NR_RRC_Configuration pc5_rrc_config;
|
||||
NR_PC5_RRCReconfiguration_Status_t pc5_rrcreconfiguration_rsp;
|
||||
NR_SL_RpoolConfig_t rpool_config;
|
||||
} nr_sidelinkPrimitive;
|
||||
};
|
||||
|
||||
#endif
|
||||
/** @} */
|
||||
|
||||
@@ -177,6 +177,10 @@ void nr_rrc_handle_SetupRelease_RLF_TimersAndConstants(NR_UE_RRC_INST_t *rrc,
|
||||
int configure_NR_SL_Preconfig(uint8_t id,int sync_source);
|
||||
void nr_UE_configure_Sidelink(uint8_t id, uint8_t is_sync_source, ueinfo_t *ueinfo);
|
||||
|
||||
// NR_PC5 Controller
|
||||
void *nr_rrc_control_socket_thread_fct(void *arg);
|
||||
// end
|
||||
|
||||
/** @}*/
|
||||
#endif
|
||||
|
||||
|
||||
@@ -30,11 +30,12 @@
|
||||
#include "rrc_defs.h"
|
||||
#include "rrc_vars.h"
|
||||
#include "LAYER2/NR_MAC_UE/mac_proto.h"
|
||||
#include "LAYER2/NR_MAC_UE/mac_defs.h" //jin get num.UE
|
||||
#include "RRC/NAS/nas_config.h"
|
||||
#include "executables/nr-uesoftmodem.h"
|
||||
#include "LAYER2/nr_rlc/nr_rlc_oai_api.h"
|
||||
#include "LAYER2/nr_pdcp/nr_pdcp_oai_api.h"
|
||||
|
||||
#include <inttypes.h> //JIn add
|
||||
#define GNSS_SUPPORT 0
|
||||
|
||||
#define SL_SYNC_SOURCE_NONE 0 //No sync source selected
|
||||
@@ -626,7 +627,8 @@ void nr_UE_configure_Sidelink(uint8_t id, uint8_t is_sync_source, ueinfo_t *uein
|
||||
nas_config(1 + ueinfo->srcid, ueinfo->thirdOctet, ueinfo->fourthOctet, "oai_sl_tun");
|
||||
nr_rrc_mac_config_req_sl_preconfig(id, sl_preconfig, sync_source);
|
||||
|
||||
|
||||
//JIn origin : comment
|
||||
/*
|
||||
// SL RadioBearers
|
||||
for (int i=0; i<sl_preconfig->sidelinkPreconfigNR_r16.sl_RadioBearerPreConfigList_r16->list.count; i++) {
|
||||
add_drb_sl(ueinfo->srcid, (NR_SL_RadioBearerConfig_r16_t *)sl_preconfig->sidelinkPreconfigNR_r16.sl_RadioBearerPreConfigList_r16->list.array[i], 0, 0, NULL, NULL);
|
||||
@@ -635,6 +637,52 @@ void nr_UE_configure_Sidelink(uint8_t id, uint8_t is_sync_source, ueinfo_t *uein
|
||||
for (int i=0; i<sl_preconfig->sidelinkPreconfigNR_r16.sl_RLC_BearerPreConfigList_r16->list.count; i++) {
|
||||
nr_rlc_add_drb_sl(ueinfo->srcid, 1, (NR_SL_RLC_BearerConfig_r16_t *)sl_preconfig->sidelinkPreconfigNR_r16.sl_RLC_BearerPreConfigList_r16->list.array[i]);
|
||||
}
|
||||
*/ //JIn end
|
||||
|
||||
//Jin replace for multiple UEs : ID Syn-ref 0 , then UE1 1, UE2 2, hardcoded for now...
|
||||
void create_for(ue_id_t sid)
|
||||
{
|
||||
/* SL RadioBearers for sid */
|
||||
for (int i = 0;
|
||||
i < sl_preconfig->sidelinkPreconfigNR_r16.sl_RadioBearerPreConfigList_r16->list.count;
|
||||
i++) {
|
||||
add_drb_sl(sid,
|
||||
(NR_SL_RadioBearerConfig_r16_t *)
|
||||
sl_preconfig->sidelinkPreconfigNR_r16.sl_RadioBearerPreConfigList_r16->list.array[i],
|
||||
0, 0, NULL, NULL);
|
||||
}
|
||||
|
||||
/* RLC bearers for sid */
|
||||
for (int i = 0;
|
||||
i < sl_preconfig->sidelinkPreconfigNR_r16.sl_RLC_BearerPreConfigList_r16->list.count;
|
||||
i++) {
|
||||
nr_rlc_add_drb_sl(sid, 1,
|
||||
(NR_SL_RLC_BearerConfig_r16_t *)
|
||||
sl_preconfig->sidelinkPreconfigNR_r16.sl_RLC_BearerPreConfigList_r16->list.array[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Always provision self */
|
||||
create_for(ueinfo->srcid);
|
||||
|
||||
/* Provision peers deterministically */
|
||||
/* //Comment only 2 UES
|
||||
if (ueinfo->srcid == 0) {
|
||||
create_for(1);
|
||||
create_for(2);
|
||||
} else {
|
||||
create_for(0);
|
||||
}*/
|
||||
//Update to more UEs
|
||||
for (int peer = 0; peer <= CUR_SL_UE_CONNECTIONS; peer++) {
|
||||
if (peer == (int)ueinfo->srcid)
|
||||
continue; /* skip self — already done above */
|
||||
create_for(peer);
|
||||
}
|
||||
|
||||
//Jin end
|
||||
|
||||
|
||||
//TBD.. These should be chosen by RRC according to 3GPP 38.331 RRC specification.
|
||||
//Currently hardcoding the values to these
|
||||
uint16_t slss_id = 671, ssb_ta_index = 1;
|
||||
|
||||
@@ -71,8 +71,9 @@ void sdap_data_ind(rb_id_t pdcp_entity,
|
||||
int size) {
|
||||
nr_sdap_entity_t *sdap_entity;
|
||||
sdap_entity = nr_sdap_get_entity(ue_id, pdusession_id);
|
||||
|
||||
|
||||
if (sdap_entity == NULL) {
|
||||
// ADD THIS LOG FIRST THING:
|
||||
LOG_E(SDAP, "%s:%d:%s: Entity not found for ue rnti/ue_id: %lx and pdusession id: %d\n", __FILE__, __LINE__, __FUNCTION__, ue_id, pdusession_id);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "nr_sdap.h"
|
||||
#include "nr_sdap_entity.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "common/openairinterface5g_limits.h" //jIN ADD
|
||||
#include <openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h>
|
||||
#include <openair3/ocp-gtpu/gtp_itf.h>
|
||||
#include "openair2/LAYER2/nr_pdcp/nr_pdcp_ue_manager.h"
|
||||
@@ -30,6 +31,8 @@
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
|
||||
typedef struct {
|
||||
nr_sdap_entity_t *sdap_entity_llist;
|
||||
} nr_sdap_entity_info;
|
||||
@@ -88,7 +91,7 @@ static bool nr_sdap_tx_entity(nr_sdap_entity_t *entity,
|
||||
if(pdcp_entity){
|
||||
sdap_drb_id = pdcp_entity;
|
||||
pdcp_ent_has_sdap = entity->qfi2drb_table[qfi].has_sdap_tx;
|
||||
LOG_D(SDAP, "TX - QFI: %u is mapped to DRB ID: %ld\n", qfi, entity->qfi2drb_table[qfi].drb_id);
|
||||
LOG_I(SDAP, "TX - QFI: %u is mapped to DRB ID: %ld\n", qfi, entity->qfi2drb_table[qfi].drb_id);
|
||||
}
|
||||
|
||||
if(!pdcp_ent_has_sdap){
|
||||
@@ -149,9 +152,9 @@ static bool nr_sdap_tx_entity(nr_sdap_entity_t *entity,
|
||||
/* Add the SDAP UL Header to the buffer */
|
||||
memcpy(&sdap_buf[0], &sdap_hdr, SDAP_HDR_LENGTH);
|
||||
memcpy(&sdap_buf[SDAP_HDR_LENGTH], sdu_buffer, sdu_buffer_size);
|
||||
LOG_D(SDAP, "TX Entity QFI: %u \n", sdap_hdr.QFI);
|
||||
LOG_D(SDAP, "TX Entity R: %u \n", sdap_hdr.R);
|
||||
LOG_D(SDAP, "TX Entity DC: %u \n", sdap_hdr.DC);
|
||||
LOG_I(SDAP, "TX Entity QFI: %u \n", sdap_hdr.QFI);
|
||||
LOG_I(SDAP, "TX Entity R: %u \n", sdap_hdr.R);
|
||||
LOG_I(SDAP, "TX Entity DC: %u \n", sdap_hdr.DC);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -188,7 +191,7 @@ static void nr_sdap_rx_entity(nr_sdap_entity_t *entity,
|
||||
int size) {
|
||||
/* The offset of the SDAP header, it might be 0 if has_sdap_rx is not true in the pdcp entity. */
|
||||
int offset=0;
|
||||
|
||||
LOG_I(SDAP, "[JIN-SDAP-RX] !!!!!!!!! ue_id=%lu is_gnb=%d pdcp_entity=%ld\n", ue_id, is_gnb, pdcp_entity);
|
||||
if (is_gnb) { // gNB
|
||||
if (has_sdap_rx) { // Handling the SDAP Header
|
||||
offset = SDAP_HDR_LENGTH;
|
||||
@@ -233,34 +236,46 @@ static void nr_sdap_rx_entity(nr_sdap_entity_t *entity,
|
||||
* if the DRB from which this SDAP data PDU is received is configured by RRC with the presence of SDAP header.
|
||||
*/
|
||||
if (has_sdap_rx) { // Handling the SDAP Header
|
||||
offset = SDAP_HDR_LENGTH;
|
||||
unsigned char first = (unsigned char)buf[0];
|
||||
if (first == 0x45 || first == 0x60) {
|
||||
// no SDAP header present despite has_sdap_rx=true
|
||||
offset = 0;
|
||||
LOG_I(SDAP, "[SDAP-RX] No SDAP header detected, offset=0\n");
|
||||
} else {
|
||||
offset = SDAP_HDR_LENGTH;
|
||||
nr_sdap_ul_hdr_t *sdap_hdr = (nr_sdap_ul_hdr_t *)buf;
|
||||
LOG_I(SDAP, "RX Entity Received QFI : %u\n", sdap_hdr->QFI);
|
||||
}
|
||||
// //offset = SDAP_HDR_LENGTH;
|
||||
/*
|
||||
* TS 37.324 5.2 Data transfer
|
||||
* 5.2.2 Downlink
|
||||
* retrieve the SDAP SDU from the DL SDAP data PDU as specified in the subclause 6.2.2.2.
|
||||
*/
|
||||
nr_sdap_dl_hdr_t *sdap_hdr = (nr_sdap_dl_hdr_t *)buf;
|
||||
LOG_D(SDAP, "RX Entity Received QFI : %u\n", sdap_hdr->QFI);
|
||||
LOG_D(SDAP, "RX Entity Received RQI : %u\n", sdap_hdr->RQI);
|
||||
LOG_D(SDAP, "RX Entity Received RDI : %u\n", sdap_hdr->RDI);
|
||||
//nr_sdap_dl_hdr_t *sdap_hdr = (nr_sdap_dl_hdr_t *)buf;
|
||||
// // nr_sdap_ul_hdr_t *sdap_hdr = (nr_sdap_ul_hdr_t *)buf; // sidelink: always parse as UL header since both peers use UL format
|
||||
// //LOG_I(SDAP, "RX Entity Received QFI : %u\n", sdap_hdr->QFI);
|
||||
//LOG_I(SDAP, "RX Entity Received RQI : %u\n", sdap_hdr->RQI); //Jin skip RQI
|
||||
//LOG_I(SDAP, "RX Entity Received RDI : %u\n", sdap_hdr->RDI); //Jin skip RQI
|
||||
|
||||
/*
|
||||
* TS 37.324 5.2 Data transfer
|
||||
* 5.2.2 Downlink
|
||||
* Perform reflective QoS flow to DRB mapping as specified in the subclause 5.3.2.
|
||||
*/
|
||||
if(sdap_hdr->RDI == SDAP_REFLECTIVE_MAPPING) {
|
||||
LOG_D(SDAP, "RX - Performing Reflective Mapping\n");
|
||||
//Jin : skip RDI
|
||||
//if(sdap_hdr->RDI == SDAP_REFLECTIVE_MAPPING) {
|
||||
// LOG_I(SDAP, "RX - Performing Reflective Mapping\n");
|
||||
/*
|
||||
* TS 37.324 5.3 QoS flow to DRB Mapping
|
||||
* 5.3.2 Reflective mapping
|
||||
* If there is no stored QoS flow to DRB mapping rule for the QoS flow and a default DRB is configured.
|
||||
*/
|
||||
if(!entity->qfi2drb_table[sdap_hdr->QFI].drb_id && entity->default_drb){
|
||||
nr_sdap_ul_hdr_t sdap_ctrl_pdu = entity->sdap_construct_ctrl_pdu(sdap_hdr->QFI);
|
||||
rb_id_t sdap_ctrl_pdu_drb = entity->sdap_map_ctrl_pdu(entity, pdcp_entity, SDAP_CTRL_PDU_MAP_DEF_DRB, sdap_hdr->QFI);
|
||||
entity->sdap_submit_ctrl_pdu(ue_id, sdap_ctrl_pdu_drb, sdap_ctrl_pdu);
|
||||
}
|
||||
// if(!entity->qfi2drb_table[sdap_hdr->QFI].drb_id && entity->default_drb){
|
||||
// nr_sdap_ul_hdr_t sdap_ctrl_pdu = entity->sdap_construct_ctrl_pdu(sdap_hdr->QFI);
|
||||
// rb_id_t sdap_ctrl_pdu_drb = entity->sdap_map_ctrl_pdu(entity, pdcp_entity, SDAP_CTRL_PDU_MAP_DEF_DRB, sdap_hdr->QFI);
|
||||
// entity->sdap_submit_ctrl_pdu(ue_id, sdap_ctrl_pdu_drb, sdap_ctrl_pdu);
|
||||
// }
|
||||
|
||||
/*
|
||||
* TS 37.324 5.3 QoS flow to DRB mapping
|
||||
@@ -271,28 +286,29 @@ static void nr_sdap_rx_entity(nr_sdap_entity_t *entity,
|
||||
* the DRB according to the stored QoS flow to DRB mapping rule is configured by RRC
|
||||
* with the presence of UL SDAP header
|
||||
*/
|
||||
if (pdcp_entity != entity->qfi2drb_table[sdap_hdr->QFI].drb_id) {
|
||||
nr_sdap_ul_hdr_t sdap_ctrl_pdu = entity->sdap_construct_ctrl_pdu(sdap_hdr->QFI);
|
||||
rb_id_t sdap_ctrl_pdu_drb = entity->sdap_map_ctrl_pdu(entity, pdcp_entity, SDAP_CTRL_PDU_MAP_RULE_DRB, sdap_hdr->QFI);
|
||||
entity->sdap_submit_ctrl_pdu(ue_id, sdap_ctrl_pdu_drb, sdap_ctrl_pdu);
|
||||
}
|
||||
//if (pdcp_entity != entity->qfi2drb_table[sdap_hdr->QFI].drb_id) {
|
||||
// nr_sdap_ul_hdr_t sdap_ctrl_pdu = entity->sdap_construct_ctrl_pdu(sdap_hdr->QFI);
|
||||
// rb_id_t sdap_ctrl_pdu_drb = entity->sdap_map_ctrl_pdu(entity, pdcp_entity, SDAP_CTRL_PDU_MAP_RULE_DRB, sdap_hdr->QFI);
|
||||
// entity->sdap_submit_ctrl_pdu(ue_id, sdap_ctrl_pdu_drb, sdap_ctrl_pdu);
|
||||
//}
|
||||
|
||||
/*
|
||||
* TS 37.324 5.3 QoS flow to DRB Mapping
|
||||
* 5.3.2 Reflective mapping
|
||||
* store the QoS flow to DRB mapping of the DL SDAP data PDU as the QoS flow to DRB mapping rule for the UL.
|
||||
*/
|
||||
entity->qfi2drb_table[sdap_hdr->QFI].drb_id = pdcp_entity;
|
||||
}
|
||||
//entity->qfi2drb_table[sdap_hdr->QFI].drb_id = pdcp_entity;
|
||||
//} //Jin comment end
|
||||
|
||||
/*
|
||||
* TS 37.324 5.2 Data transfer
|
||||
* 5.2.2 Downlink
|
||||
* perform RQI handling as specified in the subclause 5.4
|
||||
*/
|
||||
if(sdap_hdr->RQI == SDAP_RQI_HANDLING) {
|
||||
LOG_W(SDAP, "UE - TODD 5.4\n");
|
||||
}
|
||||
//Jin : skip RQI
|
||||
//if(sdap_hdr->RQI == SDAP_RQI_HANDLING) {
|
||||
// LOG_W(SDAP, "UE - TODD 5.4\n");
|
||||
//}
|
||||
} /* else - retrieve the SDAP SDU from the DL SDAP data PDU as specified in the subclause 6.2.2.1 */
|
||||
|
||||
/*
|
||||
@@ -301,10 +317,32 @@ static void nr_sdap_rx_entity(nr_sdap_entity_t *entity,
|
||||
* deliver the retrieved SDAP SDU to the upper layer.
|
||||
*/
|
||||
extern int nas_sock_fd[];
|
||||
int len = write(nas_sock_fd[0], &buf[offset], size-offset);
|
||||
LOG_D(SDAP, "RX Entity len : %d\n", len);
|
||||
LOG_D(SDAP, "RX Entity size : %d\n", size);
|
||||
LOG_D(SDAP, "RX Entity offset : %d\n", offset);
|
||||
|
||||
//int len = write(nas_sock_fd[0], &buf[offset], size-offset); //Jin origin replace by below for MultiUES
|
||||
// Find the valid TUN file descriptor for this UE
|
||||
int ue_index = -1;
|
||||
for (int i = 0; i < NUMBER_OF_UE_MAX * 2; i++) {
|
||||
if (nas_sock_fd[i] > 0) {
|
||||
ue_index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (ue_index < 0) {
|
||||
LOG_E(SDAP, "No valid TUN interface found!\n");
|
||||
return;
|
||||
}
|
||||
LOG_D(SDAP, "[JIN DEBUG -------- TUN-WRITE][FD-DEBUG] ue_id=%lu ue_index=%d nas_sock_fd[%d]=%d\n", ue_id, ue_index, ue_index, nas_sock_fd[ue_index]);
|
||||
LOG_I(SDAP, "[BUF] first_byte=0x%02x size-offset=%d\n", (unsigned char)buf[offset], size-offset);
|
||||
int len = write(nas_sock_fd[ue_index], &buf[offset], size-offset);
|
||||
LOG_I(SDAP, "[JIN DEBUG -------- FD-DEBUG] ue_index=%d fd_value=%d write=%d errno=%d\n", ue_index, nas_sock_fd[ue_index], len, errno);
|
||||
//Jin end
|
||||
|
||||
|
||||
LOG_I(SDAP, "RX Entity len : %d\n", len);
|
||||
LOG_I(SDAP, "RX Entity size : %d\n", size);
|
||||
LOG_I(SDAP, "RX Entity offset : %d\n", offset);
|
||||
|
||||
if (len != size-offset)
|
||||
LOG_E(SDAP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
@@ -320,9 +358,9 @@ void nr_sdap_qfi2drb_map_update(nr_sdap_entity_t *entity, uint8_t qfi, rb_id_t d
|
||||
entity->qfi2drb_table[qfi].drb_id = drb;
|
||||
entity->qfi2drb_table[qfi].has_sdap_rx = has_sdap_rx;
|
||||
entity->qfi2drb_table[qfi].has_sdap_tx = has_sdap_tx;
|
||||
LOG_D(SDAP, "Updated mapping: QFI %u -> DRB %ld \n", qfi, entity->qfi2drb_table[qfi].drb_id);
|
||||
LOG_I(SDAP, "Updated mapping: QFI %u -> DRB %ld \n", qfi, entity->qfi2drb_table[qfi].drb_id);
|
||||
} else {
|
||||
LOG_D(SDAP, "Map updated failed, QFI: %u, DRB: %ld\n", qfi, drb);
|
||||
LOG_I(SDAP, "Map updated failed, QFI: %u, DRB: %ld\n", qfi, drb);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -438,7 +476,7 @@ nr_sdap_entity_t *new_nr_sdap_entity(int is_gnb, bool has_sdap_rx, bool has_sdap
|
||||
sdap_entity->qfi2drb_map_update = nr_sdap_qfi2drb_map_update;
|
||||
sdap_entity->qfi2drb_map_delete = nr_sdap_qfi2drb_map_del;
|
||||
sdap_entity->qfi2drb_map = nr_sdap_qfi2drb_map;
|
||||
|
||||
|
||||
if(is_defaultDRB) {
|
||||
sdap_entity->default_drb = drb_identity;
|
||||
LOG_I(SDAP, "Default DRB for the created SDAP entity: %ld \n", sdap_entity->default_drb);
|
||||
@@ -450,7 +488,7 @@ nr_sdap_entity_t *new_nr_sdap_entity(int is_gnb, bool has_sdap_rx, bool has_sdap
|
||||
sdap_entity->qfi2drb_map_update(sdap_entity, qfi, sdap_entity->default_drb, has_sdap_rx, has_sdap_tx);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sdap_entity->next_entity = sdap_info.sdap_entity_llist;
|
||||
sdap_info.sdap_entity_llist = sdap_entity;
|
||||
return sdap_entity;
|
||||
|
||||
@@ -1,10 +1,19 @@
|
||||
find_library(ZeroMQ zmq REQUIRED)
|
||||
add_library(rfsimulator MODULE
|
||||
simulator.c
|
||||
apply_channelmod.c
|
||||
../../openair1/PHY/TOOLS/signal_energy.c
|
||||
simulator.c
|
||||
apply_channelmod.c
|
||||
../../openair1/PHY/TOOLS/signal_energy.c
|
||||
)
|
||||
target_link_libraries(rfsimulator PRIVATE SIMU)
|
||||
find_package(PkgConfig REQUIRED)
|
||||
|
||||
pkg_check_modules(ZMQ REQUIRED libzmq)
|
||||
|
||||
target_include_directories(rfsimulator PRIVATE ${ZMQ_INCLUDE_DIRS})
|
||||
|
||||
set_target_properties(rfsimulator PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||
|
||||
add_executable(replay_node stored_node.c)
|
||||
target_link_libraries (replay_node minimal_lib)
|
||||
target_link_libraries(rfsimulator PRIVATE SIMU ${ZMQ_LIBRARIES})
|
||||
|
||||
add_executable(broker broker.c)
|
||||
target_link_libraries(broker PRIVATE ${ZMQ_LIBRARIES})
|
||||
set_target_properties(broker PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||
|
||||
26
radio/rfsimulator/broker.c
Normal file
26
radio/rfsimulator/broker.c
Normal file
@@ -0,0 +1,26 @@
|
||||
#include <zmq.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main() {
|
||||
void *context = zmq_ctx_new();
|
||||
int io_threads = 2;
|
||||
zmq_ctx_set(context, ZMQ_IO_THREADS, io_threads);
|
||||
// XSUB socket for publishers
|
||||
void *xsub_socket = zmq_socket(context, ZMQ_XSUB);
|
||||
zmq_bind(xsub_socket, "tcp://*:5555");
|
||||
|
||||
// XPUB socket for subscribers
|
||||
void *xpub_socket = zmq_socket(context, ZMQ_XPUB);
|
||||
zmq_bind(xpub_socket, "tcp://*:5556");
|
||||
printf("Broker is running using zmq proxy\n");
|
||||
// Proxy between XSUB and XPUB sockets
|
||||
zmq_proxy(xsub_socket, xpub_socket, NULL);
|
||||
|
||||
// Clean up
|
||||
zmq_close(xsub_socket);
|
||||
zmq_close(xpub_socket);
|
||||
zmq_ctx_destroy(context);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -40,7 +40,7 @@
|
||||
#include <errno.h>
|
||||
#include <sys/epoll.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <zmq.h>
|
||||
#include <common/utils/assertions.h>
|
||||
#include <common/utils/LOG/log.h>
|
||||
#include <common/utils/load_module_shlib.h>
|
||||
@@ -52,18 +52,22 @@
|
||||
#define CHANNELMOD_DYNAMICLOAD
|
||||
#include <openair1/SIMULATION/TOOLS/sim.h>
|
||||
#include "rfsimulator.h"
|
||||
#include <sys/time.h>
|
||||
#define XSUBPORT 5555 // default ports for this simulator in pubsub
|
||||
#define XPUBPORT 5556
|
||||
|
||||
#define PORT 4043 //default TCP port for this simulator
|
||||
#define CirSize 6144000 // 100ms is enough
|
||||
#define PORT 4043
|
||||
#define CirSize 48880000
|
||||
// #define CirSize 6144000 // 100ms is enough
|
||||
#define sampleToByte(a,b) ((a)*(b)*sizeof(sample_t))
|
||||
#define byteToSample(a,b) ((a)/(sizeof(sample_t)*(b)))
|
||||
|
||||
#define MAX_SIMULATION_CONNECTED_NODES 5
|
||||
#define GENERATE_CHANNEL 10 //each frame in DL
|
||||
|
||||
#define SEND_BUFF_SIZE 100000000 // Socket buffer size
|
||||
|
||||
//
|
||||
|
||||
// typedef enum { SIMU_ROLE_SERVER = 1, SIMU_ROLE_CLIENT } simuRole;
|
||||
#define RFSIMU_SECTION "rfsimulator"
|
||||
#define RFSIMU_OPTIONS_PARAMNAME "options"
|
||||
|
||||
@@ -77,8 +81,11 @@
|
||||
/*-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
#define simOpt PARAMFLAG_NOFREE|PARAMFLAG_CMDLINE_NOPREFIXENABLED
|
||||
#define RFSIMULATOR_PARAMS_DESC { \
|
||||
{"brokerip", "<broker ip address to connect to>\n", simOpt, .strptr=&rfsimulator->brokerip, .defstrval="0.0.0.0", TYPE_STRING, 0 },\
|
||||
{"serveraddr", "<ip address to connect to>\n", simOpt, .strptr=&rfsimulator->ip, .defstrval="127.0.0.1", TYPE_STRING, 0 },\
|
||||
{"serverport", "<port to connect to>\n", simOpt, .u16ptr=&(rfsimulator->port), .defuintval=PORT, TYPE_UINT16, 0 },\
|
||||
{"xsubport", "<port to connect to xsubsocket>\n", simOpt, .u16ptr=&rfsimulator->xsubport, .defuintval=XSUBPORT, TYPE_UINT16, 0 },\
|
||||
{"xpubport", "<port to connect to xpubsocket>\n", simOpt, .u16ptr=&rfsimulator->xpubport, .defuintval=XPUBPORT, TYPE_UINT16, 0 },\
|
||||
{"device_id", "<device id>\n", simOpt, .strptr=&rfsimulator->device_id, .defstrval="0", TYPE_STRING, 0 },\
|
||||
{RFSIMU_OPTIONS_PARAMNAME, RFSIM_CONFIG_HELP_OPTIONS, 0, .strlistptr=NULL, .defstrlistval=NULL, TYPE_STRINGLIST,0 },\
|
||||
{"IQfile", "<file path to use when saving IQs>\n",simOpt, .strptr=&saveF, .defstrval="/tmp/rfsimulator.iqs",TYPE_STRING, 0 },\
|
||||
{"modelname", "<channel model name>\n", simOpt, .strptr=&modelname, .defstrval="AWGN", TYPE_STRING, 0 },\
|
||||
@@ -107,10 +114,14 @@ static telnetshell_cmddef_t *setmodel_cmddef = &(rfsimu_cmdarray[1]);
|
||||
static telnetshell_vardef_t rfsimu_vardef[] = {{"", 0, 0, NULL}};
|
||||
pthread_mutex_t Sockmutex;
|
||||
|
||||
unsigned int nb_ue = 0;
|
||||
|
||||
typedef c16_t sample_t; // 2*16 bits complex number
|
||||
|
||||
typedef struct buffer_s {
|
||||
int conn_sock;
|
||||
int fd_pub_sock;
|
||||
int fd_sub_sock;
|
||||
int conn_device_id;
|
||||
openair0_timestamp lastReceivedTS;
|
||||
bool headerMode;
|
||||
bool trashingPacket;
|
||||
@@ -123,10 +134,19 @@ typedef struct buffer_s {
|
||||
} buffer_t;
|
||||
|
||||
typedef struct {
|
||||
int listen_sock, epollfd;
|
||||
openair0_timestamp nextRxTstamp;
|
||||
openair0_timestamp lastWroteTS;
|
||||
uint64_t typeStamp;
|
||||
char *device_id;
|
||||
void *context;
|
||||
void *pub_sock;
|
||||
void *sub_sock;
|
||||
int fd_pub_sock;
|
||||
int fd_sub_sock;
|
||||
char connected_devices[16]; // to keep track of connected devices
|
||||
char *brokerip;
|
||||
uint16_t xsubport;
|
||||
uint16_t xpubport;
|
||||
char *ip;
|
||||
uint16_t port;
|
||||
int saveIQfile;
|
||||
@@ -143,25 +163,34 @@ typedef struct {
|
||||
void *telnetcmd_qid;
|
||||
poll_telnetcmdq_func_t poll_telnetcmdq;
|
||||
int wait_timeout;
|
||||
char *transferPtrTr;
|
||||
} rfsimulator_state_t;
|
||||
|
||||
|
||||
static void allocCirBuf(rfsimulator_state_t *bridge, int sock) {
|
||||
buffer_t *ptr=&bridge->buf[sock];
|
||||
static void allocCirBuf(rfsimulator_state_t *bridge, int id) {
|
||||
buffer_t *ptr=&bridge->buf[id];
|
||||
AssertFatal ( (ptr->circularBuf=(sample_t *) malloc(sampleToByte(CirSize,1))) != NULL, "");
|
||||
ptr->circularBufEnd=((char *)ptr->circularBuf)+sampleToByte(CirSize,1);
|
||||
ptr->conn_sock=sock;
|
||||
ptr->conn_device_id = id;
|
||||
ptr->fd_pub_sock = bridge->fd_pub_sock;
|
||||
ptr->fd_sub_sock = bridge->fd_sub_sock;
|
||||
ptr->lastReceivedTS=0;
|
||||
ptr->headerMode=true;
|
||||
ptr->trashingPacket=false;
|
||||
ptr->transferPtr=(char *)&ptr->th;
|
||||
ptr->remainToTransfer=sizeof(samplesBlockHeader_t);
|
||||
int sendbuff=1000*1000*100;
|
||||
AssertFatal ( setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &sendbuff, sizeof(sendbuff)) == 0, "");
|
||||
struct epoll_event ev= {0};
|
||||
ev.events = EPOLLIN | EPOLLRDHUP;
|
||||
ev.data.fd = sock;
|
||||
AssertFatal(epoll_ctl(bridge->epollfd, EPOLL_CTL_ADD, sock, &ev) != -1, "");
|
||||
int sendbuff=1000*1000*100;;
|
||||
size_t optlen = sizeof(sendbuff);
|
||||
if (zmq_setsockopt(bridge->pub_sock, ZMQ_SNDBUF, &sendbuff, optlen) != 0) {
|
||||
LOG_E(HW, "zmq_setsockopt(SO_SNDBUF) failed\n");
|
||||
}
|
||||
|
||||
if (bridge->typeStamp == ENB_MAGICDL) {
|
||||
int rcvhwm = 0;
|
||||
if (zmq_setsockopt(bridge->sub_sock, ZMQ_RCVHWM, &rcvhwm, sizeof(int)) != 0) {
|
||||
LOG_E(HW, "zmq_setsockopt(ZMQ_RCVHWM) failed\n");
|
||||
};
|
||||
}
|
||||
|
||||
if ( bridge->channelmod > 0) {
|
||||
// create channel simulation model for this mode reception
|
||||
@@ -198,75 +227,90 @@ static void allocCirBuf(rfsimulator_state_t *bridge, int sock) {
|
||||
}
|
||||
}
|
||||
|
||||
static void removeCirBuf(rfsimulator_state_t *bridge, int sock) {
|
||||
AssertFatal( epoll_ctl(bridge->epollfd, EPOLL_CTL_DEL, sock, NULL) != -1, "");
|
||||
close(sock);
|
||||
free(bridge->buf[sock].circularBuf);
|
||||
static void removeCirBuf(rfsimulator_state_t *bridge, int id) {
|
||||
free(bridge->buf[id].circularBuf);
|
||||
// Fixme: no free_channel_desc_scm(bridge->buf[sock].channel_model) implemented
|
||||
// a lot of mem leaks
|
||||
//free(bridge->buf[sock].channel_model);
|
||||
memset(&bridge->buf[sock], 0, sizeof(buffer_t));
|
||||
bridge->buf[sock].conn_sock=-1;
|
||||
memset(&bridge->buf[id], 0, sizeof(buffer_t));
|
||||
bridge->buf[id].fd_pub_sock=-1;
|
||||
bridge->buf[id].fd_sub_sock=-1;
|
||||
nb_ue--;
|
||||
}
|
||||
|
||||
static void socketError(rfsimulator_state_t *bridge, int sock) {
|
||||
if (bridge->buf[sock].conn_sock!=-1) {
|
||||
LOG_W(HW,"Lost socket \n");
|
||||
removeCirBuf(bridge, sock);
|
||||
|
||||
if (bridge->typeStamp==UE_MAGICDL)
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
enum blocking_t {
|
||||
notBlocking,
|
||||
blocking
|
||||
};
|
||||
|
||||
static void setblocking(int sock, enum blocking_t active) {
|
||||
int opts = fcntl(sock, F_GETFL);
|
||||
AssertFatal(opts >= 0, "fcntl(): errno %d, %s\n", errno, strerror(errno));
|
||||
|
||||
if (active==blocking)
|
||||
opts = opts & ~O_NONBLOCK;
|
||||
else
|
||||
opts = opts | O_NONBLOCK;
|
||||
|
||||
opts = fcntl(sock, F_SETFL, opts);
|
||||
AssertFatal(opts >= 0, "fcntl(): errno %d, %s\n", errno, strerror(errno));
|
||||
}
|
||||
|
||||
static bool flushInput(rfsimulator_state_t *t, int timeout, int nsamps);
|
||||
static int rfsimulator_write_internal(rfsimulator_state_t *t,
|
||||
openair0_timestamp timestamp,
|
||||
void **samplesVoid,
|
||||
int nsamps,
|
||||
int nbAnt,
|
||||
int flags,
|
||||
bool alreadyLocked,
|
||||
int firstMessage);
|
||||
|
||||
static void fullwrite(int fd, void *_buf, ssize_t count, rfsimulator_state_t *t) {
|
||||
static void fullwrite(int *pub_sock, void *_buf, ssize_t count, rfsimulator_state_t *t, int firstMessage) {
|
||||
if (t->saveIQfile != -1) {
|
||||
if (write(t->saveIQfile, _buf, count) != count )
|
||||
LOG_E(HW,"write in save iq file failed (%s)\n",strerror(errno));
|
||||
}
|
||||
|
||||
AssertFatal(fd>=0 && _buf && count >0 && t,
|
||||
"Bug: %d/%p/%zd/%p", fd, _buf, count, t);
|
||||
char *buf = _buf;
|
||||
ssize_t l;
|
||||
|
||||
// Sending topic
|
||||
while (count) {
|
||||
l = write(fd, buf, count);
|
||||
if (t->typeStamp == ENB_MAGICDL){
|
||||
if (firstMessage) { // to avoid race conditions when having multiple UEs
|
||||
char topic[] = "first";
|
||||
LOG_D(HW,"sending first message\n");
|
||||
// zmq_send(pub_sock, topic, strlen(topic), ZMQ_SNDMORE | ZMQ_DONTWAIT);
|
||||
zmq_send(pub_sock, topic, strlen(topic), ZMQ_SNDMORE);
|
||||
} else {
|
||||
char topic[] = "sync";
|
||||
LOG_D(HW,"sending data on sync topic\n");
|
||||
// zmq_send(pub_sock, topic, strlen(topic), ZMQ_SNDMORE | ZMQ_DONTWAIT);
|
||||
zmq_send(pub_sock, topic, strlen(topic), ZMQ_SNDMORE);
|
||||
}
|
||||
} else {
|
||||
LOG_D(HW,"sending data on ue topic\n");
|
||||
char topic[] = "ue";
|
||||
char formatted_topic[256];
|
||||
|
||||
if (l <= 0) {
|
||||
if (errno==EINTR)
|
||||
continue;
|
||||
|
||||
if(errno==EAGAIN) {
|
||||
// The opposite side is saturated
|
||||
// we read incoming sockets meawhile waiting
|
||||
//flushInput(t, 5);
|
||||
usleep(500);
|
||||
continue;
|
||||
} else
|
||||
return;
|
||||
// Format the topic with the device ID
|
||||
sprintf(formatted_topic, "%s %s", topic, t->device_id);
|
||||
// zmq_send(pub_sock, formatted_topic, strlen(formatted_topic), ZMQ_SNDMORE | ZMQ_DONTWAIT);
|
||||
zmq_send(pub_sock, formatted_topic, strlen(formatted_topic), ZMQ_SNDMORE);
|
||||
LOG_D(HW,"sending formatted topic: %s\n",formatted_topic);
|
||||
}
|
||||
|
||||
// l = zmq_send(pub_sock, buf, count, ZMQ_DONTWAIT);
|
||||
l = zmq_send(pub_sock, buf, count, 0);
|
||||
|
||||
if (l == 0) {
|
||||
LOG_E(HW, "write() failed, returned 0\n");
|
||||
return;
|
||||
}
|
||||
if (l < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
|
||||
if (errno == EAGAIN) {
|
||||
LOG_D(HW, "write() failed, errno(%d)\n", errno);
|
||||
usleep(250);
|
||||
continue;
|
||||
} else {
|
||||
LOG_E(HW, "write() failed, errno(%d)\n", errno);
|
||||
return;
|
||||
}
|
||||
}
|
||||
LOG_D(HW, "Successfully sent %zd bytes.\n", l);
|
||||
|
||||
count -= l;
|
||||
buf += l;
|
||||
}
|
||||
@@ -346,7 +390,7 @@ static int rfsimu_setchanmod_cmd(char *buff, int debug, telnet_printfunc_t prnt,
|
||||
continue;
|
||||
if (b->channel_model->model_name==NULL)
|
||||
continue;
|
||||
if (b->conn_sock >= 0 && (strcmp(b->channel_model->model_name,modelname)==0)) {
|
||||
if (b->fd_pub_sock >= 0 && (strcmp(b->channel_model->model_name,modelname)==0)) {
|
||||
channel_desc_t *newmodel = new_channel_desc_scm(t->tx_num_channels,
|
||||
t->rx_num_channels,
|
||||
channelmod,
|
||||
@@ -493,7 +537,7 @@ static int rfsimu_setdistance_cmd(char *buff, int debug, telnet_printfunc_t prnt
|
||||
/* Set distance in rfsim and channel model, update channel and ringbuffer */
|
||||
for (int i=0; i<FD_SETSIZE; i++) {
|
||||
buffer_t *b=&t->buf[i];
|
||||
if (b->conn_sock <= 0 || b->channel_model == NULL || b->channel_model->model_name == NULL || strcmp(b->channel_model->model_name, modelname) != 0) {
|
||||
if (b->fd_pub_sock <= 0 || b->channel_model == NULL || b->channel_model->model_name == NULL || strcmp(b->channel_model->model_name, modelname) != 0) {
|
||||
if (b->channel_model != NULL && b->channel_model->model_name != NULL)
|
||||
prnt(" model %s unmodified\n", b->channel_model->model_name);
|
||||
continue;
|
||||
@@ -524,7 +568,7 @@ static int rfsimu_getdistance_cmd(char *buff, int debug, telnet_printfunc_t prnt
|
||||
|
||||
for (int i=0; i<FD_SETSIZE; i++) {
|
||||
buffer_t *b=&t->buf[i];
|
||||
if (b->conn_sock <= 0 || b->channel_model == NULL || b->channel_model->model_name == NULL)
|
||||
if (b->fd_pub_sock <= 0 || b->channel_model == NULL || b->channel_model->model_name == NULL)
|
||||
continue;
|
||||
|
||||
channel_desc_t *cd = b->channel_model;
|
||||
@@ -548,72 +592,237 @@ static int rfsimu_vtime_cmd(char *buff, int debug, telnet_printfunc_t prnt, void
|
||||
static int startServer(openair0_device *device) {
|
||||
rfsimulator_state_t *t = (rfsimulator_state_t *) device->priv;
|
||||
t->typeStamp=ENB_MAGICDL;
|
||||
AssertFatal((t->listen_sock = socket(AF_INET, SOCK_STREAM, 0)) >= 0, "");
|
||||
int enable = 1;
|
||||
AssertFatal(setsockopt(t->listen_sock, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) == 0, "");
|
||||
struct sockaddr_in addr = {
|
||||
.sin_family=
|
||||
AF_INET,
|
||||
.sin_port=
|
||||
htons(t->port),
|
||||
.sin_addr=
|
||||
{ .s_addr= INADDR_ANY }
|
||||
};
|
||||
int rc = bind(t->listen_sock, (struct sockaddr *)&addr, sizeof(addr));
|
||||
AssertFatal(rc == 0, "bind failed: errno %d, %s", errno, strerror(errno));
|
||||
AssertFatal(listen(t->listen_sock, 5) == 0, "");
|
||||
struct epoll_event ev= {0};
|
||||
ev.events = EPOLLIN;
|
||||
ev.data.fd = t->listen_sock;
|
||||
AssertFatal(epoll_ctl(t->epollfd, EPOLL_CTL_ADD, t->listen_sock, &ev) != -1, "");
|
||||
t->context = zmq_ctx_new();
|
||||
AssertFatal(t->context != NULL, "Failed to create ZeroMQ context");
|
||||
int io_threads = 4;
|
||||
zmq_ctx_set(t->context, ZMQ_IO_THREADS, io_threads);
|
||||
// Create the publisher socket
|
||||
t->pub_sock = zmq_socket(t->context, ZMQ_PUB);
|
||||
AssertFatal(t->pub_sock != NULL, "Failed to create publisher socket");
|
||||
|
||||
// Set up monitoring for publisher socket to detect connection to the broker
|
||||
int rc = zmq_socket_monitor(t->pub_sock, "inproc://monitor.pub", ZMQ_EVENT_ALL);
|
||||
AssertFatal(rc == 0, "Failed to set up socket monitoring for publisher");
|
||||
|
||||
void *pub_monitor = zmq_socket(t->context, ZMQ_PAIR);
|
||||
AssertFatal(pub_monitor != NULL, "Failed to create publisher monitor socket");
|
||||
rc = zmq_connect(pub_monitor, "inproc://monitor.pub");
|
||||
AssertFatal(rc == 0, "Failed to connect publisher monitor socket");
|
||||
|
||||
// Create the subscriber socket
|
||||
t->sub_sock = zmq_socket(t->context, ZMQ_SUB);
|
||||
AssertFatal(t->sub_sock != NULL, "Failed to create subscriber socket");
|
||||
|
||||
// Set up monitoring for subscriber socket to detect connection to the broker
|
||||
rc = zmq_socket_monitor(t->sub_sock, "inproc://monitor.sub", ZMQ_EVENT_ALL);
|
||||
AssertFatal(rc == 0, "Failed to set up socket monitoring for subscriber");
|
||||
|
||||
void *sub_monitor = zmq_socket(t->context, ZMQ_PAIR);
|
||||
AssertFatal(sub_monitor != NULL, "Failed to create subscriber monitor socket");
|
||||
rc = zmq_connect(sub_monitor, "inproc://monitor.sub");
|
||||
AssertFatal(rc == 0, "Failed to connect subscriber monitor socket");
|
||||
|
||||
// Connect the sockets to the broker
|
||||
char pub_endpoint[256];
|
||||
snprintf(pub_endpoint, sizeof(pub_endpoint), "tcp://%s:%d", t->brokerip, t->xsubport);
|
||||
rc = zmq_connect(t->pub_sock, pub_endpoint);
|
||||
AssertFatal(rc == 0, "Failed to connect publisher socket");
|
||||
|
||||
char sub_endpoint[256];
|
||||
snprintf(sub_endpoint, sizeof(sub_endpoint), "tcp://%s:%d", t->brokerip, t->xpubport);
|
||||
rc = zmq_connect(t->sub_sock, sub_endpoint);
|
||||
AssertFatal(rc == 0, "Failed to connect subscriber socket");
|
||||
const char *topic = "ue"; // receive data from nearby UEs
|
||||
rc = zmq_setsockopt(t->sub_sock, ZMQ_SUBSCRIBE, topic, strlen(topic));
|
||||
AssertFatal(rc == 0, "Failed to subscribe to topic");
|
||||
const char *topic2 = "join"; // detect UE connections
|
||||
rc = zmq_setsockopt(t->sub_sock, ZMQ_SUBSCRIBE, topic2, strlen(topic2));
|
||||
AssertFatal(rc == 0, "Failed to subscribe to topic");
|
||||
size_t fd_size = sizeof(t->fd_pub_sock);
|
||||
rc = zmq_getsockopt(t->pub_sock, ZMQ_FD, &t->fd_pub_sock, &fd_size);
|
||||
AssertFatal(rc == 0, "Cannot get fd for pub_sock");
|
||||
rc = zmq_getsockopt(t->sub_sock, ZMQ_FD, &t->fd_sub_sock, &fd_size);
|
||||
AssertFatal(rc == 0, "Cannot get fd for sub_sock");
|
||||
|
||||
// Monitor the sockets to detect when they are connected
|
||||
bool pub_connected = false;
|
||||
bool sub_connected = false;
|
||||
struct timeval start, now;
|
||||
gettimeofday(&start, NULL);
|
||||
|
||||
while (!pub_connected || !sub_connected) {
|
||||
// Process events for publisher
|
||||
printf("trying to connect to the broker\n");
|
||||
zmq_msg_t event_msg;
|
||||
zmq_msg_init(&event_msg);
|
||||
rc = zmq_msg_recv(&event_msg, pub_monitor, ZMQ_DONTWAIT);
|
||||
if (rc != -1) {
|
||||
uint16_t event = *(uint16_t *)zmq_msg_data(&event_msg);
|
||||
zmq_msg_close(&event_msg);
|
||||
|
||||
if (event == ZMQ_EVENT_CONNECTED) {
|
||||
LOG_D(HW, "Publisher socket connected \n");
|
||||
pub_connected = true;
|
||||
}
|
||||
} else {
|
||||
zmq_msg_close(&event_msg);
|
||||
}
|
||||
|
||||
// Process events for subscriber
|
||||
zmq_msg_init(&event_msg);
|
||||
rc = zmq_msg_recv(&event_msg, sub_monitor, ZMQ_DONTWAIT);
|
||||
if (rc != -1) {
|
||||
uint16_t event = *(uint16_t *)zmq_msg_data(&event_msg);
|
||||
zmq_msg_close(&event_msg);
|
||||
|
||||
if (event == ZMQ_EVENT_CONNECTED) {
|
||||
LOG_D(HW, "Subscriber socket connected \n");
|
||||
sub_connected = true;
|
||||
}
|
||||
} else {
|
||||
zmq_msg_close(&event_msg);
|
||||
}
|
||||
// Avoid infinite loop
|
||||
gettimeofday(&now, NULL);
|
||||
double elapsed = (now.tv_sec - start.tv_sec) + (now.tv_usec - start.tv_usec) / 1000000.0;
|
||||
if (elapsed > 7.0) {
|
||||
LOG_W(HW, "Waited more than 7 seconds for connection to the broker, exiting loop\n");
|
||||
break;
|
||||
}
|
||||
usleep(10000);
|
||||
}
|
||||
|
||||
LOG_I(HW, "Connection to the broker established\n");
|
||||
zmq_close(pub_monitor);
|
||||
zmq_close(sub_monitor);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int startClient(openair0_device *device) {
|
||||
rfsimulator_state_t *t = device->priv;
|
||||
t->typeStamp=UE_MAGICDL;
|
||||
int sock;
|
||||
AssertFatal((sock = socket(AF_INET, SOCK_STREAM, 0)) >= 0, "");
|
||||
struct sockaddr_in addr = {
|
||||
.sin_family=
|
||||
AF_INET,
|
||||
.sin_port=
|
||||
htons(t->port),
|
||||
.sin_addr=
|
||||
{ .s_addr= INADDR_ANY }
|
||||
};
|
||||
addr.sin_addr.s_addr = inet_addr(t->ip);
|
||||
t->context = zmq_ctx_new();
|
||||
// Create the publisher socket
|
||||
t->pub_sock = zmq_socket(t->context, ZMQ_PUB);
|
||||
AssertFatal(t->pub_sock != NULL, "Failed to create publisher socket");
|
||||
// Set up monitoring for publisher socket to detect connection to the broker
|
||||
int rc = zmq_socket_monitor(t->pub_sock, "inproc://monitor.pub", ZMQ_EVENT_ALL);
|
||||
AssertFatal(rc == 0, "Failed to set up socket monitoring for publisher");
|
||||
bool connected=false;
|
||||
void *pub_monitor = zmq_socket(t->context, ZMQ_PAIR);
|
||||
AssertFatal(pub_monitor != NULL, "Failed to create publisher monitor socket");
|
||||
rc = zmq_connect(pub_monitor, "inproc://monitor.pub");
|
||||
AssertFatal(rc == 0, "Failed to connect publisher monitor socket");
|
||||
// Create the subscriber socket
|
||||
t->sub_sock = zmq_socket(t->context, ZMQ_SUB);
|
||||
AssertFatal(t->sub_sock != NULL, "Failed to create subscriber socket");
|
||||
|
||||
while(!connected) {
|
||||
LOG_I(HW,"rfsimulator: trying to connect to %s:%d\n", t->ip, t->port);
|
||||
// Set up monitoring for subscriber socket to detect connection to the broker
|
||||
rc = zmq_socket_monitor(t->sub_sock, "inproc://monitor.sub", ZMQ_EVENT_ALL);
|
||||
AssertFatal(rc == 0, "Failed to set up socket monitoring for subscriber");
|
||||
|
||||
if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == 0) {
|
||||
LOG_I(HW,"rfsimulator: connection established\n");
|
||||
connected=true;
|
||||
void *sub_monitor = zmq_socket(t->context, ZMQ_PAIR);
|
||||
AssertFatal(sub_monitor != NULL, "Failed to create subscriber monitor socket");
|
||||
rc = zmq_connect(sub_monitor, "inproc://monitor.sub");
|
||||
AssertFatal(rc == 0, "Failed to connect subscriber monitor socket");
|
||||
// Connect the sockets to the broker
|
||||
char pub_endpoint[256];
|
||||
snprintf(pub_endpoint, sizeof(pub_endpoint), "tcp://%s:%d", t->brokerip, t->xsubport);
|
||||
rc = zmq_connect(t->pub_sock, pub_endpoint);
|
||||
AssertFatal(rc == 0, "Failed to connect publisher socket");
|
||||
printf("connecting to endpoint: %s\n", pub_endpoint);
|
||||
|
||||
char sub_endpoint[256];
|
||||
snprintf(sub_endpoint, sizeof(sub_endpoint), "tcp://%s:%d", t->brokerip, t->xpubport);
|
||||
rc = zmq_connect(t->sub_sock, sub_endpoint);
|
||||
AssertFatal(rc == 0, "Failed to connect subscriber socket");
|
||||
const char *topic = "first";
|
||||
rc = zmq_setsockopt(t->sub_sock, ZMQ_SUBSCRIBE, topic, strlen(topic));
|
||||
AssertFatal(rc == 0, "Failed to subscribe to topic");
|
||||
size_t fd_size = sizeof(t->fd_pub_sock);
|
||||
rc = zmq_getsockopt(t->pub_sock, ZMQ_FD, &t->fd_pub_sock, &fd_size);
|
||||
AssertFatal(rc == 0, "Cannot get fd for pub_sock");
|
||||
rc = zmq_getsockopt(t->sub_sock, ZMQ_FD, &t->fd_sub_sock, &fd_size);
|
||||
AssertFatal(rc == 0, "Cannot get fd for sub_sock");
|
||||
|
||||
// Monitor the sockets to detect when they are connected
|
||||
bool pub_connected = false;
|
||||
bool sub_connected = false;
|
||||
while (!pub_connected || !sub_connected) {
|
||||
// Process events for publisher
|
||||
printf("trying to connect to the broker\n");
|
||||
zmq_msg_t event_msg;
|
||||
zmq_msg_init(&event_msg);
|
||||
rc = zmq_msg_recv(&event_msg, pub_monitor, ZMQ_DONTWAIT);
|
||||
if (rc != -1) {
|
||||
uint16_t event = *(uint16_t *)zmq_msg_data(&event_msg);
|
||||
zmq_msg_close(&event_msg);
|
||||
|
||||
if (event == ZMQ_EVENT_CONNECTED) {
|
||||
LOG_D(HW, "Publisher socket connected\n");
|
||||
pub_connected = true;
|
||||
}
|
||||
} else {
|
||||
zmq_msg_close(&event_msg);
|
||||
}
|
||||
|
||||
perror("rfsimulator");
|
||||
sleep(1);
|
||||
// Process events for subscriber
|
||||
zmq_msg_init(&event_msg);
|
||||
rc = zmq_msg_recv(&event_msg, sub_monitor, ZMQ_DONTWAIT);
|
||||
if (rc != -1) {
|
||||
uint16_t event = *(uint16_t *)zmq_msg_data(&event_msg);
|
||||
zmq_msg_close(&event_msg);
|
||||
|
||||
if (event == ZMQ_EVENT_CONNECTED) {
|
||||
LOG_D(HW, "Subscriber socket connected\n");
|
||||
sub_connected = true;
|
||||
}
|
||||
} else {
|
||||
zmq_msg_close(&event_msg);
|
||||
}
|
||||
|
||||
usleep(10000);
|
||||
}
|
||||
|
||||
setblocking(sock, notBlocking);
|
||||
allocCirBuf(t, sock);
|
||||
LOG_I(HW, "Connection to the broker established\n");
|
||||
zmq_close(pub_monitor);
|
||||
zmq_close(sub_monitor);
|
||||
// Subscribe to the sync topic
|
||||
const char *topic1 = "sync"; // recieve data from synchref
|
||||
rc = zmq_setsockopt(t->sub_sock, ZMQ_SUBSCRIBE, topic1, strlen(topic1));
|
||||
AssertFatal(rc == 0, "Failed to subscribe to topic");
|
||||
char jointopic[] = "join"; // send a join message
|
||||
zmq_send(t->pub_sock, jointopic, strlen(jointopic), ZMQ_SNDMORE);
|
||||
zmq_send(t->pub_sock, t->device_id, strlen(t->device_id), 0);
|
||||
allocCirBuf(t, atoi(t->device_id));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rfsimulator_write_internal(rfsimulator_state_t *t, openair0_timestamp timestamp, void **samplesVoid, int nsamps, int nbAnt, int flags, bool alreadyLocked) {
|
||||
static int rfsimulator_write_internal(rfsimulator_state_t *t,
|
||||
openair0_timestamp timestamp,
|
||||
void **samplesVoid,
|
||||
int nsamps,
|
||||
int nbAnt,
|
||||
int flags,
|
||||
bool alreadyLocked,
|
||||
int firstMessage) {
|
||||
if (!alreadyLocked)
|
||||
pthread_mutex_lock(&Sockmutex);
|
||||
|
||||
LOG_D(HW,"sending %d samples at time: %ld, nbAnt %d\n", nsamps, timestamp, nbAnt);
|
||||
|
||||
for (int i=0; i<FD_SETSIZE; i++) {
|
||||
buffer_t *b=&t->buf[i];
|
||||
|
||||
if (b->conn_sock >= 0 ) {
|
||||
// all connected UEs need to have a buffer to broadcast the data
|
||||
int count = 0;
|
||||
for (int i = 0; i < FD_SETSIZE; i++) {
|
||||
buffer_t *b = &t->buf[i];
|
||||
if (b->fd_pub_sock >= 0)
|
||||
count++;
|
||||
LOG_D(HW,"there are %d connect UE",count);
|
||||
}
|
||||
if (((count != 0))) { // changed here
|
||||
if (t->fd_pub_sock >= 0) {
|
||||
samplesBlockHeader_t header= {t->typeStamp, nsamps, nbAnt, timestamp};
|
||||
fullwrite(b->conn_sock,&header, sizeof(header), t);
|
||||
fullwrite(t->pub_sock,&header, sizeof(header), t,0);
|
||||
sample_t tmpSamples[nsamps][nbAnt];
|
||||
|
||||
for(int a=0; a<nbAnt; a++) {
|
||||
@@ -622,9 +831,8 @@ static int rfsimulator_write_internal(rfsimulator_state_t *t, openair0_timestamp
|
||||
for(int s=0; s<nsamps; s++)
|
||||
tmpSamples[s][a]=in[s];
|
||||
}
|
||||
|
||||
if (b->conn_sock >= 0 ) {
|
||||
fullwrite(b->conn_sock, (void *)tmpSamples, sampleToByte(nsamps,nbAnt), t);
|
||||
if (t->fd_pub_sock >= 0 ) {
|
||||
fullwrite(t->pub_sock, (void *)tmpSamples, sampleToByte(nsamps,nbAnt), t,0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -647,51 +855,114 @@ static int rfsimulator_write_internal(rfsimulator_state_t *t, openair0_timestamp
|
||||
}
|
||||
|
||||
static int rfsimulator_write(openair0_device *device, openair0_timestamp timestamp, void **samplesVoid, int nsamps, int nbAnt, int flags) {
|
||||
return rfsimulator_write_internal(device->priv, timestamp, samplesVoid, nsamps, nbAnt, flags, false);
|
||||
return rfsimulator_write_internal(device->priv, timestamp, samplesVoid, nsamps, nbAnt, flags, false,0);
|
||||
}
|
||||
|
||||
static bool flushInput(rfsimulator_state_t *t, int timeout, int nsamps_for_initial) {
|
||||
// Process all incoming events on sockets
|
||||
// store the data in lists
|
||||
struct epoll_event events[FD_SETSIZE]= {{0}};
|
||||
int nfds = epoll_wait(t->epollfd, events, FD_SETSIZE, timeout);
|
||||
|
||||
if ( nfds==-1 ) {
|
||||
if ( errno==EINTR || errno==EAGAIN ) {
|
||||
zmq_pollitem_t items[] = {
|
||||
{t->sub_sock, 0, ZMQ_POLLIN, 0} // maybe this should be moved to another function
|
||||
};
|
||||
int rc = zmq_poll(items, 1, timeout);
|
||||
if (rc < 0) {
|
||||
if (errno == EINTR) {
|
||||
return false;
|
||||
} else
|
||||
AssertFatal(false,"error in epoll_wait\n");
|
||||
}
|
||||
LOG_W(HW, "zmq_poll() failed, errno(%d)\n", errno);
|
||||
return false;
|
||||
}
|
||||
if (rc == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int nbEv = 0; nbEv < nfds; ++nbEv) {
|
||||
int fd=events[nbEv].data.fd;
|
||||
|
||||
if (events[nbEv].events & EPOLLIN && fd == t->listen_sock) {
|
||||
int conn_sock;
|
||||
AssertFatal( (conn_sock = accept(t->listen_sock,NULL,NULL)) != -1, "");
|
||||
setblocking(conn_sock, notBlocking);
|
||||
allocCirBuf(t, conn_sock);
|
||||
if (items[0].revents & ZMQ_POLLIN) {
|
||||
// receiving topic
|
||||
char topic[256];
|
||||
int cap = sizeof(topic);
|
||||
// int tsize= zmq_recv(t->sub_sock, topic,cap-1 , ZMQ_DONTWAIT);
|
||||
int tsize = zmq_recv(t->sub_sock, topic, cap - 1, 0);
|
||||
if (tsize < 0) {
|
||||
if (errno != EAGAIN) {
|
||||
LOG_E(HW, "zmq_recv() failed, errno(%d)\n", errno);
|
||||
AssertFatal(false, "Failed in reading the topic\n");
|
||||
// abort();
|
||||
}
|
||||
}
|
||||
topic[tsize < cap ? tsize : cap - 1] = '\0';
|
||||
LOG_D(HW, "received topic %s\n", topic);
|
||||
// handle first message
|
||||
// if (strncasecmp(topic, "first", 2) == 0 && t->nextRxTstamp == 0) {
|
||||
// rc = zmq_setsockopt(t->sub_sock, ZMQ_SUBSCRIBE, topic1, strlen(topic1));
|
||||
// AssertFatal(rc == 0, "Failed to subscribe to topic");
|
||||
// // Subscribe to the ue topic
|
||||
// // const char *topic2 = "ue";
|
||||
// // rc = zmq_setsockopt(t->sub_sock, ZMQ_SUBSCRIBE, topic2, strlen(topic2));
|
||||
// // AssertFatal(rc == 0, "Failed to subscribe to topic");
|
||||
// nb_ue++;
|
||||
// }
|
||||
if ((strncasecmp(topic, "join", 2) == 0)) {
|
||||
char deviceid[256];
|
||||
int cap = sizeof(deviceid);
|
||||
// int idsize= zmq_recv(t->sub_sock, deviceid,cap-1 , ZMQ_DONTWAIT);
|
||||
int idsize = zmq_recv(t->sub_sock, deviceid, cap - 1, 0);
|
||||
if (idsize < 0) {
|
||||
if (errno != EAGAIN) {
|
||||
LOG_E(HW, "zmq_recv() failed, errno(%d)\n", errno);
|
||||
AssertFatal(false, "Failed in reading the device id\n");
|
||||
}
|
||||
}
|
||||
deviceid[idsize < cap ? idsize : cap - 1] = '\0';
|
||||
LOG_D(HW, "received device_id %s\n", deviceid);
|
||||
int device_id = atoi(deviceid);
|
||||
allocCirBuf(t, device_id);
|
||||
LOG_I(HW,"A client connected, sending the current time\n");
|
||||
c16_t v= {0};
|
||||
// nb_ue++;
|
||||
void *samplesVoid[t->tx_num_channels];
|
||||
|
||||
for ( int i=0; i < t->tx_num_channels; i++)
|
||||
samplesVoid[i]=(void *)&v;
|
||||
|
||||
rfsimulator_write_internal(t, t->lastWroteTS > 1 ? t->lastWroteTS-1 : 0,
|
||||
samplesVoid, 1,
|
||||
t->tx_num_channels, 1, false);
|
||||
} else {
|
||||
if ( events[nbEv].events & (EPOLLHUP | EPOLLERR | EPOLLRDHUP) ) {
|
||||
socketError(t,fd);
|
||||
continue;
|
||||
samplesVoid, 1,
|
||||
t->tx_num_channels, 1, false,0);
|
||||
return rc > 0;
|
||||
}
|
||||
|
||||
buffer_t *b=&t->buf[fd];
|
||||
|
||||
buffer_t *b = NULL;
|
||||
// Receiving formatted topic = topic + device_id
|
||||
if ((t->typeStamp == ENB_MAGICDL) && (strncasecmp(topic, "ue", 2) == 0)) {// recv by server (sync ref)
|
||||
char deviceid[256];
|
||||
sscanf(topic, "ue %255s", deviceid);
|
||||
int id = atoi(deviceid);
|
||||
LOG_D(HW,"received data from device:%d\n",id);
|
||||
b = &t->buf[id];
|
||||
}
|
||||
// if ((t->typeStamp == UE_MAGICDL) && (strncasecmp(topic, "ue", 2) == 0)){
|
||||
// char deviceid[256];
|
||||
// sscanf(topic, "ue %255s", deviceid);
|
||||
// int id = atoi(deviceid);
|
||||
// if (id != atoi(t->device_id)){
|
||||
// b = &t->buf[id];
|
||||
// LOG_D(HW,"recieved data from another UE\n");
|
||||
// } else {
|
||||
// // Empty recv socket, we don't need our message
|
||||
// zmq_msg_t msg;
|
||||
// int rc = zmq_msg_init (&msg);
|
||||
// zmq_msg_recv(&msg,t->sub_sock, ZMQ_DONTWAIT);
|
||||
// LOG_D(HW,"recieved from myself\n");
|
||||
// zmq_msg_close (&msg);
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
if ((strncasecmp(topic, "sync", 2) == 0)) {
|
||||
b = &t->buf[atoi(t->device_id)];// buffer of itself means the comm buf with the syncref
|
||||
}
|
||||
if (!b)
|
||||
return false;
|
||||
if ( b->circularBuf == NULL ) {
|
||||
LOG_E(HW, "received data on not connected socket %d\n", events[nbEv].data.fd);
|
||||
continue;
|
||||
LOG_E(HW, "received data on not connected socket\n");
|
||||
return rc > 0;
|
||||
}
|
||||
|
||||
ssize_t blockSz;
|
||||
@@ -703,28 +974,28 @@ static bool flushInput(rfsimulator_state_t *t, int timeout, int nsamps_for_initi
|
||||
b->remainToTransfer :
|
||||
b->circularBufEnd - b->transferPtr ;
|
||||
|
||||
ssize_t sz=recv(fd, b->transferPtr, blockSz, MSG_DONTWAIT);
|
||||
|
||||
// receiving data ( iq samples ) or header
|
||||
ssize_t sz = zmq_recv(t->sub_sock, b->transferPtr, blockSz, ZMQ_DONTWAIT);
|
||||
if ( sz < 0 ) {
|
||||
if ( errno != EAGAIN ) {
|
||||
LOG_E(HW,"socket failed %s\n", strerror(errno));
|
||||
LOG_E(HW, "zmq_recv() failed, errno(%d)\n", errno);
|
||||
//abort();
|
||||
}
|
||||
} else if ( sz == 0 )
|
||||
continue;
|
||||
return rc > 0;
|
||||
if (sz > 0) {
|
||||
LOG_D(HW, "Received on topic %s, %zd bytes\n", topic, sz);
|
||||
AssertFatal((b->remainToTransfer-=sz) >= 0, "");
|
||||
b->transferPtr+=sz;
|
||||
|
||||
LOG_D(HW, "Socket rcv %zd bytes\n", sz);
|
||||
AssertFatal((b->remainToTransfer-=sz) >= 0, "");
|
||||
b->transferPtr+=sz;
|
||||
if (b->transferPtr==b->circularBufEnd )
|
||||
b->transferPtr=(char *)b->circularBuf;
|
||||
|
||||
if (b->transferPtr==b->circularBufEnd )
|
||||
b->transferPtr=(char *)b->circularBuf;
|
||||
|
||||
// check the header and start block transfer
|
||||
if ( b->headerMode==true && b->remainToTransfer==0) {
|
||||
AssertFatal( (t->typeStamp == UE_MAGICDL && b->th.magic==ENB_MAGICDL) ||
|
||||
(t->typeStamp == ENB_MAGICDL && b->th.magic==UE_MAGICDL), "Socket Error in protocol");
|
||||
b->headerMode=false;
|
||||
// check the header and start block transfer
|
||||
if ( b->headerMode==true && b->remainToTransfer==0) {
|
||||
AssertFatal( (t->typeStamp == UE_MAGICDL && b->th.magic==ENB_MAGICDL) ||
|
||||
(t->typeStamp == ENB_MAGICDL && b->th.magic==UE_MAGICDL), "Socket Error in protocol");
|
||||
b->headerMode=false;
|
||||
|
||||
if ( t->nextRxTstamp == 0 ) { // First block in UE, resync with the eNB current TS
|
||||
t->nextRxTstamp=b->th.timestamp> nsamps_for_initial ?
|
||||
@@ -750,7 +1021,7 @@ static bool flushInput(rfsimulator_state_t *t, int timeout, int nsamps_for_initi
|
||||
}
|
||||
|
||||
if (b->lastReceivedTS != 0 && b->th.timestamp-b->lastReceivedTS < 1000)
|
||||
LOG_W(HW,"UEsock: %d gap of: %ld in reception\n", fd, b->th.timestamp-b->lastReceivedTS );
|
||||
LOG_W(HW,"gap of: %ld in reception\n", b->th.timestamp-b->lastReceivedTS );
|
||||
|
||||
b->lastReceivedTS=b->th.timestamp;
|
||||
} else if ( b->lastReceivedTS > b->th.timestamp && b->th.size == 1 ) {
|
||||
@@ -766,7 +1037,7 @@ static bool flushInput(rfsimulator_state_t *t, int timeout, int nsamps_for_initi
|
||||
pthread_mutex_lock(&Sockmutex);
|
||||
|
||||
if (t->lastWroteTS != 0 && (fabs((double)t->lastWroteTS-b->lastReceivedTS) > (double)CirSize))
|
||||
LOG_E(HW,"UEsock: %d Tx/Rx shift too large Tx:%lu, Rx:%lu\n", fd, t->lastWroteTS, b->lastReceivedTS);
|
||||
LOG_W(HW, "UEsock(sub_sock) Tx/Rx shift too large Tx:%lu, Rx:%lu\n", t->lastWroteTS, b->lastReceivedTS);
|
||||
|
||||
pthread_mutex_unlock(&Sockmutex);
|
||||
b->transferPtr=(char *)&b->circularBuf[(b->lastReceivedTS*b->th.nbAnt)%CirSize];
|
||||
@@ -776,11 +1047,11 @@ static bool flushInput(rfsimulator_state_t *t, int timeout, int nsamps_for_initi
|
||||
if ( b->headerMode==false ) {
|
||||
if ( ! b->trashingPacket ) {
|
||||
b->lastReceivedTS=b->th.timestamp+b->th.size-byteToSample(b->remainToTransfer,b->th.nbAnt);
|
||||
LOG_D(HW,"UEsock: %d Set b->lastReceivedTS %ld\n", fd, b->lastReceivedTS);
|
||||
LOG_D(HW, "UEsock: sub_sock Set b->lastReceivedTS %ld\n", b->lastReceivedTS);
|
||||
}
|
||||
|
||||
if ( b->remainToTransfer==0) {
|
||||
LOG_D(HW,"UEsock: %d Completed block reception: %ld\n", fd, b->lastReceivedTS);
|
||||
LOG_D(HW, "UEsock: sub_sock Completed block reception: %ld\n", b->lastReceivedTS);
|
||||
b->headerMode=true;
|
||||
b->transferPtr=(char *)&b->th;
|
||||
b->remainToTransfer=sizeof(samplesBlockHeader_t);
|
||||
@@ -788,10 +1059,11 @@ static bool flushInput(rfsimulator_state_t *t, int timeout, int nsamps_for_initi
|
||||
b->trashingPacket=false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return nfds>0;
|
||||
return rc>0;
|
||||
}
|
||||
|
||||
static int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, void **samplesVoid, int nsamps, int nbAnt) {
|
||||
@@ -832,9 +1104,9 @@ static int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimest
|
||||
|
||||
do {
|
||||
have_to_wait=false;
|
||||
|
||||
buffer_t *b = NULL;
|
||||
for ( int sock=0; sock<FD_SETSIZE; sock++) {
|
||||
buffer_t *b=&t->buf[sock];
|
||||
b=&t->buf[sock];
|
||||
|
||||
if ( b->circularBuf )
|
||||
if ( t->nextRxTstamp+nsamps > b->lastReceivedTS ) {
|
||||
@@ -843,12 +1115,11 @@ static int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimest
|
||||
}
|
||||
}
|
||||
|
||||
if (have_to_wait)
|
||||
/*printf("Waiting on socket, current last ts: %ld, expected at least : %ld\n",
|
||||
ptr->lastReceivedTS,
|
||||
t->nextRxTstamp+nsamps);
|
||||
*/
|
||||
flushInput(t, 3, nsamps);
|
||||
if (have_to_wait){
|
||||
|
||||
// LOG_D(HW,"Waiting, current last ts: %ld, expected at least : %ld\n",b->lastReceivedTS,t->nextRxTstamp + nsamps);
|
||||
flushInput(t, 3, nsamps);
|
||||
}
|
||||
} while (have_to_wait);
|
||||
}
|
||||
|
||||
@@ -919,12 +1190,16 @@ static int rfsimulator_reset_stats(openair0_device *device) {
|
||||
}
|
||||
static void rfsimulator_end(openair0_device *device) {
|
||||
rfsimulator_state_t* s = device->priv;
|
||||
zmq_close(s->sub_sock);
|
||||
zmq_close(s->pub_sock);
|
||||
zmq_ctx_destroy(s->context);
|
||||
for (int i = 0; i < FD_SETSIZE; i++) {
|
||||
buffer_t *b = &s->buf[i];
|
||||
if (b->conn_sock >= 0 )
|
||||
close(b->conn_sock);
|
||||
if (b->fd_pub_sock >= 0 )
|
||||
removeCirBuf(s, b->conn_device_id);
|
||||
}
|
||||
close(s->epollfd);
|
||||
s->fd_pub_sock = -1;
|
||||
s->fd_sub_sock = -1;
|
||||
}
|
||||
static int rfsimulator_stop(openair0_device *device) {
|
||||
return 0;
|
||||
@@ -970,11 +1245,13 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
|
||||
device->priv = rfsimulator;
|
||||
device->trx_write_init = rfsimulator_write_init;
|
||||
|
||||
for (int i=0; i<FD_SETSIZE; i++)
|
||||
rfsimulator->buf[i].conn_sock=-1;
|
||||
|
||||
AssertFatal((rfsimulator->epollfd = epoll_create1(0)) != -1,"");
|
||||
|
||||
for (int i = 0; i < FD_SETSIZE; i++) {
|
||||
rfsimulator->buf[i].fd_sub_sock = -1;
|
||||
rfsimulator->buf[i].fd_pub_sock = -1;
|
||||
}
|
||||
rfsimulator->fd_pub_sock = -1;
|
||||
rfsimulator->fd_sub_sock = -1;
|
||||
|
||||
// we need to call randominit() for telnet server (use gaussdouble=>uniformrand)
|
||||
randominit(0);
|
||||
set_taus_seed(0);
|
||||
|
||||
@@ -16,7 +16,7 @@ SIDELINK_PRECONFIGURATION = (
|
||||
slot_Offset = 0;
|
||||
slot_Periodicity = 5;
|
||||
# Indicates if CSI Reporting is enabled in UNICAST. is 0-ENABLED, 1-DISABLED
|
||||
sl_CSI_Acquisition = 1;
|
||||
sl_CSI_Acquisition = 1; //Jin disable CSI
|
||||
sl_LatencyBoundCSI_Report = 8;
|
||||
}
|
||||
);
|
||||
@@ -88,7 +88,7 @@ SIDELINK_PRECONFIGURATION = (
|
||||
sl_NumSubchannel = 1;
|
||||
# period of PSFCH resource in units of slots within this resource pool
|
||||
# Possible values sl0 means no PSFCH resource, {sl0, sl1, sl2, sl4}
|
||||
sl_PSFCH_Period = 2;
|
||||
sl_PSFCH_Period = 0; //Jin disable from 2 to 0
|
||||
# Number of cyclic shift pairs used for a PSFCH transmission that can be multiplexed in a PRB
|
||||
# Possible values {n1, n2, n3, n4}
|
||||
sl_NumMuxCS_Pair = 1;
|
||||
@@ -119,7 +119,7 @@ SIDELINK_PRECONFIGURATION = (
|
||||
sl_NumSubchannel = 1;
|
||||
# period of PSFCH resource in units of slots within this resource pool
|
||||
# Possible values sl0 means no PSFCH resource, {sl0, sl1, sl2, sl4}
|
||||
sl_PSFCH_Period = 2;
|
||||
sl_PSFCH_Period = 0; //Jin disable from 2 to 0
|
||||
# Number of cyclic shift pairs used for a PSFCH transmission that can be multiplexed in a PRB
|
||||
# Possible values {n1, n2, n3, n4}
|
||||
sl_NumMuxCS_Pair = 1;
|
||||
@@ -150,5 +150,38 @@ SIDELINK_PRECONFIGURATION = (
|
||||
fourthOctet = 1;
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
|
||||
log_config :
|
||||
{
|
||||
global_log_level = "debug";
|
||||
global_log_verbosity = "high";
|
||||
|
||||
mac_log_level = "debug";
|
||||
mac_log_verbosity = "high";
|
||||
|
||||
phy_log_level = "debug";
|
||||
phy_log_verbosity = "high";
|
||||
|
||||
pdcp_log_level = "debug";
|
||||
pdcp_log_verbosity = "high";
|
||||
|
||||
mac_ue_log_level = "debug";
|
||||
mac_ue_log_verbosity = "high";
|
||||
|
||||
pdcp_ue_log_level = "debug";
|
||||
pdcp_ue_log_verbosity = "high";
|
||||
|
||||
sdap_log_level = "debug";
|
||||
sdap_log_verbosity = "high";
|
||||
|
||||
sdap_ue_log_level = "debug";
|
||||
sdap_ue_log_verbosity = "high";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
@@ -16,7 +16,7 @@ SIDELINK_PRECONFIGURATION = (
|
||||
slot_Offset = 0;
|
||||
slot_Periodicity = 5;
|
||||
# Indicates if CSI Reporting is enabled in UNICAST. is 0-ENABLED, 1-DISABLED
|
||||
sl_CSI_Acquisition = 1;
|
||||
sl_CSI_Acquisition = 0;
|
||||
sl_LatencyBoundCSI_Report = 8;
|
||||
}
|
||||
);
|
||||
|
||||
189
targets/PROJECTS/NR-SIDELINK/CONF/ue1.conf
Normal file
189
targets/PROJECTS/NR-SIDELINK/CONF/ue1.conf
Normal file
@@ -0,0 +1,189 @@
|
||||
SIDELINK_PRECONFIGURATION = (
|
||||
{
|
||||
# TDD ULDL CONFIG used for sidelink
|
||||
sl_dl_UL_TransmissionPeriodicity = 6;
|
||||
sl_nrofDownlinkSlots = 6;
|
||||
sl_nrofDownlinkSymbols = 0;
|
||||
sl_nrofUplinkSlots = 4;
|
||||
sl_nrofUplinkSymbols = 0;
|
||||
sl_csi_rs = (
|
||||
{
|
||||
symb_l0 = 5;
|
||||
# csi_type 2 is not supported 38211, 8.4.1.5.3
|
||||
csi_Type = 1;
|
||||
sl_powerControlOffset = 1;
|
||||
sl_powerControlOffsetSS = 1;
|
||||
slot_Offset = 0;
|
||||
slot_Periodicity = 5;
|
||||
# Indicates if CSI Reporting is enabled in UNICAST. is 0-ENABLED, 1-DISABLED
|
||||
sl_CSI_Acquisition = 1;
|
||||
sl_LatencyBoundCSI_Report = 8;
|
||||
}
|
||||
);
|
||||
|
||||
sl_AllowedResourceSelectionConfig = 3; // Supported only {0, 3, 4, 6}
|
||||
|
||||
sl_FrequencyCommonConfig = (
|
||||
{
|
||||
sl_offstToCarrier = 0;
|
||||
sl_subcarrierSpacing = 1;//0-15Khz, 1-30Khz
|
||||
sl_carrierBandwidth = 106;//numPRBs
|
||||
#NR bands for Sidelink n47, n38. N47 - 5855Mhz - 5925Mhz
|
||||
#SL SSB chosen to be located from RB10 to RB21. points to the middle of the SSB block.
|
||||
#SSB location should be within Sidelink BWP
|
||||
# this is 2584.95 MHz => 301 REs from PointA 25 PRBs + 1 RE
|
||||
sl_absoluteFrequencySSB = 516990;
|
||||
# this is 2575.92 MHz (center frequency is 2585.1 MHz
|
||||
sl_absoluteFrequencyPointA = 515184;
|
||||
}
|
||||
);
|
||||
|
||||
sl_BWP = (
|
||||
{
|
||||
#RB start 0, RB size = 106. occupies complete Bw.
|
||||
sl_locationAndBandwidth = 28875;
|
||||
# Num Symbols used for Sidelink in an uplink slot
|
||||
# Herein, sl_LengthSymbols represents an index; not the number of symbols.
|
||||
# This index value can be from 0 to 7 representing the (7 to 14 symbols)
|
||||
sl_LengthSymbols = 7;
|
||||
#Sidelink Starting symbol in a slot
|
||||
#Value can be between symbols 0 to 7
|
||||
sl_StartSymbol = 0;
|
||||
}
|
||||
);
|
||||
|
||||
sl_syncCfg = (
|
||||
{
|
||||
#NUM SL-SSB within 16 frames
|
||||
sl_NumSSB_WithinPeriod_0 = 4;
|
||||
#Slot Offset for the first txn in the 16 frame period
|
||||
sl_TimeOffsetSSB_0 = 8;
|
||||
#interval in slots for repetition of SL-SSB
|
||||
sl_TimeInterval_0 = 120;
|
||||
}
|
||||
);
|
||||
sl_ConfiguredGrantConfig = (
|
||||
{
|
||||
sl_NrOfHARQ_Processes = 16;
|
||||
sl_HARQ_ProcID_offset = 0;
|
||||
sl_periodic_rsc_rsr_interval = 100;
|
||||
}
|
||||
);
|
||||
sl_RxResPools = (
|
||||
{
|
||||
#Number of symbols which carry PSCCH.
|
||||
#Possible values 0 means 2 symbols, 1 - means 3 symbols.
|
||||
sl_TimeResourcePSCCH = 0;
|
||||
#Number of RBS which carry PSCCH
|
||||
#Possible values {n10,n12,n15,n20,n25}
|
||||
sl_FreqResourcePSCCH = 1; //12RBs
|
||||
#Size of subchannel in RBs
|
||||
#Possible values - {n10,n12,n15,n20,n25,n50,n75,n100}
|
||||
sl_SubchannelSize = 5;//10RBs
|
||||
#start in RB of the lowest subchannel in a rpool
|
||||
sl_StartRB_Subchannel = 0;
|
||||
#number of PRBs in a rpool
|
||||
sl_RB_Number = 50;
|
||||
sl_NumSubchannel = 1;
|
||||
# period of PSFCH resource in units of slots within this resource pool
|
||||
# Possible values sl0 means no PSFCH resource, {sl0, sl1, sl2, sl4}
|
||||
sl_PSFCH_Period = 0;
|
||||
# Number of cyclic shift pairs used for a PSFCH transmission that can be multiplexed in a PRB
|
||||
# Possible values {n1, n2, n3, n4}
|
||||
sl_NumMuxCS_Pair = 1;
|
||||
# Minimum time gap between PSFCH and the associated PSSCH in the unit of slots {sl2, sl3}
|
||||
sl_MinTimeGapPSFCH = 1; //sl3
|
||||
# Scrambling ID {0..1023} for sequence hopping of the PSFCH used in the resource pool
|
||||
sl_PSFCH_HopID = 1;
|
||||
# Number of PSFCH resources available {startSubCH, allocSubCH} for multiplexing HARQ-ACK information in a PSFCH transmission
|
||||
sl_PSFCH_CandidateResourceType = 0; // startSubCH
|
||||
}
|
||||
);
|
||||
|
||||
sl_TxResPools = (
|
||||
{
|
||||
#Number of symbols which carry PSCCH.
|
||||
#Possible values 0 means 2 symbols, 1 - means 3 symbols.
|
||||
sl_TimeResourcePSCCH = 0;
|
||||
#Number of RBS which carry PSCCH
|
||||
#Possible values {n10,n12,n15,n20,n25}
|
||||
sl_FreqResourcePSCCH = 1; //12RBs
|
||||
#Size of subchannel in RBs
|
||||
#Possible values - {n10,n12,n15,n20,n25,n50,n75,n100}
|
||||
sl_SubchannelSize = 5;//50RBs
|
||||
#start in RB of the lowest subchannel in a rpool
|
||||
sl_StartRB_Subchannel = 0;
|
||||
#number of PRBs in a rpool
|
||||
sl_RB_Number = 50;
|
||||
sl_NumSubchannel = 1;
|
||||
# period of PSFCH resource in units of slots within this resource pool
|
||||
# Possible values sl0 means no PSFCH resource, {sl0, sl1, sl2, sl4}
|
||||
sl_PSFCH_Period = 0;
|
||||
# Number of cyclic shift pairs used for a PSFCH transmission that can be multiplexed in a PRB
|
||||
# Possible values {n1, n2, n3, n4}
|
||||
sl_NumMuxCS_Pair = 1;
|
||||
# Minimum time gap between PSFCH and the associated PSSCH in the unit of slots {sl2, sl3}
|
||||
sl_MinTimeGapPSFCH = 1; //sl3
|
||||
# Scrambling ID {0..1023} for sequence hopping of the PSFCH used in the resource pool
|
||||
sl_PSFCH_HopID = 1;
|
||||
# Number of PSFCH resources available {startSubCH, allocSubCH} for multiplexing HARQ-ACK information in a PSFCH transmission
|
||||
sl_PSFCH_CandidateResourceType = 0; // startSubCH
|
||||
}
|
||||
);
|
||||
|
||||
rsrc_selection_params = (
|
||||
{
|
||||
# Resource selection parameters
|
||||
# sl_Priority = 1;
|
||||
sl_SelectionWindow = 5; // n1, n5, n10, n20} {1,5,10,20}*2^μ
|
||||
sl_Thres_RSRP = 0; // (-128 + (n-1)*2) dBm n is 0..66
|
||||
sl_MaxNumPerReserve = 0; // n2, n3
|
||||
sl_SensingWindow = 100; // {ms100, ms1100}
|
||||
sl_ResourceReservePeriod = 100; //{ms0, ms100, ms200, ms300, ms400, ms500, ms600, ms700, ms800, ms900, ms1000}
|
||||
sl_RS_ForSensing = 0; // 0 pscch, 1 pssch
|
||||
sl_TxPercentage = 0; // index of {20, 35, 50}
|
||||
}
|
||||
);
|
||||
|
||||
sl_UEINFO = (
|
||||
{
|
||||
srcid = 1;
|
||||
thirdOctet = 0;
|
||||
fourthOctet = 2;
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
log_config :
|
||||
{
|
||||
global_log_level = "debug";
|
||||
global_log_verbosity = "high";
|
||||
|
||||
mac_log_level = "debug";
|
||||
mac_log_verbosity = "high";
|
||||
|
||||
phy_log_level = "debug";
|
||||
phy_log_verbosity = "high";
|
||||
|
||||
pdcp_log_level = "debug";
|
||||
pdcp_log_verbosity = "high";
|
||||
|
||||
mac_ue_log_level = "debug";
|
||||
mac_ue_log_verbosity = "high";
|
||||
|
||||
pdcp_ue_log_level = "debug";
|
||||
pdcp_ue_log_verbosity = "high";
|
||||
|
||||
sdap_log_level = "debug";
|
||||
sdap_log_verbosity = "high";
|
||||
|
||||
sdap_ue_log_level = "debug";
|
||||
sdap_ue_log_verbosity = "high";
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
);
|
||||
190
targets/PROJECTS/NR-SIDELINK/CONF/ue2.conf
Normal file
190
targets/PROJECTS/NR-SIDELINK/CONF/ue2.conf
Normal file
@@ -0,0 +1,190 @@
|
||||
SIDELINK_PRECONFIGURATION = (
|
||||
{
|
||||
# TDD ULDL CONFIG used for sidelink
|
||||
sl_dl_UL_TransmissionPeriodicity = 6;
|
||||
sl_nrofDownlinkSlots = 6;
|
||||
sl_nrofDownlinkSymbols = 0;
|
||||
sl_nrofUplinkSlots = 4;
|
||||
sl_nrofUplinkSymbols = 0;
|
||||
sl_csi_rs = (
|
||||
{
|
||||
symb_l0 = 5;
|
||||
# csi_type 2 is not supported 38211, 8.4.1.5.3
|
||||
csi_Type = 1;
|
||||
sl_powerControlOffset = 1;
|
||||
sl_powerControlOffsetSS = 1;
|
||||
slot_Offset = 0;
|
||||
slot_Periodicity = 5;
|
||||
# Indicates if CSI Reporting is enabled in UNICAST. is 0-ENABLED, 1-DISABLED
|
||||
sl_CSI_Acquisition = 1;
|
||||
sl_LatencyBoundCSI_Report = 8;
|
||||
}
|
||||
);
|
||||
|
||||
sl_AllowedResourceSelectionConfig = 3; // Supported only {0, 3, 4, 6}
|
||||
|
||||
sl_FrequencyCommonConfig = (
|
||||
{
|
||||
sl_offstToCarrier = 0;
|
||||
sl_subcarrierSpacing = 1;//0-15Khz, 1-30Khz
|
||||
sl_carrierBandwidth = 106;//numPRBs
|
||||
#NR bands for Sidelink n47, n38. N47 - 5855Mhz - 5925Mhz
|
||||
#SL SSB chosen to be located from RB10 to RB21. points to the middle of the SSB block.
|
||||
#SSB location should be within Sidelink BWP
|
||||
# this is 2584.95 MHz => 301 REs from PointA 25 PRBs + 1 RE
|
||||
sl_absoluteFrequencySSB = 516990;
|
||||
# this is 2575.92 MHz (center frequency is 2585.1 MHz
|
||||
sl_absoluteFrequencyPointA = 515184;
|
||||
}
|
||||
);
|
||||
|
||||
sl_BWP = (
|
||||
{
|
||||
#RB start 0, RB size = 106. occupies complete Bw.
|
||||
sl_locationAndBandwidth = 28875;
|
||||
# Num Symbols used for Sidelink in an uplink slot
|
||||
# Herein, sl_LengthSymbols represents an index; not the number of symbols.
|
||||
# This index value can be from 0 to 7 representing the (7 to 14 symbols)
|
||||
sl_LengthSymbols = 7;
|
||||
#Sidelink Starting symbol in a slot
|
||||
#Value can be between symbols 0 to 7
|
||||
sl_StartSymbol = 0;
|
||||
}
|
||||
);
|
||||
|
||||
sl_syncCfg = (
|
||||
{
|
||||
#NUM SL-SSB within 16 frames
|
||||
sl_NumSSB_WithinPeriod_0 = 4;
|
||||
#Slot Offset for the first txn in the 16 frame period
|
||||
sl_TimeOffsetSSB_0 = 8;
|
||||
#interval in slots for repetition of SL-SSB
|
||||
sl_TimeInterval_0 = 120;
|
||||
}
|
||||
);
|
||||
sl_ConfiguredGrantConfig = (
|
||||
{
|
||||
sl_NrOfHARQ_Processes = 16;
|
||||
sl_HARQ_ProcID_offset = 0;
|
||||
sl_periodic_rsc_rsr_interval = 100;
|
||||
}
|
||||
);
|
||||
sl_RxResPools = (
|
||||
{
|
||||
#Number of symbols which carry PSCCH.
|
||||
#Possible values 0 means 2 symbols, 1 - means 3 symbols.
|
||||
sl_TimeResourcePSCCH = 0;
|
||||
#Number of RBS which carry PSCCH
|
||||
#Possible values {n10,n12,n15,n20,n25}
|
||||
sl_FreqResourcePSCCH = 1; //12RBs
|
||||
#Size of subchannel in RBs
|
||||
#Possible values - {n10,n12,n15,n20,n25,n50,n75,n100}
|
||||
sl_SubchannelSize = 5;//10RBs
|
||||
#start in RB of the lowest subchannel in a rpool
|
||||
sl_StartRB_Subchannel = 0;
|
||||
#number of PRBs in a rpool
|
||||
sl_RB_Number = 50;
|
||||
sl_NumSubchannel = 1;
|
||||
# period of PSFCH resource in units of slots within this resource pool
|
||||
# Possible values sl0 means no PSFCH resource, {sl0, sl1, sl2, sl4}
|
||||
sl_PSFCH_Period = 0;
|
||||
# Number of cyclic shift pairs used for a PSFCH transmission that can be multiplexed in a PRB
|
||||
# Possible values {n1, n2, n3, n4}
|
||||
sl_NumMuxCS_Pair = 1;
|
||||
# Minimum time gap between PSFCH and the associated PSSCH in the unit of slots {sl2, sl3}
|
||||
sl_MinTimeGapPSFCH = 1; //sl3
|
||||
# Scrambling ID {0..1023} for sequence hopping of the PSFCH used in the resource pool
|
||||
sl_PSFCH_HopID = 1;
|
||||
# Number of PSFCH resources available {startSubCH, allocSubCH} for multiplexing HARQ-ACK information in a PSFCH transmission
|
||||
sl_PSFCH_CandidateResourceType = 0; // startSubCH
|
||||
}
|
||||
);
|
||||
|
||||
sl_TxResPools = (
|
||||
{
|
||||
#Number of symbols which carry PSCCH.
|
||||
#Possible values 0 means 2 symbols, 1 - means 3 symbols.
|
||||
sl_TimeResourcePSCCH = 0;
|
||||
#Number of RBS which carry PSCCH
|
||||
#Possible values {n10,n12,n15,n20,n25}
|
||||
sl_FreqResourcePSCCH = 1; //12RBs
|
||||
#Size of subchannel in RBs
|
||||
#Possible values - {n10,n12,n15,n20,n25,n50,n75,n100}
|
||||
sl_SubchannelSize = 5;//50RBs
|
||||
#start in RB of the lowest subchannel in a rpool
|
||||
sl_StartRB_Subchannel = 0;
|
||||
#number of PRBs in a rpool
|
||||
sl_RB_Number = 50;
|
||||
sl_NumSubchannel = 1;
|
||||
# period of PSFCH resource in units of slots within this resource pool
|
||||
# Possible values sl0 means no PSFCH resource, {sl0, sl1, sl2, sl4}
|
||||
sl_PSFCH_Period = 0;
|
||||
# Number of cyclic shift pairs used for a PSFCH transmission that can be multiplexed in a PRB
|
||||
# Possible values {n1, n2, n3, n4}
|
||||
sl_NumMuxCS_Pair = 1;
|
||||
# Minimum time gap between PSFCH and the associated PSSCH in the unit of slots {sl2, sl3}
|
||||
sl_MinTimeGapPSFCH = 1; //sl3
|
||||
# Scrambling ID {0..1023} for sequence hopping of the PSFCH used in the resource pool
|
||||
sl_PSFCH_HopID = 1;
|
||||
# Number of PSFCH resources available {startSubCH, allocSubCH} for multiplexing HARQ-ACK information in a PSFCH transmission
|
||||
sl_PSFCH_CandidateResourceType = 0; // startSubCH
|
||||
}
|
||||
);
|
||||
|
||||
rsrc_selection_params = (
|
||||
{
|
||||
# Resource selection parameters
|
||||
# sl_Priority = 1;
|
||||
sl_SelectionWindow = 5; // n1, n5, n10, n20} {1,5,10,20}*2^μ
|
||||
sl_Thres_RSRP = 0; // (-128 + (n-1)*2) dBm n is 0..66
|
||||
sl_MaxNumPerReserve = 0; // n2, n3
|
||||
sl_SensingWindow = 100; // {ms100, ms1100}
|
||||
sl_ResourceReservePeriod = 100; //{ms0, ms100, ms200, ms300, ms400, ms500, ms600, ms700, ms800, ms900, ms1000}
|
||||
sl_RS_ForSensing = 0; // 0 pscch, 1 pssch
|
||||
sl_TxPercentage = 0; // index of {20, 35, 50}
|
||||
}
|
||||
);
|
||||
|
||||
sl_UEINFO = (
|
||||
{
|
||||
srcid = 2;
|
||||
thirdOctet = 0;
|
||||
fourthOctet = 3;
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
log_config :
|
||||
{
|
||||
global_log_level = "debug";
|
||||
global_log_verbosity = "high";
|
||||
|
||||
mac_log_level = "debug";
|
||||
mac_log_verbosity = "high";
|
||||
|
||||
phy_log_level = "debug";
|
||||
phy_log_verbosity = "high";
|
||||
|
||||
pdcp_log_level = "debug";
|
||||
pdcp_log_verbosity = "high";
|
||||
|
||||
mac_ue_log_level = "debug";
|
||||
mac_ue_log_verbosity = "high";
|
||||
|
||||
|
||||
pdcp_ue_log_level = "debug";
|
||||
pdcp_ue_log_verbosity = "high";
|
||||
|
||||
sdap_log_level = "debug";
|
||||
sdap_log_verbosity = "high";
|
||||
|
||||
sdap_ue_log_level = "debug";
|
||||
sdap_ue_log_verbosity = "high";
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
);
|
||||
189
targets/PROJECTS/NR-SIDELINK/CONF/ue3.conf
Normal file
189
targets/PROJECTS/NR-SIDELINK/CONF/ue3.conf
Normal file
@@ -0,0 +1,189 @@
|
||||
SIDELINK_PRECONFIGURATION = (
|
||||
{
|
||||
# TDD ULDL CONFIG used for sidelink
|
||||
sl_dl_UL_TransmissionPeriodicity = 6;
|
||||
sl_nrofDownlinkSlots = 6;
|
||||
sl_nrofDownlinkSymbols = 0;
|
||||
sl_nrofUplinkSlots = 4;
|
||||
sl_nrofUplinkSymbols = 0;
|
||||
sl_csi_rs = (
|
||||
{
|
||||
symb_l0 = 5;
|
||||
# csi_type 2 is not supported 38211, 8.4.1.5.3
|
||||
csi_Type = 1;
|
||||
sl_powerControlOffset = 1;
|
||||
sl_powerControlOffsetSS = 1;
|
||||
slot_Offset = 0;
|
||||
slot_Periodicity = 5;
|
||||
# Indicates if CSI Reporting is enabled in UNICAST. is 0-ENABLED, 1-DISABLED
|
||||
sl_CSI_Acquisition = 1;
|
||||
sl_LatencyBoundCSI_Report = 8;
|
||||
}
|
||||
);
|
||||
|
||||
sl_AllowedResourceSelectionConfig = 3; // Supported only {0, 3, 4, 6}
|
||||
|
||||
sl_FrequencyCommonConfig = (
|
||||
{
|
||||
sl_offstToCarrier = 0;
|
||||
sl_subcarrierSpacing = 1;//0-15Khz, 1-30Khz
|
||||
sl_carrierBandwidth = 106;//numPRBs
|
||||
#NR bands for Sidelink n47, n38. N47 - 5855Mhz - 5925Mhz
|
||||
#SL SSB chosen to be located from RB10 to RB21. points to the middle of the SSB block.
|
||||
#SSB location should be within Sidelink BWP
|
||||
# this is 2584.95 MHz => 301 REs from PointA 25 PRBs + 1 RE
|
||||
sl_absoluteFrequencySSB = 516990;
|
||||
# this is 2575.92 MHz (center frequency is 2585.1 MHz
|
||||
sl_absoluteFrequencyPointA = 515184;
|
||||
}
|
||||
);
|
||||
|
||||
sl_BWP = (
|
||||
{
|
||||
#RB start 0, RB size = 106. occupies complete Bw.
|
||||
sl_locationAndBandwidth = 28875;
|
||||
# Num Symbols used for Sidelink in an uplink slot
|
||||
# Herein, sl_LengthSymbols represents an index; not the number of symbols.
|
||||
# This index value can be from 0 to 7 representing the (7 to 14 symbols)
|
||||
sl_LengthSymbols = 7;
|
||||
#Sidelink Starting symbol in a slot
|
||||
#Value can be between symbols 0 to 7
|
||||
sl_StartSymbol = 0;
|
||||
}
|
||||
);
|
||||
|
||||
sl_syncCfg = (
|
||||
{
|
||||
#NUM SL-SSB within 16 frames
|
||||
sl_NumSSB_WithinPeriod_0 = 4;
|
||||
#Slot Offset for the first txn in the 16 frame period
|
||||
sl_TimeOffsetSSB_0 = 8;
|
||||
#interval in slots for repetition of SL-SSB
|
||||
sl_TimeInterval_0 = 120;
|
||||
}
|
||||
);
|
||||
sl_ConfiguredGrantConfig = (
|
||||
{
|
||||
sl_NrOfHARQ_Processes = 16;
|
||||
sl_HARQ_ProcID_offset = 0;
|
||||
sl_periodic_rsc_rsr_interval = 100;
|
||||
}
|
||||
);
|
||||
sl_RxResPools = (
|
||||
{
|
||||
#Number of symbols which carry PSCCH.
|
||||
#Possible values 0 means 2 symbols, 1 - means 3 symbols.
|
||||
sl_TimeResourcePSCCH = 0;
|
||||
#Number of RBS which carry PSCCH
|
||||
#Possible values {n10,n12,n15,n20,n25}
|
||||
sl_FreqResourcePSCCH = 1; //12RBs
|
||||
#Size of subchannel in RBs
|
||||
#Possible values - {n10,n12,n15,n20,n25,n50,n75,n100}
|
||||
sl_SubchannelSize = 5;//10RBs
|
||||
#start in RB of the lowest subchannel in a rpool
|
||||
sl_StartRB_Subchannel = 0;
|
||||
#number of PRBs in a rpool
|
||||
sl_RB_Number = 50;
|
||||
sl_NumSubchannel = 1;
|
||||
# period of PSFCH resource in units of slots within this resource pool
|
||||
# Possible values sl0 means no PSFCH resource, {sl0, sl1, sl2, sl4}
|
||||
sl_PSFCH_Period = 0;
|
||||
# Number of cyclic shift pairs used for a PSFCH transmission that can be multiplexed in a PRB
|
||||
# Possible values {n1, n2, n3, n4}
|
||||
sl_NumMuxCS_Pair = 1;
|
||||
# Minimum time gap between PSFCH and the associated PSSCH in the unit of slots {sl2, sl3}
|
||||
sl_MinTimeGapPSFCH = 1; //sl3
|
||||
# Scrambling ID {0..1023} for sequence hopping of the PSFCH used in the resource pool
|
||||
sl_PSFCH_HopID = 1;
|
||||
# Number of PSFCH resources available {startSubCH, allocSubCH} for multiplexing HARQ-ACK information in a PSFCH transmission
|
||||
sl_PSFCH_CandidateResourceType = 0; // startSubCH
|
||||
}
|
||||
);
|
||||
|
||||
sl_TxResPools = (
|
||||
{
|
||||
#Number of symbols which carry PSCCH.
|
||||
#Possible values 0 means 2 symbols, 1 - means 3 symbols.
|
||||
sl_TimeResourcePSCCH = 0;
|
||||
#Number of RBS which carry PSCCH
|
||||
#Possible values {n10,n12,n15,n20,n25}
|
||||
sl_FreqResourcePSCCH = 1; //12RBs
|
||||
#Size of subchannel in RBs
|
||||
#Possible values - {n10,n12,n15,n20,n25,n50,n75,n100}
|
||||
sl_SubchannelSize = 5;//50RBs
|
||||
#start in RB of the lowest subchannel in a rpool
|
||||
sl_StartRB_Subchannel = 0;
|
||||
#number of PRBs in a rpool
|
||||
sl_RB_Number = 50;
|
||||
sl_NumSubchannel = 1;
|
||||
# period of PSFCH resource in units of slots within this resource pool
|
||||
# Possible values sl0 means no PSFCH resource, {sl0, sl1, sl2, sl4}
|
||||
sl_PSFCH_Period = 0;
|
||||
# Number of cyclic shift pairs used for a PSFCH transmission that can be multiplexed in a PRB
|
||||
# Possible values {n1, n2, n3, n4}
|
||||
sl_NumMuxCS_Pair = 1;
|
||||
# Minimum time gap between PSFCH and the associated PSSCH in the unit of slots {sl2, sl3}
|
||||
sl_MinTimeGapPSFCH = 1; //sl3
|
||||
# Scrambling ID {0..1023} for sequence hopping of the PSFCH used in the resource pool
|
||||
sl_PSFCH_HopID = 1;
|
||||
# Number of PSFCH resources available {startSubCH, allocSubCH} for multiplexing HARQ-ACK information in a PSFCH transmission
|
||||
sl_PSFCH_CandidateResourceType = 0; // startSubCH
|
||||
}
|
||||
);
|
||||
|
||||
rsrc_selection_params = (
|
||||
{
|
||||
# Resource selection parameters
|
||||
# sl_Priority = 1;
|
||||
sl_SelectionWindow = 5; // n1, n5, n10, n20} {1,5,10,20}*2^μ
|
||||
sl_Thres_RSRP = 0; // (-128 + (n-1)*2) dBm n is 0..66
|
||||
sl_MaxNumPerReserve = 0; // n2, n3
|
||||
sl_SensingWindow = 100; // {ms100, ms1100}
|
||||
sl_ResourceReservePeriod = 100; //{ms0, ms100, ms200, ms300, ms400, ms500, ms600, ms700, ms800, ms900, ms1000}
|
||||
sl_RS_ForSensing = 0; // 0 pscch, 1 pssch
|
||||
sl_TxPercentage = 0; // index of {20, 35, 50}
|
||||
}
|
||||
);
|
||||
|
||||
sl_UEINFO = (
|
||||
{
|
||||
srcid = 3;
|
||||
thirdOctet = 0;
|
||||
fourthOctet = 4;
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
log_config :
|
||||
{
|
||||
global_log_level = "debug";
|
||||
global_log_verbosity = "high";
|
||||
|
||||
mac_log_level = "debug";
|
||||
mac_log_verbosity = "high";
|
||||
|
||||
phy_log_level = "debug";
|
||||
phy_log_verbosity = "high";
|
||||
|
||||
pdcp_log_level = "debug";
|
||||
pdcp_log_verbosity = "high";
|
||||
|
||||
mac_ue_log_level = "debug";
|
||||
mac_ue_log_verbosity = "high";
|
||||
|
||||
pdcp_ue_log_level = "debug";
|
||||
pdcp_ue_log_verbosity = "high";
|
||||
|
||||
sdap_log_level = "debug";
|
||||
sdap_log_verbosity = "high";
|
||||
|
||||
sdap_ue_log_level = "debug";
|
||||
sdap_ue_log_verbosity = "high";
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
);
|
||||
Reference in New Issue
Block a user