Compare commits

...

24 Commits

Author SHA1 Message Date
J.Y
439bcdf9f8 reverse TDMA to hardcoded 2026-05-28 09:39:06 +02:00
J.Y
4d21f2fd3e add flag for sl-nas SLC control, by run with or without --sl-nas 2026-05-06 16:14:45 +02:00
J.Y
bcac6783da modify hardcoded QFI 2026-04-28 15:27:48 +02:00
J.Y
f35a75baa2 debug bearer 2026-04-19 10:20:16 +02:00
J.Y
ef201f1419 fix SLC bearer control 2026-04-09 15:18:04 +02:00
J.Y
eb38ab0a56 add SLC for resource pool 2026-04-07 15:26:53 +02:00
J.Y
26700cbb18 SLC modification for scheduler 2026-03-20 14:54:35 +01:00
J.Y
bbaf90c64d update Readme ASN 2026-03-17 14:09:15 +01:00
J.Y
5c0497c92a Enable support for >3 UEs 2026-03-06 14:11:15 +01:00
J.Y
13c035ef77 fix bug 2026-03-02 11:15:55 +01:00
Jérôme Härri
9c9e50391e PC5_S PC5_C controller revision 1 2026-02-20 15:56:37 +01:00
Jérôme Härri
801886c8d9 PC5_S PC5_C controller 2026-02-19 12:31:00 +01:00
J.Y
a957cc7b59 update manual 2026-02-17 15:04:51 +01:00
J.Y
6eba4d2abe Batman works! 2026-02-13 15:06:38 +01:00
J.Y
82af5bb27b SDAP reached, not batman 2026-02-13 12:10:04 +01:00
J.Y
7d0119efa6 PDCP patch, batman can show two neighbours, but not on routing table yet 2026-02-06 16:49:06 +01:00
J.Y
c67c11b380 updated TAP, unfinished, now second UE broke on PDCP layer 2026-02-06 14:11:51 +01:00
J.Y
92c5b04cdb TAP version1; problem with batman 2026-02-04 10:28:06 +01:00
J.Y
ad6e003ad3 clean log 2026-02-01 09:10:03 +01:00
J.Y
0a1d4ba709 working version multiple UEs 2026-01-30 18:23:45 +01:00
beraoudabdelkhalek
9ae927b862 Updated JSUC.md 2025-05-15 19:21:41 +02:00
beraoudabdelkhalek
fd54152a53 Added diagram 2025-05-15 19:20:12 +02:00
beraoudabdelkhalek
d01693b901 Added JSUC doc 2025-05-15 11:59:37 +02:00
beraoudabdelkhalek
cf65d02fd4 Added pubsub RFsim, enabled CSI reporting 2025-05-08 16:40:01 +02:00
44 changed files with 3815 additions and 422 deletions

376
README.md
View File

@@ -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

Submodule cmake_targets/babeld added at 950992f282

View File

@@ -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
View 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
View 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.
![Hybrid Communication Setup Diagram](doc/images/hybrid_communication_setup.png)
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`

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

View File

@@ -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;

View File

@@ -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);

View File

@@ -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

View File

@@ -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

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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");

View File

@@ -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,

View File

@@ -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

View File

@@ -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[];

View File

@@ -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;

View File

@@ -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);

View File

@@ -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;

View File

@@ -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) {

View File

@@ -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

View File

@@ -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.

View File

@@ -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) {

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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

View File

@@ -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 */
/***********************************************************************/

View File

@@ -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 */
}

View File

@@ -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;
/***********************************************************************/

View 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];

View File

@@ -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;
}

View File

@@ -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
/** @} */

View File

@@ -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

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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})

View 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;
}

View File

@@ -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);

View File

@@ -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";
}
}
);

View File

@@ -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;
}
);

View 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";
}
}
);

View 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";
}
}
);

View 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";
}
}
);