mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-19 23:50:30 +00:00
Compare commits
25 Commits
runel-reve
...
new_pdcp
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f141935669 | ||
|
|
cba6c72f3b | ||
|
|
9759746ec9 | ||
|
|
d0bc934f20 | ||
|
|
4f73f79b8b | ||
|
|
f28a5e2de1 | ||
|
|
61bcf7b736 | ||
|
|
64a5f68572 | ||
|
|
4f55943b3b | ||
|
|
0ab5a4c590 | ||
|
|
b365b57cf4 | ||
|
|
50962242dd | ||
|
|
3ad36982dd | ||
|
|
0b7489b122 | ||
|
|
445cf84e94 | ||
|
|
b7908ec25d | ||
|
|
c94a3b85e9 | ||
|
|
09fefc7162 | ||
|
|
03526f90a8 | ||
|
|
7090357e53 | ||
|
|
6a9c5884f3 | ||
|
|
c71e763919 | ||
|
|
8e17a35cef | ||
|
|
c86f8d6539 | ||
|
|
0fe0dd89bb |
7
ci-scripts/.gitignore
vendored
Normal file
7
ci-scripts/.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
enb_*.log
|
||||
ue_*.log
|
||||
ping_*.*
|
||||
iperf_*.*
|
||||
phones_list.txt
|
||||
modules_list.txt
|
||||
test_results*.html
|
||||
421
ci-scripts/Jenkinsfile-inria-r2lab
Normal file
421
ci-scripts/Jenkinsfile-inria-r2lab
Normal file
@@ -0,0 +1,421 @@
|
||||
#!/bin/groovy
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
// Abstraction function to send social media messages:
|
||||
// like on Slack or Mattermost
|
||||
def sendSocialMediaMessage(pipeChannel, pipeColor, pipeMessage) {
|
||||
if (params.pipelineUsesSlack != null) {
|
||||
if (params.pipelineUsesSlack) {
|
||||
slackSend channel: pipeChannel, color: pipeColor, message: pipeMessage
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Location of the test XML file to be run
|
||||
def testXMLFile = params.pythonTestXmlFile
|
||||
def mainPythonAllXmlFiles = ""
|
||||
def buildStageStatus = true
|
||||
|
||||
// Name of the test stage
|
||||
def testStageName = params.pipelineTestStageName
|
||||
|
||||
// Name of the branch to work on
|
||||
def ranRepoBranch = params.pythonWorkingBranch
|
||||
|
||||
// Lease booking parameters
|
||||
def r2labStartTime = params.R2LAB_LeaseBookStartTime
|
||||
def r2labDuration = params.R2LAB_LeaseBookDuration
|
||||
|
||||
|
||||
// Fixed deployment
|
||||
def r2labBaseIpAddr = '192.168.3.'
|
||||
def r2labPythonExeIdx = '14'
|
||||
def r2labPythonExe = 'fit' + r2labPythonExeIdx
|
||||
def r2labENB0Idx = '23'
|
||||
def r2labENB0 = 'fit' + r2labENB0Idx
|
||||
def r2labENB0IpAddr = r2labBaseIpAddr + r2labENB0Idx
|
||||
def r2labEPC0Idx = '17'
|
||||
def r2labEPC0 = 'fit' + r2labEPC0Idx
|
||||
def r2labEPC0IpAddr = r2labBaseIpAddr + r2labEPC0Idx
|
||||
def r2labUE0Idx = '6'
|
||||
def r2labUE0 = 'fit0' + r2labUE0Idx
|
||||
def r2labUE0IpAddr = r2labBaseIpAddr + r2labUE0Idx
|
||||
|
||||
pipeline {
|
||||
agent {
|
||||
label 'master'
|
||||
}
|
||||
|
||||
options {
|
||||
disableConcurrentBuilds()
|
||||
timestamps()
|
||||
ansiColor('xterm')
|
||||
}
|
||||
|
||||
stages {
|
||||
stage ("Book session") {
|
||||
steps {
|
||||
script {
|
||||
echo '\u2705 \u001B[32mVerify Parameters\u001B[0m'
|
||||
|
||||
def allParametersPresent = true
|
||||
if (params.R2LAB_Credentials == null) {
|
||||
allParametersPresent = false
|
||||
}
|
||||
if (params.R2LAB_FitNode_Credentials == null) {
|
||||
allParametersPresent = false
|
||||
}
|
||||
if (params.R2LAB_LeaseBookStartTime == null) {
|
||||
allParametersPresent = false
|
||||
}
|
||||
if (params.R2LAB_LeaseBookDuration == null) {
|
||||
allParametersPresent = false
|
||||
}
|
||||
|
||||
// If not present picking a default Stage Name
|
||||
if (params.pipelineTestStageName == null) {
|
||||
// picking default
|
||||
testStageName = 'Tests at Inria R2LAB'
|
||||
}
|
||||
// If not present picking a default branch name
|
||||
if (params.pythonWorkingBranch == null) {
|
||||
ranRepoBranch = 'develop'
|
||||
}
|
||||
|
||||
if (params.pythonTestXmlFile == null) {
|
||||
// picking default
|
||||
testXMLFile = 'xml_files/inria/enb_usrp210_band7_build.xml'
|
||||
echo "Test XML file(default): ${testXMLFile}"
|
||||
mainPythonAllXmlFiles += "--XMLTestFile=" + testXMLFile + " "
|
||||
} else {
|
||||
String[] myXmlTestSuite = testXMLFile.split("\\r?\\n")
|
||||
for (xmlFile in myXmlTestSuite) {
|
||||
mainPythonAllXmlFiles += "--XMLTestFile=" + xmlFile + " "
|
||||
echo "Test XML file : ${xmlFile}"
|
||||
}
|
||||
}
|
||||
|
||||
if (!allParametersPresent) {
|
||||
currentBuild.result = 'ABORTED'
|
||||
error('Stopping early because no R2LAB credentials')
|
||||
}
|
||||
|
||||
JOB_TIMESTAMP = sh returnStdout: true, script: 'date --rfc-3339=seconds | sed -e "s#+00:00##"'
|
||||
JOB_TIMESTAMP = JOB_TIMESTAMP.trim()
|
||||
|
||||
echo '\u2705 \u001B[32mBook a Session\u001B[0m'
|
||||
|
||||
BOOK_TIMESTAMP = sh returnStdout: true, script: 'date --rfc-3339=date'
|
||||
BOOK_TIMESTAMP = BOOK_TIMESTAMP.trim()
|
||||
|
||||
withCredentials([
|
||||
[$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.R2LAB_Credentials}", usernameVariable: 'r2labuser', passwordVariable: 'r2labpassword']
|
||||
]) {
|
||||
sh "python3 /home/eurecom/inria-scripts/booking-lease.py --book-lease --from ${BOOK_TIMESTAMP}T${r2labStartTime} --duration ${r2labDuration} --slice inria_oaici ${r2labuser} ${r2labpassword}"
|
||||
sh "python3 /home/eurecom/inria-scripts/booking-lease.py --get-leases ${r2labuser} ${r2labpassword}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage ("Load Images") {
|
||||
steps {
|
||||
script {
|
||||
echo '\u2705 \u001B[32mLoad Image for Python Executor\u001B[0m'
|
||||
sh "ssh -t inria_oaici@faraday.inria.fr 'rload -i oai-ci-cd-u18-lowlatency-enb-ue ${r2labPythonExeIdx} > /dev/null 2>&1'"
|
||||
sh "ssh -t inria_oaici@faraday.inria.fr 'rwait --silent ${r2labPythonExeIdx}'"
|
||||
|
||||
echo '\u2705 \u001B[32mLoad Image for one eNB\u001B[0m'
|
||||
sh "ssh -t inria_oaici@faraday.inria.fr 'rload -i oai-ci-cd-u18-lowlatency-enb-ue ${r2labENB0Idx} > /dev/null 2>&1'"
|
||||
sh "ssh -t inria_oaici@faraday.inria.fr 'rwait --silent ${r2labENB0Idx}'"
|
||||
sh "ssh -t inria_oaici@faraday.inria.fr 'uon ${r2labENB0Idx}'"
|
||||
|
||||
echo '\u2705 \u001B[32mLoad Image for one OAI UE\u001B[0m'
|
||||
sh "ssh -t inria_oaici@faraday.inria.fr 'rload -i oai-ci-cd-u18-lowlatency-enb-ue ${r2labUE0Idx} > /dev/null 2>&1'"
|
||||
sh "ssh -t inria_oaici@faraday.inria.fr 'rwait --silent ${r2labUE0Idx}'"
|
||||
sh "ssh -t inria_oaici@faraday.inria.fr 'uon ${r2labUE0Idx}'"
|
||||
|
||||
echo '\u2705 \u001B[32mLoad Image for one EPC\u001B[0m'
|
||||
sh "ssh -t inria_oaici@faraday.inria.fr 'rload -i oai-ci-cd-u18-lowlatency-epc ${r2labEPC0Idx} > /dev/null 2>&1'"
|
||||
sh "ssh -t inria_oaici@faraday.inria.fr 'rwait --silent ${r2labEPC0Idx}'"
|
||||
|
||||
sh "ssh -t inria_oaici@faraday.inria.fr 'nodes ${r2labUE0Idx},${r2labPythonExeIdx},${r2labEPC0Idx},${r2labENB0Idx} && st'"
|
||||
}
|
||||
}
|
||||
}
|
||||
stage ("Prepare Python Executor") {
|
||||
steps {
|
||||
script {
|
||||
withCredentials([
|
||||
[$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.R2LAB_FitNode_Credentials}", usernameVariable: 'fituser', passwordVariable: 'fitpasswd']
|
||||
]) {
|
||||
sh "ssh -t inria_oaici@faraday.inria.fr 'ssh -t -b 192.168.3.100 ${fituser}@${r2labPythonExe} \"cd openairinterface5g && git fetch --all --prune --quiet\"'"
|
||||
sh "ssh -t inria_oaici@faraday.inria.fr 'ssh -t -b 192.168.3.100 ${fituser}@${r2labPythonExe} \"cd openairinterface5g && git checkout --quiet ${ranRepoBranch}\"'"
|
||||
sh "ssh -t inria_oaici@faraday.inria.fr 'ssh -t -b 192.168.3.100 ${fituser}@${r2labPythonExe} \"cd openairinterface5g && git pull --quiet origin ${ranRepoBranch}\"'"
|
||||
GIT_COMMIT_TO_RUN = sh returnStdout: true, script: "ssh -t inria_oaici@faraday.inria.fr 'ssh -t -b 192.168.3.100 ${fituser}@${r2labPythonExe} \"cd openairinterface5g && git log -n1 --pretty=format:%H\"' | grep -v fit"
|
||||
GIT_COMMIT_TO_RUN = GIT_COMMIT_TO_RUN.trim()
|
||||
echo "Latest commit to use is ${GIT_COMMIT_TO_RUN}"
|
||||
|
||||
// Putting the adaptation parameters for the OAI UE
|
||||
sh "ssh -t inria_oaici@faraday.inria.fr 'scp /home/inria_oaici/for-ci/adapt_usim_parameters_${r2labUE0}.sed ${fituser}@${r2labUE0}:/tmp/adapt_usim_parameters.sed'"
|
||||
sh "ssh -t inria_oaici@faraday.inria.fr 'scp /home/inria_oaici/for-ci/phones_list.txt ${fituser}@${r2labEPC0}:/tmp'"
|
||||
sh "ssh -t inria_oaici@faraday.inria.fr 'ssh -t -b 192.168.3.100 ${fituser}@${r2labEPC0} \"echo ${fitpasswd} | sudo -S cp /tmp/phones_list.txt /etc/ci\"'"
|
||||
|
||||
// Out of rload, the sub-network-interfaces are not up
|
||||
sh "ssh -t inria_oaici@faraday.inria.fr 'ssh -t -b 192.168.3.100 ${fituser}@${r2labEPC0} \"echo ${fitpasswd} | sudo -S ifconfig control:m11 172.16.1.102 up\"'"
|
||||
sh "ssh -t inria_oaici@faraday.inria.fr 'ssh -t -b 192.168.3.100 ${fituser}@${r2labEPC0} \"echo ${fitpasswd} | sudo -S ifconfig control:m10 192.168.10.110 up\"'"
|
||||
sh "ssh -t inria_oaici@faraday.inria.fr 'ssh -t -b 192.168.3.100 ${fituser}@${r2labEPC0} \"echo ${fitpasswd} | sudo -S ifconfig control:sxu 172.55.55.102 up\"'"
|
||||
sh "ssh -t inria_oaici@faraday.inria.fr 'ssh -t -b 192.168.3.100 ${fituser}@${r2labEPC0} \"echo ${fitpasswd} | sudo -S ifconfig control:s1u 192.168.248.159 up\"'"
|
||||
sh "ssh -t inria_oaici@faraday.inria.fr 'ssh -t -b 192.168.3.100 ${fituser}@${r2labEPC0} \"echo ${fitpasswd} | sudo -S ifconfig control:sxc 172.55.55.101 up\"'"
|
||||
sh "ssh -t inria_oaici@faraday.inria.fr 'ssh -t -b 192.168.3.100 ${fituser}@${r2labEPC0} \"echo ${fitpasswd} | sudo -S ifconfig control:s5c 172.58.58.102 up\"'"
|
||||
sh "ssh -t inria_oaici@faraday.inria.fr 'ssh -t -b 192.168.3.100 ${fituser}@${r2labEPC0} \"echo ${fitpasswd} | sudo -S ifconfig control:p5c 172.58.58.101 up\"'"
|
||||
sh "ssh -t inria_oaici@faraday.inria.fr 'ssh -t -b 192.168.3.100 ${fituser}@${r2labEPC0} \"echo ${fitpasswd} | sudo -S ifconfig control:s11 172.16.1.104 up\"'"
|
||||
sh "ssh -t inria_oaici@faraday.inria.fr 'ssh -t -b 192.168.3.100 ${fituser}@${r2labEPC0} \"ifconfig\"'"
|
||||
|
||||
// Adding routes on the EPC
|
||||
sh "ssh -t inria_oaici@faraday.inria.fr 'ssh -t -b 192.168.3.100 ${fituser}@${r2labEPC0} \"echo ${fitpasswd} | sudo -S ip route add default via 192.168.3.100 dev control table lte\"'"
|
||||
sh "ssh -t inria_oaici@faraday.inria.fr 'ssh -t -b 192.168.3.100 ${fituser}@${r2labEPC0} \"echo ${fitpasswd} | sudo -S ip rule add from 12.0.0.0/8 table lte\"'"
|
||||
sh "ssh -t inria_oaici@faraday.inria.fr 'ssh -t -b 192.168.3.100 ${fituser}@${r2labEPC0} \"echo ${fitpasswd} | sudo -S ip rule add from 12.1.1.0/8 table lte\"'"
|
||||
|
||||
// Adding a route on the eNB for the S1U interface
|
||||
sh "ssh -t inria_oaici@faraday.inria.fr 'ssh -t -b 192.168.3.100 ${fituser}@${r2labENB0} \"echo ${fitpasswd} | sudo -S ip route add 192.168.248.0/24 via ${r2labEPC0IpAddr} dev control\"'"
|
||||
|
||||
// For the moment, simple way to route traffic from python executor to any UEs
|
||||
sh "ssh -t inria_oaici@faraday.inria.fr 'ssh -t -b 192.168.3.100 ${fituser}@${r2labPythonExe} \"echo ${fitpasswd} | sudo -S ip route add 12.1.1.0/24 via ${r2labEPC0IpAddr} dev control\"'"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage ("Build and Test") {
|
||||
steps {
|
||||
script {
|
||||
withCredentials([
|
||||
[$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.R2LAB_FitNode_Credentials}", usernameVariable: 'fituser', passwordVariable: 'fitpasswd']
|
||||
]) {
|
||||
sh "ssh -t -t inria_oaici@faraday.inria.fr 'ssh -t -t -b 192.168.3.100 ${fituser}@${r2labPythonExe} \"cd openairinterface5g/ci-scripts && python3 main.py --mode=InitiateHtml --ranRepository=https://gitlab.eurecom.fr/oai/openairinterface5g --ranBranch=${ranRepoBranch} --ranCommitID=${GIT_COMMIT_TO_RUN} --ranAllowMerge=false --ADBIPAddress=${r2labEPC0IpAddr} --ADBUserName=${fituser} --ADBPassword=${fitpasswd} --ADBType=distributed ${mainPythonAllXmlFiles}\"'"
|
||||
String[] myXmlTestSuite = testXMLFile.split("\\r?\\n")
|
||||
for (xmlFile in myXmlTestSuite) {
|
||||
try {
|
||||
sh "ssh -t -t inria_oaici@faraday.inria.fr 'ssh -t -t -b 192.168.3.100 ${fituser}@${r2labPythonExe} \"cd openairinterface5g/ci-scripts && python3 main.py --mode=TesteNB --ranRepository=https://gitlab.eurecom.fr/oai/openairinterface5g --ranBranch=${ranRepoBranch} --ranCommitID=${GIT_COMMIT_TO_RUN} --ranAllowMerge=false --eNBIPAddress=${r2labENB0IpAddr} --eNBUserName=${fituser} --eNBPassword=${fitpasswd} --eNBSourceCodePath=/home/${fituser}/openairinterface5g --UEIPAddress=${r2labUE0IpAddr} --UEUserName=${fituser} --UEPassword=${fitpasswd} --UESourceCodePath=/home/${fituser}/openairinterface5g --EPCIPAddress=${r2labEPC0IpAddr} --EPCType=OAI-Rel14-CUPS --EPCUserName=${fituser} --EPCPassword=${fitpasswd} --EPCSourceCodePath=/home/${fituser}/openair-cn --ADBIPAddress=${r2labEPC0IpAddr} --ADBUserName=${fituser} --ADBPassword=${fitpasswd} --ADBType=distributed --XMLTestFile=${xmlFile}\"'"
|
||||
} catch (Exception e) {
|
||||
currentBuild.result = 'FAILURE'
|
||||
buildStageStatus = false
|
||||
}
|
||||
}
|
||||
sh "ssh -t -t inria_oaici@faraday.inria.fr 'ssh -t -t -b 192.168.3.100 ${fituser}@${r2labPythonExe} \"cd openairinterface5g/ci-scripts && python3 main.py --mode=FinalizeHtml --finalStatus=${buildStageStatus} --eNBIPAddress=${r2labENB0IpAddr} --eNBUserName=${fituser} --eNBPassword=${fitpasswd}\"'"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage ("Prepare Log Collection") {
|
||||
steps {
|
||||
sh "ssh -t inria_oaici@faraday.inria.fr 'mkdir -p /home/inria_oaici/archives'"
|
||||
sh "ssh -t inria_oaici@faraday.inria.fr 'touch /home/inria_oaici/archives/no_error.txt'"
|
||||
sh "ssh -t inria_oaici@faraday.inria.fr 'rm -f /home/inria_oaici/archives/*.*'"
|
||||
withCredentials([
|
||||
[$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.R2LAB_FitNode_Credentials}", usernameVariable: 'fituser', passwordVariable: 'fitpasswd']
|
||||
]) {
|
||||
sh "ssh -t inria_oaici@faraday.inria.fr 'scp ${fituser}@${r2labPythonExe}:/home/${fituser}/openairinterface5g/ci-scripts/test_results.html /home/inria_oaici/archives'"
|
||||
}
|
||||
sh "scp inria_oaici@faraday.inria.fr:/home/inria_oaici/archives/test_results.html ."
|
||||
script {
|
||||
if(fileExists("./test_results.html")) {
|
||||
sh "mv ./test_results.html test_results-${JOB_NAME}.html"
|
||||
sh "sed -i -e 's#TEMPLATE_JOB_NAME#${JOB_NAME}#' -e 's@build #TEMPLATE_BUILD_ID@build #${BUILD_ID}@' -e 's#Build-ID: TEMPLATE_BUILD_ID#Build-ID: <a href=\"${BUILD_URL}\">${BUILD_ID}</a>#' -e 's#TEMPLATE_STAGE_NAME#${testStageName}#' -e 's#TEMPLATE_BUILD_TIME#${JOB_TIMESTAMP}#' test_results-${JOB_NAME}.html"
|
||||
archiveArtifacts "test_results-${JOB_NAME}.html"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage ("Log Collection") {
|
||||
parallel {
|
||||
stage('Log Collection (OAI eNB - Build)') {
|
||||
steps {
|
||||
withCredentials([
|
||||
[$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.R2LAB_FitNode_Credentials}", usernameVariable: 'fituser', passwordVariable: 'fitpasswd']
|
||||
]) {
|
||||
echo '\u2705 \u001B[32mLog Collection (OAI eNB - Build)\u001B[0m'
|
||||
sh "ssh -t -t inria_oaici@faraday.inria.fr 'ssh -t -t -b 192.168.3.100 ${fituser}@${r2labPythonExe} \"cd openairinterface5g/ci-scripts && python3 main.py --mode=LogCollectBuild --eNBIPAddress=${r2labENB0IpAddr} --eNBUserName=${fituser} --eNBPassword=${fitpasswd} --eNBSourceCodePath=/home/${fituser}/openairinterface5g\"'"
|
||||
sh "ssh -t inria_oaici@faraday.inria.fr 'scp ${fituser}@${r2labENB0}:/home/${fituser}/openairinterface5g/cmake_targets/build.log.zip /home/inria_oaici/archives/enb.build.log.zip'"
|
||||
}
|
||||
sh "scp inria_oaici@faraday.inria.fr:/home/inria_oaici/archives/enb.build.log.zip enb.build.log.${env.BUILD_ID}.zip"
|
||||
script {
|
||||
if(fileExists("enb.build.log.${env.BUILD_ID}.zip")) {
|
||||
archiveArtifacts "enb.build.log.${env.BUILD_ID}.zip"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Log Collection (OAI UE - Build)') {
|
||||
steps {
|
||||
withCredentials([
|
||||
[$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.R2LAB_FitNode_Credentials}", usernameVariable: 'fituser', passwordVariable: 'fitpasswd']
|
||||
]) {
|
||||
echo '\u2705 \u001B[32mLog Collection (OAI UE - Build)\u001B[0m'
|
||||
sh "ssh -t -t inria_oaici@faraday.inria.fr 'ssh -t -t -b 192.168.3.100 ${fituser}@${r2labPythonExe} \"cd openairinterface5g/ci-scripts && python3 main.py --mode=LogCollectBuild --UEIPAddress=${r2labUE0IpAddr} --UEUserName=${fituser} --UEPassword=${fitpasswd} --UESourceCodePath=/home/${fituser}/openairinterface5g\"'"
|
||||
sh "ssh -t inria_oaici@faraday.inria.fr 'scp ${fituser}@${r2labUE0}:/home/${fituser}/openairinterface5g/cmake_targets/build.log.zip /home/inria_oaici/archives/ue.build.log.zip'"
|
||||
}
|
||||
sh "scp inria_oaici@faraday.inria.fr:/home/inria_oaici/archives/ue.build.log.zip ue.build.log.${env.BUILD_ID}.zip"
|
||||
script {
|
||||
if(fileExists("ue.build.log.${env.BUILD_ID}.zip")) {
|
||||
archiveArtifacts "ue.build.log.${env.BUILD_ID}.zip"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Log Collection (OAI eNB - Runs)') {
|
||||
steps {
|
||||
withCredentials([
|
||||
[$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.R2LAB_FitNode_Credentials}", usernameVariable: 'fituser', passwordVariable: 'fitpasswd']
|
||||
]) {
|
||||
echo '\u2705 \u001B[32mLog Collection (OAI eNB - Runs)\u001B[0m'
|
||||
sh "ssh -t -t inria_oaici@faraday.inria.fr 'ssh -t -t -b 192.168.3.100 ${fituser}@${r2labPythonExe} \"cd openairinterface5g/ci-scripts && python3 main.py --mode=LogCollecteNB --eNBIPAddress=${r2labENB0IpAddr} --eNBUserName=${fituser} --eNBPassword=${fitpasswd} --eNBSourceCodePath=/home/${fituser}/openairinterface5g\"'"
|
||||
sh "ssh -t inria_oaici@faraday.inria.fr 'scp ${fituser}@${r2labENB0}:/home/${fituser}/openairinterface5g/cmake_targets/enb.log.zip /home/inria_oaici/archives/enb.run.log.zip'"
|
||||
}
|
||||
sh "scp inria_oaici@faraday.inria.fr:/home/inria_oaici/archives/enb.run.log.zip enb.run.log.${env.BUILD_ID}.zip"
|
||||
script {
|
||||
if(fileExists("enb.run.log.${env.BUILD_ID}.zip")) {
|
||||
archiveArtifacts "enb.run.log.${env.BUILD_ID}.zip"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Log Collection (OAI UE - Runs)') {
|
||||
steps {
|
||||
withCredentials([
|
||||
[$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.R2LAB_FitNode_Credentials}", usernameVariable: 'fituser', passwordVariable: 'fitpasswd']
|
||||
]) {
|
||||
echo '\u2705 \u001B[32mLog Collection (OAI UE - Runs)\u001B[0m'
|
||||
sh "ssh -t -t inria_oaici@faraday.inria.fr 'ssh -t -t -b 192.168.3.100 ${fituser}@${r2labPythonExe} \"cd openairinterface5g/ci-scripts && python3 main.py --mode=LogCollectOAIUE --UEIPAddress=${r2labUE0IpAddr} --UEUserName=${fituser} --UEPassword=${fitpasswd} --UESourceCodePath=/home/${fituser}/openairinterface5g\"'"
|
||||
sh "ssh -t inria_oaici@faraday.inria.fr 'scp ${fituser}@${r2labUE0}:/home/${fituser}/openairinterface5g/cmake_targets/ue.log.zip /home/inria_oaici/archives/ue.run.log.zip'"
|
||||
}
|
||||
sh "scp inria_oaici@faraday.inria.fr:/home/inria_oaici/archives/ue.run.log.zip ue.run.log.${env.BUILD_ID}.zip"
|
||||
script {
|
||||
if(fileExists("ue.run.log.${env.BUILD_ID}.zip")) {
|
||||
archiveArtifacts "ue.run.log.${env.BUILD_ID}.zip"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Log Collection (MME)') {
|
||||
steps {
|
||||
withCredentials([
|
||||
[$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.R2LAB_FitNode_Credentials}", usernameVariable: 'fituser', passwordVariable: 'fitpasswd']
|
||||
]) {
|
||||
echo '\u2705 \u001B[32mLog Collection (MME)\u001B[0m'
|
||||
sh "ssh -t -t inria_oaici@faraday.inria.fr 'ssh -t -t -b 192.168.3.100 ${fituser}@${r2labPythonExe} \"cd openairinterface5g/ci-scripts && python3 main.py --mode=LogCollectMME --EPCIPAddress=${r2labEPC0IpAddr} --EPCUserName=${fituser} --EPCPassword=${fitpasswd} --EPCSourceCodePath=/home/${fituser}/openair-cn --EPCType=OAI-Rel14-CUPS\"'"
|
||||
sh "ssh -t inria_oaici@faraday.inria.fr 'scp ${fituser}@${r2labEPC0}:/home/${fituser}/openair-cn/scripts/mme.log.zip /home/inria_oaici/archives/mme.log.zip'"
|
||||
}
|
||||
sh "scp inria_oaici@faraday.inria.fr:/home/inria_oaici/archives/mme.log.zip mme.log.${env.BUILD_ID}.zip"
|
||||
script {
|
||||
if(fileExists("mme.log.${env.BUILD_ID}.zip")) {
|
||||
archiveArtifacts "mme.log.${env.BUILD_ID}.zip"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Log Collection (HSS)') {
|
||||
steps {
|
||||
withCredentials([
|
||||
[$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.R2LAB_FitNode_Credentials}", usernameVariable: 'fituser', passwordVariable: 'fitpasswd']
|
||||
]) {
|
||||
echo '\u2705 \u001B[32mLog Collection (HSS)\u001B[0m'
|
||||
sh "ssh -t -t inria_oaici@faraday.inria.fr 'ssh -t -t -b 192.168.3.100 ${fituser}@${r2labPythonExe} \"cd openairinterface5g/ci-scripts && python3 main.py --mode=LogCollectHSS --EPCIPAddress=${r2labEPC0IpAddr} --EPCUserName=${fituser} --EPCPassword=${fitpasswd} --EPCSourceCodePath=/home/${fituser}/openair-cn --EPCType=OAI-Rel14-CUPS\"'"
|
||||
sh "ssh -t inria_oaici@faraday.inria.fr 'scp ${fituser}@${r2labEPC0}:/home/${fituser}/openair-cn/scripts/hss.log.zip /home/inria_oaici/archives/hss.log.zip'"
|
||||
}
|
||||
sh "scp inria_oaici@faraday.inria.fr:/home/inria_oaici/archives/hss.log.zip hss.log.${env.BUILD_ID}.zip"
|
||||
script {
|
||||
if(fileExists("hss.log.${env.BUILD_ID}.zip")) {
|
||||
archiveArtifacts "hss.log.${env.BUILD_ID}.zip"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Log Collection (SPGW)') {
|
||||
steps {
|
||||
withCredentials([
|
||||
[$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.R2LAB_FitNode_Credentials}", usernameVariable: 'fituser', passwordVariable: 'fitpasswd']
|
||||
]) {
|
||||
echo '\u2705 \u001B[32mLog Collection (SPGW)\u001B[0m'
|
||||
sh "ssh -t -t inria_oaici@faraday.inria.fr 'ssh -t -t -b 192.168.3.100 ${fituser}@${r2labPythonExe} \"cd openairinterface5g/ci-scripts && python3 main.py --mode=LogCollectSPGW --EPCIPAddress=${r2labEPC0IpAddr} --EPCUserName=${fituser} --EPCPassword=${fitpasswd} --EPCSourceCodePath=/home/${fituser}/openair-cn --EPCType=OAI-Rel14-CUPS\"'"
|
||||
sh "ssh -t inria_oaici@faraday.inria.fr 'scp ${fituser}@${r2labEPC0}:/home/${fituser}/openair-cn/scripts/spgw.log.zip /home/inria_oaici/archives/spgw.log.zip'"
|
||||
}
|
||||
sh "scp inria_oaici@faraday.inria.fr:/home/inria_oaici/archives/spgw.log.zip spgw.log.${env.BUILD_ID}.zip"
|
||||
script {
|
||||
if(fileExists("spgw.log.${env.BUILD_ID}.zip")) {
|
||||
archiveArtifacts "spgw.log.${env.BUILD_ID}.zip"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Log Collection (Ping)') {
|
||||
steps {
|
||||
withCredentials([
|
||||
[$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.R2LAB_FitNode_Credentials}", usernameVariable: 'fituser', passwordVariable: 'fitpasswd']
|
||||
]) {
|
||||
echo '\u2705 \u001B[32mLog Collection (Ping)\u001B[0m'
|
||||
sh "ssh -t -t inria_oaici@faraday.inria.fr 'ssh -t -t -b 192.168.3.100 ${fituser}@${r2labPythonExe} \"cd openairinterface5g/ci-scripts && python3 main.py --mode=LogCollectPing --EPCIPAddress=${r2labEPC0IpAddr} --EPCUserName=${fituser} --EPCPassword=${fitpasswd} --EPCSourceCodePath=/home/${fituser}/openair-cn --EPCType=OAI-Rel14-CUPS\"'"
|
||||
sh "ssh -t inria_oaici@faraday.inria.fr 'scp ${fituser}@${r2labEPC0}:/home/${fituser}/openair-cn/scripts/ping.log.zip /home/inria_oaici/archives/ping.log.zip'"
|
||||
}
|
||||
sh "scp inria_oaici@faraday.inria.fr:/home/inria_oaici/archives/ping.log.zip ping.log.${env.BUILD_ID}.zip"
|
||||
script {
|
||||
if(fileExists("ping.log.${env.BUILD_ID}.zip")) {
|
||||
archiveArtifacts "ping.log.${env.BUILD_ID}.zip"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Log Collection (Iperf)') {
|
||||
steps {
|
||||
withCredentials([
|
||||
[$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.R2LAB_FitNode_Credentials}", usernameVariable: 'fituser', passwordVariable: 'fitpasswd']
|
||||
]) {
|
||||
echo '\u2705 \u001B[32mLog Collection (Iperf)\u001B[0m'
|
||||
sh "ssh -t -t inria_oaici@faraday.inria.fr 'ssh -t -t -b 192.168.3.100 ${fituser}@${r2labPythonExe} \"cd openairinterface5g/ci-scripts && python3 main.py --mode=LogCollectIperf --EPCIPAddress=${r2labEPC0IpAddr} --EPCUserName=${fituser} --EPCPassword=${fitpasswd} --EPCSourceCodePath=/home/${fituser}/openair-cn --EPCType=OAI-Rel14-CUPS\"'"
|
||||
sh "ssh -t inria_oaici@faraday.inria.fr 'scp ${fituser}@${r2labEPC0}:/home/${fituser}/openair-cn/scripts/iperf.log.zip /home/inria_oaici/archives/iperf.log.zip'"
|
||||
}
|
||||
sh "scp inria_oaici@faraday.inria.fr:/home/inria_oaici/archives/iperf.log.zip iperf.log.${env.BUILD_ID}.zip"
|
||||
script {
|
||||
if(fileExists("iperf.log.${env.BUILD_ID}.zip")) {
|
||||
archiveArtifacts "iperf.log.${env.BUILD_ID}.zip"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage ("Clean-up Log Collection") {
|
||||
steps {
|
||||
sh "ssh -t inria_oaici@faraday.inria.fr 'rm -Rf /home/inria_oaici/archives'"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
post {
|
||||
always {
|
||||
script {
|
||||
echo '\u2705 \u001B[32mShutdown every node\u001B[0m'
|
||||
sh 'ssh -t inria_oaici@faraday.inria.fr "all-off"'
|
||||
sh 'ssh -t inria_oaici@faraday.inria.fr "all-off"'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -76,6 +76,11 @@ nullPointer:common/utils/T/local_tracer.c:243
|
||||
// first iteration of the loop
|
||||
nullPointer:common/utils/T/tracer/multi.c:264
|
||||
nullPointer:common/utils/T/tracer/multi.c:265
|
||||
//-----------------------------------------------------------------------------
|
||||
// this file is used for testing the RLC V2 implementation, this error is
|
||||
// not a problem, the programmer has to know what she does when writing
|
||||
// the tests
|
||||
arrayIndexOutOfBounds:openair2/LAYER2/rlc_v2/tests/test.c:401
|
||||
//
|
||||
//*****************************************************************************
|
||||
//
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -56,7 +56,6 @@
|
||||
<testCase id="040302">
|
||||
<class>Attach_UE</class>
|
||||
<desc>Attach UE</desc>
|
||||
<nbMaxUEtoAttach>1</nbMaxUEtoAttach>
|
||||
</testCase>
|
||||
|
||||
<testCase id="040401">
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
<!--
|
||||
|
||||
Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The OpenAirInterface Software Alliance licenses this file to You under
|
||||
the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.openairinterface.org/?page_id=698
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
contact@openairinterface.org
|
||||
|
||||
-->
|
||||
<testCaseList>
|
||||
<htmlTabRef>epc-start-oai-ue</htmlTabRef>
|
||||
<htmlTabName>EPC-Start-OAI-UE</htmlTabName>
|
||||
<htmlTabIcon>log-in</htmlTabIcon>
|
||||
<TestCaseRequestedList>
|
||||
050101 000001 060101 000001 070101
|
||||
</TestCaseRequestedList>
|
||||
<TestCaseExclusionList></TestCaseExclusionList>
|
||||
|
||||
<testCase id="000001">
|
||||
<class>IdleSleep</class>
|
||||
<desc>Sleep</desc>
|
||||
<idle_sleep_time_in_sec>20</idle_sleep_time_in_sec>
|
||||
</testCase>
|
||||
|
||||
<testCase id="050101">
|
||||
<class>Initialize_HSS</class>
|
||||
<desc>Initialize HSS</desc>
|
||||
</testCase>
|
||||
|
||||
<testCase id="060101">
|
||||
<class>Initialize_MME</class>
|
||||
<desc>Initialize MME</desc>
|
||||
</testCase>
|
||||
|
||||
<testCase id="070101">
|
||||
<class>Initialize_SPGW</class>
|
||||
<desc>Initialize SPGW</desc>
|
||||
</testCase>
|
||||
|
||||
</testCaseList>
|
||||
47
ci-scripts/xml_files/inria/enb_ue_usrp210_band7_epc_stop.xml
Normal file
47
ci-scripts/xml_files/inria/enb_ue_usrp210_band7_epc_stop.xml
Normal file
@@ -0,0 +1,47 @@
|
||||
<!--
|
||||
|
||||
Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The OpenAirInterface Software Alliance licenses this file to You under
|
||||
the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.openairinterface.org/?page_id=698
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
contact@openairinterface.org
|
||||
|
||||
-->
|
||||
<testCaseList>
|
||||
<htmlTabRef>epc-closure</htmlTabRef>
|
||||
<htmlTabName>EPC-Closure</htmlTabName>
|
||||
<htmlTabIcon>log-out</htmlTabIcon>
|
||||
<TestCaseRequestedList>
|
||||
050201 060201 070201
|
||||
</TestCaseRequestedList>
|
||||
<TestCaseExclusionList></TestCaseExclusionList>
|
||||
|
||||
<testCase id="050201">
|
||||
<class>Terminate_HSS</class>
|
||||
<desc>Terminate HSS</desc>
|
||||
</testCase>
|
||||
|
||||
<testCase id="060201">
|
||||
<class>Terminate_MME</class>
|
||||
<desc>Terminate MME</desc>
|
||||
</testCase>
|
||||
|
||||
<testCase id="070201">
|
||||
<class>Terminate_SPGW</class>
|
||||
<desc>Terminate SPGW</desc>
|
||||
</testCase>
|
||||
|
||||
</testCaseList>
|
||||
@@ -0,0 +1,42 @@
|
||||
<!--
|
||||
|
||||
Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The OpenAirInterface Software Alliance licenses this file to You under
|
||||
the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.openairinterface.org/?page_id=698
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
contact@openairinterface.org
|
||||
|
||||
-->
|
||||
<testCaseList>
|
||||
<htmlTabRef>terminate-enb-oai-ue</htmlTabRef>
|
||||
<htmlTabName>Terminate-all-eNBs-OAI-UEs</htmlTabName>
|
||||
<htmlTabIcon>tasks</htmlTabIcon>
|
||||
<TestCaseRequestedList>
|
||||
030201 090109
|
||||
</TestCaseRequestedList>
|
||||
<TestCaseExclusionList></TestCaseExclusionList>
|
||||
|
||||
<testCase id="030201">
|
||||
<class>Terminate_eNB</class>
|
||||
<desc>Terminate eNB</desc>
|
||||
</testCase>
|
||||
|
||||
<testCase id="090109">
|
||||
<class>Terminate_OAI_UE</class>
|
||||
<desc>Terminate OAI UE</desc>
|
||||
</testCase>
|
||||
|
||||
</testCaseList>
|
||||
@@ -0,0 +1,103 @@
|
||||
<!--
|
||||
|
||||
Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The OpenAirInterface Software Alliance licenses this file to You under
|
||||
the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.openairinterface.org/?page_id=698
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
contact@openairinterface.org
|
||||
|
||||
-->
|
||||
<testCaseList>
|
||||
<htmlTabRef>test-05-tm1-oai-ue</htmlTabRef>
|
||||
<htmlTabName>Test-05MHz-TM1-OAI-UE</htmlTabName>
|
||||
<htmlTabIcon>tasks</htmlTabIcon>
|
||||
<repeatCount>4</repeatCount>
|
||||
<TestCaseRequestedList>
|
||||
030201 090109
|
||||
030102 000001 090102 000002 040503 000002 040603 040604 040643 040644 000002 090109 000001 030201
|
||||
</TestCaseRequestedList>
|
||||
<TestCaseExclusionList></TestCaseExclusionList>
|
||||
|
||||
<testCase id="000001">
|
||||
<class>IdleSleep</class>
|
||||
<desc>Sleep for 10 sec</desc>
|
||||
<idle_sleep_time_in_sec>10</idle_sleep_time_in_sec>
|
||||
</testCase>
|
||||
|
||||
<testCase id="000002">
|
||||
<class>IdleSleep</class>
|
||||
<desc>Sleep for 3 sec</desc>
|
||||
<idle_sleep_time_in_sec>3</idle_sleep_time_in_sec>
|
||||
</testCase>
|
||||
|
||||
<testCase id="030102">
|
||||
<class>Initialize_eNB</class>
|
||||
<desc>Initialize eNB (FDD/Band7/5MHz)</desc>
|
||||
<Initialize_eNB_args>-O ci-scripts/conf_files/enb.band7.tm1.25PRB.usrpb210.conf --eNBs.[0].rrc_inactivity_threshold 0 --RUs.[0].max_rxgain 120 --eNBs.[0].component_carriers.[0].pusch_p0_Nominal -90 --eNBs.[0].component_carriers.[0].pucch_p0_Nominal -96 --eNBs.[0].tracking_area_code 600 --eNBs.[0].plmn_list.[0].mnc 95 --THREAD_STRUCT.[0].parallel_config PARALLEL_RU_L1_TRX_SPLIT</Initialize_eNB_args>
|
||||
</testCase>
|
||||
|
||||
<testCase id="030201">
|
||||
<class>Terminate_eNB</class>
|
||||
<desc>Terminate eNB</desc>
|
||||
</testCase>
|
||||
|
||||
<testCase id="090102">
|
||||
<class>Initialize_OAI_UE</class>
|
||||
<desc>Initialize OAI UE (FDD/Band7/5MHz)</desc>
|
||||
<Initialize_OAI_UE_args>-C 2680000000 -r 25 --ue-rxgain 130 --ue-txgain 1 --ue-max-power -6 --ue-scan-carrier --nokrnmod 1</Initialize_OAI_UE_args>
|
||||
</testCase>
|
||||
|
||||
<testCase id="090109">
|
||||
<class>Terminate_OAI_UE</class>
|
||||
<desc>Terminate OAI UE</desc>
|
||||
</testCase>
|
||||
|
||||
<testCase id="040503">
|
||||
<class>Ping</class>
|
||||
<desc>ping (5MHz - 20 sec)</desc>
|
||||
<ping_args>-I 192.168.248.159 -c 20</ping_args>
|
||||
<ping_packetloss_threshold>5</ping_packetloss_threshold>
|
||||
</testCase>
|
||||
|
||||
<testCase id="040603">
|
||||
<class>Iperf</class>
|
||||
<desc>iperf (5MHz - DL/1Mbps/UDP)(30 sec)</desc>
|
||||
<iperf_args>-u -b 1M -t 30 -i 1 -fm</iperf_args>
|
||||
<iperf_packetloss_threshold>50</iperf_packetloss_threshold>
|
||||
</testCase>
|
||||
|
||||
<testCase id="040604">
|
||||
<class>Iperf</class>
|
||||
<desc>iperf (5MHz - DL/12Mbps/UDP)(30 sec)</desc>
|
||||
<iperf_args>-u -b 12M -t 30 -i 1 -fm</iperf_args>
|
||||
<iperf_packetloss_threshold>50</iperf_packetloss_threshold>
|
||||
</testCase>
|
||||
|
||||
<testCase id="040643">
|
||||
<class>Iperf</class>
|
||||
<desc>iperf (5MHz - UL/1Mbps/UDP)(30 sec)</desc>
|
||||
<iperf_args>-u -b 1M -t 30 -i 1 -fm -R</iperf_args>
|
||||
<iperf_packetloss_threshold>50</iperf_packetloss_threshold>
|
||||
</testCase>
|
||||
|
||||
<testCase id="040644">
|
||||
<class>Iperf</class>
|
||||
<desc>iperf (5MHz - UL/2Mbps/UDP)(30 sec)</desc>
|
||||
<iperf_args>-u -b 2M -t 30 -i 1 -fm -R</iperf_args>
|
||||
<iperf_packetloss_threshold>50</iperf_packetloss_threshold>
|
||||
</testCase>
|
||||
|
||||
</testCaseList>
|
||||
@@ -0,0 +1,118 @@
|
||||
<!--
|
||||
|
||||
Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The OpenAirInterface Software Alliance licenses this file to You under
|
||||
the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.openairinterface.org/?page_id=698
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
contact@openairinterface.org
|
||||
|
||||
-->
|
||||
<testCaseList>
|
||||
<htmlTabRef>test-05-tm1-nos1-tunnel</htmlTabRef>
|
||||
<htmlTabName>Test-05MHz-TM1-noS1-tunnel</htmlTabName>
|
||||
<htmlTabIcon>tasks</htmlTabIcon>
|
||||
<repeatCount>2</repeatCount>
|
||||
<TestCaseRequestedList>
|
||||
030201 090109
|
||||
030101 000001 090101 000002 040501 040502 000001 040601 040602 040641 040642 000001 090109 030201
|
||||
</TestCaseRequestedList>
|
||||
<TestCaseExclusionList></TestCaseExclusionList>
|
||||
|
||||
<testCase id="000001">
|
||||
<class>IdleSleep</class>
|
||||
<desc>Sleep</desc>
|
||||
<idle_sleep_time_in_sec>10</idle_sleep_time_in_sec>
|
||||
</testCase>
|
||||
|
||||
<testCase id="000002">
|
||||
<class>IdleSleep</class>
|
||||
<desc>Sleep</desc>
|
||||
<idle_sleep_time_in_sec>5</idle_sleep_time_in_sec>
|
||||
</testCase>
|
||||
|
||||
<testCase id="000003">
|
||||
<class>IdleSleep</class>
|
||||
<desc>Sleep</desc>
|
||||
<idle_sleep_time_in_sec>60</idle_sleep_time_in_sec>
|
||||
</testCase>
|
||||
|
||||
<testCase id="030101">
|
||||
<class>Initialize_eNB</class>
|
||||
<desc>Initialize eNB (FDD/Band7/5MHz)</desc>
|
||||
<Initialize_eNB_args>-O ci-scripts/conf_files/enb.band7.tm1.25PRB.usrpb210.conf --noS1 --eNBs.[0].rrc_inactivity_threshold 0 --RUs.[0].max_rxgain 120 --eNBs.[0].component_carriers.[0].pusch_p0_Nominal -90 --eNBs.[0].component_carriers.[0].pucch_p0_Nominal -96 --eNBs.[0].tracking_area_code 600 --eNBs.[0].plmn_list.[0].mnc 95 --THREAD_STRUCT.[0].parallel_config PARALLEL_RU_L1_TRX_SPLIT</Initialize_eNB_args>
|
||||
</testCase>
|
||||
|
||||
<testCase id="030201">
|
||||
<class>Terminate_eNB</class>
|
||||
<desc>Terminate eNB</desc>
|
||||
</testCase>
|
||||
|
||||
<testCase id="090101">
|
||||
<class>Initialize_OAI_UE</class>
|
||||
<desc>Initialize OAI UE (FDD/Band7/5MHz)</desc>
|
||||
<Initialize_OAI_UE_args>-C 2680000000 -r 25 --ue-rxgain 130 --ue-txgain 1 --ue-max-power -6 --ue-scan-carrier --nokrnmod 1 --noS1</Initialize_OAI_UE_args>
|
||||
</testCase>
|
||||
|
||||
<testCase id="090109">
|
||||
<class>Terminate_OAI_UE</class>
|
||||
<desc>Terminate OAI UE</desc>
|
||||
</testCase>
|
||||
|
||||
<testCase id="040501">
|
||||
<class>Ping</class>
|
||||
<desc>ping (5MHz - 20 sec)(from eNB to OAI UE)</desc>
|
||||
<ping_args>-I oaitun_enb1 -c 20 10.0.1.2</ping_args>
|
||||
<ping_packetloss_threshold>5</ping_packetloss_threshold>
|
||||
</testCase>
|
||||
|
||||
<testCase id="040502">
|
||||
<class>Ping</class>
|
||||
<desc>ping (5MHz - 20 sec)(from OAI UE to eNB)</desc>
|
||||
<ping_args>-I oaitun_ue1 -c 20 10.0.1.1</ping_args>
|
||||
<ping_packetloss_threshold>5</ping_packetloss_threshold>
|
||||
</testCase>
|
||||
|
||||
<testCase id="040601">
|
||||
<class>Iperf</class>
|
||||
<desc>iperf (5MHz - DL/1Mbps/UDP)(30 sec)</desc>
|
||||
<iperf_args>-c 10.0.1.2 -u -b 1M -t 30 -i 1 -fm -B 10.0.1.1</iperf_args>
|
||||
<iperf_packetloss_threshold>50</iperf_packetloss_threshold>
|
||||
</testCase>
|
||||
|
||||
<testCase id="040602">
|
||||
<class>Iperf</class>
|
||||
<desc>iperf (5MHz - DL/10Mbps/UDP)(30 sec)</desc>
|
||||
<iperf_args>-c 10.0.1.2 -u -b 10M -t 30 -i 1 -fm -B 10.0.1.1</iperf_args>
|
||||
<iperf_packetloss_threshold>50</iperf_packetloss_threshold>
|
||||
</testCase>
|
||||
|
||||
<testCase id="040641">
|
||||
<class>Iperf</class>
|
||||
<desc>iperf (5MHz - UL/1Mbps/UDP)(30 sec)</desc>
|
||||
<iperf_args>-c 10.0.1.1 -u -b 1M -t 30 -i 1 -fm -B 10.0.1.2 -R</iperf_args>
|
||||
<iperf_packetloss_threshold>50</iperf_packetloss_threshold>
|
||||
<iperf_profile>balanced</iperf_profile>
|
||||
</testCase>
|
||||
|
||||
<testCase id="040642">
|
||||
<class>Iperf</class>
|
||||
<desc>iperf (5MHz - UL/2Mbps/UDP)(30 sec)</desc>
|
||||
<iperf_args>-c 10.0.1.1 -u -b 2M -t 30 -i 1 -fm -B 10.0.1.2 -R</iperf_args>
|
||||
<iperf_packetloss_threshold>50</iperf_packetloss_threshold>
|
||||
<iperf_profile>balanced</iperf_profile>
|
||||
</testCase>
|
||||
|
||||
</testCaseList>
|
||||
38
ci-scripts/xml_files/inria/enb_usrp210_band7_build.xml
Normal file
38
ci-scripts/xml_files/inria/enb_usrp210_band7_build.xml
Normal file
@@ -0,0 +1,38 @@
|
||||
<!--
|
||||
|
||||
Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The OpenAirInterface Software Alliance licenses this file to You under
|
||||
the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.openairinterface.org/?page_id=698
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
contact@openairinterface.org
|
||||
|
||||
-->
|
||||
<testCaseList>
|
||||
<htmlTabRef>build-tab-enb0</htmlTabRef>
|
||||
<htmlTabName>Build eNB0</htmlTabName>
|
||||
<htmlTabIcon>wrench</htmlTabIcon>
|
||||
<TestCaseRequestedList>
|
||||
010101
|
||||
</TestCaseRequestedList>
|
||||
<TestCaseExclusionList></TestCaseExclusionList>
|
||||
|
||||
<testCase id="010101">
|
||||
<class>Build_eNB</class>
|
||||
<desc>Build eNB (USRP)</desc>
|
||||
<Build_eNB_args>-w USRP -c --eNB</Build_eNB_args>
|
||||
</testCase>
|
||||
|
||||
</testCaseList>
|
||||
53
ci-scripts/xml_files/inria/enb_usrp210_band7_epc_start.xml
Normal file
53
ci-scripts/xml_files/inria/enb_usrp210_band7_epc_start.xml
Normal file
@@ -0,0 +1,53 @@
|
||||
<!--
|
||||
|
||||
Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The OpenAirInterface Software Alliance licenses this file to You under
|
||||
the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.openairinterface.org/?page_id=698
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
contact@openairinterface.org
|
||||
|
||||
-->
|
||||
<testCaseList>
|
||||
<htmlTabRef>epc-start</htmlTabRef>
|
||||
<htmlTabName>EPC-Start</htmlTabName>
|
||||
<htmlTabIcon>log-in</htmlTabIcon>
|
||||
<TestCaseRequestedList>
|
||||
050102 000001 060102 000001 070102
|
||||
</TestCaseRequestedList>
|
||||
<TestCaseExclusionList></TestCaseExclusionList>
|
||||
|
||||
<testCase id="000001">
|
||||
<class>IdleSleep</class>
|
||||
<desc>Sleep</desc>
|
||||
<idle_sleep_time_in_sec>20</idle_sleep_time_in_sec>
|
||||
</testCase>
|
||||
|
||||
<testCase id="050102">
|
||||
<class>Initialize_HSS</class>
|
||||
<desc>Initialize HSS</desc>
|
||||
</testCase>
|
||||
|
||||
<testCase id="060102">
|
||||
<class>Initialize_MME</class>
|
||||
<desc>Initialize MME</desc>
|
||||
</testCase>
|
||||
|
||||
<testCase id="070102">
|
||||
<class>Initialize_SPGW</class>
|
||||
<desc>Initialize SPGW</desc>
|
||||
</testCase>
|
||||
|
||||
</testCaseList>
|
||||
53
ci-scripts/xml_files/inria/enb_usrp210_band7_epc_stop.xml
Normal file
53
ci-scripts/xml_files/inria/enb_usrp210_band7_epc_stop.xml
Normal file
@@ -0,0 +1,53 @@
|
||||
<!--
|
||||
|
||||
Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The OpenAirInterface Software Alliance licenses this file to You under
|
||||
the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.openairinterface.org/?page_id=698
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
contact@openairinterface.org
|
||||
|
||||
-->
|
||||
<testCaseList>
|
||||
<htmlTabRef>epc-stop</htmlTabRef>
|
||||
<htmlTabName>EPC-Stop</htmlTabName>
|
||||
<htmlTabIcon>log-out</htmlTabIcon>
|
||||
<TestCaseRequestedList>
|
||||
050201 060201 070201
|
||||
040101
|
||||
</TestCaseRequestedList>
|
||||
<TestCaseExclusionList></TestCaseExclusionList>
|
||||
|
||||
<testCase id="050201">
|
||||
<class>Terminate_HSS</class>
|
||||
<desc>Terminate HSS</desc>
|
||||
</testCase>
|
||||
|
||||
<testCase id="060201">
|
||||
<class>Terminate_MME</class>
|
||||
<desc>Terminate MME</desc>
|
||||
</testCase>
|
||||
|
||||
<testCase id="070201">
|
||||
<class>Terminate_SPGW</class>
|
||||
<desc>Terminate SPGW</desc>
|
||||
</testCase>
|
||||
|
||||
<testCase id="040101">
|
||||
<class>Initialize_UE</class>
|
||||
<desc>Initialize UE</desc>
|
||||
</testCase>
|
||||
|
||||
</testCaseList>
|
||||
108
ci-scripts/xml_files/inria/enb_usrp210_band7_test_05mhz_tm1.xml
Normal file
108
ci-scripts/xml_files/inria/enb_usrp210_band7_test_05mhz_tm1.xml
Normal file
@@ -0,0 +1,108 @@
|
||||
<!--
|
||||
|
||||
Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The OpenAirInterface Software Alliance licenses this file to You under
|
||||
the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.openairinterface.org/?page_id=698
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
contact@openairinterface.org
|
||||
|
||||
030102 000002 040301 000002 040504 040605 040606 040645 040646 000001 040401 000002 030201
|
||||
-->
|
||||
<testCaseList>
|
||||
<htmlTabRef>test-05-tm1</htmlTabRef>
|
||||
<htmlTabName>Test-05MHz-TM1</htmlTabName>
|
||||
<htmlTabIcon>tasks</htmlTabIcon>
|
||||
<repeatCount>2</repeatCount>
|
||||
<TestCaseRequestedList>
|
||||
030201 040101
|
||||
030102 000002 040301 000002 040504 000001 040401 000002 030201
|
||||
</TestCaseRequestedList>
|
||||
<TestCaseExclusionList></TestCaseExclusionList>
|
||||
|
||||
<testCase id="040101">
|
||||
<class>Initialize_UE</class>
|
||||
<desc>Initialize UE</desc>
|
||||
</testCase>
|
||||
|
||||
<testCase id="000001">
|
||||
<class>IdleSleep</class>
|
||||
<desc>Sleep for 10 sec</desc>
|
||||
<idle_sleep_time_in_sec>10</idle_sleep_time_in_sec>
|
||||
</testCase>
|
||||
|
||||
<testCase id="000002">
|
||||
<class>IdleSleep</class>
|
||||
<desc>Sleep for 3 sec</desc>
|
||||
<idle_sleep_time_in_sec>3</idle_sleep_time_in_sec>
|
||||
</testCase>
|
||||
|
||||
<testCase id="030102">
|
||||
<class>Initialize_eNB</class>
|
||||
<desc>Initialize eNB (FDD/Band7/5MHz)</desc>
|
||||
<Initialize_eNB_args>-O ci-scripts/conf_files/enb.band7.tm1.25PRB.usrpb210.conf --eNBs.[0].rrc_inactivity_threshold 0 --RUs.[0].max_rxgain 120 --eNBs.[0].component_carriers.[0].pusch_p0_Nominal -90 --eNBs.[0].component_carriers.[0].pucch_p0_Nominal -96 --eNBs.[0].tracking_area_code 600 --eNBs.[0].plmn_list.[0].mnc 95 --THREAD_STRUCT.[0].parallel_config PARALLEL_RU_L1_TRX_SPLIT</Initialize_eNB_args>
|
||||
</testCase>
|
||||
|
||||
<testCase id="030201">
|
||||
<class>Terminate_eNB</class>
|
||||
<desc>Terminate eNB</desc>
|
||||
</testCase>
|
||||
|
||||
<testCase id="040301">
|
||||
<class>Attach_UE</class>
|
||||
<desc>Attach UE</desc>
|
||||
</testCase>
|
||||
|
||||
<testCase id="040401">
|
||||
<class>Detach_UE</class>
|
||||
<desc>Detach UE</desc>
|
||||
</testCase>
|
||||
|
||||
<testCase id="040504">
|
||||
<class>Ping</class>
|
||||
<desc>ping (5MHz - 20 sec)</desc>
|
||||
<ping_args>-I 192.168.248.159 -c 20</ping_args>
|
||||
<ping_packetloss_threshold>5</ping_packetloss_threshold>
|
||||
</testCase>
|
||||
|
||||
<testCase id="040605">
|
||||
<class>Iperf</class>
|
||||
<desc>iperf (5MHz - DL/1Mbps/UDP)(30 sec)</desc>
|
||||
<iperf_args>-u -b 1M -t 30 -i 1 -fm</iperf_args>
|
||||
<iperf_packetloss_threshold>50</iperf_packetloss_threshold>
|
||||
</testCase>
|
||||
|
||||
<testCase id="040606">
|
||||
<class>Iperf</class>
|
||||
<desc>iperf (5MHz - DL/12Mbps/UDP)(30 sec)</desc>
|
||||
<iperf_args>-u -b 12M -t 30 -i 1 -fm</iperf_args>
|
||||
<iperf_packetloss_threshold>50</iperf_packetloss_threshold>
|
||||
</testCase>
|
||||
|
||||
<testCase id="040645">
|
||||
<class>Iperf</class>
|
||||
<desc>iperf (5MHz - UL/1Mbps/UDP)(30 sec)</desc>
|
||||
<iperf_args>-u -b 1M -t 30 -i 1 -fm -R</iperf_args>
|
||||
<iperf_packetloss_threshold>50</iperf_packetloss_threshold>
|
||||
</testCase>
|
||||
|
||||
<testCase id="040646">
|
||||
<class>Iperf</class>
|
||||
<desc>iperf (5MHz - UL/2Mbps/UDP)(30 sec)</desc>
|
||||
<iperf_args>-u -b 2M -t 30 -i 1 -fm -R</iperf_args>
|
||||
<iperf_packetloss_threshold>50</iperf_packetloss_threshold>
|
||||
</testCase>
|
||||
|
||||
</testCaseList>
|
||||
38
ci-scripts/xml_files/inria/ue_usrp210_band7_build.xml
Normal file
38
ci-scripts/xml_files/inria/ue_usrp210_band7_build.xml
Normal file
@@ -0,0 +1,38 @@
|
||||
<!--
|
||||
|
||||
Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The OpenAirInterface Software Alliance licenses this file to You under
|
||||
the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.openairinterface.org/?page_id=698
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
contact@openairinterface.org
|
||||
|
||||
-->
|
||||
<testCaseList>
|
||||
<htmlTabRef>build-tab-ue0</htmlTabRef>
|
||||
<htmlTabName>Build UE0</htmlTabName>
|
||||
<htmlTabIcon>wrench</htmlTabIcon>
|
||||
<TestCaseRequestedList>
|
||||
090101
|
||||
</TestCaseRequestedList>
|
||||
<TestCaseExclusionList></TestCaseExclusionList>
|
||||
|
||||
<testCase id="090101">
|
||||
<class>Build_OAI_UE</class>
|
||||
<desc>Build OAI UE</desc>
|
||||
<Build_OAI_UE_args>-w USRP --UE</Build_OAI_UE_args>
|
||||
</testCase>
|
||||
|
||||
</testCaseList>
|
||||
@@ -183,8 +183,8 @@ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath -Wl,${CMAKE_CU
|
||||
#########################
|
||||
# set a flag for changes in the source code
|
||||
# these changes are related to hardcoded path to include .h files
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS} -g -DMALLOC_CHECK_=3")
|
||||
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS} -g -DMALLOC_CHECK_=3 -O2")
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS} -g3 -DMALLOC_CHECK_=3")
|
||||
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS} -g3 -DMALLOC_CHECK_=3 -O2")
|
||||
|
||||
|
||||
set(GIT_BRANCH "UNKNOWN")
|
||||
@@ -616,7 +616,6 @@ Message("CPU_Affinity flag is ${CPU_AFFINITY}")
|
||||
##############################################################
|
||||
add_boolean_option(ENABLE_USE_MME True "eNB connected to MME (INTERFACE S1-C), not standalone eNB")
|
||||
add_boolean_option(NO_RRM True "DO WE HAVE A RADIO RESSOURCE MANAGER: NO")
|
||||
add_boolean_option(RRC_DEFAULT_RAB_IS_AM False "set the RLC mode to AM for the default bearer")
|
||||
|
||||
add_boolean_option(OAI_NW_DRIVER_TYPE_ETHERNET False "????")
|
||||
add_boolean_option(DEADLINE_SCHEDULER True "Use the Linux scheduler SCHED_DEADLINE: kernel >= 3.14")
|
||||
@@ -719,7 +718,7 @@ add_boolean_option(TRACE_RLC_UM_TX_STATUS False "TRACE for RLC UM, TO BE CHANGE
|
||||
##########################
|
||||
# RRC LAYER OPTIONS
|
||||
##########################
|
||||
add_boolean_option(RRC_DEFAULT_RAB_IS_AM False "Otherwise it is UM, configure params are actually set in rrc_eNB.c:rrc_eNB_generate_defaultRRCConnectionReconfiguration(...)")
|
||||
add_boolean_option(RRC_DEFAULT_RAB_IS_AM True "set the RLC mode to AM for the default bearer, otherwise it is UM.")
|
||||
|
||||
|
||||
##########################
|
||||
@@ -1324,23 +1323,7 @@ add_library(PHY_MEX ${PHY_MEX_UE})
|
||||
|
||||
#Layer 2 library
|
||||
#####################
|
||||
set(MAC_DIR ${OPENAIR2_DIR}/LAYER2/MAC)
|
||||
set(PHY_INTERFACE_DIR ${OPENAIR2_DIR}/PHY_INTERFACE)
|
||||
set(RLC_DIR ${OPENAIR2_DIR}/LAYER2/RLC)
|
||||
set(RLC_UM_DIR ${OPENAIR2_DIR}/LAYER2/RLC/UM_v9.3.0)
|
||||
set(RLC_AM_DIR ${OPENAIR2_DIR}/LAYER2/RLC/AM_v9.3.0)
|
||||
set(RLC_TM_DIR ${OPENAIR2_DIR}/LAYER2/RLC/TM_v9.3.0)
|
||||
set(RRC_DIR ${OPENAIR2_DIR}/RRC/LTE)
|
||||
set(PDCP_DIR ${OPENAIR2_DIR}/LAYER2/PDCP_v10.1.0)
|
||||
set(L2_SRC
|
||||
${OPENAIR2_DIR}/LAYER2/openair2_proc.c
|
||||
${PDCP_DIR}/pdcp.c
|
||||
${PDCP_DIR}/pdcp_fifo.c
|
||||
${PDCP_DIR}/pdcp_sequence_manager.c
|
||||
${PDCP_DIR}/pdcp_primitives.c
|
||||
${PDCP_DIR}/pdcp_util.c
|
||||
${PDCP_DIR}/pdcp_security.c
|
||||
${PDCP_DIR}/pdcp_netlink.c
|
||||
set(RLC_V1
|
||||
${RLC_AM_DIR}/rlc_am.c
|
||||
${RLC_AM_DIR}/rlc_am_init.c
|
||||
${RLC_AM_DIR}/rlc_am_timer_poll_retransmit.c
|
||||
@@ -1368,6 +1351,40 @@ set(L2_SRC
|
||||
${RLC_DIR}/rlc.c
|
||||
${RLC_DIR}/rlc_rrc.c
|
||||
${RLC_DIR}/rlc_mpls.c
|
||||
)
|
||||
set(RLC_V2
|
||||
${OPENAIR2_DIR}/LAYER2/rlc_v2/rlc_oai_api.c
|
||||
${OPENAIR2_DIR}/LAYER2/rlc_v2/asn1_utils.c
|
||||
${OPENAIR2_DIR}/LAYER2/rlc_v2/rlc_ue_manager.c
|
||||
${OPENAIR2_DIR}/LAYER2/rlc_v2/rlc_entity.c
|
||||
${OPENAIR2_DIR}/LAYER2/rlc_v2/rlc_entity_am.c
|
||||
${OPENAIR2_DIR}/LAYER2/rlc_v2/rlc_entity_um.c
|
||||
${OPENAIR2_DIR}/LAYER2/rlc_v2/rlc_pdu.c
|
||||
${OPENAIR2_DIR}/LAYER2/rlc_v2/rlc_sdu.c
|
||||
)
|
||||
set(MAC_DIR ${OPENAIR2_DIR}/LAYER2/MAC)
|
||||
set(PHY_INTERFACE_DIR ${OPENAIR2_DIR}/PHY_INTERFACE)
|
||||
set(RLC_DIR ${OPENAIR2_DIR}/LAYER2/RLC)
|
||||
set(RLC_UM_DIR ${OPENAIR2_DIR}/LAYER2/RLC/UM_v9.3.0)
|
||||
set(RLC_AM_DIR ${OPENAIR2_DIR}/LAYER2/RLC/AM_v9.3.0)
|
||||
set(RLC_TM_DIR ${OPENAIR2_DIR}/LAYER2/RLC/TM_v9.3.0)
|
||||
set(RRC_DIR ${OPENAIR2_DIR}/RRC/LTE)
|
||||
set(PDCP_DIR ${OPENAIR2_DIR}/LAYER2/PDCP_v10.1.0)
|
||||
set(L2_SRC
|
||||
${OPENAIR2_DIR}/LAYER2/openair2_proc.c
|
||||
# ${PDCP_DIR}/pdcp.c
|
||||
# ${PDCP_DIR}/pdcp_fifo.c
|
||||
# ${PDCP_DIR}/pdcp_sequence_manager.c
|
||||
# ${PDCP_DIR}/pdcp_primitives.c
|
||||
# ${PDCP_DIR}/pdcp_util.c
|
||||
# ${PDCP_DIR}/pdcp_security.c
|
||||
# ${PDCP_DIR}/pdcp_netlink.c
|
||||
${OPENAIR2_DIR}/LAYER2/pdcp_v2/pdcp_oai_api.c
|
||||
${OPENAIR2_DIR}/LAYER2/pdcp_v2/pdcp_ue_manager.c
|
||||
${OPENAIR2_DIR}/LAYER2/pdcp_v2/pdcp_entity.c
|
||||
${OPENAIR2_DIR}/LAYER2/pdcp_v2/pdcp_entity_srb.c
|
||||
${OPENAIR2_DIR}/LAYER2/pdcp_v2/pdcp_entity_drb_am.c
|
||||
${RLC_V2}
|
||||
# ${RRC_DIR}/rrc_UE.c
|
||||
${RRC_DIR}/rrc_eNB.c
|
||||
${RRC_DIR}/rrc_eNB_S1AP.c
|
||||
@@ -1386,33 +1403,7 @@ set(L2_SRC_UE
|
||||
${PDCP_DIR}/pdcp_util.c
|
||||
${PDCP_DIR}/pdcp_security.c
|
||||
${PDCP_DIR}/pdcp_netlink.c
|
||||
${RLC_AM_DIR}/rlc_am.c
|
||||
${RLC_AM_DIR}/rlc_am_init.c
|
||||
${RLC_AM_DIR}/rlc_am_timer_poll_retransmit.c
|
||||
${RLC_AM_DIR}/rlc_am_timer_reordering.c
|
||||
${RLC_AM_DIR}/rlc_am_timer_status_prohibit.c
|
||||
${RLC_AM_DIR}/rlc_am_segment.c
|
||||
${RLC_AM_DIR}/rlc_am_segments_holes.c
|
||||
${RLC_AM_DIR}/rlc_am_in_sdu.c
|
||||
${RLC_AM_DIR}/rlc_am_receiver.c
|
||||
${RLC_AM_DIR}/rlc_am_retransmit.c
|
||||
${RLC_AM_DIR}/rlc_am_windows.c
|
||||
${RLC_AM_DIR}/rlc_am_rx_list.c
|
||||
${RLC_AM_DIR}/rlc_am_reassembly.c
|
||||
${RLC_AM_DIR}/rlc_am_status_report.c
|
||||
${RLC_TM_DIR}/rlc_tm.c
|
||||
${RLC_TM_DIR}/rlc_tm_init.c
|
||||
${RLC_UM_DIR}/rlc_um.c
|
||||
${RLC_UM_DIR}/rlc_um_fsm.c
|
||||
${RLC_UM_DIR}/rlc_um_control_primitives.c
|
||||
${RLC_UM_DIR}/rlc_um_segment.c
|
||||
${RLC_UM_DIR}/rlc_um_reassembly.c
|
||||
${RLC_UM_DIR}/rlc_um_receiver.c
|
||||
${RLC_UM_DIR}/rlc_um_dar.c
|
||||
${RLC_DIR}/rlc_mac.c
|
||||
${RLC_DIR}/rlc.c
|
||||
${RLC_DIR}/rlc_rrc.c
|
||||
${RLC_DIR}/rlc_mpls.c
|
||||
${RLC_V2}
|
||||
${RRC_DIR}/rrc_UE.c
|
||||
${RRC_DIR}/rrc_common.c
|
||||
${RRC_DIR}/L2_interface_common.c
|
||||
|
||||
@@ -12,6 +12,7 @@ void usage(void)
|
||||
"usage: <number of tags> <input record file> <output curated record file>\n"
|
||||
"options:\n"
|
||||
" -d <database file> this option is mandatory\n"
|
||||
" -e <event name> trace given event (default CALIBRATION_CHANNEL_ESTIMATES)\n"
|
||||
);
|
||||
exit(1);
|
||||
}
|
||||
@@ -88,6 +89,7 @@ int main(int n, char **v)
|
||||
int number_of_tags = -1;
|
||||
char *input_filename = NULL;
|
||||
char *output_filename = NULL;
|
||||
char *event_name = "CALIBRATION_CHANNEL_ESTIMATES";
|
||||
int i;
|
||||
FILE *in;
|
||||
FILE *out;
|
||||
@@ -107,6 +109,8 @@ int main(int n, char **v)
|
||||
if (!strcmp(v[i], "-h") || !strcmp(v[i], "--help")) usage();
|
||||
if (!strcmp(v[i], "-d")) { if (i > n-2) usage();
|
||||
database_filename = v[++i]; continue; }
|
||||
if (!strcmp(v[i], "-e")) { if (i > n-2) usage();
|
||||
event_name = v[++i]; continue; }
|
||||
if (number_of_tags == -1) { number_of_tags = atoi(v[i]);
|
||||
if (number_of_tags <= 0) {usage();} continue; }
|
||||
if (input_filename == NULL) { input_filename = v[i]; continue; }
|
||||
@@ -124,7 +128,7 @@ int main(int n, char **v)
|
||||
|
||||
database = parse_database(database_filename);
|
||||
|
||||
channel_estimate_id = event_id_from_name(database, "CALIBRATION_CHANNEL_ESTIMATES");
|
||||
channel_estimate_id = event_id_from_name(database, event_name);
|
||||
f = get_format(database, channel_estimate_id);
|
||||
|
||||
frame_arg = get_field(&f, "frame", "int");
|
||||
|
||||
15
common/utils/T/tracer/hacks/pilot_timeplot.sh
Executable file
15
common/utils/T/tracer/hacks/pilot_timeplot.sh
Executable file
@@ -0,0 +1,15 @@
|
||||
#!/bin/bash
|
||||
|
||||
# use UP and DOWN arrow keys to scroll the view displayed by timeplot
|
||||
|
||||
while read -n 1 key
|
||||
do
|
||||
case "$key" in
|
||||
'B' )
|
||||
kill -SIGUSR1 `ps aux|grep timeplot|grep -v grep|grep -v sh|tr -s ' ' :|cut -f 2 -d :`
|
||||
;;
|
||||
'A' )
|
||||
kill -SIGUSR2 `ps aux|grep timeplot|grep -v grep|grep -v sh|tr -s ' ' :|cut -f 2 -d :`
|
||||
;;
|
||||
esac
|
||||
done
|
||||
@@ -13,7 +13,8 @@ void usage(void)
|
||||
"options:\n"
|
||||
" -d <database file> this option is mandatory\n"
|
||||
" -ip <host> connect to given IP address (default %s)\n"
|
||||
" -p <port> connect to given port (default %d)\n",
|
||||
" -p <port> connect to given port (default %d)\n"
|
||||
" -e <event> event to trace (default VCD_FUNCTION_ENB_DLSCH_ULSCH_SCHEDULER)\n",
|
||||
DEFAULT_REMOTE_IP,
|
||||
DEFAULT_REMOTE_PORT
|
||||
);
|
||||
@@ -47,6 +48,7 @@ int main(int n, char **v)
|
||||
int ev_fun;
|
||||
int start_valid = 0;
|
||||
struct timespec start_time, stop_time, delta_time;
|
||||
char *name = "VCD_FUNCTION_ENB_DLSCH_ULSCH_SCHEDULER";
|
||||
|
||||
for (i = 1; i < n; i++) {
|
||||
if (!strcmp(v[i], "-h") || !strcmp(v[i], "--help")) usage();
|
||||
@@ -55,6 +57,7 @@ int main(int n, char **v)
|
||||
if (!strcmp(v[i], "-ip")) { if (i > n-2) usage(); ip = v[++i]; continue; }
|
||||
if (!strcmp(v[i], "-p"))
|
||||
{ if (i > n-2) usage(); port = atoi(v[++i]); continue; }
|
||||
if (!strcmp(v[i], "-e")) { if (i > n-2) usage(); name = v[++i]; continue; }
|
||||
usage();
|
||||
}
|
||||
|
||||
@@ -71,10 +74,9 @@ int main(int n, char **v)
|
||||
is_on = calloc(number_of_events, sizeof(int));
|
||||
if (is_on == NULL) abort();
|
||||
|
||||
on_off(database, "VCD_FUNCTION_ENB_DLSCH_ULSCH_SCHEDULER", is_on, 1);
|
||||
on_off(database, name, is_on, 1);
|
||||
|
||||
ev_fun = event_id_from_name(database,
|
||||
"VCD_FUNCTION_ENB_DLSCH_ULSCH_SCHEDULER");
|
||||
ev_fun = event_id_from_name(database, name);
|
||||
|
||||
socket = connect_to(ip, port);
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ int bins[50];
|
||||
|
||||
#define N 1000
|
||||
int data[N];
|
||||
long start = 100;
|
||||
|
||||
void plot(void)
|
||||
{
|
||||
@@ -45,7 +46,8 @@ void plot(void)
|
||||
if (data[i] < vmin) vmin = data[i];
|
||||
if (data[i] > vmax) vmax = data[i];
|
||||
vavg += data[i];
|
||||
int ms2 = data[i]/binsize_ns;
|
||||
int ms2 = (data[i] - start * 1000)/binsize_ns;
|
||||
if (ms2 < 0) ms2 = 0;
|
||||
if (ms2 > 49) ms2 = 49;
|
||||
bins[ms2]++;
|
||||
if (bins[ms2] > max) max = bins[ms2];
|
||||
@@ -55,7 +57,7 @@ void plot(void)
|
||||
|
||||
GOTO(1,1);
|
||||
for (i = 0; i < 50; i++) {
|
||||
double binend = (i+1) * binsize_ns / 1000.;
|
||||
double binend = (i+1) * binsize_ns / 1000. + start;
|
||||
int k;
|
||||
int width = bins[i] * 70 / max;
|
||||
/* force at least width of 1 if some point is there */
|
||||
@@ -68,11 +70,23 @@ void plot(void)
|
||||
printf("min %d ns max %d ns avg %ld ns\n", vmin, vmax, vavg);
|
||||
}
|
||||
|
||||
void up(int x)
|
||||
{
|
||||
start += 5;
|
||||
}
|
||||
|
||||
void down(int x)
|
||||
{
|
||||
start -= 5;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int i;
|
||||
int pos = 0;
|
||||
signal(SIGINT, sig);
|
||||
signal(SIGUSR1, up);
|
||||
signal(SIGUSR2, down);
|
||||
RESET();
|
||||
HIDE_CURSOR();
|
||||
while (!feof(stdin)) {
|
||||
|
||||
@@ -59,7 +59,7 @@ int lte_segmentation(unsigned char *input_buffer,
|
||||
}
|
||||
|
||||
if ((*C)>MAX_NUM_DLSCH_SEGMENTS) {
|
||||
printf("%d\n",*(int*)0);
|
||||
printf("%d\n",*(int *)0);
|
||||
LOG_E(PHY,"lte_segmentation.c: too many segments %d, B %d, L %d, Bprime %d\n",*C,B,L,Bprime);
|
||||
return(-1);
|
||||
}
|
||||
@@ -105,7 +105,7 @@ int lte_segmentation(unsigned char *input_buffer,
|
||||
#endif
|
||||
*Kminus = (*Kplus - 64);
|
||||
} else {
|
||||
printf("lte_segmentation.c: Illegal codeword size !!!\n");
|
||||
LOG_E(PHY,"lte_segmentation.c: Illegal codeword size !!!\n");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
*/
|
||||
#include "PHY/defs_eNB.h"
|
||||
#ifdef DEBUG_UCI_TOOLS
|
||||
#include "PHY/vars.h"
|
||||
#include "PHY/vars.h"
|
||||
#endif
|
||||
|
||||
//#define DEBUG_UCI 1
|
||||
@@ -41,15 +41,21 @@ int16_t find_uci(uint16_t rnti, int frame, int subframe, PHY_VARS_eNB *eNB,find_
|
||||
uint16_t i;
|
||||
int16_t first_free_index=-1;
|
||||
AssertFatal(eNB!=NULL,"eNB is null\n");
|
||||
|
||||
for (i=0; i<NUMBER_OF_UCI_VARS_MAX; i++) {
|
||||
if ((eNB->uci_vars[i].active >0) &&
|
||||
(eNB->uci_vars[i].rnti==rnti) &&
|
||||
(eNB->uci_vars[i].frame==frame) &&
|
||||
(eNB->uci_vars[i].subframe==subframe)) return(i);
|
||||
(eNB->uci_vars[i].rnti==rnti) &&
|
||||
(eNB->uci_vars[i].frame==frame) &&
|
||||
(eNB->uci_vars[i].subframe==subframe)) return(i);
|
||||
else if ((eNB->uci_vars[i].active == 0) && (first_free_index==-1)) first_free_index=i;
|
||||
}
|
||||
|
||||
if (type == SEARCH_EXIST) return(-1);
|
||||
else return(first_free_index);
|
||||
|
||||
if (first_free_index==-1)
|
||||
LOG_E(MAC,"UCI table is full\n");
|
||||
|
||||
return(first_free_index);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -563,8 +563,8 @@ int ulsch_decoding_data(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr8_flag)
|
||||
else
|
||||
tc = *decoder8;
|
||||
|
||||
if(ulsch_harq->repetition_number == 1){
|
||||
memset(pusch_rep_buffer,0,(sizeof(int32_t)*3*(6144+64))) ; // reset the buffer every new repetitions
|
||||
if(ulsch_harq->repetition_number == 1) {
|
||||
memset(pusch_rep_buffer,0,(sizeof(int32_t)*3*(6144+64))) ; // reset the buffer every new repetitions
|
||||
}
|
||||
|
||||
for (r=0; r<ulsch_harq->C; r++) {
|
||||
@@ -581,11 +581,10 @@ int ulsch_decoding_data(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr8_flag)
|
||||
(uint8_t *)&dummy_w[r][0],
|
||||
(r==0) ? ulsch_harq->F : 0);
|
||||
#ifdef DEBUG_ULSCH_DECODING
|
||||
printf("Rate Matching Segment %u (coded bits (G) %d,unpunctured/repeated bits %u, Q_m %d, nb_rb %d, Nl %d)...\n",
|
||||
printf("Rate Matching Segment %u (coded bits (G) %d,unpunctured/repeated bits %u, Q_m %d, Nl %d)...\n",
|
||||
r, G,
|
||||
Kr*3,
|
||||
Q_m,
|
||||
nb_rb,
|
||||
ulsch_harq->Qm,
|
||||
ulsch_harq->Nl);
|
||||
#endif
|
||||
start_meas(&eNB->ulsch_rate_unmatching_stats);
|
||||
@@ -610,27 +609,23 @@ int ulsch_decoding_data(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr8_flag)
|
||||
}
|
||||
|
||||
stop_meas(&eNB->ulsch_rate_unmatching_stats);
|
||||
|
||||
max_Ncb = 3*ulsch_harq->RTC[r]*32 ;
|
||||
|
||||
if(ulsch_harq->total_number_of_repetitions > 1)
|
||||
{
|
||||
if (ulsch_harq->rvidx==1)
|
||||
{ // Store the result of HARQ combining in the last emtc repetitions of sequence 0,2,3,1
|
||||
for (int nn=0;nn<max_Ncb;nn++)
|
||||
{
|
||||
pusch_rep_buffer[nn] += ulsch_harq->w[r][nn] ;
|
||||
}
|
||||
if(ulsch_harq->total_number_of_repetitions > 1) {
|
||||
if (ulsch_harq->rvidx==1) {
|
||||
// Store the result of HARQ combining in the last emtc repetitions of sequence 0,2,3,1
|
||||
for (int nn=0; nn<max_Ncb; nn++) {
|
||||
pusch_rep_buffer[nn] += ulsch_harq->w[r][nn] ;
|
||||
}
|
||||
if (ulsch_harq->repetition_number == ulsch_harq->total_number_of_repetitions)
|
||||
{
|
||||
for (int nn=0;nn<max_Ncb;nn++)
|
||||
{
|
||||
ulsch_harq->w[r][nn] = pusch_rep_buffer[nn] ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ulsch_harq->repetition_number == ulsch_harq->total_number_of_repetitions) {
|
||||
for (int nn=0; nn<max_Ncb; nn++) {
|
||||
ulsch_harq->w[r][nn] = pusch_rep_buffer[nn] ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
r_offset += E;
|
||||
start_meas(&eNB->ulsch_deinterleaving_stats);
|
||||
sub_block_deinterleaving_turbo(4+Kr,
|
||||
@@ -764,18 +759,17 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc,
|
||||
int frame = proc->frame_rx;
|
||||
int subframe = proc->subframe_rx;
|
||||
LTE_UL_eNB_HARQ_t *ulsch_harq;
|
||||
|
||||
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
|
||||
LOG_D(PHY,"ue_type %d\n",ulsch->ue_type);
|
||||
|
||||
if (ulsch->ue_type>0) harq_pid = 0;
|
||||
else
|
||||
#endif
|
||||
{
|
||||
harq_pid = subframe2harq_pid(frame_parms,proc->frame_rx,subframe);
|
||||
}
|
||||
{
|
||||
harq_pid = subframe2harq_pid(frame_parms,proc->frame_rx,subframe);
|
||||
}
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_ULSCH_DECODING0+harq_pid,1);
|
||||
|
||||
// x1 is set in lte_gold_generic
|
||||
x2 = ((uint32_t)ulsch->rnti<<14) + ((uint32_t)subframe<<9) + frame_parms->Nid_cell; //this is c_init in 36.211 Sec 6.3.1
|
||||
ulsch_harq = ulsch->harq_processes[harq_pid];
|
||||
|
||||
@@ -50,7 +50,6 @@ int pbch_detection(PHY_VARS_UE *ue, runmode_t mode) {
|
||||
uint8_t l,pbch_decoded,frame_mod4,pbch_tx_ant,dummy;
|
||||
LTE_DL_FRAME_PARMS *frame_parms=&ue->frame_parms;
|
||||
char phich_resource[6];
|
||||
|
||||
LOG_D(PHY,"[UE%d] Initial sync: starting PBCH detection (rx_offset %d)\n",ue->Mod_id,
|
||||
ue->rx_offset);
|
||||
|
||||
@@ -95,7 +94,6 @@ int pbch_detection(PHY_VARS_UE *ue, runmode_t mode) {
|
||||
0);
|
||||
}
|
||||
|
||||
|
||||
LOG_D(PHY,"[UE %d] RX RSSI %d dBm, digital (%d, %d) dB, linear (%d, %d), avg rx power %d dB (%d lin), RX gain %d dB\n",
|
||||
ue->Mod_id,
|
||||
ue->measurements.rx_rssi_dBm[0] - ((ue->frame_parms.nb_antennas_rx==2) ? 3 : 0),
|
||||
@@ -106,7 +104,6 @@ int pbch_detection(PHY_VARS_UE *ue, runmode_t mode) {
|
||||
ue->measurements.rx_power_avg_dB[0],
|
||||
ue->measurements.rx_power_avg[0],
|
||||
ue->rx_total_gain_dB);
|
||||
|
||||
LOG_D(PHY,"[UE %d] N0 %d dBm digital (%d, %d) dB, linear (%d, %d), avg noise power %d dB (%d lin)\n",
|
||||
ue->Mod_id,
|
||||
ue->measurements.n0_power_tot_dBm,
|
||||
@@ -116,57 +113,60 @@ int pbch_detection(PHY_VARS_UE *ue, runmode_t mode) {
|
||||
ue->measurements.n0_power[1],
|
||||
ue->measurements.n0_power_avg_dB,
|
||||
ue->measurements.n0_power_avg);
|
||||
|
||||
pbch_decoded = 0;
|
||||
|
||||
for (frame_mod4=0; frame_mod4<4; frame_mod4++) {
|
||||
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
|
||||
if (ue->FeMBMS_active != 2){
|
||||
|
||||
if (ue->FeMBMS_active != 2) {
|
||||
#endif
|
||||
pbch_tx_ant = rx_pbch(&ue->common_vars,
|
||||
ue->pbch_vars[0],
|
||||
frame_parms,
|
||||
0,
|
||||
SISO,
|
||||
ue->high_speed_flag,
|
||||
frame_mod4);
|
||||
pbch_tx_ant = rx_pbch(&ue->common_vars,
|
||||
ue->pbch_vars[0],
|
||||
frame_parms,
|
||||
0,
|
||||
SISO,
|
||||
ue->high_speed_flag,
|
||||
frame_mod4);
|
||||
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
|
||||
}else{
|
||||
pbch_tx_ant = rx_pbch_fembms(&ue->common_vars,
|
||||
ue->pbch_vars[0],
|
||||
frame_parms,
|
||||
0,
|
||||
SISO,
|
||||
ue->high_speed_flag,
|
||||
frame_mod4);
|
||||
}
|
||||
} else {
|
||||
pbch_tx_ant = rx_pbch_fembms(&ue->common_vars,
|
||||
ue->pbch_vars[0],
|
||||
frame_parms,
|
||||
0,
|
||||
SISO,
|
||||
ue->high_speed_flag,
|
||||
frame_mod4);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if ((pbch_tx_ant>0) && (pbch_tx_ant<=2)) {
|
||||
pbch_decoded = 1;
|
||||
break;
|
||||
if ((pbch_tx_ant>0) && (pbch_tx_ant<=2)) {
|
||||
pbch_decoded = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
|
||||
if (ue->FeMBMS_active != 2){
|
||||
|
||||
if (ue->FeMBMS_active != 2) {
|
||||
#endif
|
||||
pbch_tx_ant = rx_pbch(&ue->common_vars,
|
||||
ue->pbch_vars[0],
|
||||
frame_parms,
|
||||
0,
|
||||
ALAMOUTI,
|
||||
ue->high_speed_flag,
|
||||
frame_mod4);
|
||||
pbch_tx_ant = rx_pbch(&ue->common_vars,
|
||||
ue->pbch_vars[0],
|
||||
frame_parms,
|
||||
0,
|
||||
ALAMOUTI,
|
||||
ue->high_speed_flag,
|
||||
frame_mod4);
|
||||
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
|
||||
}else{
|
||||
pbch_tx_ant = rx_pbch_fembms(&ue->common_vars,
|
||||
ue->pbch_vars[0],
|
||||
frame_parms,
|
||||
0,
|
||||
ALAMOUTI,
|
||||
ue->high_speed_flag,
|
||||
frame_mod4);
|
||||
} else {
|
||||
pbch_tx_ant = rx_pbch_fembms(&ue->common_vars,
|
||||
ue->pbch_vars[0],
|
||||
frame_parms,
|
||||
0,
|
||||
ALAMOUTI,
|
||||
ue->high_speed_flag,
|
||||
frame_mod4);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if ((pbch_tx_ant>0) && (pbch_tx_ant<=2)) {
|
||||
@@ -218,73 +218,72 @@ int pbch_detection(PHY_VARS_UE *ue, runmode_t mode) {
|
||||
}
|
||||
|
||||
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
|
||||
if(ue->FeMBMS_active != 2) {
|
||||
|
||||
if(ue->FeMBMS_active != 2) {
|
||||
#endif
|
||||
// now check for PHICH parameters
|
||||
frame_parms->phich_config_common.phich_duration = (PHICH_DURATION_t)((ue->pbch_vars[0]->decoded_output[2]>>4)&1);
|
||||
dummy = (ue->pbch_vars[0]->decoded_output[2]>>2)&3;
|
||||
// now check for PHICH parameters
|
||||
frame_parms->phich_config_common.phich_duration = (PHICH_DURATION_t)((ue->pbch_vars[0]->decoded_output[2]>>4)&1);
|
||||
dummy = (ue->pbch_vars[0]->decoded_output[2]>>2)&3;
|
||||
|
||||
switch (dummy) {
|
||||
case 0:
|
||||
frame_parms->phich_config_common.phich_resource = oneSixth;
|
||||
sprintf(phich_resource,"1/6");
|
||||
break;
|
||||
switch (dummy) {
|
||||
case 0:
|
||||
frame_parms->phich_config_common.phich_resource = oneSixth;
|
||||
sprintf(phich_resource,"1/6");
|
||||
break;
|
||||
|
||||
case 1:
|
||||
frame_parms->phich_config_common.phich_resource = half;
|
||||
sprintf(phich_resource,"1/2");
|
||||
break;
|
||||
case 1:
|
||||
frame_parms->phich_config_common.phich_resource = half;
|
||||
sprintf(phich_resource,"1/2");
|
||||
break;
|
||||
|
||||
case 2:
|
||||
frame_parms->phich_config_common.phich_resource = one;
|
||||
sprintf(phich_resource,"1");
|
||||
break;
|
||||
case 2:
|
||||
frame_parms->phich_config_common.phich_resource = one;
|
||||
sprintf(phich_resource,"1");
|
||||
break;
|
||||
|
||||
case 3:
|
||||
frame_parms->phich_config_common.phich_resource = two;
|
||||
sprintf(phich_resource,"2");
|
||||
break;
|
||||
case 3:
|
||||
frame_parms->phich_config_common.phich_resource = two;
|
||||
sprintf(phich_resource,"2");
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_E(PHY,"[UE%d] Initial sync: Unknown PHICH_DURATION\n",ue->Mod_id);
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
LOG_E(PHY,"[UE%d] Initial sync: Unknown PHICH_DURATION\n",ue->Mod_id);
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
|
||||
for(int i=0; i<RX_NB_TH; i++) {
|
||||
ue->proc.proc_rxtx[i].frame_rx = (((ue->pbch_vars[0]->decoded_output[2]&3)<<6) + (ue->pbch_vars[0]->decoded_output[1]>>2))<<2;
|
||||
ue->proc.proc_rxtx[i].frame_rx = (((ue->pbch_vars[0]->decoded_output[2]&3)<<6) + (ue->pbch_vars[0]->decoded_output[1]>>2))<<2;
|
||||
ue->proc.proc_rxtx[i].frame_tx = ue->proc.proc_rxtx[0].frame_rx;
|
||||
}
|
||||
for(int i=0; i<RX_NB_TH; i++) {
|
||||
ue->proc.proc_rxtx[i].frame_rx = (((ue->pbch_vars[0]->decoded_output[2]&3)<<6) + (ue->pbch_vars[0]->decoded_output[1]>>2))<<2;
|
||||
ue->proc.proc_rxtx[i].frame_rx = (((ue->pbch_vars[0]->decoded_output[2]&3)<<6) + (ue->pbch_vars[0]->decoded_output[1]>>2))<<2;
|
||||
ue->proc.proc_rxtx[i].frame_tx = ue->proc.proc_rxtx[0].frame_rx;
|
||||
}
|
||||
|
||||
|
||||
LOG_D(PHY,"[UE%d] Initial sync: pbch decoded sucessfully p %d, tx_ant %d, frame %d, N_RB_DL %d, phich_duration %d, phich_resource %s!\n",
|
||||
ue->Mod_id,
|
||||
frame_parms->nb_antenna_ports_eNB,
|
||||
pbch_tx_ant,
|
||||
ue->proc.proc_rxtx[0].frame_rx,
|
||||
frame_parms->N_RB_DL,
|
||||
frame_parms->phich_config_common.phich_duration,
|
||||
phich_resource); //frame_parms->phich_config_common.phich_resource);
|
||||
|
||||
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
|
||||
}else{
|
||||
for(int i=0; i<RX_NB_TH;i++)
|
||||
{
|
||||
ue->proc.proc_rxtx[i].frame_rx = (((ue->pbch_vars[0]->decoded_output[2]&31)<<1) + (ue->pbch_vars[0]->decoded_output[1]>>7))<<4;
|
||||
ue->proc.proc_rxtx[i].frame_tx = ue->proc.proc_rxtx[0].frame_rx;
|
||||
}
|
||||
LOG_D(PHY,"[UE%d] Initial sync: FeMBMS pbch decoded sucessfully p %d, tx_ant %d, frame %d, N_RB_DL %d, AdditionalNonMBSFN_SF %d, frame_mod4 %d\n",
|
||||
LOG_D(PHY,"[UE%d] Initial sync: pbch decoded sucessfully p %d, tx_ant %d, frame %d, N_RB_DL %d, phich_duration %d, phich_resource %s!\n",
|
||||
ue->Mod_id,
|
||||
frame_parms->nb_antenna_ports_eNB,
|
||||
pbch_tx_ant,
|
||||
ue->proc.proc_rxtx[0].frame_rx,
|
||||
frame_parms->N_RB_DL,
|
||||
0,
|
||||
frame_mod4
|
||||
);
|
||||
|
||||
}
|
||||
frame_parms->phich_config_common.phich_duration,
|
||||
phich_resource); //frame_parms->phich_config_common.phich_resource);
|
||||
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
|
||||
} else {
|
||||
for(int i=0; i<RX_NB_TH; i++) {
|
||||
ue->proc.proc_rxtx[i].frame_rx = (((ue->pbch_vars[0]->decoded_output[2]&31)<<1) + (ue->pbch_vars[0]->decoded_output[1]>>7))<<4;
|
||||
ue->proc.proc_rxtx[i].frame_tx = ue->proc.proc_rxtx[0].frame_rx;
|
||||
}
|
||||
|
||||
LOG_D(PHY,"[UE%d] Initial sync: FeMBMS pbch decoded sucessfully p %d, tx_ant %d, frame %d, N_RB_DL %d, AdditionalNonMBSFN_SF %d, frame_mod4 %d\n",
|
||||
ue->Mod_id,
|
||||
frame_parms->nb_antenna_ports_eNB,
|
||||
pbch_tx_ant,
|
||||
ue->proc.proc_rxtx[0].frame_rx,
|
||||
frame_parms->N_RB_DL,
|
||||
0,
|
||||
frame_mod4
|
||||
);
|
||||
}
|
||||
|
||||
#endif
|
||||
return(0);
|
||||
} else {
|
||||
@@ -310,7 +309,6 @@ int initial_sync(PHY_VARS_UE *ue, runmode_t mode) {
|
||||
frame_parms->frame_type=FDD;
|
||||
frame_parms->nb_antenna_ports_eNB = 2;
|
||||
init_frame_parms(frame_parms,1);
|
||||
|
||||
/*
|
||||
LOG_M("rxdata0.m","rxd0",ue->common_vars.rxdata[0],10*frame_parms->samples_per_tti,1,1);
|
||||
exit(-1);
|
||||
@@ -325,9 +323,7 @@ int initial_sync(PHY_VARS_UE *ue, runmode_t mode) {
|
||||
else
|
||||
sync_pos2 = sync_pos + FRAME_LENGTH_COMPLEX_SAMPLES - frame_parms->nb_prefix_samples;
|
||||
|
||||
|
||||
LOG_D(PHY,"[UE%d] Initial sync : Estimated PSS position %d, Nid2 %d\n",ue->Mod_id,sync_pos,ue->common_vars.eNb_id);
|
||||
|
||||
// SSS detection
|
||||
// PSS is hypothesized in last symbol of first slot in Frame
|
||||
sync_pos_slot = (frame_parms->samples_per_tti>>1) - frame_parms->ofdm_symbol_size - frame_parms->nb_prefix_samples;
|
||||
@@ -350,22 +346,23 @@ int initial_sync(PHY_VARS_UE *ue, runmode_t mode) {
|
||||
lte_gold(frame_parms,ue->lte_gold_table[0],frame_parms->Nid_cell);
|
||||
ret = pbch_detection(ue,mode);
|
||||
// LOG_M("rxdata2.m","rxd2",ue->common_vars.rxdata[0],10*frame_parms->samples_per_tti,1,1);
|
||||
|
||||
LOG_D(PHY,"FDD Normal prefix: CellId %d metric %d, phase %d, flip %d, pbch %d\n",
|
||||
frame_parms->Nid_cell,metric_fdd_ncp,phase_fdd_ncp,flip_fdd_ncp,ret);
|
||||
|
||||
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
|
||||
if (ret==-1){
|
||||
ue->FeMBMS_active = 2;
|
||||
ret = pbch_detection(ue,mode);
|
||||
if (ret==-1){
|
||||
ue->FeMBMS_active = 0;
|
||||
frame_parms->FeMBMS_active = 0;
|
||||
}
|
||||
else frame_parms->FeMBMS_active = 1;
|
||||
|
||||
if (ret==-1) {
|
||||
ue->FeMBMS_active = 2;
|
||||
ret = pbch_detection(ue,mode);
|
||||
|
||||
if (ret==-1) {
|
||||
ue->FeMBMS_active = 0;
|
||||
frame_parms->FeMBMS_active = 0;
|
||||
} else frame_parms->FeMBMS_active = 1;
|
||||
|
||||
LOG_D(PHY,"FeMBMS Normal prefix: CellId %d metric %d, phase %d, flip %d, pbch %d\n",
|
||||
frame_parms->Nid_cell,metric_fdd_ncp,phase_fdd_ncp,flip_fdd_ncp,ret);
|
||||
}
|
||||
frame_parms->Nid_cell,metric_fdd_ncp,phase_fdd_ncp,flip_fdd_ncp,ret);
|
||||
}
|
||||
|
||||
#endif
|
||||
} else {
|
||||
LOG_D(PHY,"FDD Normal prefix: SSS error condition: sync_pos %d, sync_pos_slot %d\n", sync_pos, sync_pos_slot);
|
||||
@@ -406,23 +403,22 @@ int initial_sync(PHY_VARS_UE *ue, runmode_t mode) {
|
||||
// LOG_M("rxdata3.m","rxd3",ue->common_vars.rxdata[0],10*frame_parms->samples_per_tti,1,1);
|
||||
LOG_D(PHY,"FDD Extended prefix: CellId %d metric %d, phase %d, flip %d, pbch %d\n",
|
||||
frame_parms->Nid_cell,metric_fdd_ecp,phase_fdd_ecp,flip_fdd_ecp,ret);
|
||||
|
||||
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
|
||||
if (ret==-1){
|
||||
ue->FeMBMS_active = 2;
|
||||
ret = pbch_detection(ue,mode);
|
||||
if (ret==-1){
|
||||
ue->FeMBMS_active = 0;
|
||||
frame_parms->FeMBMS_active = 0;
|
||||
}
|
||||
else frame_parms->FeMBMS_active = 1;
|
||||
LOG_I(PHY,"FeMBMS CAS Extended prefix: CellId %d metric %d, phase %d, flip %d, pbch %d\n",
|
||||
frame_parms->Nid_cell,metric_fdd_ecp,phase_fdd_ecp,flip_fdd_ecp,ret);
|
||||
|
||||
if (ret==-1) {
|
||||
ue->FeMBMS_active = 2;
|
||||
ret = pbch_detection(ue,mode);
|
||||
|
||||
if (ret==-1) {
|
||||
ue->FeMBMS_active = 0;
|
||||
frame_parms->FeMBMS_active = 0;
|
||||
} else frame_parms->FeMBMS_active = 1;
|
||||
|
||||
LOG_I(PHY,"FeMBMS CAS Extended prefix: CellId %d metric %d, phase %d, flip %d, pbch %d\n",
|
||||
frame_parms->Nid_cell,metric_fdd_ecp,phase_fdd_ecp,flip_fdd_ecp,ret);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
} else {
|
||||
LOG_D(PHY,"FDD Extended prefix: SSS error condition: sync_pos %d, sync_pos_slot %d\n", sync_pos, sync_pos_slot);
|
||||
}
|
||||
@@ -460,9 +456,7 @@ int initial_sync(PHY_VARS_UE *ue, runmode_t mode) {
|
||||
lte_gold(frame_parms,ue->lte_gold_table[0],frame_parms->Nid_cell);
|
||||
ret = pbch_detection(ue,mode);
|
||||
// LOG_M("rxdata4.m","rxd4",ue->common_vars.rxdata[0],10*frame_parms->samples_per_tti,1,1);
|
||||
|
||||
LOG_D(PHY,"TDD Normal prefix: CellId %d metric %d, phase %d, flip %d, pbch %d\n",
|
||||
|
||||
frame_parms->Nid_cell,metric_tdd_ncp,phase_tdd_ncp,flip_tdd_ncp,ret);
|
||||
|
||||
if (ret==-1) {
|
||||
@@ -496,9 +490,7 @@ int initial_sync(PHY_VARS_UE *ue, runmode_t mode) {
|
||||
lte_gold(frame_parms,ue->lte_gold_table[0],frame_parms->Nid_cell);
|
||||
ret = pbch_detection(ue,mode);
|
||||
// LOG_M("rxdata5.m","rxd5",ue->common_vars.rxdata[0],10*frame_parms->samples_per_tti,1,1);
|
||||
|
||||
LOG_D(PHY,"TDD Extended prefix: CellId %d metric %d, phase %d, flip %d, pbch %d\n",
|
||||
|
||||
frame_parms->Nid_cell,metric_tdd_ecp,phase_tdd_ecp,flip_tdd_ecp,ret);
|
||||
}
|
||||
}
|
||||
@@ -525,7 +517,6 @@ int initial_sync(PHY_VARS_UE *ue, runmode_t mode) {
|
||||
generate_pcfich_reg_mapping(frame_parms);
|
||||
generate_phich_reg_mapping(frame_parms);
|
||||
ue->pbch_vars[0]->pdu_errors_conseq=0;
|
||||
|
||||
}
|
||||
|
||||
LOG_I(PHY, "[UE %d] Frame %d RRC Measurements => rssi %3.1f dBm (dig %3.1f dB, gain %d), N0 %d dBm, rsrp %3.1f dBm/RE, rsrq %3.1f dB\n",ue->Mod_id,
|
||||
@@ -562,7 +553,6 @@ int initial_sync(PHY_VARS_UE *ue, runmode_t mode) {
|
||||
metric_tdd_ecp,Nid_cell_tdd_ecp);*/
|
||||
LOG_D(PHY,"[UE%d] Initial sync : Estimated Nid_cell %d, Frame_type %d\n",ue->Mod_id,
|
||||
frame_parms->Nid_cell,frame_parms->frame_type);
|
||||
|
||||
ue->UE_mode[0] = NOT_SYNCHED;
|
||||
ue->pbch_vars[0]->pdu_errors_last=ue->pbch_vars[0]->pdu_errors;
|
||||
ue->pbch_vars[0]->pdu_errors++;
|
||||
@@ -587,15 +577,13 @@ int initial_sync(PHY_VARS_UE *ue, runmode_t mode) {
|
||||
// we might add a low-pass filter here later
|
||||
ue->measurements.rx_power_avg[0] = rx_power/frame_parms->nb_antennas_rx;
|
||||
ue->measurements.rx_power_avg_dB[0] = dB_fixed(ue->measurements.rx_power_avg[0]);
|
||||
|
||||
LOG_I(PHY,"[UE%d] Initial sync : Estimated power: %d dB\n",ue->Mod_id,ue->measurements.rx_power_avg_dB[0] );
|
||||
|
||||
if (IS_SOFTMODEM_BASICSIM || IS_SOFTMODEM_RFSIM )
|
||||
if (IS_SOFTMODEM_BASICSIM )
|
||||
phy_adjust_gain(ue,ue->measurements.rx_power_avg_dB[0],0);
|
||||
} else {
|
||||
if (IS_SOFTMODEM_BASICSIM || IS_SOFTMODEM_RFSIM )
|
||||
if (IS_SOFTMODEM_BASICSIM )
|
||||
phy_adjust_gain(ue,dB_fixed(ue->measurements.rssi),0);
|
||||
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -80,7 +80,7 @@ int32_t generate_prach( PHY_VARS_UE *ue, uint8_t eNB_id, uint8_t subframe, uint1
|
||||
int i, prach_len;
|
||||
uint16_t first_nonzero_root_idx=0;
|
||||
|
||||
if ( !(IS_SOFTMODEM_BASICSIM || IS_SOFTMODEM_RFSIM) ) {
|
||||
if ( !(IS_SOFTMODEM_BASICSIM ) ) {
|
||||
prach_start = (ue->rx_offset+subframe*ue->frame_parms.samples_per_tti-ue->hw_timing_advance-ue->N_TA_offset);
|
||||
#ifdef PRACH_DEBUG
|
||||
LOG_I(PHY,"[UE %d] prach_start %d, rx_offset %d, hw_timing_advance %d, N_TA_offset %d\n", ue->Mod_id,
|
||||
@@ -473,7 +473,7 @@ int32_t generate_prach( PHY_VARS_UE *ue, uint8_t eNB_id, uint8_t subframe, uint1
|
||||
AssertFatal(prach_fmt<4,
|
||||
"prach_fmt4 not fully implemented" );
|
||||
|
||||
if (!(IS_SOFTMODEM_BASICSIM || IS_SOFTMODEM_RFSIM) ) {
|
||||
if (!(IS_SOFTMODEM_BASICSIM ) ) {
|
||||
int j;
|
||||
int overflow = prach_start + prach_len - LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*ue->frame_parms.samples_per_tti;
|
||||
LOG_I( PHY, "prach_start=%d, overflow=%d\n", prach_start, overflow );
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -75,3 +75,6 @@ MESSAGE_DEF(NAS_DOWNLINK_DATA_IND, MESSAGE_PRIORITY_MED, NasDlDataInd
|
||||
|
||||
// eNB: realtime -> RRC messages
|
||||
MESSAGE_DEF(RRC_SUBFRAME_PROCESS, MESSAGE_PRIORITY_MED, RrcSubframeProcess, rrc_subframe_process)
|
||||
|
||||
// eNB: RLC -> RRC messages
|
||||
MESSAGE_DEF(RLC_SDU_INDICATION, MESSAGE_PRIORITY_MED, RlcSduIndication, rlc_sdu_indication)
|
||||
|
||||
@@ -85,6 +85,8 @@
|
||||
|
||||
#define RRC_SUBFRAME_PROCESS(mSGpTR) (mSGpTR)->ittiMsg.rrc_subframe_process
|
||||
|
||||
#define RLC_SDU_INDICATION(mSGpTR) (mSGpTR)->ittiMsg.rlc_sdu_indication
|
||||
|
||||
//-------------------------------------------------------------------------------------------//
|
||||
typedef struct RrcStateInd_s {
|
||||
Rrc_State_t state;
|
||||
@@ -422,4 +424,12 @@ typedef struct rrc_subframe_process_s {
|
||||
int CC_id;
|
||||
} RrcSubframeProcess;
|
||||
|
||||
// eNB: RLC -> RRC messages
|
||||
typedef struct rlc_sdu_indication_s {
|
||||
int rnti;
|
||||
int is_successful;
|
||||
int srb_id;
|
||||
int message_id;
|
||||
} RlcSduIndication;
|
||||
|
||||
#endif /* RRC_MESSAGES_TYPES_H_ */
|
||||
|
||||
@@ -143,13 +143,14 @@ add_msg3(module_id_t module_idP, int CC_id, RA_t *ra, frame_t frameP,
|
||||
ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.size = get_TBS_UL (ra->msg3_mcs, ra->msg3_nb_rb);
|
||||
// Re13 fields
|
||||
ul_config_pdu->ulsch_pdu.ulsch_pdu_rel13.ue_type = ra->rach_resource_type > 2 ? 2 : 1;
|
||||
|
||||
if (ra->rach_resource_type > 0) {
|
||||
pusch_maxNumRepetitionCEmodeA_r13= *(rrc->configuration.pusch_maxNumRepetitionCEmodeA_r13[CC_id]);
|
||||
ul_config_pdu->ulsch_pdu.ulsch_pdu_rel13.total_number_of_repetitions= pusch_repetition_Table8_2_36213[pusch_maxNumRepetitionCEmodeA_r13][ra->pusch_repetition_levels];
|
||||
}
|
||||
else{
|
||||
ul_config_pdu->ulsch_pdu.ulsch_pdu_rel13.total_number_of_repetitions=1;
|
||||
pusch_maxNumRepetitionCEmodeA_r13= *(rrc->configuration.pusch_maxNumRepetitionCEmodeA_r13[CC_id]);
|
||||
ul_config_pdu->ulsch_pdu.ulsch_pdu_rel13.total_number_of_repetitions= pusch_repetition_Table8_2_36213[pusch_maxNumRepetitionCEmodeA_r13][ra->pusch_repetition_levels];
|
||||
} else {
|
||||
ul_config_pdu->ulsch_pdu.ulsch_pdu_rel13.total_number_of_repetitions=1;
|
||||
}
|
||||
|
||||
ul_config_pdu->ulsch_pdu.ulsch_pdu_rel13.repetition_number = 1;
|
||||
ul_config_pdu->ulsch_pdu.ulsch_pdu_rel13.initial_transmission_sf_io = (ra->Msg3_frame * 10) + ra->Msg3_subframe;
|
||||
ul_req_body->number_of_pdus++;
|
||||
@@ -273,10 +274,9 @@ void generate_Msg2(module_id_t module_idP,
|
||||
uint16_t absSF_Msg2 = (10 * ra->Msg2_frame) + ra->Msg2_subframe;
|
||||
|
||||
if (ra->rach_resource_type > 0) {
|
||||
PUSCH_Rep_Level= *(rrc->configuration.pusch_repetitionLevelCEmodeA_r13[CC_idP]);
|
||||
}
|
||||
else {
|
||||
PUSCH_Rep_Level= 0;
|
||||
PUSCH_Rep_Level= *(rrc->configuration.pusch_repetitionLevelCEmodeA_r13[CC_idP]);
|
||||
} else {
|
||||
PUSCH_Rep_Level= 0;
|
||||
}
|
||||
|
||||
if (absSF > absSF_Msg2) {
|
||||
@@ -347,9 +347,7 @@ void generate_Msg2(module_id_t module_idP,
|
||||
dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.mpdcch_tansmission_type = 1; // imposed (9.1.5 in 213) for Type 2 Common search space
|
||||
AssertFatal (cc[CC_idP].sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13 != NULL, "cc[CC_idP].sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13 is null\n");
|
||||
dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.start_symbol = cc[CC_idP].sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13->startSymbolBR_r13;
|
||||
|
||||
LOG_E(MAC, "start_symbol = %d \n", dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.start_symbol);
|
||||
|
||||
dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.ecce_index = 0; // Note: this should be dynamic
|
||||
dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.aggregation_level = 24; // OK for CEModeA r1-3 (9.1.5-1b) or CEModeB r1-4
|
||||
dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.rnti_type = 2; // RA-RNTI
|
||||
@@ -421,7 +419,7 @@ void generate_Msg2(module_id_t module_idP,
|
||||
}
|
||||
|
||||
ra->pusch_repetition_levels = PUSCH_Rep_Level;
|
||||
|
||||
|
||||
if((ra->Msg2_frame == frameP) && (ra->Msg2_subframe == subframeP)) {
|
||||
/* Program PDSCH */
|
||||
LOG_D(MAC, "[eNB %d][RAPROC] Frame %d, Subframe %d : In generate_Msg2, Programming PDSCH\n",
|
||||
@@ -913,11 +911,10 @@ generate_Msg4(module_id_t module_idP,
|
||||
ul_req_body->number_of_pdus++;
|
||||
T (T_ENB_MAC_UE_DL_PDU_WITH_DATA, T_INT (module_idP), T_INT (CC_idP), T_INT (ra->rnti), T_INT (frameP), T_INT (subframeP),
|
||||
T_INT (0 /*harq_pid always 0? */ ), T_BUFFER (&mac->UE_list.DLSCH_pdu[CC_idP][0][UE_id].payload[0], ra->msg4_TBsize));
|
||||
|
||||
if (opt_enabled == 1) {
|
||||
trace_pdu (1, (uint8_t *) mac->UE_list.DLSCH_pdu[CC_idP][0][(unsigned char) UE_id].payload[0], ra->msg4_rrc_sdu_length, UE_id, 3, UE_RNTI (module_idP, UE_id), mac->frame, mac->subframe, 0, 0);
|
||||
LOG_D (OPT, "[eNB %d][DLSCH] CC_id %d Frame %d trace pdu for rnti %x with size %d\n", module_idP, CC_idP, frameP, UE_RNTI (module_idP, UE_id), ra->msg4_rrc_sdu_length);
|
||||
}
|
||||
trace_pdu (DIRECTION_DOWNLINK, (uint8_t *) mac->UE_list.DLSCH_pdu[CC_idP][0][(unsigned char) UE_id].payload[0],
|
||||
ra->msg4_rrc_sdu_length,
|
||||
UE_id, 3, UE_RNTI (module_idP, UE_id),
|
||||
mac->frame, mac->subframe, 0, 0);
|
||||
} // Msg4 frame/subframe
|
||||
} // rach_resource_type > 0
|
||||
else
|
||||
@@ -979,12 +976,10 @@ generate_Msg4(module_id_t module_idP,
|
||||
1, // tpc, none
|
||||
getRIV(N_RB_DL, first_rb, 4), // resource_block_coding
|
||||
ra->msg4_mcs, // mcs
|
||||
1 - UE_list->UE_template[CC_idP][UE_id].oldNDI[ra->harq_pid],
|
||||
1 - UE_list->UE_template[CC_idP][UE_id].oldNDI[ra->harq_pid],
|
||||
0, // rv
|
||||
0); // vrb_flag
|
||||
|
||||
UE_list->UE_template[CC_idP][UE_id].oldNDI[ra->harq_pid] = 1 - UE_list->UE_template[CC_idP][UE_id].oldNDI[ra->harq_pid];
|
||||
|
||||
UE_list->UE_template[CC_idP][UE_id].oldNDI[ra->harq_pid] = 1 - UE_list->UE_template[CC_idP][UE_id].oldNDI[ra->harq_pid];
|
||||
LOG_D(MAC,
|
||||
"Frame %d, subframe %d: Msg4 DCI pdu_num %d (rnti %x,rnti_type %d,harq_pid %d, resource_block_coding (%p) %d\n",
|
||||
frameP, subframeP, dl_req_body->number_pdu,
|
||||
@@ -1074,7 +1069,7 @@ generate_Msg4(module_id_t module_idP,
|
||||
mac->TX_req[CC_idP].sfn_sf =
|
||||
fill_nfapi_tx_req(&mac->TX_req[CC_idP].tx_request_body,
|
||||
(frameP * 10) + subframeP,
|
||||
rrc_sdu_length+offset,
|
||||
rrc_sdu_length+offset,
|
||||
mac->pdu_index[CC_idP],
|
||||
mac->UE_list.
|
||||
DLSCH_pdu[CC_idP][0][(unsigned char)UE_id].payload[0]);
|
||||
@@ -1094,20 +1089,12 @@ generate_Msg4(module_id_t module_idP,
|
||||
T_INT(subframeP), T_INT(0 /*harq_pid always 0? */ ),
|
||||
T_BUFFER(&mac->UE_list.DLSCH_pdu[CC_idP][0][UE_id].
|
||||
payload[0], ra->msg4_TBsize));
|
||||
|
||||
if (opt_enabled == 1) {
|
||||
trace_pdu(DIRECTION_DOWNLINK,
|
||||
(uint8_t *) mac->
|
||||
UE_list.DLSCH_pdu[CC_idP][0][(unsigned char)UE_id].payload[0],
|
||||
rrc_sdu_length, UE_id, WS_C_RNTI,
|
||||
UE_RNTI(module_idP, UE_id), mac->frame,
|
||||
mac->subframe, 0, 0);
|
||||
LOG_D(OPT,
|
||||
"[eNB %d][DLSCH] CC_id %d Frame %d trace pdu for rnti %x with size %d\n",
|
||||
module_idP, CC_idP, frameP, UE_RNTI(module_idP,
|
||||
UE_id),
|
||||
rrc_sdu_length);
|
||||
}
|
||||
trace_pdu(DIRECTION_DOWNLINK,
|
||||
(uint8_t *) mac->
|
||||
UE_list.DLSCH_pdu[CC_idP][0][(unsigned char)UE_id].payload[0],
|
||||
rrc_sdu_length, UE_id, WS_C_RNTI,
|
||||
UE_RNTI(module_idP, UE_id), mac->frame,
|
||||
mac->subframe, 0, 0);
|
||||
|
||||
if(RC.mac[module_idP]->scheduler_mode == SCHED_MODE_FAIR_RR) {
|
||||
set_dl_ue_select_msg4(CC_idP, 4, UE_id, ra->rnti);
|
||||
@@ -1219,7 +1206,7 @@ check_Msg4_retransmission(module_id_t module_idP, int CC_idP,
|
||||
1, // tpc, none
|
||||
getRIV(N_RB_DL, first_rb, 4), // resource_block_coding
|
||||
ra->msg4_mcs, // mcs
|
||||
UE_list->UE_template[CC_idP][UE_id].oldNDI[ra->harq_pid],
|
||||
UE_list->UE_template[CC_idP][UE_id].oldNDI[ra->harq_pid],
|
||||
round & 3, // rv
|
||||
0); // vrb_flag
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -565,7 +565,6 @@ schedule_ue_spec(module_id_t module_idP,
|
||||
dl_Bandwidth = cc[CC_id].mib->message.dl_Bandwidth;
|
||||
N_RB_DL[CC_id] = to_prb(dl_Bandwidth);
|
||||
min_rb_unit[CC_id] = get_min_rb_unit(module_idP, CC_id);
|
||||
|
||||
// get number of PRBs less those used by common channels
|
||||
total_nb_available_rb[CC_id] = N_RB_DL[CC_id];
|
||||
|
||||
@@ -622,7 +621,6 @@ schedule_ue_spec(module_id_t module_idP,
|
||||
LOG_D(MAC, "doing schedule_ue_spec for CC_id %d UE %d\n",
|
||||
CC_id,
|
||||
UE_id);
|
||||
|
||||
continue_flag = 0; // reset the flag to allow allocation for the remaining UEs
|
||||
rnti = UE_RNTI(module_idP, UE_id);
|
||||
ue_sched_ctrl = &UE_list->UE_sched_ctrl[UE_id];
|
||||
@@ -776,7 +774,8 @@ schedule_ue_spec(module_id_t module_idP,
|
||||
|
||||
if (ue_sched_ctrl->cdrx_configured) {
|
||||
ue_sched_ctrl->drx_retransmission_timer[harq_pid] = 0; // stop drx retransmission
|
||||
/*
|
||||
|
||||
/*
|
||||
* Note: contrary to the spec drx_retransmission_timer[harq_pid] is reset not stop.
|
||||
*/
|
||||
if (harq_pid == 0) {
|
||||
@@ -1011,9 +1010,10 @@ schedule_ue_spec(module_id_t module_idP,
|
||||
);
|
||||
|
||||
if((rrc_release_info.num_UEs > 0) && (rlc_am_mui.rrc_mui_num > 0)) {
|
||||
while(pthread_mutex_trylock(&rrc_release_freelist)){
|
||||
while(pthread_mutex_trylock(&rrc_release_freelist)) {
|
||||
/* spin... */
|
||||
}
|
||||
|
||||
uint16_t release_total = 0;
|
||||
|
||||
for (release_num = 0, release_ctrl = &rrc_release_info.RRC_release_ctrl[0];
|
||||
@@ -1060,10 +1060,10 @@ schedule_ue_spec(module_id_t module_idP,
|
||||
if(release_total >= rrc_release_info.num_UEs)
|
||||
break;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&rrc_release_freelist);
|
||||
}
|
||||
|
||||
|
||||
for (ra_ii = 0, ra = &eNB->common_channels[CC_id].ra[0]; ra_ii < NB_RA_PROC_MAX; ra_ii++, ra++) {
|
||||
if ((ra->rnti == rnti) && (ra->state == MSGCRNTI)) {
|
||||
for (uint16_t mui_num = 0; mui_num < rlc_am_mui.rrc_mui_num; mui_num++) {
|
||||
@@ -1254,7 +1254,6 @@ schedule_ue_spec(module_id_t module_idP,
|
||||
header_length_total += header_length_last;
|
||||
num_sdus++;
|
||||
ue_sched_ctrl->uplane_inactivity_timer = 0;
|
||||
|
||||
// reset RRC inactivity timer after uplane activity
|
||||
ue_contextP = rrc_eNB_get_ue_context(RC.rrc[module_idP], rnti);
|
||||
|
||||
@@ -1422,27 +1421,17 @@ schedule_ue_spec(module_id_t module_idP,
|
||||
dlsch_pdu->payload[0][offset + sdu_length_total + j] = 0;
|
||||
}
|
||||
|
||||
if (opt_enabled == 1) {
|
||||
trace_pdu(DIRECTION_DOWNLINK,
|
||||
(uint8_t *) dlsch_pdu->payload[0],
|
||||
TBS,
|
||||
module_idP,
|
||||
WS_C_RNTI,
|
||||
UE_RNTI(module_idP,
|
||||
UE_id),
|
||||
eNB->frame,
|
||||
eNB->subframe,
|
||||
0,
|
||||
0);
|
||||
LOG_D(OPT, "[eNB %d][DLSCH] CC_id %d Frame %d rnti %x with size %d\n",
|
||||
module_idP,
|
||||
CC_id,
|
||||
frameP,
|
||||
UE_RNTI(module_idP,
|
||||
UE_id),
|
||||
TBS);
|
||||
}
|
||||
|
||||
trace_pdu(DIRECTION_DOWNLINK,
|
||||
(uint8_t *) dlsch_pdu->payload[0],
|
||||
TBS,
|
||||
module_idP,
|
||||
WS_C_RNTI,
|
||||
UE_RNTI(module_idP,
|
||||
UE_id),
|
||||
eNB->frame,
|
||||
eNB->subframe,
|
||||
0,
|
||||
0);
|
||||
T(T_ENB_MAC_UE_DL_PDU_WITH_DATA,
|
||||
T_INT(module_idP),
|
||||
T_INT(CC_id),
|
||||
@@ -1506,7 +1495,7 @@ schedule_ue_spec(module_id_t module_idP,
|
||||
tpc = 1; //0
|
||||
}
|
||||
|
||||
LOG_D(MAC, "[eNB %d] DLSCH scheduler: frame %d, subframe %d, harq_pid %d, tpc %d, snr/target snr %d/%d\n",
|
||||
LOG_D(MAC, "[eNB %d] DLSCH scheduler: frame %d, subframe %d, harq_pid %d, tpc %d, snr/target snr %d/%d (normal case)\n",
|
||||
module_idP,
|
||||
frameP,
|
||||
subframeP,
|
||||
@@ -1578,17 +1567,17 @@ schedule_ue_spec(module_id_t module_idP,
|
||||
dl_req->tl.tag = NFAPI_DL_CONFIG_REQUEST_BODY_TAG;
|
||||
eNB->DL_req[CC_id].sfn_sf = frameP << 4 | subframeP;
|
||||
eNB->DL_req[CC_id].header.message_id = NFAPI_DL_CONFIG_REQUEST;
|
||||
|
||||
/* CDRX */
|
||||
ue_sched_ctrl->harq_rtt_timer[CC_id][harq_pid] = 1; // restart HARQ RTT timer
|
||||
|
||||
if (ue_sched_ctrl->cdrx_configured) {
|
||||
ue_sched_ctrl->drx_inactivity_timer = 1; // restart drx inactivity timer when new transmission
|
||||
ue_sched_ctrl->drx_retransmission_timer[harq_pid] = 0; // stop drx retransmission
|
||||
/*
|
||||
/*
|
||||
* Note: contrary to the spec drx_retransmission_timer[harq_pid] is reset not stop.
|
||||
*/
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DRX_INACTIVITY, (unsigned long) ue_sched_ctrl->drx_inactivity_timer);
|
||||
|
||||
if (harq_pid == 0) {
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DRX_RETRANSMISSION_HARQ0, (unsigned long) ue_sched_ctrl->drx_retransmission_timer[0]);
|
||||
}
|
||||
@@ -2345,25 +2334,16 @@ schedule_ue_spec_br(module_id_t module_idP,
|
||||
UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0][offset + sdu_length_total + j] = (char)(taus()&0xff);
|
||||
}
|
||||
|
||||
if (opt_enabled == 1) {
|
||||
trace_pdu(1,
|
||||
(uint8_t *)UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0],
|
||||
TBS,
|
||||
module_idP,
|
||||
3,
|
||||
UE_RNTI(module_idP,UE_id),
|
||||
mac->frame,
|
||||
mac->subframe,
|
||||
0,
|
||||
0);
|
||||
LOG_D(OPT,"[eNB %d][DLSCH] CC_id %d Frame %d rnti %x with size %d\n",
|
||||
module_idP,
|
||||
CC_id,
|
||||
frameP,
|
||||
UE_RNTI(module_idP, UE_id),
|
||||
TBS);
|
||||
}
|
||||
|
||||
trace_pdu(DIRECTION_DOWNLINK,
|
||||
(uint8_t *)UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0],
|
||||
TBS,
|
||||
module_idP,
|
||||
3,
|
||||
UE_RNTI(module_idP,UE_id),
|
||||
mac->frame,
|
||||
mac->subframe,
|
||||
0,
|
||||
0);
|
||||
T(T_ENB_MAC_UE_DL_PDU_WITH_DATA,
|
||||
T_INT(module_idP),
|
||||
T_INT(CC_id),
|
||||
@@ -2556,25 +2536,16 @@ schedule_ue_spec_br(module_id_t module_idP,
|
||||
T_INT (subframeP),
|
||||
T_INT (0 /* harq_pid always 0? */ ),
|
||||
T_BUFFER (&mac->UE_list.DLSCH_pdu[CC_id][0][UE_id].payload[0], TX_req->pdu_length));
|
||||
|
||||
if (opt_enabled == 1) {
|
||||
trace_pdu(1,
|
||||
(uint8_t *) mac->UE_list.DLSCH_pdu[CC_id][0][(unsigned char) UE_id].payload[0],
|
||||
TX_req->pdu_length,
|
||||
UE_id,
|
||||
3,
|
||||
rnti,
|
||||
frameP,
|
||||
subframeP,
|
||||
0,
|
||||
0);
|
||||
LOG_D(OPT, "[eNB %d][DLSCH] CC_id %d Frame %d trace pdu for rnti %x with size %d\n",
|
||||
module_idP,
|
||||
CC_id,
|
||||
frameP,
|
||||
rnti,
|
||||
TX_req->pdu_length);
|
||||
}
|
||||
trace_pdu(1,
|
||||
(uint8_t *) mac->UE_list.DLSCH_pdu[CC_id][0][(unsigned char) UE_id].payload[0],
|
||||
TX_req->pdu_length,
|
||||
UE_id,
|
||||
3,
|
||||
rnti,
|
||||
frameP,
|
||||
subframeP,
|
||||
0,
|
||||
0);
|
||||
} // end else if ((subframeP == 7) && (round_DL < 8))
|
||||
} // end loop on UE_id
|
||||
}
|
||||
@@ -3089,8 +3060,8 @@ schedule_PCH(module_id_t module_idP,
|
||||
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format = NFAPI_DL_DCI_FORMAT_1A;
|
||||
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.harq_process = 0;
|
||||
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tpc = 1; // no TPC
|
||||
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.new_data_indicator_1 = 0;
|
||||
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_1 = 0;
|
||||
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.new_data_indicator_1 = 0;
|
||||
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_1 = 0;
|
||||
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding = getRIV(n_rb_dl, first_rb, 4);
|
||||
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.virtual_resource_block_assignment_flag = 0;
|
||||
#endif
|
||||
@@ -3180,25 +3151,16 @@ schedule_PCH(module_id_t module_idP,
|
||||
continue;
|
||||
}
|
||||
|
||||
if (opt_enabled == 1) {
|
||||
trace_pdu(DIRECTION_DOWNLINK,
|
||||
&eNB->common_channels[CC_id].PCCH_pdu.payload[0],
|
||||
pcch_sdu_length,
|
||||
0xffff,
|
||||
PCCH,
|
||||
P_RNTI,
|
||||
eNB->frame,
|
||||
eNB->subframe,
|
||||
0,
|
||||
0);
|
||||
LOG_D(OPT,"[eNB %d][PCH] Frame %d trace pdu for CC_id %d rnti %x with size %d\n",
|
||||
module_idP,
|
||||
frameP,
|
||||
CC_id,
|
||||
0xffff,
|
||||
pcch_sdu_length);
|
||||
}
|
||||
|
||||
trace_pdu(DIRECTION_DOWNLINK,
|
||||
&eNB->common_channels[CC_id].PCCH_pdu.payload[0],
|
||||
pcch_sdu_length,
|
||||
0xffff,
|
||||
PCCH,
|
||||
P_RNTI,
|
||||
eNB->frame,
|
||||
eNB->subframe,
|
||||
0,
|
||||
0);
|
||||
eNB->eNB_stats[CC_id].total_num_pcch_pdu++;
|
||||
eNB->eNB_stats[CC_id].pcch_buffer = pcch_sdu_length;
|
||||
eNB->eNB_stats[CC_id].total_pcch_buffer += pcch_sdu_length;
|
||||
|
||||
@@ -644,16 +644,18 @@ void dlsch_scheduler_pre_processor_fairRR (module_id_t Mod_id,
|
||||
// Get total available RBS count and total UE count
|
||||
N_RB_DL = to_prb(cc->mib->message.dl_Bandwidth);
|
||||
temp_total_rbs_count = 0;
|
||||
for(uint8_t rbg_i = 0;rbg_i < N_RBG[CC_id];rbg_i++ ){
|
||||
if(rballoc_sub[CC_id][rbg_i] == 0){
|
||||
|
||||
for(uint8_t rbg_i = 0; rbg_i < N_RBG[CC_id]; rbg_i++ ) {
|
||||
if(rballoc_sub[CC_id][rbg_i] == 0) {
|
||||
if((rbg_i == N_RBG[CC_id] -1) &&
|
||||
((N_RB_DL == 25) || (N_RB_DL == 50))){
|
||||
((N_RB_DL == 25) || (N_RB_DL == 50))) {
|
||||
temp_total_rbs_count += (min_rb_unit[CC_id] -1);
|
||||
}else{
|
||||
} else {
|
||||
temp_total_rbs_count += min_rb_unit[CC_id];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
temp_total_ue_count = dlsch_ue_select[CC_id].ue_num;
|
||||
|
||||
for (i = 0; i < dlsch_ue_select[CC_id].ue_num; i++) {
|
||||
@@ -1305,10 +1307,11 @@ schedule_ue_spec_fairRR(module_id_t module_idP,
|
||||
#endif
|
||||
);
|
||||
|
||||
if((rrc_release_info.num_UEs > 0) && (rlc_am_mui.rrc_mui_num > 0)){
|
||||
if((rrc_release_info.num_UEs > 0) && (rlc_am_mui.rrc_mui_num > 0)) {
|
||||
while(pthread_mutex_trylock(&rrc_release_freelist)) {
|
||||
/* spin... */
|
||||
}
|
||||
|
||||
uint16_t release_total = 0;
|
||||
|
||||
for(uint16_t release_num = 0; release_num < NUMBER_OF_UE_MAX; release_num++) {
|
||||
@@ -1345,6 +1348,7 @@ schedule_ue_spec_fairRR(module_id_t module_idP,
|
||||
if(release_total >= rrc_release_info.num_UEs)
|
||||
break;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&rrc_release_freelist);
|
||||
}
|
||||
|
||||
@@ -1703,14 +1707,9 @@ schedule_ue_spec_fairRR(module_id_t module_idP,
|
||||
UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0][offset+sdu_length_total+j] = (char)(taus()&0xff);
|
||||
}
|
||||
|
||||
if (opt_enabled == 1) {
|
||||
trace_pdu(DIRECTION_DOWNLINK, (uint8_t *)UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0],
|
||||
TBS, module_idP, WS_RA_RNTI, UE_RNTI(module_idP, UE_id),
|
||||
eNB->frame, eNB->subframe,0,0);
|
||||
LOG_D(OPT,"[eNB %d][DLSCH] CC_id %d Frame %d rnti %x with size %d\n",
|
||||
module_idP, CC_id, frameP, UE_RNTI(module_idP, UE_id), TBS);
|
||||
}
|
||||
|
||||
trace_pdu(DIRECTION_DOWNLINK, (uint8_t *)UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0],
|
||||
TBS, module_idP, WS_RA_RNTI, UE_RNTI(module_idP, UE_id),
|
||||
eNB->frame, eNB->subframe,0,0);
|
||||
T(T_ENB_MAC_UE_DL_PDU_WITH_DATA, T_INT(module_idP), T_INT(CC_id), T_INT(rnti), T_INT(frameP), T_INT(subframeP),
|
||||
T_INT(harq_pid), T_BUFFER(UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0], TBS));
|
||||
UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid] = nb_rb;
|
||||
@@ -2052,6 +2051,7 @@ void ulsch_scheduler_pre_ue_select_fairRR(
|
||||
hi_dci0_pdu = &HI_DCI0_req->hi_dci0_pdu_list[HI_DCI0_req->number_of_dci+HI_DCI0_req->number_of_hi];
|
||||
format_flag = 2;
|
||||
aggregation=get_aggregation(get_bw_index(module_idP,CC_id),UE_list->UE_sched_ctrl[UE_id].dl_cqi[CC_id],format0);
|
||||
|
||||
if (CCE_allocation_infeasible(module_idP,CC_id,format_flag,subframeP,aggregation,rnti) == 1) {
|
||||
cc_id_flag[CC_id] = 1;
|
||||
continue;
|
||||
@@ -2130,7 +2130,8 @@ void ulsch_scheduler_pre_ue_select_fairRR(
|
||||
hi_dci0_pdu = &HI_DCI0_req->hi_dci0_pdu_list[HI_DCI0_req->number_of_dci+HI_DCI0_req->number_of_hi];
|
||||
format_flag = 2;
|
||||
rnti = UE_RNTI(module_idP,first_ue_id[CC_id][temp]);
|
||||
aggregation=get_aggregation(get_bw_index(module_idP,CC_id),UE_list->UE_sched_ctrl[first_ue_id[CC_id][temp]].dl_cqi[CC_id],format0);
|
||||
aggregation=get_aggregation(get_bw_index(module_idP,CC_id),UE_list->UE_sched_ctrl[first_ue_id[CC_id][temp]].dl_cqi[CC_id],format0);
|
||||
|
||||
if (CCE_allocation_infeasible(module_idP,CC_id,format_flag,subframeP,aggregation,rnti) == 1) {
|
||||
cc_id_flag[CC_id] = 1;
|
||||
break;
|
||||
@@ -2203,6 +2204,7 @@ void ulsch_scheduler_pre_ue_select_fairRR(
|
||||
hi_dci0_pdu = &HI_DCI0_req->hi_dci0_pdu_list[HI_DCI0_req->number_of_dci+HI_DCI0_req->number_of_hi];
|
||||
format_flag = 2;
|
||||
aggregation=get_aggregation(get_bw_index(module_idP,CC_id),UE_list->UE_sched_ctrl[UE_id].dl_cqi[CC_id],format0);
|
||||
|
||||
if (CCE_allocation_infeasible(module_idP,CC_id,format_flag,subframeP,aggregation,rnti) == 1) {
|
||||
cc_id_flag[CC_id] = 1;
|
||||
continue;
|
||||
@@ -2256,6 +2258,7 @@ void ulsch_scheduler_pre_ue_select_fairRR(
|
||||
format_flag = 2;
|
||||
rnti = UE_RNTI(module_idP,ul_inactivity_id[CC_id][temp]);
|
||||
aggregation=get_aggregation(get_bw_index(module_idP,CC_id),UE_list->UE_sched_ctrl[ul_inactivity_id[CC_id][temp]].dl_cqi[CC_id],format0);
|
||||
|
||||
if (CCE_allocation_infeasible(module_idP,CC_id,format_flag,subframeP,aggregation,rnti) == 1) {
|
||||
cc_id_flag[CC_id] = 1;
|
||||
continue;
|
||||
@@ -2454,20 +2457,20 @@ void ulsch_scheduler_pre_processor_fairRR(module_id_t module_idP,
|
||||
UE_list->UE_template[CC_id][UE_id].pre_assigned_mcs_ul = mcs;
|
||||
}
|
||||
} else {
|
||||
if (mac_eNB_get_rrc_status(module_idP,UE_RNTI(module_idP, UE_id)) < RRC_CONNECTED){
|
||||
if (mac_eNB_get_rrc_status(module_idP,UE_RNTI(module_idP, UE_id)) < RRC_CONNECTED) {
|
||||
// assigne RBS( 6 RBs)
|
||||
first_rb[CC_id] = first_rb[CC_id] + 6;
|
||||
UE_list->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul[0] = 6;
|
||||
UE_list->UE_template[CC_id][UE_id].pre_allocated_rb_table_index_ul = 5;
|
||||
UE_list->UE_template[CC_id][UE_id].pre_assigned_mcs_ul = 10;
|
||||
}else{
|
||||
} else {
|
||||
// assigne RBS( 3 RBs)
|
||||
first_rb[CC_id] = first_rb[CC_id] + 3;
|
||||
UE_list->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul[0] = 3;
|
||||
UE_list->UE_template[CC_id][UE_id].pre_allocated_rb_table_index_ul = 2;
|
||||
UE_list->UE_template[CC_id][UE_id].pre_assigned_mcs_ul = 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if ( ulsch_ue_select[CC_id].list[ulsch_ue_num].ue_priority == SCH_UL_INACTIVE ) {
|
||||
// assigne RBS( 3 RBs)
|
||||
first_rb[CC_id] = first_rb[CC_id] + 3;
|
||||
@@ -2766,7 +2769,7 @@ void schedule_ulsch_rnti_fairRR(module_id_t module_idP,
|
||||
UE_sched_ctrl = &UE_list->UE_sched_ctrl[UE_id];
|
||||
harq_pid = subframe2harqpid(cc,sched_frame,sched_subframeP);
|
||||
rnti = UE_RNTI(CC_id,UE_id);
|
||||
aggregation=get_aggregation(get_bw_index(module_idP,CC_id),UE_sched_ctrl[UE_id].dl_cqi[CC_id],format0);
|
||||
aggregation=get_aggregation(get_bw_index(module_idP,CC_id),UE_sched_ctrl[UE_id].dl_cqi[CC_id],format0);
|
||||
LOG_D(MAC,"[eNB %d] frame %d subframe %d,Checking PUSCH %d for UE %d/%x CC %d : aggregation level %d, N_RB_UL %d\n",
|
||||
module_idP,frameP,subframeP,harq_pid,UE_id,rnti,CC_id, aggregation,N_RB_UL);
|
||||
int bytes_to_schedule = UE_template->estimated_ul_buffer - UE_template->scheduled_ul_bytes;
|
||||
@@ -2836,7 +2839,7 @@ void schedule_ulsch_rnti_fairRR(module_id_t module_idP,
|
||||
}
|
||||
|
||||
if (tpc!=1) {
|
||||
LOG_D(MAC,"[eNB %d] ULSCH scheduler: frame %d, subframe %d, harq_pid %d, tpc %d, accumulated %d, snr/target snr %d/%d\n",
|
||||
LOG_D(MAC,"[eNB %d] ULSCH schedulerRR: frame %d, subframe %d, harq_pid %d, tpc %d, accumulated %d, snr/target snr %d/%d\n",
|
||||
module_idP,frameP,subframeP,harq_pid,tpc,
|
||||
tpc_accumulated,snr,target_snr);
|
||||
}
|
||||
@@ -3047,7 +3050,6 @@ void schedule_ulsch_rnti_fairRR(module_id_t module_idP,
|
||||
LOG_D(MAC,"[eNB %d][PUSCH %d/%x] CC_id %d Frame %d subframeP %d Scheduled UE %d (mcs %d, first rb %d, nb_rb %d, TBS %d, harq_pid %d)\n",
|
||||
module_idP,harq_pid,rnti,CC_id,frameP,subframeP,UE_id,mcs_rv,first_rb[CC_id],ulsch_ue_select[CC_id].list[ulsch_ue_num].nb_rb,UE_template->TBS_UL[harq_pid],harq_pid);
|
||||
|
||||
|
||||
// bad indices : 20 (40 PRB), 21 (45 PRB), 22 (48 PRB)
|
||||
//store for possible retransmission
|
||||
UE_template->nb_rb_ul[harq_pid] = ulsch_ue_select[CC_id].list[ulsch_ue_num].nb_rb;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -146,7 +146,7 @@ void mac_top_init_eNB(void)
|
||||
|
||||
RC.mac = mac;
|
||||
|
||||
AssertFatal(rlc_module_init() == 0,
|
||||
AssertFatal(rlc_module_init(1) == 0,
|
||||
"Could not initialize RLC layer\n");
|
||||
|
||||
// These should be out of here later
|
||||
@@ -184,7 +184,7 @@ int rlcmac_init_global_param(void)
|
||||
|
||||
LOG_I(MAC, "[MAIN] CALLING RLC_MODULE_INIT...\n");
|
||||
|
||||
if (rlc_module_init() != 0) {
|
||||
if (rlc_module_init(1) != 0) {
|
||||
return (-1);
|
||||
}
|
||||
|
||||
|
||||
@@ -110,7 +110,7 @@ mac_top_init_ue(int eMBMS_active, char *uecap_xer,
|
||||
int rlcmac_init_global_param_ue(void) {
|
||||
LOG_I(MAC, "[MAIN] CALLING RLC_MODULE_INIT...\n");
|
||||
|
||||
if (rlc_module_init() != 0) {
|
||||
if (rlc_module_init(0) != 0) {
|
||||
return (-1);
|
||||
}
|
||||
|
||||
|
||||
@@ -255,17 +255,11 @@ Msg1_transmitted(module_id_t module_idP, uint8_t CC_id,
|
||||
"Transmission on secondary CCs is not supported yet\n");
|
||||
// start contention resolution timer
|
||||
UE_mac_inst[module_idP].RA_attempt_number++;
|
||||
|
||||
if (opt_enabled) {
|
||||
trace_pdu(DIRECTION_UPLINK, NULL, 0, module_idP, WS_NO_RNTI,
|
||||
UE_mac_inst[module_idP].RA_prach_resources.
|
||||
ra_PreambleIndex, UE_mac_inst[module_idP].txFrame,
|
||||
UE_mac_inst[module_idP].txSubframe, 0,
|
||||
UE_mac_inst[module_idP].RA_attempt_number);
|
||||
LOG_D(OPT,
|
||||
"[UE %d][RAPROC] TX MSG1 Frame %d trace pdu for rnti %x with size %d\n",
|
||||
module_idP, frameP, 1, UE_mac_inst[module_idP].RA_Msg3_size);
|
||||
}
|
||||
trace_pdu(DIRECTION_UPLINK, NULL, 0, module_idP, WS_NO_RNTI,
|
||||
UE_mac_inst[module_idP].RA_prach_resources.
|
||||
ra_PreambleIndex, UE_mac_inst[module_idP].txFrame,
|
||||
UE_mac_inst[module_idP].txSubframe, 0,
|
||||
UE_mac_inst[module_idP].RA_attempt_number);
|
||||
}
|
||||
|
||||
|
||||
@@ -280,19 +274,11 @@ Msg3_transmitted(module_id_t module_idP, uint8_t CC_id,
|
||||
module_idP, frameP);
|
||||
UE_mac_inst[module_idP].RA_contention_resolution_cnt = 0;
|
||||
UE_mac_inst[module_idP].RA_contention_resolution_timer_active = 1;
|
||||
|
||||
if (opt_enabled) { // msg3
|
||||
trace_pdu(DIRECTION_UPLINK, &UE_mac_inst[module_idP].CCCH_pdu.payload[0],
|
||||
UE_mac_inst[module_idP].RA_Msg3_size, module_idP, WS_C_RNTI,
|
||||
UE_mac_inst[module_idP].crnti,
|
||||
UE_mac_inst[module_idP].txFrame,
|
||||
UE_mac_inst[module_idP].txSubframe, 0, 0);
|
||||
LOG_D(OPT,
|
||||
"[UE %d][RAPROC] MSG3 Frame %d trace pdu Preamble %d with size %d\n",
|
||||
module_idP, frameP, UE_mac_inst[module_idP].crnti
|
||||
/*UE_mac_inst[module_idP].RA_prach_resources.ra_PreambleIndex */
|
||||
, UE_mac_inst[module_idP].RA_Msg3_size);
|
||||
}
|
||||
trace_pdu(DIRECTION_UPLINK, &UE_mac_inst[module_idP].CCCH_pdu.payload[0],
|
||||
UE_mac_inst[module_idP].RA_Msg3_size, module_idP, WS_C_RNTI,
|
||||
UE_mac_inst[module_idP].crnti,
|
||||
UE_mac_inst[module_idP].txFrame,
|
||||
UE_mac_inst[module_idP].txSubframe, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -49,63 +49,54 @@ extern RAN_CONTEXT_t RC;
|
||||
//------------------------------------------------------------------------------
|
||||
unsigned short
|
||||
fill_rar(const module_id_t module_idP,
|
||||
const int CC_id,
|
||||
RA_t * ra,
|
||||
const frame_t frameP,
|
||||
uint8_t * const dlsch_buffer,
|
||||
const uint16_t N_RB_UL, const uint8_t input_buffer_length)
|
||||
const int CC_id,
|
||||
RA_t *ra,
|
||||
const frame_t frameP,
|
||||
uint8_t *const dlsch_buffer,
|
||||
const uint16_t N_RB_UL, const uint8_t input_buffer_length)
|
||||
//------------------------------------------------------------------------------
|
||||
{
|
||||
RA_HEADER_RAPID *rarh = (RA_HEADER_RAPID *) dlsch_buffer;
|
||||
uint8_t *rar = (uint8_t *) (dlsch_buffer + 1);
|
||||
// subheader fixed
|
||||
rarh->E = 0; // First and last RAR
|
||||
rarh->T = 1; // 0 for E/T/R/R/BI subheader, 1 for E/T/RAPID subheader
|
||||
rarh->RAPID = ra->preamble_index; // Respond to Preamble 0 only for the moment
|
||||
rar[4] = (uint8_t) (ra->rnti >> 8);
|
||||
rar[5] = (uint8_t) (ra->rnti & 0xff);
|
||||
//ra->timing_offset = 0;
|
||||
ra->timing_offset /= 16; //T_A = N_TA/16, where N_TA should be on a 30.72Msps
|
||||
rar[0] = (uint8_t) (ra->timing_offset >> (2 + 4)); // 7 MSBs of timing advance + divide by 4
|
||||
rar[1] = (uint8_t) (ra->timing_offset << (4 - 2)) & 0xf0; // 4 LSBs of timing advance + divide by 4
|
||||
COMMON_channels_t *cc = &RC.mac[module_idP]->common_channels[CC_id];
|
||||
|
||||
RA_HEADER_RAPID *rarh = (RA_HEADER_RAPID *) dlsch_buffer;
|
||||
uint8_t *rar = (uint8_t *) (dlsch_buffer + 1);
|
||||
|
||||
|
||||
// subheader fixed
|
||||
rarh->E = 0; // First and last RAR
|
||||
rarh->T = 1; // 0 for E/T/R/R/BI subheader, 1 for E/T/RAPID subheader
|
||||
rarh->RAPID = ra->preamble_index; // Respond to Preamble 0 only for the moment
|
||||
rar[4] = (uint8_t) (ra->rnti >> 8);
|
||||
rar[5] = (uint8_t) (ra->rnti & 0xff);
|
||||
//ra->timing_offset = 0;
|
||||
ra->timing_offset /= 16; //T_A = N_TA/16, where N_TA should be on a 30.72Msps
|
||||
rar[0] = (uint8_t) (ra->timing_offset >> (2 + 4)); // 7 MSBs of timing advance + divide by 4
|
||||
rar[1] = (uint8_t) (ra->timing_offset << (4 - 2)) & 0xf0; // 4 LSBs of timing advance + divide by 4
|
||||
COMMON_channels_t *cc = &RC.mac[module_idP]->common_channels[CC_id];
|
||||
if(N_RB_UL == 25){
|
||||
ra->msg3_first_rb = 1;
|
||||
}else{
|
||||
if (cc->tdd_Config && N_RB_UL == 100) {
|
||||
ra->msg3_first_rb = 3;
|
||||
} else {
|
||||
ra->msg3_first_rb = 2;
|
||||
}
|
||||
if(N_RB_UL == 25) {
|
||||
ra->msg3_first_rb = 1;
|
||||
} else {
|
||||
if (cc->tdd_Config && N_RB_UL == 100) {
|
||||
ra->msg3_first_rb = 3;
|
||||
} else {
|
||||
ra->msg3_first_rb = 2;
|
||||
}
|
||||
ra->msg3_nb_rb = 1;
|
||||
uint16_t rballoc = mac_computeRIV(N_RB_UL, ra->msg3_first_rb, ra->msg3_nb_rb); // first PRB only for UL Grant
|
||||
rar[1] |= (rballoc >> 7) & 7; // Hopping = 0 (bit 3), 3 MSBs of rballoc
|
||||
rar[2] = ((uint8_t) (rballoc & 0xff)) << 1; // 7 LSBs of rballoc
|
||||
ra->msg3_mcs = 10;
|
||||
ra->msg3_TPC = 3;
|
||||
ra->msg3_ULdelay = 0;
|
||||
ra->msg3_cqireq = 0;
|
||||
ra->msg3_round = 0;
|
||||
rar[2] |= ((ra->msg3_mcs & 0x8) >> 3); // mcs 10
|
||||
rar[3] =
|
||||
(((ra->msg3_mcs & 0x7) << 5)) | ((ra->msg3_TPC & 7) << 2) |
|
||||
((ra->msg3_ULdelay & 1) << 1) | (ra->msg3_cqireq & 1);
|
||||
}
|
||||
|
||||
if (opt_enabled) {
|
||||
trace_pdu(DIRECTION_DOWNLINK , dlsch_buffer, input_buffer_length, module_idP, WS_RA_RNTI , 1,
|
||||
RC.mac[module_idP]->frame, RC.mac[module_idP]->subframe,
|
||||
0, 0);
|
||||
LOG_D(OPT,
|
||||
"[eNB %d][RAPROC] CC_id %d RAR Frame %d trace pdu for rnti %x and rapid %d size %d\n",
|
||||
module_idP, CC_id, frameP, ra->rnti, rarh->RAPID,
|
||||
input_buffer_length);
|
||||
}
|
||||
|
||||
return (ra->rnti);
|
||||
ra->msg3_nb_rb = 1;
|
||||
uint16_t rballoc = mac_computeRIV(N_RB_UL, ra->msg3_first_rb, ra->msg3_nb_rb); // first PRB only for UL Grant
|
||||
rar[1] |= (rballoc >> 7) & 7; // Hopping = 0 (bit 3), 3 MSBs of rballoc
|
||||
rar[2] = ((uint8_t) (rballoc & 0xff)) << 1; // 7 LSBs of rballoc
|
||||
ra->msg3_mcs = 10;
|
||||
ra->msg3_TPC = 3;
|
||||
ra->msg3_ULdelay = 0;
|
||||
ra->msg3_cqireq = 0;
|
||||
ra->msg3_round = 0;
|
||||
rar[2] |= ((ra->msg3_mcs & 0x8) >> 3); // mcs 10
|
||||
rar[3] =
|
||||
(((ra->msg3_mcs & 0x7) << 5)) | ((ra->msg3_TPC & 7) << 2) |
|
||||
((ra->msg3_ULdelay & 1) << 1) | (ra->msg3_cqireq & 1);
|
||||
trace_pdu(DIRECTION_DOWNLINK, dlsch_buffer, input_buffer_length, module_idP, WS_RA_RNTI, 1,
|
||||
RC.mac[module_idP]->frame, RC.mac[module_idP]->subframe,
|
||||
0, 0);
|
||||
return (ra->rnti);
|
||||
}
|
||||
|
||||
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
|
||||
@@ -118,14 +109,13 @@ unsigned short fill_rar_br(eNB_MAC_INST *eNB,
|
||||
RA_t *ra,
|
||||
const frame_t frameP,
|
||||
const sub_frame_t subframeP,
|
||||
uint8_t* const dlsch_buffer,
|
||||
uint8_t *const dlsch_buffer,
|
||||
const uint8_t ce_level)
|
||||
//------------------------------------------------------------------------------
|
||||
{
|
||||
RA_HEADER_RAPID *rarh = (RA_HEADER_RAPID *) dlsch_buffer;
|
||||
COMMON_channels_t *cc = &eNB->common_channels[CC_id];
|
||||
uint8_t *rar = (uint8_t *)(dlsch_buffer + 1);
|
||||
|
||||
uint32_t rballoc = 0;
|
||||
uint32_t ULdelay = 0;
|
||||
uint32_t cqireq = 0;
|
||||
@@ -133,30 +123,24 @@ unsigned short fill_rar_br(eNB_MAC_INST *eNB,
|
||||
uint32_t TPC = 0;
|
||||
int input_buffer_length = 0;
|
||||
int N_NB_index = 0;
|
||||
|
||||
AssertFatal(ra != NULL, "RA is null \n");
|
||||
|
||||
/* Subheader fixed */
|
||||
rarh->E = 0; // First and last RAR
|
||||
rarh->T = 1; // 0 for E/T/R/R/BI subheader, 1 for E/T/RAPID subheader
|
||||
rarh->RAPID = ra->preamble_index; // Respond to Preamble
|
||||
|
||||
rarh->E = 0; // First and last RAR
|
||||
rarh->T = 1; // 0 for E/T/R/R/BI subheader, 1 for E/T/RAPID subheader
|
||||
rarh->RAPID = ra->preamble_index; // Respond to Preamble
|
||||
/* RAR PDU */
|
||||
/* TA Command */
|
||||
ra->timing_offset /= 16; // T_A = N_TA/16, where N_TA should be on a 30.72Msps
|
||||
rar[0] = (uint8_t) (ra->timing_offset >> 4) & 0x7f; // 7 MSBs of timing advance
|
||||
rar[1] = (uint8_t) (ra->timing_offset & 0x0f) << 4; // 4 LSBs of timing advance
|
||||
|
||||
ra->timing_offset /= 16; // T_A = N_TA/16, where N_TA should be on a 30.72Msps
|
||||
rar[0] = (uint8_t) (ra->timing_offset >> 4) & 0x7f; // 7 MSBs of timing advance
|
||||
rar[1] = (uint8_t) (ra->timing_offset & 0x0f) << 4; // 4 LSBs of timing advance
|
||||
/* Copy the Msg2 narrowband */
|
||||
ra->msg34_narrowband = ra->msg2_narrowband;
|
||||
ra->msg3_first_rb = 0;
|
||||
ra->msg3_nb_rb = 2;
|
||||
|
||||
if (ce_level < 2) { // CE Level 0, 1 (CEmodeA)
|
||||
if (ce_level < 2) { // CE Level 0, 1 (CEmodeA)
|
||||
input_buffer_length = 6;
|
||||
|
||||
N_NB_index = get_numnarrowbandbits(cc->mib->message.dl_Bandwidth);
|
||||
|
||||
/* UL Grant */
|
||||
ra->msg3_mcs = 7;
|
||||
TPC = 3; // no power increase
|
||||
@@ -164,7 +148,6 @@ unsigned short fill_rar_br(eNB_MAC_INST *eNB,
|
||||
cqireq = 0;
|
||||
mpdcch_nb_index = 0;
|
||||
rballoc = mac_computeRIV(6, ra->msg3_first_rb, ra->msg3_nb_rb);
|
||||
|
||||
uint32_t buffer = 0;
|
||||
buffer |= ra->msg34_narrowband << (16 + (4 - N_NB_index));
|
||||
buffer |= ((rballoc & 0x0F) << (12 + (4 - N_NB_index)));
|
||||
@@ -174,21 +157,15 @@ unsigned short fill_rar_br(eNB_MAC_INST *eNB,
|
||||
buffer |= ((cqireq & 0x01) << (3 + (4 - N_NB_index)));
|
||||
buffer |= ((ULdelay & 0x01) << (2 + (4 - N_NB_index)));
|
||||
buffer |= (mpdcch_nb_index << (4 - N_NB_index));
|
||||
|
||||
rar[1] |= (uint8_t) (buffer >> 16) & 0x0F;
|
||||
rar[2] = (uint8_t) (buffer >> 8) & 0xFF;
|
||||
rar[3] = (uint8_t) buffer & 0xFF;
|
||||
|
||||
/* RA CRNTI */
|
||||
rar[4] = (uint8_t)(ra->rnti >> 8);
|
||||
rar[5] = (uint8_t)(ra->rnti & 0xff);
|
||||
|
||||
} else { // CE level 2, 3 (CEModeB)
|
||||
|
||||
AssertFatal(1 == 0, "Shouldn't get here ...\n");
|
||||
|
||||
input_buffer_length = 5;
|
||||
|
||||
rar[3] = (uint8_t)(ra->rnti >> 8);
|
||||
rar[4] = (uint8_t)(ra->rnti & 0xff);
|
||||
}
|
||||
@@ -196,7 +173,7 @@ unsigned short fill_rar_br(eNB_MAC_INST *eNB,
|
||||
LOG_I(MAC, "[RAPROC] Frame %d Subframe %d : Generating RAR BR (%02x|%02x.%02x.%02x.%02x.%02x.%02x) for ce_level %d, CRNTI %x, preamble %d/%d, TIMING OFFSET %d\n",
|
||||
frameP,
|
||||
subframeP,
|
||||
*(uint8_t*) rarh,
|
||||
*(uint8_t *) rarh,
|
||||
rar[0],
|
||||
rar[1],
|
||||
rar[2],
|
||||
@@ -208,26 +185,16 @@ unsigned short fill_rar_br(eNB_MAC_INST *eNB,
|
||||
rarh->RAPID,
|
||||
ra->preamble_index,
|
||||
ra->timing_offset);
|
||||
|
||||
if (opt_enabled) {
|
||||
trace_pdu(DIRECTION_DOWNLINK,
|
||||
dlsch_buffer,
|
||||
input_buffer_length,
|
||||
eNB->Mod_id,
|
||||
WS_RA_RNTI,
|
||||
1,
|
||||
eNB->frame,
|
||||
eNB->subframe,
|
||||
0,
|
||||
0);
|
||||
|
||||
LOG_D(OPT, "[RAPROC] RAR Frame %d trace pdu for rnti %x and rapid %d size %d\n",
|
||||
frameP,
|
||||
ra->rnti,
|
||||
rarh->RAPID,
|
||||
input_buffer_length);
|
||||
}
|
||||
|
||||
trace_pdu(DIRECTION_DOWNLINK,
|
||||
dlsch_buffer,
|
||||
input_buffer_length,
|
||||
eNB->Mod_id,
|
||||
WS_RA_RNTI,
|
||||
1,
|
||||
eNB->frame,
|
||||
eNB->subframe,
|
||||
0,
|
||||
0);
|
||||
return (ra->rnti);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -41,103 +41,96 @@
|
||||
#define DEBUG_RAR
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
uint16_t ue_process_rar(const module_id_t module_idP, const int CC_id, const frame_t frameP, const rnti_t ra_rnti, uint8_t * const dlsch_buffer, rnti_t * const t_crnti, const uint8_t preamble_index, uint8_t * selected_rar_buffer // output argument for storing the selected RAR header and RAR payload
|
||||
)
|
||||
uint16_t ue_process_rar(const module_id_t module_idP, const int CC_id, const frame_t frameP, const rnti_t ra_rnti, uint8_t *const dlsch_buffer, rnti_t *const t_crnti, const uint8_t preamble_index,
|
||||
uint8_t *selected_rar_buffer // output argument for storing the selected RAR header and RAR payload
|
||||
)
|
||||
//------------------------------------------------------------------------------
|
||||
{
|
||||
uint16_t ret = 0; // return value
|
||||
uint16_t ret = 0; // return value
|
||||
RA_HEADER_RAPID *rarh = (RA_HEADER_RAPID *) dlsch_buffer;
|
||||
// RAR_PDU *rar = (RAR_PDU *)(dlsch_buffer+1);
|
||||
uint8_t *rar = (uint8_t *) (dlsch_buffer + 1);
|
||||
// get the last RAR payload for working with CMW500
|
||||
uint8_t n_rarpy = 0; // number of RAR payloads
|
||||
uint8_t n_rarh = 0; // number of MAC RAR subheaders
|
||||
uint8_t best_rx_rapid = -1; // the closest RAPID receive from all RARs
|
||||
|
||||
RA_HEADER_RAPID *rarh = (RA_HEADER_RAPID *) dlsch_buffer;
|
||||
// RAR_PDU *rar = (RAR_PDU *)(dlsch_buffer+1);
|
||||
uint8_t *rar = (uint8_t *) (dlsch_buffer + 1);
|
||||
while (1) {
|
||||
n_rarh++;
|
||||
|
||||
// get the last RAR payload for working with CMW500
|
||||
uint8_t n_rarpy = 0; // number of RAR payloads
|
||||
uint8_t n_rarh = 0; // number of MAC RAR subheaders
|
||||
uint8_t best_rx_rapid = -1; // the closest RAPID receive from all RARs
|
||||
while (1) {
|
||||
n_rarh++;
|
||||
if (rarh->T == 1) {
|
||||
n_rarpy++;
|
||||
LOG_D(MAC, "RAPID %d\n", rarh->RAPID);
|
||||
}
|
||||
|
||||
if (rarh->RAPID == preamble_index) {
|
||||
LOG_D(PHY, "Found RAR with the intended RAPID %d\n",
|
||||
rarh->RAPID);
|
||||
rar = (uint8_t *) (dlsch_buffer + n_rarh + (n_rarpy - 1) * 6);
|
||||
break;
|
||||
}
|
||||
|
||||
if (abs((int) rarh->RAPID - (int) preamble_index) <
|
||||
abs((int) best_rx_rapid - (int) preamble_index)) {
|
||||
best_rx_rapid = rarh->RAPID;
|
||||
rar = (uint8_t *) (dlsch_buffer + n_rarh + (n_rarpy - 1) * 6);
|
||||
}
|
||||
|
||||
if (rarh->E == 0) {
|
||||
LOG_I(PHY,
|
||||
"No RAR found with the intended RAPID. The closest RAPID in all RARs is %d\n",
|
||||
best_rx_rapid);
|
||||
break;
|
||||
} else {
|
||||
rarh++;
|
||||
}
|
||||
};
|
||||
LOG_D(MAC, "number of RAR subheader %d; number of RAR pyloads %d\n",
|
||||
n_rarh, n_rarpy);
|
||||
|
||||
if (CC_id > 0) {
|
||||
LOG_W(MAC, "Should not have received RAR on secondary CCs! \n");
|
||||
return (0xffff);
|
||||
if (rarh->T == 1) {
|
||||
n_rarpy++;
|
||||
LOG_D(MAC, "RAPID %d\n", rarh->RAPID);
|
||||
}
|
||||
|
||||
LOG_I(MAC,
|
||||
"[UE %d][RAPROC] Frame %d Received RAR (%02x|%02x.%02x.%02x.%02x.%02x.%02x) for preamble %d/%d\n",
|
||||
module_idP, frameP, *(uint8_t *) rarh, rar[0], rar[1], rar[2],
|
||||
rar[3], rar[4], rar[5], rarh->RAPID, preamble_index);
|
||||
#ifdef DEBUG_RAR
|
||||
LOG_D(MAC, "[UE %d][RAPROC] rarh->E %d\n", module_idP, rarh->E);
|
||||
LOG_D(MAC, "[UE %d][RAPROC] rarh->T %d\n", module_idP, rarh->T);
|
||||
LOG_D(MAC, "[UE %d][RAPROC] rarh->RAPID %d\n", module_idP,
|
||||
rarh->RAPID);
|
||||
|
||||
// LOG_I(MAC,"[UE %d][RAPROC] rar->R %d\n",module_idP,rar->R);
|
||||
LOG_D(MAC, "[UE %d][RAPROC] rar->Timing_Advance_Command %d\n",
|
||||
module_idP, (((uint16_t) (rar[0] & 0x7f)) << 4) + (rar[1] >> 4));
|
||||
// LOG_I(MAC,"[UE %d][RAPROC] rar->hopping_flag %d\n",module_idP,rar->hopping_flag);
|
||||
// LOG_I(MAC,"[UE %d][RAPROC] rar->rb_alloc %d\n",module_idP,rar->rb_alloc);
|
||||
// LOG_I(MAC,"[UE %d][RAPROC] rar->mcs %d\n",module_idP,rar->mcs);
|
||||
// LOG_I(MAC,"[UE %d][RAPROC] rar->TPC %d\n",module_idP,rar->TPC);
|
||||
// LOG_I(MAC,"[UE %d][RAPROC] rar->UL_delay %d\n",module_idP,rar->UL_delay);
|
||||
// LOG_I(MAC,"[UE %d][RAPROC] rar->cqi_req %d\n",module_idP,rar->cqi_req);
|
||||
LOG_D(MAC, "[UE %d][RAPROC] rar->t_crnti %x\n", module_idP,
|
||||
(uint16_t) rar[5] + (rar[4] << 8));
|
||||
#endif
|
||||
|
||||
if (opt_enabled) {
|
||||
LOG_D(OPT,
|
||||
"[UE %d][RAPROC] CC_id %d RAR Frame %d trace pdu for ra-RNTI %x\n",
|
||||
module_idP, CC_id, frameP, ra_rnti);
|
||||
trace_pdu(DIRECTION_DOWNLINK, (uint8_t *) dlsch_buffer, n_rarh + n_rarpy * 6,
|
||||
module_idP, WS_RA_RNTI, ra_rnti, UE_mac_inst[module_idP].rxFrame,
|
||||
UE_mac_inst[module_idP].rxSubframe, 0, 0);
|
||||
if (rarh->RAPID == preamble_index) {
|
||||
LOG_D(PHY, "Found RAR with the intended RAPID %d\n",
|
||||
rarh->RAPID);
|
||||
rar = (uint8_t *) (dlsch_buffer + n_rarh + (n_rarpy - 1) * 6);
|
||||
break;
|
||||
}
|
||||
|
||||
if (preamble_index == rarh->RAPID) {
|
||||
*t_crnti = (uint16_t) rar[5] + (rar[4] << 8); //rar->t_crnti;
|
||||
UE_mac_inst[module_idP].crnti = *t_crnti; //rar->t_crnti;
|
||||
//return(rar->Timing_Advance_Command);
|
||||
ret = ((((uint16_t) (rar[0] & 0x7f)) << 4) + (rar[1] >> 4));
|
||||
if (abs((int) rarh->RAPID - (int) preamble_index) <
|
||||
abs((int) best_rx_rapid - (int) preamble_index)) {
|
||||
best_rx_rapid = rarh->RAPID;
|
||||
rar = (uint8_t *) (dlsch_buffer + n_rarh + (n_rarpy - 1) * 6);
|
||||
}
|
||||
|
||||
if (rarh->E == 0) {
|
||||
LOG_I(PHY,
|
||||
"No RAR found with the intended RAPID. The closest RAPID in all RARs is %d\n",
|
||||
best_rx_rapid);
|
||||
break;
|
||||
} else {
|
||||
UE_mac_inst[module_idP].crnti = 0;
|
||||
ret = (0xffff);
|
||||
rarh++;
|
||||
}
|
||||
};
|
||||
|
||||
// move the selected RAR to the front of the RA_PDSCH buffer
|
||||
memcpy(selected_rar_buffer + 0, (uint8_t *) rarh, 1);
|
||||
memcpy(selected_rar_buffer + 1, (uint8_t *) rar, 6);
|
||||
LOG_D(MAC, "number of RAR subheader %d; number of RAR pyloads %d\n",
|
||||
n_rarh, n_rarpy);
|
||||
|
||||
return ret;
|
||||
if (CC_id > 0) {
|
||||
LOG_W(MAC, "Should not have received RAR on secondary CCs! \n");
|
||||
return (0xffff);
|
||||
}
|
||||
|
||||
LOG_I(MAC,
|
||||
"[UE %d][RAPROC] Frame %d Received RAR (%02x|%02x.%02x.%02x.%02x.%02x.%02x) for preamble %d/%d\n",
|
||||
module_idP, frameP, *(uint8_t *) rarh, rar[0], rar[1], rar[2],
|
||||
rar[3], rar[4], rar[5], rarh->RAPID, preamble_index);
|
||||
#ifdef DEBUG_RAR
|
||||
LOG_D(MAC, "[UE %d][RAPROC] rarh->E %d\n", module_idP, rarh->E);
|
||||
LOG_D(MAC, "[UE %d][RAPROC] rarh->T %d\n", module_idP, rarh->T);
|
||||
LOG_D(MAC, "[UE %d][RAPROC] rarh->RAPID %d\n", module_idP,
|
||||
rarh->RAPID);
|
||||
// LOG_I(MAC,"[UE %d][RAPROC] rar->R %d\n",module_idP,rar->R);
|
||||
LOG_D(MAC, "[UE %d][RAPROC] rar->Timing_Advance_Command %d\n",
|
||||
module_idP, (((uint16_t) (rar[0] & 0x7f)) << 4) + (rar[1] >> 4));
|
||||
// LOG_I(MAC,"[UE %d][RAPROC] rar->hopping_flag %d\n",module_idP,rar->hopping_flag);
|
||||
// LOG_I(MAC,"[UE %d][RAPROC] rar->rb_alloc %d\n",module_idP,rar->rb_alloc);
|
||||
// LOG_I(MAC,"[UE %d][RAPROC] rar->mcs %d\n",module_idP,rar->mcs);
|
||||
// LOG_I(MAC,"[UE %d][RAPROC] rar->TPC %d\n",module_idP,rar->TPC);
|
||||
// LOG_I(MAC,"[UE %d][RAPROC] rar->UL_delay %d\n",module_idP,rar->UL_delay);
|
||||
// LOG_I(MAC,"[UE %d][RAPROC] rar->cqi_req %d\n",module_idP,rar->cqi_req);
|
||||
LOG_D(MAC, "[UE %d][RAPROC] rar->t_crnti %x\n", module_idP,
|
||||
(uint16_t) rar[5] + (rar[4] << 8));
|
||||
#endif
|
||||
trace_pdu(DIRECTION_DOWNLINK, (uint8_t *) dlsch_buffer, n_rarh + n_rarpy * 6,
|
||||
module_idP, WS_RA_RNTI, ra_rnti, UE_mac_inst[module_idP].rxFrame,
|
||||
UE_mac_inst[module_idP].rxSubframe, 0, 0);
|
||||
|
||||
if (preamble_index == rarh->RAPID) {
|
||||
*t_crnti = (uint16_t) rar[5] + (rar[4] << 8); //rar->t_crnti;
|
||||
UE_mac_inst[module_idP].crnti = *t_crnti; //rar->t_crnti;
|
||||
//return(rar->Timing_Advance_Command);
|
||||
ret = ((((uint16_t) (rar[0] & 0x7f)) << 4) + (rar[1] >> 4));
|
||||
} else {
|
||||
UE_mac_inst[module_idP].crnti = 0;
|
||||
ret = (0xffff);
|
||||
}
|
||||
|
||||
// move the selected RAR to the front of the RA_PDSCH buffer
|
||||
memcpy(selected_rar_buffer + 0, (uint8_t *) rarh, 1);
|
||||
memcpy(selected_rar_buffer + 1, (uint8_t *) rar, 6);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -400,17 +400,9 @@ ue_send_sdu(module_id_t module_idP,
|
||||
#endif
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME
|
||||
(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_SDU, VCD_FUNCTION_IN);
|
||||
|
||||
//LOG_D(MAC,"sdu: %x.%x.%x\n",sdu[0],sdu[1],sdu[2]);
|
||||
|
||||
if (opt_enabled) {
|
||||
trace_pdu(DIRECTION_DOWNLINK, sdu, sdu_len, module_idP, WS_C_RNTI,
|
||||
UE_mac_inst[module_idP].crnti, frameP, subframeP, 0, 0);
|
||||
LOG_D(OPT,
|
||||
"[UE %d][DLSCH] Frame %d trace pdu for rnti %x with size %d\n",
|
||||
module_idP, frameP, UE_mac_inst[module_idP].crnti, sdu_len);
|
||||
}
|
||||
|
||||
trace_pdu(DIRECTION_DOWNLINK, sdu, sdu_len, module_idP, WS_C_RNTI,
|
||||
UE_mac_inst[module_idP].crnti, frameP, subframeP, 0, 0);
|
||||
payload_ptr =
|
||||
parse_header(sdu, &num_ce, &num_sdu, rx_ces, rx_lcids, rx_lengths,
|
||||
sdu_len);
|
||||
@@ -597,39 +589,31 @@ ue_send_sdu(module_id_t module_idP,
|
||||
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
|
||||
void
|
||||
ue_decode_si_mbms(module_id_t module_idP, int CC_id, frame_t frameP,
|
||||
uint8_t eNB_index, void *pdu, uint16_t len)
|
||||
{
|
||||
uint8_t eNB_index, void *pdu, uint16_t len) {
|
||||
#if UE_TIMING_TRACE
|
||||
start_meas(&UE_mac_inst[module_idP].rx_si);
|
||||
start_meas(&UE_mac_inst[module_idP].rx_si);
|
||||
#endif
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME
|
||||
(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_SI, VCD_FUNCTION_IN);
|
||||
|
||||
LOG_D(MAC, "[UE %d] Frame %d Sending SI MBMS to RRC (LCID Id %d,len %d)\n",
|
||||
module_idP, frameP, BCCH, len);
|
||||
|
||||
mac_rrc_data_ind_ue(module_idP, CC_id, frameP, 0, // unknown subframe
|
||||
SI_RNTI,
|
||||
BCCH_SI_MBMS, (uint8_t *) pdu, len, eNB_index,
|
||||
0);
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME
|
||||
(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_SI, VCD_FUNCTION_OUT);
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME
|
||||
(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_SI, VCD_FUNCTION_IN);
|
||||
LOG_D(MAC, "[UE %d] Frame %d Sending SI MBMS to RRC (LCID Id %d,len %d)\n",
|
||||
module_idP, frameP, BCCH, len);
|
||||
mac_rrc_data_ind_ue(module_idP, CC_id, frameP, 0, // unknown subframe
|
||||
SI_RNTI,
|
||||
BCCH_SI_MBMS, (uint8_t *) pdu, len, eNB_index,
|
||||
0);
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME
|
||||
(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_SI, VCD_FUNCTION_OUT);
|
||||
#if UE_TIMING_TRACE
|
||||
stop_meas(&UE_mac_inst[module_idP].rx_si);
|
||||
stop_meas(&UE_mac_inst[module_idP].rx_si);
|
||||
#endif
|
||||
if (opt_enabled == 1) {
|
||||
trace_pdu(DIRECTION_UPLINK,
|
||||
(uint8_t *) pdu,
|
||||
len,
|
||||
module_idP,
|
||||
WS_SI_RNTI,
|
||||
0xffff,
|
||||
UE_mac_inst[module_idP].rxFrame,
|
||||
UE_mac_inst[module_idP].rxSubframe, 0, 0);
|
||||
LOG_D(OPT,
|
||||
"[UE %d][BCH] Frame %d trace pdu for CC_id %d rnti %x with size %d\n",
|
||||
module_idP, frameP, CC_id, 0xffff, len);
|
||||
}
|
||||
trace_pdu(DIRECTION_UPLINK,
|
||||
(uint8_t *) pdu,
|
||||
len,
|
||||
module_idP,
|
||||
WS_SI_RNTI,
|
||||
0xffff,
|
||||
UE_mac_inst[module_idP].rxFrame,
|
||||
UE_mac_inst[module_idP].rxSubframe, 0, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -652,20 +636,14 @@ ue_decode_si(module_id_t module_idP, int CC_id, frame_t frameP,
|
||||
#if UE_TIMING_TRACE
|
||||
stop_meas(&UE_mac_inst[module_idP].rx_si);
|
||||
#endif
|
||||
|
||||
if (opt_enabled == 1) {
|
||||
trace_pdu(DIRECTION_UPLINK,
|
||||
(uint8_t *) pdu,
|
||||
len,
|
||||
module_idP,
|
||||
WS_SI_RNTI,
|
||||
0xffff,
|
||||
UE_mac_inst[module_idP].rxFrame,
|
||||
UE_mac_inst[module_idP].rxSubframe, 0, 0);
|
||||
LOG_D(OPT,
|
||||
"[UE %d][BCH] Frame %d trace pdu for CC_id %d rnti %x with size %d\n",
|
||||
module_idP, frameP, CC_id, 0xffff, len);
|
||||
}
|
||||
trace_pdu(DIRECTION_UPLINK,
|
||||
(uint8_t *) pdu,
|
||||
len,
|
||||
module_idP,
|
||||
WS_SI_RNTI,
|
||||
0xffff,
|
||||
UE_mac_inst[module_idP].rxFrame,
|
||||
UE_mac_inst[module_idP].rxSubframe, 0, 0);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -688,20 +666,14 @@ ue_decode_p(module_id_t module_idP, int CC_id, frame_t frameP,
|
||||
#if UE_TIMING_TRACE
|
||||
stop_meas(&UE_mac_inst[module_idP].rx_p);
|
||||
#endif
|
||||
|
||||
if (opt_enabled == 1) {
|
||||
trace_pdu(DIRECTION_UPLINK,
|
||||
(uint8_t *) pdu,
|
||||
len,
|
||||
module_idP,
|
||||
WS_SI_RNTI,
|
||||
P_RNTI,
|
||||
UE_mac_inst[module_idP].rxFrame,
|
||||
UE_mac_inst[module_idP].rxSubframe, 0, 0);
|
||||
LOG_D(OPT,
|
||||
"[UE %d][BCH] Frame %d trace pdu for CC_id %d rnti %x with size %d\n",
|
||||
module_idP, frameP, CC_id, P_RNTI, len);
|
||||
}
|
||||
trace_pdu(DIRECTION_UPLINK,
|
||||
(uint8_t *) pdu,
|
||||
len,
|
||||
module_idP,
|
||||
WS_SI_RNTI,
|
||||
P_RNTI,
|
||||
UE_mac_inst[module_idP].rxFrame,
|
||||
UE_mac_inst[module_idP].rxSubframe, 0, 0);
|
||||
}
|
||||
|
||||
#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
|
||||
@@ -2461,17 +2433,10 @@ ue_get_sdu(module_id_t module_idP, int CC_id, frame_t frameP,
|
||||
#if UE_TIMING_TRACE
|
||||
stop_meas(&UE_mac_inst[module_idP].tx_ulsch_sdu);
|
||||
#endif
|
||||
|
||||
if (opt_enabled) {
|
||||
trace_pdu(DIRECTION_UPLINK, ulsch_buffer, buflen, module_idP, WS_C_RNTI,
|
||||
UE_mac_inst[module_idP].crnti,
|
||||
UE_mac_inst[module_idP].txFrame,
|
||||
UE_mac_inst[module_idP].txSubframe, 0, 0);
|
||||
LOG_D(OPT,
|
||||
"[UE %d][ULSCH] Frame %d subframe %d trace pdu for rnti %x with size %d\n",
|
||||
module_idP, frameP, subframe, UE_mac_inst[module_idP].crnti,
|
||||
buflen);
|
||||
}
|
||||
trace_pdu(DIRECTION_UPLINK, ulsch_buffer, buflen, module_idP, WS_C_RNTI,
|
||||
UE_mac_inst[module_idP].crnti,
|
||||
UE_mac_inst[module_idP].txFrame,
|
||||
UE_mac_inst[module_idP].txSubframe, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -630,7 +630,8 @@ void rlc_data_conf (const protocol_ctxt_t *const ctxt_pP,
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
int
|
||||
rlc_module_init (void) {
|
||||
rlc_module_init (int enb_flag) { /* enb_flag is unused, but needed for binary
|
||||
* compatibility with rlc_v2 */
|
||||
//-----------------------------------------------------------------------------
|
||||
int k;
|
||||
module_id_t module_id1;
|
||||
|
||||
@@ -654,10 +654,10 @@ rlc_op_status_t rlc_stat_req (
|
||||
unsigned int* const stat_timer_poll_retransmit_timed_out,
|
||||
unsigned int* const stat_timer_status_prohibit_timed_out);
|
||||
|
||||
/*! \fn int rlc_module_init(void)
|
||||
/*! \fn int rlc_module_init(int enb_flag)
|
||||
* \brief RAZ the memory of the RLC layer, initialize the memory pool manager (mem_block_t structures mainly used in RLC module).
|
||||
*/
|
||||
int rlc_module_init(void);
|
||||
int rlc_module_init(int enb_flag);
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
135
openair2/LAYER2/pdcp_v2/pdcp_entity.c
Normal file
135
openair2/LAYER2/pdcp_v2/pdcp_entity.c
Normal file
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#include "pdcp_entity.h"
|
||||
|
||||
#include "pdcp_entity_srb.h"
|
||||
#include "pdcp_entity_drb_am.h"
|
||||
|
||||
#include "LOG/log.h"
|
||||
|
||||
pdcp_entity_t *new_pdcp_entity_srb(
|
||||
int rb_id,
|
||||
void (*deliver_sdu)(void *deliver_sdu_data, struct pdcp_entity_t *entity,
|
||||
char *buf, int size),
|
||||
void *deliver_sdu_data,
|
||||
void (*deliver_pdu)(void *deliver_pdu_data, struct pdcp_entity_t *entity,
|
||||
char *buf, int size, int sdu_id),
|
||||
void *deliver_pdu_data)
|
||||
{
|
||||
pdcp_entity_srb_t *ret;
|
||||
|
||||
ret = calloc(1, sizeof(pdcp_entity_srb_t));
|
||||
if (ret == NULL) {
|
||||
LOG_E(PDCP, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ret->common.recv_pdu = pdcp_entity_srb_recv_pdu;
|
||||
ret->common.recv_sdu = pdcp_entity_srb_recv_sdu;
|
||||
ret->common.set_integrity_key = pdcp_entity_srb_set_integrity_key;
|
||||
|
||||
ret->common.delete = pdcp_entity_srb_delete;
|
||||
|
||||
ret->common.deliver_sdu = deliver_sdu;
|
||||
ret->common.deliver_sdu_data = deliver_sdu_data;
|
||||
|
||||
ret->common.deliver_pdu = deliver_pdu;
|
||||
ret->common.deliver_pdu_data = deliver_pdu_data;
|
||||
|
||||
ret->rb_id = rb_id;
|
||||
|
||||
ret->common.maximum_pdcp_sn = 31;
|
||||
|
||||
return (pdcp_entity_t *)ret;
|
||||
|
||||
#if 0
|
||||
ret->common.recv_pdu = rlc_entity_am_recv_pdu;
|
||||
ret->common.buffer_status = rlc_entity_am_buffer_status;
|
||||
ret->common.generate_pdu = rlc_entity_am_generate_pdu;
|
||||
|
||||
ret->common.recv_sdu = rlc_entity_am_recv_sdu;
|
||||
|
||||
ret->common.set_time = rlc_entity_am_set_time;
|
||||
|
||||
ret->common.discard_sdu = rlc_entity_am_discard_sdu;
|
||||
|
||||
ret->common.reestablishment = rlc_entity_am_reestablishment;
|
||||
|
||||
ret->common.delete = rlc_entity_am_delete;
|
||||
|
||||
ret->common.deliver_sdu = deliver_sdu;
|
||||
ret->common.deliver_sdu_data = deliver_sdu_data;
|
||||
|
||||
ret->common.sdu_successful_delivery = sdu_successful_delivery;
|
||||
ret->common.sdu_successful_delivery_data = sdu_successful_delivery_data;
|
||||
|
||||
ret->common.max_retx_reached = max_retx_reached;
|
||||
ret->common.max_retx_reached_data = max_retx_reached_data;
|
||||
|
||||
ret->rx_maxsize = rx_maxsize;
|
||||
ret->tx_maxsize = tx_maxsize;
|
||||
ret->t_reordering = t_reordering;
|
||||
ret->t_status_prohibit = t_status_prohibit;
|
||||
ret->t_poll_retransmit = t_poll_retransmit;
|
||||
ret->poll_pdu = poll_pdu;
|
||||
ret->poll_byte = poll_byte;
|
||||
ret->max_retx_threshold = max_retx_threshold;
|
||||
|
||||
return (rlc_entity_t *)ret;
|
||||
#endif
|
||||
}
|
||||
|
||||
pdcp_entity_t *new_pdcp_entity_drb_am(
|
||||
int rb_id,
|
||||
void (*deliver_sdu)(void *deliver_sdu_data, struct pdcp_entity_t *entity,
|
||||
char *buf, int size),
|
||||
void *deliver_sdu_data,
|
||||
void (*deliver_pdu)(void *deliver_pdu_data, struct pdcp_entity_t *entity,
|
||||
char *buf, int size, int sdu_id),
|
||||
void *deliver_pdu_data)
|
||||
{
|
||||
pdcp_entity_drb_am_t *ret;
|
||||
|
||||
ret = calloc(1, sizeof(pdcp_entity_drb_am_t));
|
||||
if (ret == NULL) {
|
||||
LOG_E(PDCP, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ret->common.recv_pdu = pdcp_entity_drb_am_recv_pdu;
|
||||
ret->common.recv_sdu = pdcp_entity_drb_am_recv_sdu;
|
||||
ret->common.set_integrity_key = pdcp_entity_drb_am_set_integrity_key;
|
||||
|
||||
ret->common.delete = pdcp_entity_drb_am_delete;
|
||||
|
||||
ret->common.deliver_sdu = deliver_sdu;
|
||||
ret->common.deliver_sdu_data = deliver_sdu_data;
|
||||
|
||||
ret->common.deliver_pdu = deliver_pdu;
|
||||
ret->common.deliver_pdu_data = deliver_pdu_data;
|
||||
|
||||
ret->rb_id = rb_id;
|
||||
|
||||
ret->common.maximum_pdcp_sn = 4095;
|
||||
|
||||
return (pdcp_entity_t *)ret;
|
||||
}
|
||||
63
openair2/LAYER2/pdcp_v2/pdcp_entity.h
Normal file
63
openair2/LAYER2/pdcp_v2/pdcp_entity.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#ifndef _PDCP_ENTITY_H_
|
||||
#define _PDCP_ENTITY_H_
|
||||
|
||||
typedef struct pdcp_entity_t {
|
||||
/* functions provided by the PDCP module */
|
||||
void (*recv_pdu)(struct pdcp_entity_t *entity, char *buffer, int size);
|
||||
void (*recv_sdu)(struct pdcp_entity_t *entity, char *buffer, int size,
|
||||
int sdu_id);
|
||||
void (*delete)(struct pdcp_entity_t *entity);
|
||||
void (*set_integrity_key)(struct pdcp_entity_t *entity, char *key);
|
||||
|
||||
/* callbacks provided to the PDCP module */
|
||||
void (*deliver_sdu)(void *deliver_sdu_data, struct pdcp_entity_t *entity,
|
||||
char *buf, int size);
|
||||
void *deliver_sdu_data;
|
||||
void (*deliver_pdu)(void *deliver_pdu_data, struct pdcp_entity_t *entity,
|
||||
char *buf, int size, int sdu_id);
|
||||
void *deliver_pdu_data;
|
||||
int tx_hfn;
|
||||
int next_pdcp_tx_sn;
|
||||
int maximum_pdcp_sn;
|
||||
} pdcp_entity_t;
|
||||
|
||||
pdcp_entity_t *new_pdcp_entity_srb(
|
||||
int rb_id,
|
||||
void (*deliver_sdu)(void *deliver_sdu_data, struct pdcp_entity_t *entity,
|
||||
char *buf, int size),
|
||||
void *deliver_sdu_data,
|
||||
void (*deliver_pdu)(void *deliver_pdu_data, struct pdcp_entity_t *entity,
|
||||
char *buf, int size, int sdu_id),
|
||||
void *deliver_pdu_data);
|
||||
|
||||
pdcp_entity_t *new_pdcp_entity_drb_am(
|
||||
int rb_id,
|
||||
void (*deliver_sdu)(void *deliver_sdu_data, struct pdcp_entity_t *entity,
|
||||
char *buf, int size),
|
||||
void *deliver_sdu_data,
|
||||
void (*deliver_pdu)(void *deliver_pdu_data, struct pdcp_entity_t *entity,
|
||||
char *buf, int size, int sdu_id),
|
||||
void *deliver_pdu_data);
|
||||
|
||||
#endif /* _PDCP_ENTITY_H_ */
|
||||
70
openair2/LAYER2/pdcp_v2/pdcp_entity_drb_am.c
Normal file
70
openair2/LAYER2/pdcp_v2/pdcp_entity_drb_am.c
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#include "pdcp_entity_drb_am.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
void pdcp_entity_drb_am_recv_pdu(pdcp_entity_t *_entity, char *buffer, int size)
|
||||
{
|
||||
pdcp_entity_drb_am_t *entity = (pdcp_entity_drb_am_t *)_entity;
|
||||
|
||||
if (size < 3) abort();
|
||||
if (!(buffer[0] & 0x80)) { printf("%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); exit(1); }
|
||||
entity->common.deliver_sdu(entity->common.deliver_sdu_data,
|
||||
(pdcp_entity_t *)entity, buffer+2, size-2);
|
||||
}
|
||||
|
||||
void pdcp_entity_drb_am_recv_sdu(pdcp_entity_t *_entity, char *buffer, int size,
|
||||
int sdu_id)
|
||||
{
|
||||
pdcp_entity_drb_am_t *entity = (pdcp_entity_drb_am_t *)_entity;
|
||||
int sn;
|
||||
char buf[size+2];
|
||||
|
||||
sn = entity->common.next_pdcp_tx_sn;
|
||||
|
||||
entity->common.next_pdcp_tx_sn++;
|
||||
if (entity->common.next_pdcp_tx_sn > entity->common.maximum_pdcp_sn) {
|
||||
entity->common.next_pdcp_tx_sn = 0;
|
||||
entity->common.tx_hfn++;
|
||||
}
|
||||
|
||||
buf[0] = 0x80 | ((sn >> 8) & 0x0f);
|
||||
buf[1] = sn & 0xff;
|
||||
memcpy(buf+2, buffer, size);
|
||||
|
||||
entity->common.deliver_pdu(entity->common.deliver_pdu_data,
|
||||
(pdcp_entity_t *)entity, buf, size+2, sdu_id);
|
||||
}
|
||||
|
||||
void pdcp_entity_drb_am_set_integrity_key(pdcp_entity_t *_entity, char *key)
|
||||
{
|
||||
/* nothing to do */
|
||||
}
|
||||
|
||||
void pdcp_entity_drb_am_delete(pdcp_entity_t *_entity)
|
||||
{
|
||||
pdcp_entity_drb_am_t *entity = (pdcp_entity_drb_am_t *)_entity;
|
||||
free(entity);
|
||||
}
|
||||
38
openair2/LAYER2/pdcp_v2/pdcp_entity_drb_am.h
Normal file
38
openair2/LAYER2/pdcp_v2/pdcp_entity_drb_am.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#ifndef _PDCP_ENTITY_DRB_AM_H_
|
||||
#define _PDCP_ENTITY_DRB_AM_H_
|
||||
|
||||
#include "pdcp_entity.h"
|
||||
|
||||
typedef struct {
|
||||
pdcp_entity_t common;
|
||||
int rb_id;
|
||||
} pdcp_entity_drb_am_t;
|
||||
|
||||
void pdcp_entity_drb_am_recv_pdu(pdcp_entity_t *entity, char *buffer, int size);
|
||||
void pdcp_entity_drb_am_recv_sdu(pdcp_entity_t *entity, char *buffer, int size,
|
||||
int sdu_id);
|
||||
void pdcp_entity_drb_am_set_integrity_key(pdcp_entity_t *entity, char *key);
|
||||
void pdcp_entity_drb_am_delete(pdcp_entity_t *entity);
|
||||
|
||||
#endif /* _PDCP_ENTITY_DRB_AM_H_ */
|
||||
93
openair2/LAYER2/pdcp_v2/pdcp_entity_srb.c
Normal file
93
openair2/LAYER2/pdcp_v2/pdcp_entity_srb.c
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#include "pdcp_entity_srb.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
void pdcp_entity_srb_recv_pdu(pdcp_entity_t *_entity, char *buffer, int size)
|
||||
{
|
||||
pdcp_entity_srb_t *entity = (pdcp_entity_srb_t *)_entity;
|
||||
|
||||
entity->common.deliver_sdu(entity->common.deliver_sdu_data,
|
||||
(pdcp_entity_t *)entity, buffer+1, size-5);
|
||||
}
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include "UTIL/OSA/osa_defs.h"
|
||||
|
||||
void pdcp_entity_srb_recv_sdu(pdcp_entity_t *_entity, char *buffer, int size,
|
||||
int sdu_id)
|
||||
{
|
||||
pdcp_entity_srb_t *entity = (pdcp_entity_srb_t *)_entity;
|
||||
int sn;
|
||||
char buf[size+5];
|
||||
|
||||
sn = entity->common.next_pdcp_tx_sn;
|
||||
|
||||
entity->common.next_pdcp_tx_sn++;
|
||||
if (entity->common.next_pdcp_tx_sn > entity->common.maximum_pdcp_sn) {
|
||||
entity->common.next_pdcp_tx_sn = 0;
|
||||
entity->common.tx_hfn++;
|
||||
}
|
||||
|
||||
buf[0] = sn & 0x1f;
|
||||
memcpy(buf+1, buffer, size);
|
||||
|
||||
if (entity->integrity_active) {
|
||||
stream_cipher_t params;
|
||||
params.message = (unsigned char *)buf;
|
||||
params.blength = (size + 1) << 3;
|
||||
params.key = (unsigned char *)entity->key_integrity + 16;
|
||||
params.key_length = 16;
|
||||
params.count = (entity->common.tx_hfn << 5) | sn;
|
||||
params.bearer = entity->rb_id - 1;
|
||||
params.direction = SECU_DIRECTION_DOWNLINK;
|
||||
printf("call stream_compute_integrity\n");
|
||||
stream_compute_integrity(EIA2_128_ALG_ID, ¶ms,
|
||||
(unsigned char *)&buf[size+1]);
|
||||
} else {
|
||||
printf("no integrity\n");
|
||||
buf[size+1] = 0;
|
||||
buf[size+2] = 0;
|
||||
buf[size+3] = 0;
|
||||
buf[size+4] = 0;
|
||||
}
|
||||
|
||||
entity->common.deliver_pdu(entity->common.deliver_pdu_data,
|
||||
(pdcp_entity_t *)entity, buf, size+5, sdu_id);
|
||||
}
|
||||
|
||||
void pdcp_entity_srb_set_integrity_key(pdcp_entity_t *_entity, char *key)
|
||||
{
|
||||
printf("activate integrity\n");
|
||||
pdcp_entity_srb_t *entity = (pdcp_entity_srb_t *)_entity;
|
||||
|
||||
memcpy(entity->key_integrity, key, 32);
|
||||
entity->integrity_active = 1;
|
||||
}
|
||||
|
||||
void pdcp_entity_srb_delete(pdcp_entity_t *_entity)
|
||||
{
|
||||
pdcp_entity_srb_t *entity = (pdcp_entity_srb_t *)_entity;
|
||||
free(entity);
|
||||
}
|
||||
40
openair2/LAYER2/pdcp_v2/pdcp_entity_srb.h
Normal file
40
openair2/LAYER2/pdcp_v2/pdcp_entity_srb.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#ifndef _PDCP_ENTITY_SRB_H_
|
||||
#define _PDCP_ENTITY_SRB_H_
|
||||
|
||||
#include "pdcp_entity.h"
|
||||
|
||||
typedef struct {
|
||||
pdcp_entity_t common;
|
||||
int rb_id;
|
||||
char key_integrity[32];
|
||||
int integrity_active;
|
||||
} pdcp_entity_srb_t;
|
||||
|
||||
void pdcp_entity_srb_recv_pdu(pdcp_entity_t *entity, char *buffer, int size);
|
||||
void pdcp_entity_srb_recv_sdu(pdcp_entity_t *entity, char *buffer, int size,
|
||||
int sdu_id);
|
||||
void pdcp_entity_srb_set_integrity_key(pdcp_entity_t *entity, char *key);
|
||||
void pdcp_entity_srb_delete(pdcp_entity_t *entity);
|
||||
|
||||
#endif /* _PDCP_ENTITY_SRB_H_ */
|
||||
755
openair2/LAYER2/pdcp_v2/pdcp_oai_api.c
Normal file
755
openair2/LAYER2/pdcp_v2/pdcp_oai_api.c
Normal file
@@ -0,0 +1,755 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#include "pdcp_ue_manager.h"
|
||||
|
||||
/* from OAI */
|
||||
#include "pdcp.h"
|
||||
#include "targets/RT/USER/lte-softmodem.h"
|
||||
|
||||
#define TODO do { \
|
||||
printf("%s:%d:%s: todo\n", __FILE__, __LINE__, __FUNCTION__); \
|
||||
exit(1); \
|
||||
} while (0)
|
||||
|
||||
static pdcp_ue_manager_t *pdcp_ue_manager;
|
||||
|
||||
/* necessary globals for OAI, not used internally */
|
||||
hash_table_t *pdcp_coll_p;
|
||||
static uint64_t pdcp_optmask;
|
||||
|
||||
/****************************************************************************/
|
||||
/* rlc_data_req queue - begin */
|
||||
/****************************************************************************/
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
/* New PDCP and RLC both use "big locks". In some cases a thread may do
|
||||
* lock(rlc) followed by lock(pdcp) (typically when running 'rx_sdu').
|
||||
* Another thread may first do lock(pdcp) and then lock(rlc) (typically
|
||||
* the GTP module calls 'pdcp_data_req' that, in a previous implementation
|
||||
* was indirectly calling 'rlc_data_req' which does lock(rlc)).
|
||||
* To avoid the resulting deadlock it is enough to ensure that a call
|
||||
* to lock(pdcp) will never be followed by a call to lock(rlc). So,
|
||||
* here we chose to have a separate thread that deals with rlc_data_req,
|
||||
* out of the PDCP lock. Other solutions may be possible.
|
||||
* So instead of calling 'rlc_data_req' directly we have a queue and a
|
||||
* separate thread emptying it.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
protocol_ctxt_t ctxt_pP;
|
||||
srb_flag_t srb_flagP;
|
||||
MBMS_flag_t MBMS_flagP;
|
||||
rb_id_t rb_idP;
|
||||
mui_t muiP;
|
||||
confirm_t confirmP;
|
||||
sdu_size_t sdu_sizeP;
|
||||
mem_block_t *sdu_pP;
|
||||
} rlc_data_req_queue_item;
|
||||
|
||||
#define RLC_DATA_REQ_QUEUE_SIZE 10000
|
||||
|
||||
typedef struct {
|
||||
rlc_data_req_queue_item q[RLC_DATA_REQ_QUEUE_SIZE];
|
||||
volatile int start;
|
||||
volatile int length;
|
||||
pthread_mutex_t m;
|
||||
pthread_cond_t c;
|
||||
} rlc_data_req_queue;
|
||||
|
||||
static rlc_data_req_queue q;
|
||||
|
||||
static void *rlc_data_req_thread(void *_)
|
||||
{
|
||||
int i;
|
||||
|
||||
while (1) {
|
||||
if (pthread_mutex_lock(&q.m) != 0) abort();
|
||||
while (q.length == 0)
|
||||
if (pthread_cond_wait(&q.c, &q.m) != 0) abort();
|
||||
i = q.start;
|
||||
if (pthread_mutex_unlock(&q.m) != 0) abort();
|
||||
|
||||
rlc_data_req(&q.q[i].ctxt_pP,
|
||||
q.q[i].srb_flagP,
|
||||
q.q[i].MBMS_flagP,
|
||||
q.q[i].rb_idP,
|
||||
q.q[i].muiP,
|
||||
q.q[i].confirmP,
|
||||
q.q[i].sdu_sizeP,
|
||||
q.q[i].sdu_pP,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
if (pthread_mutex_lock(&q.m) != 0) abort();
|
||||
|
||||
q.length--;
|
||||
q.start = (q.start + 1) % RLC_DATA_REQ_QUEUE_SIZE;
|
||||
|
||||
if (pthread_cond_signal(&q.c) != 0) abort();
|
||||
if (pthread_mutex_unlock(&q.m) != 0) abort();
|
||||
}
|
||||
}
|
||||
|
||||
static void init_rlc_data_req_queue(void)
|
||||
{
|
||||
pthread_t t;
|
||||
|
||||
pthread_mutex_init(&q.m, NULL);
|
||||
pthread_cond_init(&q.c, NULL);
|
||||
|
||||
if (pthread_create(&t, NULL, rlc_data_req_thread, NULL) != 0) {
|
||||
LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
static void enqueue_rlc_data_req(const protocol_ctxt_t *const ctxt_pP,
|
||||
const srb_flag_t srb_flagP,
|
||||
const MBMS_flag_t MBMS_flagP,
|
||||
const rb_id_t rb_idP,
|
||||
const mui_t muiP,
|
||||
confirm_t confirmP,
|
||||
sdu_size_t sdu_sizeP,
|
||||
mem_block_t *sdu_pP,
|
||||
void *_unused1, void *_unused2)
|
||||
{
|
||||
int i;
|
||||
int logged = 0;
|
||||
|
||||
if (pthread_mutex_lock(&q.m) != 0) abort();
|
||||
while (q.length == RLC_DATA_REQ_QUEUE_SIZE) {
|
||||
if (!logged) {
|
||||
logged = 1;
|
||||
LOG_W(PDCP, "%s: rlc_data_req queue is full\n", __FUNCTION__);
|
||||
}
|
||||
if (pthread_cond_wait(&q.c, &q.m) != 0) abort();
|
||||
}
|
||||
|
||||
i = (q.start + q.length) % RLC_DATA_REQ_QUEUE_SIZE;
|
||||
q.length++;
|
||||
|
||||
q.q[i].ctxt_pP = *ctxt_pP;
|
||||
q.q[i].srb_flagP = srb_flagP;
|
||||
q.q[i].MBMS_flagP = MBMS_flagP;
|
||||
q.q[i].rb_idP = rb_idP;
|
||||
q.q[i].muiP = muiP;
|
||||
q.q[i].confirmP = confirmP;
|
||||
q.q[i].sdu_sizeP = sdu_sizeP;
|
||||
q.q[i].sdu_pP = sdu_pP;
|
||||
|
||||
if (pthread_cond_signal(&q.c) != 0) abort();
|
||||
if (pthread_mutex_unlock(&q.m) != 0) abort();
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/* rlc_data_req queue - end */
|
||||
/****************************************************************************/
|
||||
|
||||
void pdcp_layer_init(void)
|
||||
{
|
||||
/* be sure to initialize only once */
|
||||
static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
|
||||
static int initialized = 0;
|
||||
if (pthread_mutex_lock(&m) != 0) abort();
|
||||
if (initialized) {
|
||||
if (pthread_mutex_unlock(&m) != 0) abort();
|
||||
return;
|
||||
}
|
||||
initialized = 1;
|
||||
if (pthread_mutex_unlock(&m) != 0) abort();
|
||||
|
||||
pdcp_ue_manager = new_pdcp_ue_manager(1);
|
||||
init_rlc_data_req_queue();
|
||||
}
|
||||
|
||||
uint64_t pdcp_module_init(uint64_t _pdcp_optmask)
|
||||
{
|
||||
pdcp_optmask = _pdcp_optmask;
|
||||
return pdcp_optmask;
|
||||
}
|
||||
|
||||
static void deliver_sdu_drb(void *_ue, pdcp_entity_t *entity,
|
||||
char *buf, int size)
|
||||
{
|
||||
pdcp_ue_t *ue = _ue;
|
||||
MessageDef *message_p;
|
||||
uint8_t *gtpu_buffer_p;
|
||||
int rb_id;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 5; i++) {
|
||||
if (entity == ue->drb[i]) {
|
||||
rb_id = i+1;
|
||||
goto rb_found;
|
||||
}
|
||||
}
|
||||
|
||||
LOG_E(PDCP, "%s:%d:%s: fatal, no RB found for ue %d\n",
|
||||
__FILE__, __LINE__, __FUNCTION__, ue->rnti);
|
||||
exit(1);
|
||||
|
||||
rb_found:
|
||||
gtpu_buffer_p = itti_malloc(TASK_PDCP_ENB, TASK_GTPV1_U,
|
||||
size + GTPU_HEADER_OVERHEAD_MAX);
|
||||
AssertFatal(gtpu_buffer_p != NULL, "OUT OF MEMORY");
|
||||
memcpy(>pu_buffer_p[GTPU_HEADER_OVERHEAD_MAX], buf, size);
|
||||
message_p = itti_alloc_new_message(TASK_PDCP_ENB, GTPV1U_ENB_TUNNEL_DATA_REQ);
|
||||
AssertFatal(message_p != NULL, "OUT OF MEMORY");
|
||||
GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).buffer = gtpu_buffer_p;
|
||||
GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).length = size;
|
||||
GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).offset = GTPU_HEADER_OVERHEAD_MAX;
|
||||
GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).rnti = ue->rnti;
|
||||
GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).rab_id = rb_id + 4;
|
||||
printf("!!!!!!! deliver_sdu_drb (drb %d) sending message to gtp size %d: ", rb_id, size);
|
||||
//for (i = 0; i < size; i++) printf(" %2.2x", (unsigned char)buf[i]);
|
||||
printf("\n");
|
||||
itti_send_msg_to_task(TASK_GTPV1_U, INSTANCE_DEFAULT, message_p);
|
||||
}
|
||||
|
||||
static void deliver_pdu_drb(void *_ue, pdcp_entity_t *entity,
|
||||
char *buf, int size, int sdu_id)
|
||||
{
|
||||
pdcp_ue_t *ue = _ue;
|
||||
int rb_id;
|
||||
protocol_ctxt_t ctxt;
|
||||
int i;
|
||||
mem_block_t *memblock;
|
||||
|
||||
for (i = 0; i < 5; i++) {
|
||||
if (entity == ue->drb[i]) {
|
||||
rb_id = i+1;
|
||||
goto rb_found;
|
||||
}
|
||||
}
|
||||
|
||||
LOG_E(PDCP, "%s:%d:%s: fatal, no RB found for ue %d\n",
|
||||
__FILE__, __LINE__, __FUNCTION__, ue->rnti);
|
||||
exit(1);
|
||||
|
||||
rb_found:
|
||||
ctxt.module_id = 0;
|
||||
ctxt.enb_flag = 1;
|
||||
ctxt.instance = 0;
|
||||
ctxt.frame = 0;
|
||||
ctxt.subframe = 0;
|
||||
ctxt.eNB_index = 0;
|
||||
ctxt.configured = 1;
|
||||
ctxt.brOption = 0;
|
||||
|
||||
ctxt.rnti = ue->rnti;
|
||||
|
||||
memblock = get_free_mem_block(size, __FUNCTION__);
|
||||
memcpy(memblock->data, buf, size);
|
||||
|
||||
printf("!!!!!!! deliver_pdu_drb (srb %d) calling rlc_data_req size %d: ", rb_id, size);
|
||||
//for (i = 0; i < size; i++) printf(" %2.2x", (unsigned char)memblock->data[i]);
|
||||
printf("\n");
|
||||
enqueue_rlc_data_req(&ctxt, 0, MBMS_FLAG_NO, rb_id, sdu_id, 0, size, memblock, NULL, NULL);
|
||||
}
|
||||
|
||||
static void deliver_sdu_srb(void *_ue, pdcp_entity_t *entity,
|
||||
char *buf, int size)
|
||||
{
|
||||
pdcp_ue_t *ue = _ue;
|
||||
int rb_id;
|
||||
protocol_ctxt_t ctxt;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (entity == ue->srb[i]) {
|
||||
rb_id = i+1;
|
||||
goto rb_found;
|
||||
}
|
||||
}
|
||||
|
||||
LOG_E(PDCP, "%s:%d:%s: fatal, no RB found for ue %d\n",
|
||||
__FILE__, __LINE__, __FUNCTION__, ue->rnti);
|
||||
exit(1);
|
||||
|
||||
rb_found:
|
||||
ctxt.module_id = 0;
|
||||
ctxt.enb_flag = 1;
|
||||
ctxt.instance = 0;
|
||||
ctxt.frame = 0;
|
||||
ctxt.subframe = 0;
|
||||
ctxt.eNB_index = 0;
|
||||
ctxt.configured = 1;
|
||||
ctxt.brOption = 0;
|
||||
|
||||
ctxt.rnti = ue->rnti;
|
||||
|
||||
printf("!!!!!!! deliver_sdu_srb (srb %d) calling rrc_data_ind size %d: ", rb_id, size);
|
||||
//for (i = 0; i < size; i++) printf(" %2.2x", (unsigned char)buf[i]);
|
||||
printf("\n");
|
||||
rrc_data_ind(&ctxt, rb_id, size, (unsigned char *)buf);
|
||||
}
|
||||
|
||||
static void deliver_pdu_srb(void *_ue, pdcp_entity_t *entity,
|
||||
char *buf, int size, int sdu_id)
|
||||
{
|
||||
pdcp_ue_t *ue = _ue;
|
||||
int rb_id;
|
||||
protocol_ctxt_t ctxt;
|
||||
int i;
|
||||
mem_block_t *memblock;
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (entity == ue->srb[i]) {
|
||||
rb_id = i+1;
|
||||
goto rb_found;
|
||||
}
|
||||
}
|
||||
|
||||
LOG_E(PDCP, "%s:%d:%s: fatal, no RB found for ue %d\n",
|
||||
__FILE__, __LINE__, __FUNCTION__, ue->rnti);
|
||||
exit(1);
|
||||
|
||||
rb_found:
|
||||
ctxt.module_id = 0;
|
||||
ctxt.enb_flag = 1;
|
||||
ctxt.instance = 0;
|
||||
ctxt.frame = 0;
|
||||
ctxt.subframe = 0;
|
||||
ctxt.eNB_index = 0;
|
||||
ctxt.configured = 1;
|
||||
ctxt.brOption = 0;
|
||||
|
||||
ctxt.rnti = ue->rnti;
|
||||
|
||||
memblock = get_free_mem_block(size, __FUNCTION__);
|
||||
memcpy(memblock->data, buf, size);
|
||||
|
||||
printf("!!!!!!! deliver_pdu_srb (srb %d) calling rlc_data_req size %d: ", rb_id, size);
|
||||
//for (i = 0; i < size; i++) printf(" %2.2x", (unsigned char)memblock->data[i]);
|
||||
printf("\n");
|
||||
enqueue_rlc_data_req(&ctxt, 1, MBMS_FLAG_NO, rb_id, sdu_id, 0, size, memblock, NULL, NULL);
|
||||
}
|
||||
|
||||
boolean_t pdcp_data_ind(
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
const srb_flag_t srb_flagP,
|
||||
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)
|
||||
{
|
||||
pdcp_ue_t *ue;
|
||||
pdcp_entity_t *rb;
|
||||
int rnti = ctxt_pP->rnti;
|
||||
|
||||
if (ctxt_pP->module_id != 0 ||
|
||||
ctxt_pP->enb_flag != 1 ||
|
||||
ctxt_pP->instance != 0 ||
|
||||
ctxt_pP->eNB_index != 0 ||
|
||||
ctxt_pP->configured != 1 ||
|
||||
ctxt_pP->brOption != 0) {
|
||||
LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (ctxt_pP->enb_flag)
|
||||
T(T_ENB_PDCP_UL, T_INT(ctxt_pP->module_id), T_INT(rnti),
|
||||
T_INT(rb_id), T_INT(sdu_buffer_size));
|
||||
|
||||
pdcp_manager_lock(pdcp_ue_manager);
|
||||
ue = pdcp_manager_get_ue(pdcp_ue_manager, rnti);
|
||||
|
||||
if (srb_flagP == 1) {
|
||||
if (rb_id < 1 || rb_id > 2)
|
||||
rb = NULL;
|
||||
else
|
||||
rb = ue->srb[rb_id - 1];
|
||||
} else {
|
||||
if (rb_id < 1 || rb_id > 5)
|
||||
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: fatal: no RB found (rb_id %d, srb_flag %d)\n",
|
||||
__FILE__, __LINE__, __FUNCTION__, rb_id, srb_flagP);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
pdcp_manager_unlock(pdcp_ue_manager);
|
||||
|
||||
free_mem_block(sdu_buffer, __FUNCTION__);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void pdcp_run(const protocol_ctxt_t *const ctxt_pP)
|
||||
{
|
||||
MessageDef *msg_p;
|
||||
int result;
|
||||
protocol_ctxt_t ctxt;
|
||||
|
||||
while (1) {
|
||||
itti_poll_msg(ctxt_pP->enb_flag ? TASK_PDCP_ENB : TASK_PDCP_UE, &msg_p);
|
||||
if (msg_p == NULL)
|
||||
break;
|
||||
switch (ITTI_MSG_ID(msg_p)) {
|
||||
case RRC_DCCH_DATA_REQ:
|
||||
PROTOCOL_CTXT_SET_BY_MODULE_ID(
|
||||
&ctxt,
|
||||
RRC_DCCH_DATA_REQ(msg_p).module_id,
|
||||
RRC_DCCH_DATA_REQ(msg_p).enb_flag,
|
||||
RRC_DCCH_DATA_REQ(msg_p).rnti,
|
||||
RRC_DCCH_DATA_REQ(msg_p).frame,
|
||||
0,
|
||||
RRC_DCCH_DATA_REQ(msg_p).eNB_index);
|
||||
result = pdcp_data_req(&ctxt,
|
||||
SRB_FLAG_YES,
|
||||
RRC_DCCH_DATA_REQ(msg_p).rb_id,
|
||||
RRC_DCCH_DATA_REQ(msg_p).muip,
|
||||
RRC_DCCH_DATA_REQ(msg_p).confirmp,
|
||||
RRC_DCCH_DATA_REQ(msg_p).sdu_size,
|
||||
RRC_DCCH_DATA_REQ(msg_p).sdu_p,
|
||||
RRC_DCCH_DATA_REQ(msg_p).mode,
|
||||
NULL, NULL);
|
||||
|
||||
if (result != TRUE)
|
||||
LOG_E(PDCP, "PDCP data request failed!\n");
|
||||
result = itti_free(ITTI_MSG_ORIGIN_ID(msg_p), RRC_DCCH_DATA_REQ(msg_p).sdu_p);
|
||||
AssertFatal(result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
|
||||
break;
|
||||
default:
|
||||
LOG_E(PDCP, "Received unexpected message %s\n", ITTI_MSG_NAME(msg_p));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void add_srb(int rnti, struct LTE_SRB_ToAddMod *s)
|
||||
{
|
||||
pdcp_entity_t *pdcp_srb;
|
||||
pdcp_ue_t *ue;
|
||||
|
||||
int srb_id = s->srb_Identity;
|
||||
|
||||
printf("\n\n################# add srb %d\n\n\n", srb_id);
|
||||
|
||||
if (srb_id != 1 && srb_id != 2) {
|
||||
LOG_E(PDCP, "%s:%d:%s: fatal, bad srb id %d\n",
|
||||
__FILE__, __LINE__, __FUNCTION__, srb_id);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
pdcp_manager_lock(pdcp_ue_manager);
|
||||
ue = pdcp_manager_get_ue(pdcp_ue_manager, rnti);
|
||||
if (ue->srb[srb_id-1] != NULL) {
|
||||
LOG_D(PDCP, "%s:%d:%s: warning SRB %d already exist for ue %d, do nothing\n",
|
||||
__FILE__, __LINE__, __FUNCTION__, srb_id, rnti);
|
||||
} else {
|
||||
pdcp_srb = new_pdcp_entity_srb(srb_id, deliver_sdu_srb, ue, deliver_pdu_srb, ue);
|
||||
pdcp_ue_add_srb_pdcp_entity(ue, srb_id, pdcp_srb);
|
||||
|
||||
LOG_D(PDCP, "%s:%d:%s: added srb %d to ue %d\n",
|
||||
__FILE__, __LINE__, __FUNCTION__, srb_id, rnti);
|
||||
}
|
||||
pdcp_manager_unlock(pdcp_ue_manager);
|
||||
}
|
||||
|
||||
static void add_drb_am(int rnti, struct LTE_DRB_ToAddMod *s)
|
||||
{
|
||||
pdcp_entity_t *pdcp_drb;
|
||||
pdcp_ue_t *ue;
|
||||
|
||||
int drb_id = s->drb_Identity;
|
||||
|
||||
printf("\n\n################# add drb %d\n\n\n", drb_id);
|
||||
|
||||
if (drb_id != 1) {
|
||||
LOG_E(PDCP, "%s:%d:%s: fatal, bad drb id %d\n",
|
||||
__FILE__, __LINE__, __FUNCTION__, drb_id);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
pdcp_manager_lock(pdcp_ue_manager);
|
||||
ue = pdcp_manager_get_ue(pdcp_ue_manager, rnti);
|
||||
if (ue->drb[drb_id-1] != NULL) {
|
||||
LOG_D(PDCP, "%s:%d:%s: warning SRB %d already exist for ue %d, do nothing\n",
|
||||
__FILE__, __LINE__, __FUNCTION__, drb_id, rnti);
|
||||
} else {
|
||||
pdcp_drb = new_pdcp_entity_drb_am(drb_id, deliver_sdu_drb, ue, deliver_pdu_drb, ue);
|
||||
pdcp_ue_add_drb_pdcp_entity(ue, drb_id, pdcp_drb);
|
||||
|
||||
LOG_D(PDCP, "%s:%d:%s: added drb %d to ue %d\n",
|
||||
__FILE__, __LINE__, __FUNCTION__, drb_id, rnti);
|
||||
}
|
||||
pdcp_manager_unlock(pdcp_ue_manager);
|
||||
}
|
||||
|
||||
static void add_drb(int rnti, struct LTE_DRB_ToAddMod *s)
|
||||
{
|
||||
switch (s->rlc_Config->present) {
|
||||
case LTE_RLC_Config_PR_am:
|
||||
add_drb_am(rnti, s);
|
||||
break;
|
||||
case LTE_RLC_Config_PR_um_Bi_Directional:
|
||||
//add_drb_um(rnti, s);
|
||||
TODO;
|
||||
break;
|
||||
default:
|
||||
LOG_E(PDCP, "%s:%d:%s: fatal: unhandled DRB type\n",
|
||||
__FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
boolean_t rrc_pdcp_config_asn1_req(
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
LTE_SRB_ToAddModList_t *const srb2add_list,
|
||||
LTE_DRB_ToAddModList_t *const drb2add_list,
|
||||
LTE_DRB_ToReleaseList_t *const drb2release_list,
|
||||
const uint8_t security_modeP,
|
||||
uint8_t *const kRRCenc,
|
||||
uint8_t *const kRRCint,
|
||||
uint8_t *const kUPenc
|
||||
#if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0))
|
||||
,LTE_PMCH_InfoList_r9_t *pmch_InfoList_r9
|
||||
#endif
|
||||
,rb_id_t *const defaultDRB)
|
||||
{
|
||||
int rnti = ctxt_pP->rnti;
|
||||
int i;
|
||||
|
||||
if (ctxt_pP->enb_flag != 1 ||
|
||||
ctxt_pP->module_id != 0 ||
|
||||
ctxt_pP->instance != 0 ||
|
||||
ctxt_pP->eNB_index != 0 ||
|
||||
//ctxt_pP->configured != 2 ||
|
||||
//srb2add_list == NULL ||
|
||||
//drb2add_list != NULL ||
|
||||
drb2release_list != NULL ||
|
||||
security_modeP != 255 ||
|
||||
//kRRCenc != NULL ||
|
||||
//kRRCint != NULL ||
|
||||
//kUPenc != NULL ||
|
||||
pmch_InfoList_r9 != NULL ||
|
||||
defaultDRB != NULL) {
|
||||
TODO;
|
||||
}
|
||||
|
||||
if (srb2add_list != NULL) {
|
||||
for (i = 0; i < srb2add_list->list.count; i++) {
|
||||
add_srb(rnti, srb2add_list->list.array[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (drb2add_list != NULL) {
|
||||
for (i = 0; i < drb2add_list->list.count; i++) {
|
||||
add_drb(rnti, drb2add_list->list.array[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* update security */
|
||||
if (kRRCint != NULL) {
|
||||
/* todo */
|
||||
}
|
||||
|
||||
free(kRRCenc);
|
||||
free(kRRCint);
|
||||
free(kUPenc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t get_pdcp_optmask(void)
|
||||
{
|
||||
TODO;
|
||||
}
|
||||
|
||||
boolean_t pdcp_remove_UE(
|
||||
const protocol_ctxt_t *const ctxt_pP)
|
||||
{
|
||||
LOG_D(RLC, "%s:%d:%s: remove UE %d\n", __FILE__, __LINE__, __FUNCTION__, ctxt_pP->rnti);
|
||||
pdcp_manager_lock(pdcp_ue_manager);
|
||||
pdcp_manager_remove_ue(pdcp_ue_manager, ctxt_pP->rnti);
|
||||
pdcp_manager_unlock(pdcp_ue_manager);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void pdcp_config_set_security(const protocol_ctxt_t* const ctxt_pP, pdcp_t *pdcp_pP, rb_id_t rb_id,
|
||||
uint16_t lc_idP, uint8_t security_modeP, uint8_t *kRRCenc_pP, uint8_t *kRRCint_pP, uint8_t *kUPenc_pP)
|
||||
{
|
||||
pdcp_ue_t *ue;
|
||||
pdcp_entity_t *rb;
|
||||
int rnti = ctxt_pP->rnti;
|
||||
|
||||
if (ctxt_pP->module_id != 0 ||
|
||||
ctxt_pP->enb_flag != 1 ||
|
||||
ctxt_pP->instance != 0 ||
|
||||
ctxt_pP->eNB_index != 0) {
|
||||
LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
pdcp_manager_lock(pdcp_ue_manager);
|
||||
|
||||
ue = pdcp_manager_get_ue(pdcp_ue_manager, rnti);
|
||||
|
||||
if (rb_id < 1 || rb_id > 2)
|
||||
rb = NULL;
|
||||
else
|
||||
rb = ue->srb[rb_id - 1];
|
||||
|
||||
if (rb == NULL) {
|
||||
LOG_E(PDCP, "%s:%d:%s: fatal: no SRB found (rb_id %d)\n",
|
||||
__FILE__, __LINE__, __FUNCTION__, rb_id);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (kRRCint_pP != NULL)
|
||||
rb->set_integrity_key(rb, (char *)kRRCint_pP);
|
||||
|
||||
pdcp_manager_unlock(pdcp_ue_manager);
|
||||
|
||||
free(kRRCenc_pP);
|
||||
free(kRRCint_pP);
|
||||
free(kUPenc_pP);
|
||||
}
|
||||
|
||||
static boolean_t pdcp_data_req_srb(
|
||||
protocol_ctxt_t *ctxt_pP,
|
||||
const rb_id_t rb_id,
|
||||
const mui_t muiP,
|
||||
const confirm_t confirmP,
|
||||
const sdu_size_t sdu_buffer_size,
|
||||
unsigned char *const sdu_buffer)
|
||||
{
|
||||
pdcp_ue_t *ue;
|
||||
pdcp_entity_t *rb;
|
||||
int rnti = ctxt_pP->rnti;
|
||||
|
||||
if (ctxt_pP->module_id != 0 ||
|
||||
ctxt_pP->enb_flag != 1 ||
|
||||
ctxt_pP->instance != 0 ||
|
||||
ctxt_pP->eNB_index != 0 /*||
|
||||
ctxt_pP->configured != 1 ||
|
||||
ctxt_pP->brOption != 0*/) {
|
||||
LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
pdcp_manager_lock(pdcp_ue_manager);
|
||||
|
||||
ue = pdcp_manager_get_ue(pdcp_ue_manager, rnti);
|
||||
|
||||
if (rb_id < 1 || rb_id > 2)
|
||||
rb = NULL;
|
||||
else
|
||||
rb = ue->srb[rb_id - 1];
|
||||
|
||||
if (rb == NULL) {
|
||||
LOG_E(PDCP, "%s:%d:%s: fatal: no SRB found (rb_id %d)\n",
|
||||
__FILE__, __LINE__, __FUNCTION__, rb_id);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
rb->recv_sdu(rb, (char *)sdu_buffer, sdu_buffer_size, muiP);
|
||||
|
||||
pdcp_manager_unlock(pdcp_ue_manager);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static boolean_t pdcp_data_req_drb(
|
||||
protocol_ctxt_t *ctxt_pP,
|
||||
const rb_id_t rb_id,
|
||||
const mui_t muiP,
|
||||
const confirm_t confirmP,
|
||||
const sdu_size_t sdu_buffer_size,
|
||||
unsigned char *const sdu_buffer)
|
||||
{
|
||||
pdcp_ue_t *ue;
|
||||
pdcp_entity_t *rb;
|
||||
int rnti = ctxt_pP->rnti;
|
||||
|
||||
if (ctxt_pP->module_id != 0 ||
|
||||
ctxt_pP->enb_flag != 1 ||
|
||||
ctxt_pP->instance != 0 ||
|
||||
ctxt_pP->eNB_index != 0 /*||
|
||||
ctxt_pP->configured != 1 ||
|
||||
ctxt_pP->brOption != 0*/) {
|
||||
LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
pdcp_manager_lock(pdcp_ue_manager);
|
||||
|
||||
ue = pdcp_manager_get_ue(pdcp_ue_manager, rnti);
|
||||
|
||||
if (rb_id < 1 || rb_id > 5)
|
||||
rb = NULL;
|
||||
else
|
||||
rb = ue->drb[rb_id - 1];
|
||||
|
||||
if (rb == NULL) {
|
||||
LOG_E(PDCP, "%s:%d:%s: fatal: no DRB found (rb_id %d)\n",
|
||||
__FILE__, __LINE__, __FUNCTION__, rb_id);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
rb->recv_sdu(rb, (char *)sdu_buffer, sdu_buffer_size, muiP);
|
||||
|
||||
pdcp_manager_unlock(pdcp_ue_manager);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
boolean_t pdcp_data_req(
|
||||
protocol_ctxt_t *ctxt_pP,
|
||||
const srb_flag_t srb_flagP,
|
||||
const rb_id_t rb_id,
|
||||
const mui_t muiP,
|
||||
const confirm_t confirmP,
|
||||
const sdu_size_t sdu_buffer_size,
|
||||
unsigned char *const sdu_buffer,
|
||||
const pdcp_transmission_mode_t mode
|
||||
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
|
||||
,const uint32_t *const sourceL2Id
|
||||
,const uint32_t *const destinationL2Id
|
||||
#endif
|
||||
)
|
||||
{
|
||||
if (srb_flagP)
|
||||
return pdcp_data_req_srb(ctxt_pP, rb_id, muiP, confirmP, sdu_buffer_size,
|
||||
sdu_buffer);
|
||||
return pdcp_data_req_drb(ctxt_pP, rb_id, muiP, confirmP, sdu_buffer_size,
|
||||
sdu_buffer);
|
||||
}
|
||||
|
||||
void pdcp_set_pdcp_data_ind_func(pdcp_data_ind_func_t pdcp_data_ind)
|
||||
{
|
||||
/* nothing to do */
|
||||
}
|
||||
|
||||
void pdcp_set_rlc_data_req_func(send_rlc_data_req_func_t send_rlc_data_req)
|
||||
{
|
||||
/* nothing to do */
|
||||
}
|
||||
190
openair2/LAYER2/pdcp_v2/pdcp_ue_manager.c
Normal file
190
openair2/LAYER2/pdcp_v2/pdcp_ue_manager.c
Normal file
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#include "pdcp_ue_manager.h"
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "LOG/log.h"
|
||||
|
||||
typedef struct {
|
||||
pthread_mutex_t lock;
|
||||
pdcp_ue_t **ue_list;
|
||||
int ue_count;
|
||||
int enb_flag;
|
||||
} pdcp_ue_manager_internal_t;
|
||||
|
||||
pdcp_ue_manager_t *new_pdcp_ue_manager(int enb_flag)
|
||||
{
|
||||
pdcp_ue_manager_internal_t *ret;
|
||||
|
||||
ret = calloc(1, sizeof(pdcp_ue_manager_internal_t));
|
||||
if (ret == NULL) {
|
||||
LOG_E(PDCP, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (pthread_mutex_init(&ret->lock, NULL)) abort();
|
||||
ret->enb_flag = enb_flag;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int pdcp_manager_get_enb_flag(pdcp_ue_manager_t *_m)
|
||||
{
|
||||
pdcp_ue_manager_internal_t *m = _m;
|
||||
return m->enb_flag;
|
||||
}
|
||||
|
||||
void pdcp_manager_lock(pdcp_ue_manager_t *_m)
|
||||
{
|
||||
pdcp_ue_manager_internal_t *m = _m;
|
||||
if (pthread_mutex_lock(&m->lock)) {
|
||||
LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void pdcp_manager_unlock(pdcp_ue_manager_t *_m)
|
||||
{
|
||||
pdcp_ue_manager_internal_t *m = _m;
|
||||
if (pthread_mutex_unlock(&m->lock)) {
|
||||
LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* must be called with lock acquired */
|
||||
pdcp_ue_t *pdcp_manager_get_ue(pdcp_ue_manager_t *_m, int rnti)
|
||||
{
|
||||
/* TODO: optimze */
|
||||
pdcp_ue_manager_internal_t *m = _m;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < m->ue_count; i++)
|
||||
if (m->ue_list[i]->rnti == rnti)
|
||||
return m->ue_list[i];
|
||||
|
||||
LOG_D(PDCP, "%s:%d:%s: new UE %d\n", __FILE__, __LINE__, __FUNCTION__, rnti);
|
||||
|
||||
m->ue_count++;
|
||||
m->ue_list = realloc(m->ue_list, sizeof(pdcp_ue_t *) * m->ue_count);
|
||||
if (m->ue_list == NULL) {
|
||||
LOG_E(PDCP, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
m->ue_list[m->ue_count-1] = calloc(1, sizeof(pdcp_ue_t));
|
||||
if (m->ue_list[m->ue_count-1] == NULL) {
|
||||
LOG_E(PDCP, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
m->ue_list[m->ue_count-1]->rnti = rnti;
|
||||
|
||||
return m->ue_list[m->ue_count-1];
|
||||
}
|
||||
|
||||
/* must be called with lock acquired */
|
||||
void pdcp_manager_remove_ue(pdcp_ue_manager_t *_m, int rnti)
|
||||
{
|
||||
pdcp_ue_manager_internal_t *m = _m;
|
||||
pdcp_ue_t *ue;
|
||||
int i;
|
||||
int j;
|
||||
|
||||
for (i = 0; i < m->ue_count; i++)
|
||||
if (m->ue_list[i]->rnti == rnti)
|
||||
break;
|
||||
|
||||
if (i == m->ue_count) {
|
||||
LOG_D(PDCP, "%s:%d:%s: warning: ue %d not found\n",
|
||||
__FILE__, __LINE__, __FUNCTION__,
|
||||
rnti);
|
||||
return;
|
||||
}
|
||||
|
||||
ue = m->ue_list[i];
|
||||
|
||||
for (j = 0; j < 2; j++)
|
||||
if (ue->srb[j] != NULL)
|
||||
ue->srb[j]->delete(ue->srb[j]);
|
||||
|
||||
for (j = 0; j < 5; j++)
|
||||
if (ue->drb[j] != NULL)
|
||||
ue->drb[j]->delete(ue->drb[j]);
|
||||
|
||||
free(ue);
|
||||
|
||||
m->ue_count--;
|
||||
if (m->ue_count == 0) {
|
||||
free(m->ue_list);
|
||||
m->ue_list = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
memmove(&m->ue_list[i], &m->ue_list[i+1],
|
||||
(m->ue_count - i) * sizeof(pdcp_ue_t *));
|
||||
m->ue_list = realloc(m->ue_list, m->ue_count * sizeof(pdcp_ue_t *));
|
||||
if (m->ue_list == NULL) {
|
||||
LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* must be called with lock acquired */
|
||||
void pdcp_ue_add_srb_pdcp_entity(pdcp_ue_t *ue, int srb_id, pdcp_entity_t *entity)
|
||||
{
|
||||
if (srb_id < 1 || srb_id > 2) {
|
||||
LOG_E(PDCP, "%s:%d:%s: fatal, bad srb id\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
srb_id--;
|
||||
|
||||
if (ue->srb[srb_id] != NULL) {
|
||||
LOG_E(PDCP, "%s:%d:%s: fatal, srb already present\n",
|
||||
__FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ue->srb[srb_id] = entity;
|
||||
}
|
||||
|
||||
/* must be called with lock acquired */
|
||||
void pdcp_ue_add_drb_pdcp_entity(pdcp_ue_t *ue, int drb_id, pdcp_entity_t *entity)
|
||||
{
|
||||
if (drb_id < 1 || drb_id > 5) {
|
||||
LOG_E(PDCP, "%s:%d:%s: fatal, bad drb id\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
drb_id--;
|
||||
|
||||
if (ue->drb[drb_id] != NULL) {
|
||||
LOG_E(PDCP, "%s:%d:%s: fatal, drb already present\n",
|
||||
__FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ue->drb[drb_id] = entity;
|
||||
}
|
||||
58
openair2/LAYER2/pdcp_v2/pdcp_ue_manager.h
Normal file
58
openair2/LAYER2/pdcp_v2/pdcp_ue_manager.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#ifndef _PDCP_UE_MANAGER_H_
|
||||
#define _PDCP_UE_MANAGER_H_
|
||||
|
||||
#include "pdcp_entity.h"
|
||||
|
||||
typedef void pdcp_ue_manager_t;
|
||||
|
||||
typedef struct pdcp_ue_t {
|
||||
int rnti;
|
||||
pdcp_entity_t *srb[2];
|
||||
pdcp_entity_t *drb[5];
|
||||
} pdcp_ue_t;
|
||||
|
||||
/***********************************************************************/
|
||||
/* manager functions */
|
||||
/***********************************************************************/
|
||||
|
||||
pdcp_ue_manager_t *new_pdcp_ue_manager(int enb_flag);
|
||||
|
||||
int pdcp_manager_get_enb_flag(pdcp_ue_manager_t *m);
|
||||
|
||||
void pdcp_manager_lock(pdcp_ue_manager_t *m);
|
||||
void pdcp_manager_unlock(pdcp_ue_manager_t *m);
|
||||
|
||||
pdcp_ue_t *pdcp_manager_get_ue(pdcp_ue_manager_t *m, int rnti);
|
||||
void pdcp_manager_remove_ue(pdcp_ue_manager_t *m, int rnti);
|
||||
|
||||
/***********************************************************************/
|
||||
/* ue functions */
|
||||
/***********************************************************************/
|
||||
|
||||
void pdcp_ue_add_srb_pdcp_entity(pdcp_ue_t *ue, int srb_id,
|
||||
pdcp_entity_t *entity);
|
||||
void pdcp_ue_add_drb_pdcp_entity(pdcp_ue_t *ue, int drb_id,
|
||||
pdcp_entity_t *entity);
|
||||
|
||||
#endif /* _PDCP_UE_MANAGER_H_ */
|
||||
18
openair2/LAYER2/rlc_v2/TODO
Normal file
18
openair2/LAYER2/rlc_v2/TODO
Normal file
@@ -0,0 +1,18 @@
|
||||
RLC AM
|
||||
======
|
||||
|
||||
- 36.322 5.4 Re-establishment procedure
|
||||
when possible, reassemble RLC SDUs from any byte segments of AMD PDUs
|
||||
with SN < VR(MR) in the receiving side, remove RLC headers when doing
|
||||
so and deliver all reassembled RLC SDUs to upper layer in ascending order
|
||||
of the RLC SN, if not delivered before;
|
||||
|
||||
- 36.322 5.2.3 Status reporting
|
||||
delay triggering the STATUS report until x < VR(MS) or x >= VR(MR)
|
||||
|
||||
- 36.322 5.1.3.2.3 Actions when a RLC data PDU is placed in the reception
|
||||
buffer
|
||||
[...] and in-sequence byte segments of the AMD PDU with SN = VR(R) [...]
|
||||
|
||||
- use SOstart/SOend in NACK reporting, do not NACK full PDU if
|
||||
parts of it have been received
|
||||
129
openair2/LAYER2/rlc_v2/asn1_utils.c
Normal file
129
openair2/LAYER2/rlc_v2/asn1_utils.c
Normal file
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#include "rlc.h"
|
||||
|
||||
int decode_t_reordering(int v)
|
||||
{
|
||||
static int tab[32] = {
|
||||
0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85,
|
||||
90, 95, 100, 110, 120, 130, 140, 150, 160, 170, 180, 190, 200, 1600
|
||||
};
|
||||
|
||||
if (v < 0 || v > 31) {
|
||||
LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return tab[v];
|
||||
}
|
||||
|
||||
int decode_t_status_prohibit(int v)
|
||||
{
|
||||
static int tab[62] = {
|
||||
0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90,
|
||||
95, 100, 105, 110, 115, 120, 125, 130, 135, 140, 145, 150, 155, 160, 165,
|
||||
170, 175, 180, 185, 190, 195, 200, 205, 210, 215, 220, 225, 230, 235, 240,
|
||||
245, 250, 300, 350, 400, 450, 500, 800, 1000, 1200, 1600, 2000, 2400
|
||||
};
|
||||
|
||||
if (v < 0 || v > 61) {
|
||||
LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return tab[v];
|
||||
}
|
||||
|
||||
int decode_t_poll_retransmit(int v)
|
||||
{
|
||||
static int tab[59] = {
|
||||
5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95,
|
||||
100, 105, 110, 115, 120, 125, 130, 135, 140, 145, 150, 155, 160, 165, 170,
|
||||
175, 180, 185, 190, 195, 200, 205, 210, 215, 220, 225, 230, 235, 240, 245,
|
||||
250, 300, 350, 400, 450, 500, 800, 1000, 2000, 4000
|
||||
};
|
||||
|
||||
if (v < 0 || v > 58) {
|
||||
LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return tab[v];
|
||||
}
|
||||
|
||||
int decode_poll_pdu(int v)
|
||||
{
|
||||
static int tab[8] = {
|
||||
4, 8, 16, 32, 64, 128, 256, -1 /* -1 means infinity */
|
||||
};
|
||||
|
||||
if (v < 0 || v > 7) {
|
||||
LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return tab[v];
|
||||
}
|
||||
|
||||
int decode_poll_byte(int v)
|
||||
{
|
||||
static int tab[15] = {
|
||||
25, 50, 75, 100, 125, 250, 375, 500, 750, 1000, 1250, 1500, 2000, 3000,
|
||||
-1 /* -1 means infinity */
|
||||
};
|
||||
|
||||
if (v < 0 || v > 14) {
|
||||
LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (tab[v] == -1) return -1;
|
||||
return tab[v] * 1024;
|
||||
}
|
||||
|
||||
int decode_max_retx_threshold(int v)
|
||||
{
|
||||
static int tab[8] = {
|
||||
1, 2, 3, 4, 6, 8, 16, 32
|
||||
};
|
||||
|
||||
if (v < 0 || v > 7) {
|
||||
LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return tab[v];
|
||||
}
|
||||
|
||||
int decode_sn_field_length(int v)
|
||||
{
|
||||
static int tab[2] = {
|
||||
5, 10
|
||||
};
|
||||
|
||||
if (v < 0 || v > 1) {
|
||||
LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return tab[v];
|
||||
}
|
||||
33
openair2/LAYER2/rlc_v2/asn1_utils.h
Normal file
33
openair2/LAYER2/rlc_v2/asn1_utils.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#ifndef _ASN1_UTILS_H_
|
||||
#define _ASN1_UTILS_H_
|
||||
|
||||
int decode_t_reordering(int v);
|
||||
int decode_t_status_prohibit(int v);
|
||||
int decode_t_poll_retransmit(int v);
|
||||
int decode_poll_pdu(int v);
|
||||
int decode_poll_byte(int v);
|
||||
int decode_max_retx_threshold(int v);
|
||||
int decode_sn_field_length(int v);
|
||||
|
||||
#endif /* _ASN1_UTILS_H_ */
|
||||
144
openair2/LAYER2/rlc_v2/rlc_entity.c
Normal file
144
openair2/LAYER2/rlc_v2/rlc_entity.c
Normal file
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#include "rlc_entity.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "rlc_entity_am.h"
|
||||
#include "rlc_entity_um.h"
|
||||
|
||||
#include "LOG/log.h"
|
||||
|
||||
rlc_entity_t *new_rlc_entity_am(
|
||||
int rx_maxsize,
|
||||
int tx_maxsize,
|
||||
void (*deliver_sdu)(void *deliver_sdu_data, struct rlc_entity_t *entity,
|
||||
char *buf, int size),
|
||||
void *deliver_sdu_data,
|
||||
void (*sdu_successful_delivery)(void *sdu_successful_delivery_data,
|
||||
struct rlc_entity_t *entity,
|
||||
int sdu_id),
|
||||
void *sdu_successful_delivery_data,
|
||||
void (*max_retx_reached)(void *max_retx_reached_data,
|
||||
struct rlc_entity_t *entity),
|
||||
void *max_retx_reached_data,
|
||||
int t_reordering,
|
||||
int t_status_prohibit,
|
||||
int t_poll_retransmit,
|
||||
int poll_pdu,
|
||||
int poll_byte,
|
||||
int max_retx_threshold)
|
||||
{
|
||||
rlc_entity_am_t *ret;
|
||||
|
||||
ret = calloc(1, sizeof(rlc_entity_am_t));
|
||||
if (ret == NULL) {
|
||||
LOG_E(RLC, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ret->common.recv_pdu = rlc_entity_am_recv_pdu;
|
||||
ret->common.buffer_status = rlc_entity_am_buffer_status;
|
||||
ret->common.generate_pdu = rlc_entity_am_generate_pdu;
|
||||
|
||||
ret->common.recv_sdu = rlc_entity_am_recv_sdu;
|
||||
|
||||
ret->common.set_time = rlc_entity_am_set_time;
|
||||
|
||||
ret->common.discard_sdu = rlc_entity_am_discard_sdu;
|
||||
|
||||
ret->common.reestablishment = rlc_entity_am_reestablishment;
|
||||
|
||||
ret->common.delete = rlc_entity_am_delete;
|
||||
|
||||
ret->common.deliver_sdu = deliver_sdu;
|
||||
ret->common.deliver_sdu_data = deliver_sdu_data;
|
||||
|
||||
ret->common.sdu_successful_delivery = sdu_successful_delivery;
|
||||
ret->common.sdu_successful_delivery_data = sdu_successful_delivery_data;
|
||||
|
||||
ret->common.max_retx_reached = max_retx_reached;
|
||||
ret->common.max_retx_reached_data = max_retx_reached_data;
|
||||
|
||||
ret->rx_maxsize = rx_maxsize;
|
||||
ret->tx_maxsize = tx_maxsize;
|
||||
ret->t_reordering = t_reordering;
|
||||
ret->t_status_prohibit = t_status_prohibit;
|
||||
ret->t_poll_retransmit = t_poll_retransmit;
|
||||
ret->poll_pdu = poll_pdu;
|
||||
ret->poll_byte = poll_byte;
|
||||
ret->max_retx_threshold = max_retx_threshold;
|
||||
|
||||
return (rlc_entity_t *)ret;
|
||||
}
|
||||
|
||||
rlc_entity_t *new_rlc_entity_um(
|
||||
int rx_maxsize,
|
||||
int tx_maxsize,
|
||||
void (*deliver_sdu)(void *deliver_sdu_data, struct rlc_entity_t *entity,
|
||||
char *buf, int size),
|
||||
void *deliver_sdu_data,
|
||||
int t_reordering,
|
||||
int sn_field_length)
|
||||
{
|
||||
rlc_entity_um_t *ret;
|
||||
|
||||
ret = calloc(1, sizeof(rlc_entity_um_t));
|
||||
if (ret == NULL) {
|
||||
LOG_E(RLC, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ret->common.recv_pdu = rlc_entity_um_recv_pdu;
|
||||
ret->common.buffer_status = rlc_entity_um_buffer_status;
|
||||
ret->common.generate_pdu = rlc_entity_um_generate_pdu;
|
||||
|
||||
ret->common.recv_sdu = rlc_entity_um_recv_sdu;
|
||||
|
||||
ret->common.set_time = rlc_entity_um_set_time;
|
||||
|
||||
ret->common.discard_sdu = rlc_entity_um_discard_sdu;
|
||||
|
||||
ret->common.reestablishment = rlc_entity_um_reestablishment;
|
||||
|
||||
ret->common.delete = rlc_entity_um_delete;
|
||||
|
||||
ret->common.deliver_sdu = deliver_sdu;
|
||||
ret->common.deliver_sdu_data = deliver_sdu_data;
|
||||
|
||||
ret->sn_field_length = sn_field_length;
|
||||
ret->rx_maxsize = rx_maxsize;
|
||||
ret->tx_maxsize = tx_maxsize;
|
||||
ret->t_reordering = t_reordering;
|
||||
|
||||
if (sn_field_length == 5)
|
||||
ret->sn_modulus = 32;
|
||||
else if (sn_field_length == 10)
|
||||
ret->sn_modulus = 1024;
|
||||
else {
|
||||
LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
ret->window_size = ret->sn_modulus / 2;
|
||||
|
||||
return (rlc_entity_t *)ret;
|
||||
}
|
||||
97
openair2/LAYER2/rlc_v2/rlc_entity.h
Normal file
97
openair2/LAYER2/rlc_v2/rlc_entity.h
Normal file
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#ifndef _RLC_ENTITY_H_
|
||||
#define _RLC_ENTITY_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define SDU_MAX 16000 /* maximum PDCP SDU size is 8188, let's take more */
|
||||
|
||||
typedef struct {
|
||||
int status_size;
|
||||
int tx_size;
|
||||
int retx_size;
|
||||
} rlc_entity_buffer_status_t;
|
||||
|
||||
typedef struct rlc_entity_t {
|
||||
/* functions provided by the RLC module */
|
||||
void (*recv_pdu)(struct rlc_entity_t *entity, char *buffer, int size);
|
||||
rlc_entity_buffer_status_t (*buffer_status)(
|
||||
struct rlc_entity_t *entity, int maxsize);
|
||||
int (*generate_pdu)(struct rlc_entity_t *entity, char *buffer, int size);
|
||||
|
||||
void (*recv_sdu)(struct rlc_entity_t *entity, char *buffer, int size,
|
||||
int sdu_id);
|
||||
|
||||
void (*set_time)(struct rlc_entity_t *entity, uint64_t now);
|
||||
|
||||
void (*discard_sdu)(struct rlc_entity_t *entity, int sdu_id);
|
||||
|
||||
void (*reestablishment)(struct rlc_entity_t *entity);
|
||||
|
||||
void (*delete)(struct rlc_entity_t *entity);
|
||||
|
||||
/* callbacks provided to the RLC module */
|
||||
void (*deliver_sdu)(void *deliver_sdu_data, struct rlc_entity_t *entity,
|
||||
char *buf, int size);
|
||||
void *deliver_sdu_data;
|
||||
|
||||
void (*sdu_successful_delivery)(void *sdu_successful_delivery_data,
|
||||
struct rlc_entity_t *entity,
|
||||
int sdu_id);
|
||||
void *sdu_successful_delivery_data;
|
||||
|
||||
void (*max_retx_reached)(void *max_retx_reached_data,
|
||||
struct rlc_entity_t *entity);
|
||||
void *max_retx_reached_data;
|
||||
} rlc_entity_t;
|
||||
|
||||
rlc_entity_t *new_rlc_entity_am(
|
||||
int rx_maxsize,
|
||||
int tx_maxsize,
|
||||
void (*deliver_sdu)(void *deliver_sdu_data, struct rlc_entity_t *entity,
|
||||
char *buf, int size),
|
||||
void *deliver_sdu_data,
|
||||
void (*sdu_successful_delivery)(void *sdu_successful_delivery_data,
|
||||
struct rlc_entity_t *entity,
|
||||
int sdu_id),
|
||||
void *sdu_successful_delivery_data,
|
||||
void (*max_retx_reached)(void *max_retx_reached_data,
|
||||
struct rlc_entity_t *entity),
|
||||
void *max_retx_reached_data,
|
||||
int t_reordering,
|
||||
int t_status_prohibit,
|
||||
int t_poll_retransmit,
|
||||
int poll_pdu,
|
||||
int poll_byte,
|
||||
int max_retx_threshold);
|
||||
|
||||
rlc_entity_t *new_rlc_entity_um(
|
||||
int rx_maxsize,
|
||||
int tx_maxsize,
|
||||
void (*deliver_sdu)(void *deliver_sdu_data, struct rlc_entity_t *entity,
|
||||
char *buf, int size),
|
||||
void *deliver_sdu_data,
|
||||
int t_reordering,
|
||||
int sn_field_length);
|
||||
|
||||
#endif /* _RLC_ENTITY_H_ */
|
||||
1700
openair2/LAYER2/rlc_v2/rlc_entity_am.c
Normal file
1700
openair2/LAYER2/rlc_v2/rlc_entity_am.c
Normal file
File diff suppressed because it is too large
Load Diff
285
openair2/LAYER2/rlc_v2/rlc_entity_am.h
Normal file
285
openair2/LAYER2/rlc_v2/rlc_entity_am.h
Normal file
@@ -0,0 +1,285 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#ifndef _RLC_ENTITY_AM_H_
|
||||
#define _RLC_ENTITY_AM_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "rlc_entity.h"
|
||||
#include "rlc_pdu.h"
|
||||
#include "rlc_sdu.h"
|
||||
|
||||
/*
|
||||
* Here comes some documentation to understand the reassembly
|
||||
* logic in the code and the fields in the structure rlc_am_reassemble_t.
|
||||
*
|
||||
* Inside RLC, we deal with SDUs, PDUs and PDU segments.
|
||||
* SDUs are packets coming from upper layer.
|
||||
* A PDU is made of a header and a payload.
|
||||
* In the payload there are SDUs.
|
||||
* First SDU and last SDU in a PDU may be incomplete.
|
||||
* PDU segments exist in case of retransmissions when the MAC
|
||||
* layer asks for less data than previously, in which case
|
||||
* only part of the previous PDU is sent.
|
||||
*
|
||||
* This is PDU data (just bytes):
|
||||
* ---------------------------------------------------------
|
||||
* | PDU data |
|
||||
* ---------------------------------------------------------
|
||||
* It contains SDUs, like:
|
||||
* ---------------------------------------------------------
|
||||
* | SDU 1 | SDU 2 | [...] | SDU n |
|
||||
* ---------------------------------------------------------
|
||||
* SDU 1 may be only the end of an SDU from which previous bytes were
|
||||
* transmitted in previous PDUs.
|
||||
* SDU n may be only the start of an SDU, that is more bytes from
|
||||
* this SDU may be sent in successive PDUs.
|
||||
*
|
||||
* At front of the PDU data, we have a header:
|
||||
* --------------- ---------------------------------------------------------
|
||||
* | PDU header | | SDU 1 | SDU 2 | [...] | SDU n |
|
||||
* --------------- ---------------------------------------------------------
|
||||
* PDU header describes PDU data (most notably lengths).
|
||||
*
|
||||
* A PDU segment is a part of a PDU. For example, from this PDU data:
|
||||
* ---------------------------------------------------------
|
||||
* | SDU 1 | SDU 2 | [...] | SDU n |
|
||||
* ---------------------------------------------------------
|
||||
* We can extract the following PDU segment (data part only):
|
||||
* ----------------------
|
||||
* | PDU segment data |
|
||||
* ----------------------
|
||||
* This PDU segment would contain the end of SDU 2 above and some SDUs up to,
|
||||
* let's say SDU x (x is 5 below).
|
||||
*
|
||||
* In front of a transmitted PDU segment, we have a header,
|
||||
* containing the important variable 'so' (segment offset) that gives
|
||||
* the index of the first byte of the segment in the original PDU.
|
||||
* -------------- ----------------------
|
||||
* | seg. header| | PDU segment data |
|
||||
* -------------- ----------------------
|
||||
*
|
||||
* Let's now explain the data structure rlc_am_reassemble_t.
|
||||
*
|
||||
* In the structure rlc_am_reassemble_t, the fields fi, e, sn and so
|
||||
* are coming from the PDU segment header and the semantics is the
|
||||
* one of the RLC specs.
|
||||
*
|
||||
* The currently processed PDU segment is stored in 'start'.
|
||||
* We have 'start->s->data_offset' and 'start->s->size'.
|
||||
* start->s->data_offset is the index of the start of the data in the
|
||||
* PDU segment. That is if the header is of length 3 bytes
|
||||
* then start->s->data_offset is 3.
|
||||
* start->s->size is the total length of the PDU segment,
|
||||
* including header.
|
||||
* The size of actual data bytes in the PDU segment is thus
|
||||
* start->s->size - start->s->data_offset.
|
||||
*
|
||||
* The field sdu_len is the length of the current SDU being
|
||||
* processed.
|
||||
*
|
||||
* The field sdu_offset is the starting point of the
|
||||
* current SDU being processed (starting from beginning
|
||||
* of PDU segment, including header).
|
||||
*
|
||||
* The field data_pos is the current read pointer. 0 points to
|
||||
* the beginning of the PDU segment (including header).
|
||||
*
|
||||
* The field pdu_byte points to the current byte in the original
|
||||
* PDU (not the PDU segment). It starts at 0 when we start
|
||||
* processing a new PDU (when a new 'sn' is seen) and always
|
||||
* increases after each byte processed. This is tha variable
|
||||
* that is used to know if the next PDU segment will be used
|
||||
* or not and if yes, starting from which data byte (see
|
||||
* function rlc_am_reassemble_next_segment).
|
||||
*
|
||||
* 'so' is important and points to the byte in the original PDU
|
||||
* that is the first byte of the PDU segment.
|
||||
*
|
||||
* For example, let's take this PDU segment data from above:
|
||||
* ----------------------
|
||||
* | PDU segment data |
|
||||
* ----------------------
|
||||
* Let's say it is decomposed as:
|
||||
* ----------------------
|
||||
* |222|33|4444|55555555|
|
||||
* ----------------------
|
||||
* It contains SDUs 2, 3, 4, and 5.
|
||||
* SDU 2 is 3 bytes, SDU 3 is 2 bytes, SDU 4 is 4 bytes, SDU 5 is 8 bytes.
|
||||
*
|
||||
* Let's suppose that the original PDU starts with:
|
||||
* ----------------
|
||||
* |1111111|222222|
|
||||
* ----------------
|
||||
*
|
||||
* (In this example, in the PDU segment, SDU 2 is not full,
|
||||
* we only have its end.)
|
||||
*
|
||||
* Then 'so' is 13 (SDU 1 is 7 bytes, head of SDU 2 is 6 bytes).
|
||||
*
|
||||
* Let's continue with our PDU segment data.
|
||||
* Let's say we are current processing SDU 4.
|
||||
* Let's say the read pointer (variable 'data_pos') is there:
|
||||
* ----------------------
|
||||
* |222|33|4444|55555555|
|
||||
* ----------------------
|
||||
* ^
|
||||
* read pointer (data_pos)
|
||||
*
|
||||
* Then:
|
||||
* - sdu_len is 4
|
||||
* - sdu_offset is 5 + [PDU segment header length]
|
||||
* (it points to the beginning of SDU 4, starting
|
||||
* from the head of the PDU segment, that is
|
||||
* 3 bytes for SDU 2, 2 bytes for SDU 3, and the
|
||||
* PDU segment header length)
|
||||
* - start->s->data_offset is [PDU segment header length]
|
||||
* - pdu_byte is 20
|
||||
* (13 bytes from beginning of original PDU,
|
||||
* 3 bytes for SDU 2, 2 bytes for SDU 3, then 2 bytes for SDU 4)
|
||||
* - data_pos = read pointer = 7 + [PDU segment header length]
|
||||
*
|
||||
* To finish this description, in the code, a PDU is simply
|
||||
* seen as a PDU segment with 'so' = 0 (and is_last == 1 (lsf in the specs),
|
||||
* but this variable is not used by the reassembly logic).
|
||||
*
|
||||
* And for [PDU segment header length] we use start->s->data_offset.
|
||||
*
|
||||
* To recap, here is an illustration of the various variables
|
||||
* and what starting point they use. In the figures, the start
|
||||
* of the variable name is aligned to the byte it refers to.
|
||||
* + is used to show the starting point.
|
||||
*
|
||||
* Let's put the PDU segment back into the original PDU.
|
||||
* And let's show the values for when the read pointer
|
||||
* is on the second byte of SDU 4 (as above).
|
||||
*
|
||||
* +++++++++++++++ so
|
||||
* +++++++++++++++++++++++ pdu_byte
|
||||
* ---------------------------------------------------------
|
||||
* | SDU 1| SDU 2..222|33|4444|55555555| [...] | SDU n |
|
||||
* ---------------------------------------------------------
|
||||
*
|
||||
* And now the PDU segment with header.
|
||||
*
|
||||
*
|
||||
* ++++ sdu_len
|
||||
* ++++++++++++++++++++++ sdu_offset
|
||||
* +++++++++++++++++++++++ data_pos
|
||||
* +++++++++++++++ start->s->data_offset
|
||||
* +++++++++++++++++++++++++++++++++++++ start->s->size
|
||||
* -------------- ----------------------
|
||||
* | seg. header| |222|33|4444|55555555|
|
||||
* -------------- ----------------------
|
||||
*
|
||||
* We see three case for the starting point:
|
||||
* - start of original PDU (without any header)
|
||||
* - start of header of current PDU segment
|
||||
* - start of current SDU (for sdu_len)
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
rlc_rx_pdu_segment_t *start; /* start of list */
|
||||
rlc_rx_pdu_segment_t *end; /* end of list (last element) */
|
||||
int pos; /* byte to get from current buffer */
|
||||
char sdu[SDU_MAX]; /* sdu is reassembled here */
|
||||
int sdu_pos; /* next byte to put in sdu */
|
||||
|
||||
/* decoder of current PDU */
|
||||
rlc_pdu_decoder_t dec;
|
||||
int fi;
|
||||
int e;
|
||||
int sn;
|
||||
int so;
|
||||
int sdu_len;
|
||||
int sdu_offset;
|
||||
int data_pos;
|
||||
int pdu_byte;
|
||||
} rlc_am_reassemble_t;
|
||||
|
||||
typedef struct {
|
||||
rlc_entity_t common;
|
||||
|
||||
/* configuration */
|
||||
int t_reordering;
|
||||
int t_status_prohibit;
|
||||
int t_poll_retransmit;
|
||||
int poll_pdu; /* -1 means infinity */
|
||||
int poll_byte; /* -1 means infinity */
|
||||
int max_retx_threshold;
|
||||
|
||||
/* runtime rx */
|
||||
int vr_r;
|
||||
int vr_x;
|
||||
int vr_ms;
|
||||
int vr_h;
|
||||
|
||||
int status_triggered;
|
||||
|
||||
/* runtime tx */
|
||||
int vt_a;
|
||||
int vt_s;
|
||||
int poll_sn;
|
||||
int pdu_without_poll;
|
||||
int byte_without_poll;
|
||||
int force_poll;
|
||||
|
||||
/* set to the latest know time by the user of the module. Unit: ms */
|
||||
uint64_t t_current;
|
||||
|
||||
/* timers (stores the TTI of activation, 0 means not active) */
|
||||
uint64_t t_reordering_start;
|
||||
uint64_t t_status_prohibit_start;
|
||||
uint64_t t_poll_retransmit_start;
|
||||
|
||||
/* rx management */
|
||||
rlc_rx_pdu_segment_t *rx_list;
|
||||
int rx_size;
|
||||
int rx_maxsize;
|
||||
|
||||
/* reassembly management */
|
||||
rlc_am_reassemble_t reassemble;
|
||||
|
||||
/* tx management */
|
||||
rlc_sdu_t *tx_list;
|
||||
rlc_sdu_t *tx_end;
|
||||
int tx_size;
|
||||
int tx_maxsize;
|
||||
|
||||
rlc_tx_pdu_segment_t *wait_list;
|
||||
rlc_tx_pdu_segment_t *retransmit_list;
|
||||
|
||||
rlc_tx_pdu_segment_t *ack_list;
|
||||
} rlc_entity_am_t;
|
||||
|
||||
void rlc_entity_am_recv_sdu(rlc_entity_t *entity, char *buffer, int size,
|
||||
int sdu_id);
|
||||
void rlc_entity_am_recv_pdu(rlc_entity_t *entity, char *buffer, int size);
|
||||
rlc_entity_buffer_status_t rlc_entity_am_buffer_status(
|
||||
rlc_entity_t *entity, int maxsize);
|
||||
int rlc_entity_am_generate_pdu(rlc_entity_t *entity, char *buffer, int size);
|
||||
void rlc_entity_am_set_time(rlc_entity_t *entity, uint64_t now);
|
||||
void rlc_entity_am_discard_sdu(rlc_entity_t *entity, int sdu_id);
|
||||
void rlc_entity_am_reestablishment(rlc_entity_t *entity);
|
||||
void rlc_entity_am_delete(rlc_entity_t *entity);
|
||||
|
||||
#endif /* _RLC_ENTITY_AM_H_ */
|
||||
707
openair2/LAYER2/rlc_v2/rlc_entity_um.c
Normal file
707
openair2/LAYER2/rlc_v2/rlc_entity_um.c
Normal file
@@ -0,0 +1,707 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#include "rlc_entity_um.h"
|
||||
#include "rlc_pdu.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "LOG/log.h"
|
||||
|
||||
/*************************************************************************/
|
||||
/* PDU RX functions */
|
||||
/*************************************************************************/
|
||||
|
||||
static int modulus_rx(rlc_entity_um_t *entity, int a)
|
||||
{
|
||||
/* as per 36.322 7.1, modulus base is vr(uh)-window_size and modulus is
|
||||
* 2^sn_field_length (which is 'sn_modulus' in rlc_entity_um_t)
|
||||
*/
|
||||
int r = a - (entity->vr_uh - entity->window_size);
|
||||
if (r < 0) r += entity->sn_modulus;
|
||||
return r % entity->sn_modulus;
|
||||
}
|
||||
|
||||
static int sn_compare_rx(void *_entity, int a, int b)
|
||||
{
|
||||
rlc_entity_um_t *entity = _entity;
|
||||
return modulus_rx(entity, a) - modulus_rx(entity, b);
|
||||
}
|
||||
|
||||
static int sn_in_recv_window(void *_entity, int sn)
|
||||
{
|
||||
rlc_entity_um_t *entity = _entity;
|
||||
int mod_sn = modulus_rx(entity, sn);
|
||||
/* we simplify (VR(UH) - UM_Window_Size) <= SN < VR(UH), base is
|
||||
* (VR(UH) - UM_Window_Size) and VR(UH) = base + window_size
|
||||
*/
|
||||
return mod_sn < entity->window_size;
|
||||
}
|
||||
|
||||
/* return 1 if a PDU with SN == 'sn' is in the rx list, 0 otherwise */
|
||||
static int rlc_um_pdu_received(rlc_entity_um_t *entity, int sn)
|
||||
{
|
||||
rlc_rx_pdu_segment_t *cur = entity->rx_list;
|
||||
while (cur != NULL) {
|
||||
if (cur->sn == sn)
|
||||
return 1;
|
||||
cur = cur->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int less_than_vr_ur(rlc_entity_um_t *entity, int sn)
|
||||
{
|
||||
return sn_compare_rx(entity, sn, entity->vr_ur) < 0;
|
||||
}
|
||||
|
||||
static int outside_of_reordering_window(rlc_entity_um_t *entity, int sn)
|
||||
{
|
||||
return !sn_in_recv_window(entity, sn);
|
||||
}
|
||||
|
||||
static int less_than_vr_uh(rlc_entity_um_t *entity, int sn)
|
||||
{
|
||||
return sn_compare_rx(entity, sn, entity->vr_uh) < 0;
|
||||
}
|
||||
|
||||
static void rlc_um_reassemble_pdu(rlc_entity_um_t *entity,
|
||||
rlc_rx_pdu_segment_t *pdu)
|
||||
{
|
||||
rlc_um_reassemble_t *r = &entity->reassemble;
|
||||
|
||||
int fi;
|
||||
int e;
|
||||
int sn;
|
||||
int data_pos;
|
||||
int sdu_len;
|
||||
int sdu_offset;
|
||||
|
||||
sdu_offset = pdu->data_offset;
|
||||
|
||||
rlc_pdu_decoder_init(&r->dec, pdu->data, pdu->size);
|
||||
|
||||
if (entity->sn_field_length == 10)
|
||||
rlc_pdu_decoder_get_bits(&r->dec, 3);
|
||||
|
||||
fi = rlc_pdu_decoder_get_bits(&r->dec, 2);
|
||||
e = rlc_pdu_decoder_get_bits(&r->dec, 1);
|
||||
sn = rlc_pdu_decoder_get_bits(&r->dec, entity->sn_field_length);
|
||||
|
||||
if (e) {
|
||||
e = rlc_pdu_decoder_get_bits(&r->dec, 1);
|
||||
sdu_len = rlc_pdu_decoder_get_bits(&r->dec, 11);
|
||||
} else
|
||||
sdu_len = pdu->size - sdu_offset;
|
||||
|
||||
/* discard current SDU being reassembled if bad SN or bad FI */
|
||||
if (sn != (r->sn + 1) % entity->sn_modulus ||
|
||||
!(fi & 0x02)) {
|
||||
if (r->sdu_pos)
|
||||
LOG_D(RLC, "%s:%d:%s: warning: discard partially reassembled SDU\n",
|
||||
__FILE__, __LINE__, __FUNCTION__);
|
||||
r->sdu_pos = 0;
|
||||
}
|
||||
|
||||
/* if the head of the SDU is missing, still process the PDU
|
||||
* but remember to discard the reassembled SDU later on (the
|
||||
* head has not been received).
|
||||
* The head is missing if sdu_pos == 0 and fi says the PDU does not
|
||||
* start an SDU.
|
||||
*/
|
||||
if (r->sdu_pos == 0 && (fi & 0x02))
|
||||
r->sdu_head_missing = 1;
|
||||
|
||||
r->sn = sn;
|
||||
data_pos = pdu->data_offset;
|
||||
|
||||
while (1) {
|
||||
if (r->sdu_pos >= SDU_MAX) {
|
||||
/* TODO: proper error handling (discard PDUs with current sn from
|
||||
* reassembly queue? something else?)
|
||||
*/
|
||||
LOG_E(RLC, "%s:%d:%s: bad RLC PDU\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
r->sdu[r->sdu_pos] = pdu->data[data_pos];
|
||||
r->sdu_pos++;
|
||||
data_pos++;
|
||||
if (data_pos == sdu_offset + sdu_len) {
|
||||
/* all bytes of SDU are consumed, check if SDU is fully there.
|
||||
* It is if the data pointer is not at the end of the PDU segment
|
||||
* or if 'fi' & 1 == 0
|
||||
*/
|
||||
if (data_pos != pdu->size || (fi & 1) == 0) {
|
||||
/* time to discard the SDU if we didn't receive the head */
|
||||
if (r->sdu_head_missing) {
|
||||
LOG_D(RLC, "%s:%d:%s: warning: discard SDU, head not received\n",
|
||||
__FILE__, __LINE__, __FUNCTION__);
|
||||
r->sdu_head_missing = 0;
|
||||
} else {
|
||||
/* SDU is full - deliver to higher layer */
|
||||
entity->common.deliver_sdu(entity->common.deliver_sdu_data,
|
||||
(rlc_entity_t *)entity,
|
||||
r->sdu, r->sdu_pos);
|
||||
}
|
||||
r->sdu_pos = 0;
|
||||
}
|
||||
/* done with PDU? */
|
||||
if (data_pos == pdu->size)
|
||||
break;
|
||||
/* not at the end of PDU, process next SDU */
|
||||
sdu_offset += sdu_len;
|
||||
if (e) {
|
||||
e = rlc_pdu_decoder_get_bits(&r->dec, 1);
|
||||
sdu_len = rlc_pdu_decoder_get_bits(&r->dec, 11);
|
||||
} else
|
||||
sdu_len = pdu->size - sdu_offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void rlc_um_reassemble(rlc_entity_um_t *entity,
|
||||
int (*check_sn)(rlc_entity_um_t *entity, int sn))
|
||||
{
|
||||
rlc_rx_pdu_segment_t *cur;
|
||||
|
||||
/* process all PDUs from head of rx list until all is processed or
|
||||
* the SN is not valid anymore with respect to 'check_sn'
|
||||
*/
|
||||
while (entity->rx_list != NULL && check_sn(entity, entity->rx_list->sn)) {
|
||||
cur = entity->rx_list;
|
||||
rlc_um_reassemble_pdu(entity, cur);
|
||||
entity->rx_size -= cur->size;
|
||||
entity->rx_list = cur->next;
|
||||
rlc_rx_free_pdu_segment(cur);
|
||||
}
|
||||
}
|
||||
|
||||
static void rlc_um_reception_actions(rlc_entity_um_t *entity,
|
||||
rlc_rx_pdu_segment_t *pdu_segment)
|
||||
{
|
||||
if (!sn_in_recv_window(entity, pdu_segment->sn)) {
|
||||
entity->vr_uh = (pdu_segment->sn + 1) % entity->sn_modulus;
|
||||
rlc_um_reassemble(entity, outside_of_reordering_window);
|
||||
if (!sn_in_recv_window(entity, entity->vr_ur))
|
||||
entity->vr_ur = (entity->vr_uh - entity->window_size
|
||||
+ entity->sn_modulus) % entity->sn_modulus;
|
||||
}
|
||||
|
||||
if (rlc_um_pdu_received(entity, entity->vr_ur)) {
|
||||
do {
|
||||
entity->vr_ur = (entity->vr_ur + 1) % entity->sn_modulus;
|
||||
} while (rlc_um_pdu_received(entity, entity->vr_ur));
|
||||
rlc_um_reassemble(entity, less_than_vr_ur);
|
||||
}
|
||||
|
||||
if (entity->t_reordering_start) {
|
||||
if (sn_compare_rx(entity, entity->vr_ux, entity->vr_ur) <= 0 ||
|
||||
(!sn_in_recv_window(entity, entity->vr_ux) &&
|
||||
entity->vr_ux != entity->vr_uh))
|
||||
entity->t_reordering_start = 0;
|
||||
}
|
||||
|
||||
if (entity->t_reordering_start == 0) {
|
||||
if (sn_compare_rx(entity, entity->vr_uh, entity->vr_ur) > 0) {
|
||||
entity->t_reordering_start = entity->t_current;
|
||||
entity->vr_ux = entity->vr_uh;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void rlc_entity_um_recv_pdu(rlc_entity_t *_entity, char *buffer, int size)
|
||||
{
|
||||
#define R(d) do { if (rlc_pdu_decoder_in_error(&d)) goto err; } while (0)
|
||||
rlc_entity_um_t *entity = (rlc_entity_um_t *)_entity;
|
||||
rlc_pdu_decoder_t decoder;
|
||||
rlc_pdu_decoder_t data_decoder;
|
||||
|
||||
int e;
|
||||
int sn;
|
||||
|
||||
int data_e;
|
||||
int data_li;
|
||||
|
||||
int packet_count;
|
||||
int data_size;
|
||||
int data_start;
|
||||
int indicated_data_size;
|
||||
|
||||
rlc_rx_pdu_segment_t *pdu_segment;
|
||||
|
||||
rlc_pdu_decoder_init(&decoder, buffer, size);
|
||||
|
||||
if (entity->sn_field_length == 10) {
|
||||
rlc_pdu_decoder_get_bits(&decoder, 3); R(decoder); /* R1 */
|
||||
}
|
||||
|
||||
rlc_pdu_decoder_get_bits(&decoder, 2); R(decoder); /* FI */
|
||||
e = rlc_pdu_decoder_get_bits(&decoder, 1); R(decoder);
|
||||
sn = rlc_pdu_decoder_get_bits(&decoder, entity->sn_field_length); R(decoder);
|
||||
|
||||
/* dicard PDU if rx buffer is full */
|
||||
if (entity->rx_size + size > entity->rx_maxsize) {
|
||||
LOG_D(RLC, "%s:%d:%s: warning: discard PDU, RX buffer full\n",
|
||||
__FILE__, __LINE__, __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
/* discard according to 36.322 5.1.2.2.2 */
|
||||
if ((sn_compare_rx(entity, entity->vr_ur, sn) < 0 &&
|
||||
sn_compare_rx(entity, sn, entity->vr_uh) < 0 &&
|
||||
rlc_um_pdu_received(entity, sn)) ||
|
||||
(sn_compare_rx(entity, entity->vr_uh - entity->window_size, sn) <= 0 &&
|
||||
sn_compare_rx(entity, sn, entity->vr_ur) < 0)) {
|
||||
LOG_D(RLC, "%s:%d:%s: warning: discard PDU (sn %d vr(ur) %d vr(uh) %d)\n",
|
||||
__FILE__, __LINE__, __FUNCTION__,
|
||||
sn, entity->vr_ur, entity->vr_uh);
|
||||
return;
|
||||
}
|
||||
|
||||
packet_count = 1;
|
||||
|
||||
/* go to start of data */
|
||||
indicated_data_size = 0;
|
||||
data_decoder = decoder;
|
||||
data_e = e;
|
||||
while (data_e) {
|
||||
data_e = rlc_pdu_decoder_get_bits(&data_decoder, 1); R(data_decoder);
|
||||
data_li = rlc_pdu_decoder_get_bits(&data_decoder, 11); R(data_decoder);
|
||||
if (data_li == 0) {
|
||||
LOG_D(RLC, "%s:%d:%s: warning: discard PDU, li == 0\n",
|
||||
__FILE__, __LINE__, __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
indicated_data_size += data_li;
|
||||
packet_count++;
|
||||
}
|
||||
rlc_pdu_decoder_align(&data_decoder);
|
||||
|
||||
data_start = data_decoder.byte;
|
||||
data_size = size - data_start;
|
||||
|
||||
if (data_size <= 0) {
|
||||
LOG_D(RLC, "%s:%d:%s: warning: discard PDU, wrong data size (sum of LI %d data size %d)\n",
|
||||
__FILE__, __LINE__, __FUNCTION__,
|
||||
indicated_data_size, data_size);
|
||||
return;
|
||||
}
|
||||
if (indicated_data_size >= data_size) {
|
||||
LOG_D(RLC, "%s:%d:%s: warning: discard PDU, bad LIs (sum of LI %d data size %d)\n",
|
||||
__FILE__, __LINE__, __FUNCTION__,
|
||||
indicated_data_size, data_size);
|
||||
return;
|
||||
}
|
||||
|
||||
/* put in pdu reception list */
|
||||
entity->rx_size += size;
|
||||
pdu_segment = rlc_rx_new_pdu_segment(sn, 0, size, 1, buffer, data_start);
|
||||
entity->rx_list = rlc_rx_pdu_segment_list_add(sn_compare_rx, entity,
|
||||
entity->rx_list, pdu_segment);
|
||||
|
||||
/* do reception actions (36.322 5.1.2.2.3) */
|
||||
rlc_um_reception_actions(entity, pdu_segment);
|
||||
|
||||
return;
|
||||
|
||||
err:
|
||||
LOG_D(RLC, "%s:%d:%s: error decoding PDU, discarding\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
|
||||
#undef R
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/* TX functions */
|
||||
/*************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
int sdu_count;
|
||||
int data_size;
|
||||
int header_size;
|
||||
int last_sdu_is_full;
|
||||
int first_sdu_length;
|
||||
} tx_pdu_size_t;
|
||||
|
||||
static int header_size(int sn_field_length, int sdu_count)
|
||||
{
|
||||
int bits = 8 + 8 * (sn_field_length == 10) + 12 * (sdu_count - 1);
|
||||
/* padding if we have to */
|
||||
return (bits + 7) / 8;
|
||||
}
|
||||
|
||||
static tx_pdu_size_t tx_pdu_size(rlc_entity_um_t *entity, int maxsize)
|
||||
{
|
||||
tx_pdu_size_t ret;
|
||||
int sdu_count;
|
||||
int sdu_size;
|
||||
int pdu_data_size;
|
||||
rlc_sdu_t *sdu;
|
||||
|
||||
ret.sdu_count = 0;
|
||||
ret.data_size = 0;
|
||||
ret.header_size = 0;
|
||||
ret.last_sdu_is_full = 1;
|
||||
|
||||
/* TX PDU - let's make the biggest PDU we can with the SDUs we have */
|
||||
sdu_count = 0;
|
||||
pdu_data_size = 0;
|
||||
sdu = entity->tx_list;
|
||||
while (sdu != NULL) {
|
||||
int new_header_size = header_size(entity->sn_field_length, sdu_count+1);
|
||||
/* if we cannot put new header + at least 1 byte of data then over */
|
||||
if (new_header_size + pdu_data_size >= maxsize)
|
||||
break;
|
||||
sdu_count++;
|
||||
/* only include the bytes of this SDU not included in PDUs already */
|
||||
sdu_size = sdu->size - sdu->next_byte;
|
||||
/* don't feed more than 'maxsize' bytes */
|
||||
if (new_header_size + pdu_data_size + sdu_size > maxsize) {
|
||||
sdu_size = maxsize - new_header_size - pdu_data_size;
|
||||
ret.last_sdu_is_full = 0;
|
||||
}
|
||||
if (sdu_count == 1)
|
||||
ret.first_sdu_length = sdu_size;
|
||||
pdu_data_size += sdu_size;
|
||||
/* if we put more than 2^11-1 bytes then the LI field cannot be used,
|
||||
* so this is the last SDU we can put
|
||||
*/
|
||||
if (sdu_size > 2047)
|
||||
break;
|
||||
sdu = sdu->next;
|
||||
}
|
||||
|
||||
if (sdu_count) {
|
||||
ret.sdu_count = sdu_count;
|
||||
ret.data_size = pdu_data_size;
|
||||
ret.header_size = header_size(entity->sn_field_length, sdu_count);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
rlc_entity_buffer_status_t rlc_entity_um_buffer_status(
|
||||
rlc_entity_t *_entity, int maxsize)
|
||||
{
|
||||
rlc_entity_um_t *entity = (rlc_entity_um_t *)_entity;
|
||||
rlc_entity_buffer_status_t ret;
|
||||
tx_pdu_size_t tx_size;
|
||||
|
||||
ret.status_size = 0;
|
||||
|
||||
/* todo: if an SDU has size >2047 in the tx list then processing
|
||||
* stops and computed size will not be accurate. Change the computation
|
||||
* to be more accurate (if needed).
|
||||
*/
|
||||
tx_size = tx_pdu_size(entity, maxsize);
|
||||
ret.tx_size = tx_size.data_size + tx_size.header_size;
|
||||
|
||||
ret.retx_size = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int rlc_entity_um_generate_pdu(rlc_entity_t *_entity, char *buffer, int size)
|
||||
{
|
||||
rlc_entity_um_t *entity = (rlc_entity_um_t *)_entity;
|
||||
tx_pdu_size_t pdu_size;
|
||||
rlc_sdu_t *sdu;
|
||||
int i;
|
||||
int cursize;
|
||||
int first_sdu_full;
|
||||
int last_sdu_full;
|
||||
rlc_pdu_encoder_t encoder;
|
||||
int fi;
|
||||
int e;
|
||||
int li;
|
||||
char *out;
|
||||
int outpos;
|
||||
int first_sdu_start_byte;
|
||||
int sdu_start_byte;
|
||||
|
||||
pdu_size = tx_pdu_size(entity, size);
|
||||
if (pdu_size.sdu_count == 0)
|
||||
return 0;
|
||||
|
||||
sdu = entity->tx_list;
|
||||
|
||||
first_sdu_start_byte = sdu->next_byte;
|
||||
|
||||
/* reserve SDU bytes */
|
||||
cursize = 0;
|
||||
for (i = 0; i < pdu_size.sdu_count; i++, sdu = sdu->next) {
|
||||
int sdu_size = sdu->size - sdu->next_byte;
|
||||
if (cursize + sdu_size > pdu_size.data_size)
|
||||
sdu_size = pdu_size.data_size - cursize;
|
||||
sdu->next_byte += sdu_size;
|
||||
cursize += sdu_size;
|
||||
}
|
||||
|
||||
first_sdu_full = first_sdu_start_byte == 0;
|
||||
last_sdu_full = pdu_size.last_sdu_is_full;
|
||||
|
||||
/* generate header */
|
||||
rlc_pdu_encoder_init(&encoder, buffer, size);
|
||||
|
||||
if (entity->sn_field_length == 10)
|
||||
rlc_pdu_encoder_put_bits(&encoder, 0, 3); /* R1 */
|
||||
|
||||
fi = 0;
|
||||
if (!first_sdu_full)
|
||||
fi |= 0x02;
|
||||
if (!last_sdu_full)
|
||||
fi |= 0x01;
|
||||
rlc_pdu_encoder_put_bits(&encoder, fi, 2); /* FI */
|
||||
|
||||
/* see the AM code to understand the logic for Es and LIs */
|
||||
if (pdu_size.sdu_count >= 2)
|
||||
e = 1;
|
||||
else
|
||||
e = 0;
|
||||
rlc_pdu_encoder_put_bits(&encoder, e, 1); /* E */
|
||||
|
||||
if (entity->sn_field_length == 10)
|
||||
rlc_pdu_encoder_put_bits(&encoder, entity->vt_us, 10); /* SN */
|
||||
else
|
||||
rlc_pdu_encoder_put_bits(&encoder, entity->vt_us, 5); /* SN */
|
||||
|
||||
/* put LIs */
|
||||
sdu = entity->tx_list;
|
||||
/* first SDU */
|
||||
li = pdu_size.first_sdu_length;
|
||||
/* put E+LI only if at least 2 SDUs */
|
||||
if (pdu_size.sdu_count >= 2) {
|
||||
/* E is 1 if at least 3 SDUs */
|
||||
if (pdu_size.sdu_count >= 3)
|
||||
e = 1;
|
||||
else
|
||||
e = 0;
|
||||
rlc_pdu_encoder_put_bits(&encoder, e, 1); /* E */
|
||||
rlc_pdu_encoder_put_bits(&encoder, li, 11); /* LI */
|
||||
}
|
||||
/* next SDUs, but not the last (no LI for the last) */
|
||||
sdu = sdu->next;
|
||||
for (i = 2; i < pdu_size.sdu_count; i++, sdu = sdu->next) {
|
||||
if (i != pdu_size.sdu_count - 1)
|
||||
e = 1;
|
||||
else
|
||||
e = 0;
|
||||
li = sdu->size;
|
||||
rlc_pdu_encoder_put_bits(&encoder, e, 1); /* E */
|
||||
rlc_pdu_encoder_put_bits(&encoder, li, 11); /* LI */
|
||||
}
|
||||
|
||||
rlc_pdu_encoder_align(&encoder);
|
||||
|
||||
/* generate data */
|
||||
out = buffer + pdu_size.header_size;
|
||||
sdu = entity->tx_list;
|
||||
sdu_start_byte = first_sdu_start_byte;
|
||||
outpos = 0;
|
||||
for (i = 0; i < pdu_size.sdu_count; i++, sdu = sdu->next) {
|
||||
li = sdu->size - sdu_start_byte;
|
||||
if (outpos + li >= pdu_size.data_size)
|
||||
li = pdu_size.data_size - outpos;
|
||||
memcpy(out+outpos, sdu->data + sdu_start_byte, li);
|
||||
outpos += li;
|
||||
sdu_start_byte = 0;
|
||||
}
|
||||
|
||||
/* cleanup sdu list */
|
||||
while (entity->tx_list != NULL &&
|
||||
entity->tx_list->size == entity->tx_list->next_byte) {
|
||||
rlc_sdu_t *c = entity->tx_list;
|
||||
/* release SDU bytes */
|
||||
entity->tx_size -= c->size;
|
||||
entity->tx_list = c->next;
|
||||
rlc_free_sdu(c);
|
||||
}
|
||||
if (entity->tx_list == NULL)
|
||||
entity->tx_end = NULL;
|
||||
|
||||
/* update VT(US) */
|
||||
entity->vt_us = (entity->vt_us + 1) % entity->sn_modulus;
|
||||
|
||||
return pdu_size.header_size + pdu_size.data_size;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/* SDU RX functions */
|
||||
/*************************************************************************/
|
||||
|
||||
void rlc_entity_um_recv_sdu(rlc_entity_t *_entity, char *buffer, int size,
|
||||
int sdu_id)
|
||||
{
|
||||
rlc_entity_um_t *entity = (rlc_entity_um_t *)_entity;
|
||||
rlc_sdu_t *sdu;
|
||||
|
||||
if (size > SDU_MAX) {
|
||||
LOG_E(RLC, "%s:%d:%s: fatal: SDU size too big (%d bytes)\n",
|
||||
__FILE__, __LINE__, __FUNCTION__, size);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (entity->tx_size + size > entity->tx_maxsize) {
|
||||
LOG_D(RLC, "%s:%d:%s: warning: SDU rejected, SDU buffer full\n",
|
||||
__FILE__, __LINE__, __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
entity->tx_size += size;
|
||||
|
||||
sdu = rlc_new_sdu(buffer, size, sdu_id);
|
||||
rlc_sdu_list_add(&entity->tx_list, &entity->tx_end, sdu);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/* time/timers */
|
||||
/*************************************************************************/
|
||||
|
||||
static void check_t_reordering(rlc_entity_um_t *entity)
|
||||
{
|
||||
int sn;
|
||||
|
||||
/* is t_reordering running and if yes has it expired? */
|
||||
if (entity->t_reordering_start == 0 ||
|
||||
entity->t_current <= entity->t_reordering_start + entity->t_reordering)
|
||||
return;
|
||||
|
||||
/* stop timer */
|
||||
entity->t_reordering_start = 0;
|
||||
|
||||
LOG_D(RLC, "%s:%d:%s: t_reordering expired\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
|
||||
/* update VR(UR) to first SN >= VR(UX) of PDU not received
|
||||
*/
|
||||
sn = entity->vr_ux;
|
||||
while (rlc_um_pdu_received(entity, sn))
|
||||
sn = (sn + 1) % entity->sn_modulus;
|
||||
entity->vr_ur = sn;
|
||||
|
||||
rlc_um_reassemble(entity, less_than_vr_ur);
|
||||
|
||||
if (sn_compare_rx(entity, entity->vr_uh, entity->vr_ur) > 0) {
|
||||
entity->t_reordering_start = entity->t_current;
|
||||
entity->vr_ux = entity->vr_uh;
|
||||
}
|
||||
}
|
||||
|
||||
void rlc_entity_um_set_time(rlc_entity_t *_entity, uint64_t now)
|
||||
{
|
||||
rlc_entity_um_t *entity = (rlc_entity_um_t *)_entity;
|
||||
|
||||
entity->t_current = now;
|
||||
|
||||
check_t_reordering(entity);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/* discard/re-establishment/delete */
|
||||
/*************************************************************************/
|
||||
|
||||
void rlc_entity_um_discard_sdu(rlc_entity_t *_entity, int sdu_id)
|
||||
{
|
||||
/* implements 36.322 5.3 */
|
||||
rlc_entity_um_t *entity = (rlc_entity_um_t *)_entity;
|
||||
rlc_sdu_t head;
|
||||
rlc_sdu_t *cur;
|
||||
rlc_sdu_t *prev;
|
||||
|
||||
head.next = entity->tx_list;
|
||||
cur = entity->tx_list;
|
||||
prev = &head;
|
||||
|
||||
while (cur != NULL && cur->upper_layer_id != sdu_id) {
|
||||
prev = cur;
|
||||
cur = cur->next;
|
||||
}
|
||||
|
||||
/* if sdu_id not found or some bytes have already been 'PDU-ized'
|
||||
* then do nothing
|
||||
*/
|
||||
if (cur == NULL || cur->next_byte != 0)
|
||||
return;
|
||||
|
||||
/* remove SDU from tx_list */
|
||||
prev->next = cur->next;
|
||||
entity->tx_list = head.next;
|
||||
if (entity->tx_end == cur) {
|
||||
if (prev != &head)
|
||||
entity->tx_end = prev;
|
||||
else
|
||||
entity->tx_end = NULL;
|
||||
}
|
||||
|
||||
rlc_free_sdu(cur);
|
||||
}
|
||||
|
||||
static void clear_entity(rlc_entity_um_t *entity)
|
||||
{
|
||||
rlc_rx_pdu_segment_t *cur_rx;
|
||||
rlc_sdu_t *cur_tx;
|
||||
|
||||
entity->vr_ur = 0;
|
||||
entity->vr_ux = 0;
|
||||
entity->vr_uh = 0;
|
||||
|
||||
entity->vt_us = 0;
|
||||
|
||||
entity->t_current = 0;
|
||||
|
||||
entity->t_reordering_start = 0;
|
||||
|
||||
cur_rx = entity->rx_list;
|
||||
while (cur_rx != NULL) {
|
||||
rlc_rx_pdu_segment_t *p = cur_rx;
|
||||
cur_rx = cur_rx->next;
|
||||
rlc_rx_free_pdu_segment(p);
|
||||
}
|
||||
entity->rx_list = NULL;
|
||||
entity->rx_size = 0;
|
||||
|
||||
memset(&entity->reassemble, 0, sizeof(rlc_um_reassemble_t));
|
||||
|
||||
cur_tx = entity->tx_list;
|
||||
while (cur_tx != NULL) {
|
||||
rlc_sdu_t *p = cur_tx;
|
||||
cur_tx = cur_tx->next;
|
||||
rlc_free_sdu(p);
|
||||
}
|
||||
entity->tx_list = NULL;
|
||||
entity->tx_end = NULL;
|
||||
entity->tx_size = 0;
|
||||
}
|
||||
|
||||
void rlc_entity_um_reestablishment(rlc_entity_t *_entity)
|
||||
{
|
||||
rlc_entity_um_t *entity = (rlc_entity_um_t *)_entity;
|
||||
|
||||
rlc_um_reassemble(entity, less_than_vr_uh);
|
||||
|
||||
clear_entity(entity);
|
||||
}
|
||||
|
||||
void rlc_entity_um_delete(rlc_entity_t *_entity)
|
||||
{
|
||||
rlc_entity_um_t *entity = (rlc_entity_um_t *)_entity;
|
||||
clear_entity(entity);
|
||||
free(entity);
|
||||
}
|
||||
90
openair2/LAYER2/rlc_v2/rlc_entity_um.h
Normal file
90
openair2/LAYER2/rlc_v2/rlc_entity_um.h
Normal file
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#ifndef _RLC_ENTITY_UM_H_
|
||||
#define _RLC_ENTITY_UM_H_
|
||||
|
||||
#include "rlc_entity.h"
|
||||
#include "rlc_pdu.h"
|
||||
#include "rlc_sdu.h"
|
||||
|
||||
typedef struct {
|
||||
char sdu[SDU_MAX]; /* sdu is reassembled here */
|
||||
int sdu_pos; /* next byte to put in sdu */
|
||||
|
||||
/* decoder of current PDU */
|
||||
rlc_pdu_decoder_t dec;
|
||||
int sn;
|
||||
|
||||
int sdu_head_missing;
|
||||
} rlc_um_reassemble_t;
|
||||
|
||||
typedef struct {
|
||||
rlc_entity_t common;
|
||||
|
||||
/* configuration */
|
||||
int t_reordering;
|
||||
int sn_field_length;
|
||||
|
||||
int sn_modulus; /* 1024 for sn_field_length == 10, 32 for 5 */
|
||||
int window_size; /* 512 for sn_field_length == 10, 16 for 5 */
|
||||
|
||||
/* runtime rx */
|
||||
int vr_ur;
|
||||
int vr_ux;
|
||||
int vr_uh;
|
||||
|
||||
/* runtime tx */
|
||||
int vt_us;
|
||||
|
||||
/* set to the latest know time by the user of the module. Unit: ms */
|
||||
uint64_t t_current;
|
||||
|
||||
/* timers (stores the TTI of activation, 0 means not active) */
|
||||
uint64_t t_reordering_start;
|
||||
|
||||
/* rx management */
|
||||
rlc_rx_pdu_segment_t *rx_list;
|
||||
int rx_size;
|
||||
int rx_maxsize;
|
||||
|
||||
/* reassembly management */
|
||||
rlc_um_reassemble_t reassemble;
|
||||
|
||||
/* tx management */
|
||||
rlc_sdu_t *tx_list;
|
||||
rlc_sdu_t *tx_end;
|
||||
int tx_size;
|
||||
int tx_maxsize;
|
||||
} rlc_entity_um_t;
|
||||
|
||||
void rlc_entity_um_recv_sdu(rlc_entity_t *_entity, char *buffer, int size,
|
||||
int sdu_id);
|
||||
void rlc_entity_um_recv_pdu(rlc_entity_t *entity, char *buffer, int size);
|
||||
rlc_entity_buffer_status_t rlc_entity_um_buffer_status(
|
||||
rlc_entity_t *entity, int maxsize);
|
||||
int rlc_entity_um_generate_pdu(rlc_entity_t *_entity, char *buffer, int size);
|
||||
void rlc_entity_um_set_time(rlc_entity_t *entity, uint64_t now);
|
||||
void rlc_entity_um_discard_sdu(rlc_entity_t *entity, int sdu_id);
|
||||
void rlc_entity_um_reestablishment(rlc_entity_t *entity);
|
||||
void rlc_entity_um_delete(rlc_entity_t *entity);
|
||||
|
||||
#endif /* _RLC_ENTITY_UM_H_ */
|
||||
895
openair2/LAYER2/rlc_v2/rlc_oai_api.c
Normal file
895
openair2/LAYER2/rlc_v2/rlc_oai_api.c
Normal file
@@ -0,0 +1,895 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/* from openair */
|
||||
#include "rlc.h"
|
||||
#include "pdcp.h"
|
||||
|
||||
/* from new rlc module */
|
||||
#include "asn1_utils.h"
|
||||
#include "rlc_ue_manager.h"
|
||||
#include "rlc_entity.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
static rlc_ue_manager_t *rlc_ue_manager;
|
||||
|
||||
/* TODO: handle time a bit more properly */
|
||||
static uint64_t rlc_current_time;
|
||||
static int rlc_current_time_last_frame;
|
||||
static int rlc_current_time_last_subframe;
|
||||
|
||||
void mac_rlc_data_ind (
|
||||
const module_id_t module_idP,
|
||||
const rnti_t rntiP,
|
||||
const eNB_index_t eNB_index,
|
||||
const frame_t frameP,
|
||||
const eNB_flag_t enb_flagP,
|
||||
const MBMS_flag_t MBMS_flagP,
|
||||
const logical_chan_id_t channel_idP,
|
||||
char *buffer_pP,
|
||||
const tb_size_t tb_sizeP,
|
||||
num_tb_t num_tbP,
|
||||
crc_t *crcs_pP)
|
||||
{
|
||||
rlc_ue_t *ue;
|
||||
rlc_entity_t *rb;
|
||||
|
||||
if (module_idP != 0 || eNB_index != 0 || /*enb_flagP != 1 ||*/ MBMS_flagP != 0) {
|
||||
LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (enb_flagP)
|
||||
T(T_ENB_RLC_MAC_UL, T_INT(module_idP), T_INT(rntiP),
|
||||
T_INT(channel_idP), T_INT(tb_sizeP));
|
||||
|
||||
rlc_manager_lock(rlc_ue_manager);
|
||||
ue = rlc_manager_get_ue(rlc_ue_manager, rntiP);
|
||||
|
||||
switch (channel_idP) {
|
||||
case 1 ... 2: rb = ue->srb[channel_idP - 1]; break;
|
||||
case 3 ... 7: rb = ue->drb[channel_idP - 3]; break;
|
||||
default: rb = NULL; break;
|
||||
}
|
||||
|
||||
if (rb != NULL) {
|
||||
rb->set_time(rb, rlc_current_time);
|
||||
rb->recv_pdu(rb, buffer_pP, tb_sizeP);
|
||||
} else {
|
||||
LOG_E(RLC, "%s:%d:%s: fatal: no RB found (channel ID %d)\n",
|
||||
__FILE__, __LINE__, __FUNCTION__, channel_idP);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
rlc_manager_unlock(rlc_ue_manager);
|
||||
}
|
||||
|
||||
tbs_size_t mac_rlc_data_req(
|
||||
const module_id_t module_idP,
|
||||
const rnti_t rntiP,
|
||||
const eNB_index_t eNB_index,
|
||||
const frame_t frameP,
|
||||
const eNB_flag_t enb_flagP,
|
||||
const MBMS_flag_t MBMS_flagP,
|
||||
const logical_chan_id_t channel_idP,
|
||||
const tb_size_t tb_sizeP,
|
||||
char *buffer_pP
|
||||
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
|
||||
,const uint32_t sourceL2Id
|
||||
,const uint32_t destinationL2Id
|
||||
#endif
|
||||
)
|
||||
{
|
||||
int ret;
|
||||
rlc_ue_t *ue;
|
||||
rlc_entity_t *rb;
|
||||
int is_enb;
|
||||
int maxsize;
|
||||
|
||||
rlc_manager_lock(rlc_ue_manager);
|
||||
ue = rlc_manager_get_ue(rlc_ue_manager, rntiP);
|
||||
|
||||
switch (channel_idP) {
|
||||
case 1 ... 2: rb = ue->srb[channel_idP - 1]; break;
|
||||
case 3 ... 7: rb = ue->drb[channel_idP - 3]; break;
|
||||
default: rb = NULL; break;
|
||||
}
|
||||
|
||||
if (rb != NULL) {
|
||||
rb->set_time(rb, rlc_current_time);
|
||||
/* UE does not seem to use saved_status_ind_tb_size */
|
||||
is_enb = rlc_manager_get_enb_flag(rlc_ue_manager);
|
||||
if (is_enb)
|
||||
maxsize = ue->saved_status_ind_tb_size[channel_idP - 1];
|
||||
else
|
||||
maxsize = tb_sizeP;
|
||||
ret = rb->generate_pdu(rb, buffer_pP, maxsize);
|
||||
} else {
|
||||
LOG_E(RLC, "%s:%d:%s: fatal: data req for unknown RB\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
rlc_manager_unlock(rlc_ue_manager);
|
||||
|
||||
if (enb_flagP)
|
||||
T(T_ENB_RLC_MAC_DL, T_INT(module_idP), T_INT(rntiP),
|
||||
T_INT(channel_idP), T_INT(ret));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
mac_rlc_status_resp_t mac_rlc_status_ind(
|
||||
const module_id_t module_idP,
|
||||
const rnti_t rntiP,
|
||||
const eNB_index_t eNB_index,
|
||||
const frame_t frameP,
|
||||
const sub_frame_t subframeP,
|
||||
const eNB_flag_t enb_flagP,
|
||||
const MBMS_flag_t MBMS_flagP,
|
||||
const logical_chan_id_t channel_idP,
|
||||
const tb_size_t tb_sizeP
|
||||
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
|
||||
,const uint32_t sourceL2Id
|
||||
,const uint32_t destinationL2Id
|
||||
#endif
|
||||
)
|
||||
{
|
||||
rlc_ue_t *ue;
|
||||
mac_rlc_status_resp_t ret;
|
||||
rlc_entity_t *rb;
|
||||
|
||||
/* TODO: handle time a bit more properly */
|
||||
if (rlc_current_time_last_frame != frameP ||
|
||||
rlc_current_time_last_subframe != subframeP) {
|
||||
rlc_current_time++;
|
||||
rlc_current_time_last_frame = frameP;
|
||||
rlc_current_time_last_subframe = subframeP;
|
||||
}
|
||||
|
||||
rlc_manager_lock(rlc_ue_manager);
|
||||
ue = rlc_manager_get_ue(rlc_ue_manager, rntiP);
|
||||
|
||||
switch (channel_idP) {
|
||||
case 1 ... 2: rb = ue->srb[channel_idP - 1]; break;
|
||||
case 3 ... 7: rb = ue->drb[channel_idP - 3]; break;
|
||||
default: rb = NULL; break;
|
||||
}
|
||||
|
||||
if (rb != NULL) {
|
||||
rlc_entity_buffer_status_t buf_stat;
|
||||
rb->set_time(rb, rlc_current_time);
|
||||
/* 36.321 deals with BSR values up to 3000000 bytes, after what it
|
||||
* reports '> 3000000' (table 6.1.3.1-2). Passing 4000000 is thus
|
||||
* more than enough.
|
||||
*/
|
||||
buf_stat = rb->buffer_status(rb, 4000000);
|
||||
ret.bytes_in_buffer = buf_stat.status_size
|
||||
+ buf_stat.retx_size
|
||||
+ buf_stat.tx_size;
|
||||
ue->saved_status_ind_tb_size[channel_idP - 1] = tb_sizeP;
|
||||
} else {
|
||||
ret.bytes_in_buffer = 0;
|
||||
}
|
||||
|
||||
rlc_manager_unlock(rlc_ue_manager);
|
||||
|
||||
ret.pdus_in_buffer = 0;
|
||||
/* TODO: creation time may be important (unit: frame, as it seems) */
|
||||
ret.head_sdu_creation_time = 0;
|
||||
ret.head_sdu_remaining_size_to_send = 0;
|
||||
ret.head_sdu_is_segmented = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
rlc_buffer_occupancy_t mac_rlc_get_buffer_occupancy_ind(
|
||||
const module_id_t module_idP,
|
||||
const rnti_t rntiP,
|
||||
const eNB_index_t eNB_index,
|
||||
const frame_t frameP,
|
||||
const sub_frame_t subframeP,
|
||||
const eNB_flag_t enb_flagP,
|
||||
const logical_chan_id_t channel_idP)
|
||||
{
|
||||
rlc_ue_t *ue;
|
||||
rlc_buffer_occupancy_t ret;
|
||||
rlc_entity_t *rb;
|
||||
|
||||
if (enb_flagP) {
|
||||
LOG_E(RLC, "Tx mac_rlc_get_buffer_occupancy_ind function is not implemented for eNB LcId=%u\n", channel_idP);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* TODO: handle time a bit more properly */
|
||||
if (rlc_current_time_last_frame != frameP ||
|
||||
rlc_current_time_last_subframe != subframeP) {
|
||||
rlc_current_time++;
|
||||
rlc_current_time_last_frame = frameP;
|
||||
rlc_current_time_last_subframe = subframeP;
|
||||
}
|
||||
|
||||
rlc_manager_lock(rlc_ue_manager);
|
||||
ue = rlc_manager_get_ue(rlc_ue_manager, rntiP);
|
||||
|
||||
switch (channel_idP) {
|
||||
case 1 ... 2: rb = ue->srb[channel_idP - 1]; break;
|
||||
case 3 ... 7: rb = ue->drb[channel_idP - 3]; break;
|
||||
default: rb = NULL; break;
|
||||
}
|
||||
|
||||
if (rb != NULL) {
|
||||
rlc_entity_buffer_status_t buf_stat;
|
||||
rb->set_time(rb, rlc_current_time);
|
||||
/* 36.321 deals with BSR values up to 3000000 bytes, after what it
|
||||
* reports '> 3000000' (table 6.1.3.1-2). Passing 4000000 is thus
|
||||
* more than enough.
|
||||
*/
|
||||
buf_stat = rb->buffer_status(rb, 4000000);
|
||||
ret = buf_stat.status_size
|
||||
+ buf_stat.retx_size
|
||||
+ buf_stat.tx_size;
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
rlc_manager_unlock(rlc_ue_manager);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int oai_emulation;
|
||||
|
||||
rlc_op_status_t rlc_data_req (const protocol_ctxt_t *const ctxt_pP,
|
||||
const srb_flag_t srb_flagP,
|
||||
const MBMS_flag_t MBMS_flagP,
|
||||
const rb_id_t rb_idP,
|
||||
const mui_t muiP,
|
||||
confirm_t confirmP,
|
||||
sdu_size_t sdu_sizeP,
|
||||
mem_block_t *sdu_pP
|
||||
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
|
||||
,const uint32_t *const sourceL2Id
|
||||
,const uint32_t *const destinationL2Id
|
||||
#endif
|
||||
)
|
||||
{
|
||||
int rnti = ctxt_pP->rnti;
|
||||
rlc_ue_t *ue;
|
||||
rlc_entity_t *rb;
|
||||
|
||||
LOG_D(RLC, "%s rnti %d srb_flag %d rb_id %d mui %d confirm %d sdu_size %d MBMS_flag %d\n",
|
||||
__FUNCTION__, rnti, srb_flagP, rb_idP, muiP, confirmP, sdu_sizeP,
|
||||
MBMS_flagP);
|
||||
|
||||
if (ctxt_pP->enb_flag)
|
||||
T(T_ENB_RLC_DL, T_INT(ctxt_pP->module_id),
|
||||
T_INT(ctxt_pP->rnti), T_INT(rb_idP), T_INT(sdu_sizeP));
|
||||
|
||||
rlc_manager_lock(rlc_ue_manager);
|
||||
ue = rlc_manager_get_ue(rlc_ue_manager, rnti);
|
||||
|
||||
rb = NULL;
|
||||
|
||||
if (srb_flagP) {
|
||||
if (rb_idP >= 1 && rb_idP <= 2)
|
||||
rb = ue->srb[rb_idP - 1];
|
||||
} else {
|
||||
if (rb_idP >= 1 && rb_idP <= 5)
|
||||
rb = ue->drb[rb_idP - 1];
|
||||
}
|
||||
|
||||
if (rb != NULL) {
|
||||
rb->set_time(rb, rlc_current_time);
|
||||
rb->recv_sdu(rb, (char *)sdu_pP->data, sdu_sizeP, muiP);
|
||||
} else {
|
||||
LOG_E(RLC, "%s:%d:%s: fatal: SDU sent to unknown RB\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
rlc_manager_unlock(rlc_ue_manager);
|
||||
|
||||
free_mem_block(sdu_pP, __func__);
|
||||
|
||||
return RLC_OP_STATUS_OK;
|
||||
}
|
||||
|
||||
int rlc_module_init(int enb_flag)
|
||||
{
|
||||
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
static int inited = 0;
|
||||
|
||||
if (pthread_mutex_lock(&lock)) abort();
|
||||
|
||||
if (inited) {
|
||||
LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
inited = 1;
|
||||
|
||||
rlc_ue_manager = new_rlc_ue_manager(enb_flag);
|
||||
|
||||
if (pthread_mutex_unlock(&lock)) abort();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rlc_util_print_hex_octets(comp_name_t componentP, unsigned char *dataP, const signed long sizeP)
|
||||
{
|
||||
}
|
||||
|
||||
static void deliver_sdu(void *_ue, rlc_entity_t *entity, char *buf, int size)
|
||||
{
|
||||
rlc_ue_t *ue = _ue;
|
||||
int is_srb;
|
||||
int rb_id;
|
||||
protocol_ctxt_t ctx;
|
||||
mem_block_t *memblock;
|
||||
int i;
|
||||
int is_enb;
|
||||
|
||||
/* is it SRB? */
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (entity == ue->srb[i]) {
|
||||
is_srb = 1;
|
||||
rb_id = i+1;
|
||||
goto rb_found;
|
||||
}
|
||||
}
|
||||
|
||||
/* maybe DRB? */
|
||||
for (i = 0; i < 5; i++) {
|
||||
if (entity == ue->drb[i]) {
|
||||
is_srb = 0;
|
||||
rb_id = i+1;
|
||||
goto rb_found;
|
||||
}
|
||||
}
|
||||
|
||||
LOG_E(RLC, "%s:%d:%s: fatal, no RB found for ue %d\n",
|
||||
__FILE__, __LINE__, __FUNCTION__, ue->rnti);
|
||||
exit(1);
|
||||
|
||||
rb_found:
|
||||
LOG_D(RLC, "%s:%d:%s: delivering SDU (rnti %d is_srb %d rb_id %d) size %d",
|
||||
__FILE__, __LINE__, __FUNCTION__, ue->rnti, is_srb, rb_id, size);
|
||||
|
||||
memblock = get_free_mem_block(size, __func__);
|
||||
if (memblock == NULL) {
|
||||
LOG_E(RLC, "%s:%d:%s: ERROR: get_free_mem_block failed\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
memcpy(memblock->data, buf, size);
|
||||
|
||||
/* unused fields? */
|
||||
ctx.instance = 0;
|
||||
ctx.frame = 0;
|
||||
ctx.subframe = 0;
|
||||
ctx.eNB_index = 0;
|
||||
ctx.configured = 1;
|
||||
ctx.brOption = 0;
|
||||
|
||||
/* used fields? */
|
||||
ctx.module_id = 0;
|
||||
ctx.rnti = ue->rnti;
|
||||
|
||||
is_enb = rlc_manager_get_enb_flag(rlc_ue_manager);
|
||||
ctx.enb_flag = is_enb;
|
||||
|
||||
if (is_enb) {
|
||||
T(T_ENB_RLC_UL,
|
||||
T_INT(0 /*ctxt_pP->module_id*/),
|
||||
T_INT(ue->rnti), T_INT(rb_id), T_INT(size));
|
||||
}
|
||||
|
||||
if (!pdcp_data_ind(&ctx, is_srb, 0, rb_id, size, memblock)) {
|
||||
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 */
|
||||
}
|
||||
}
|
||||
|
||||
static void successful_delivery(void *_ue, rlc_entity_t *entity, int sdu_id)
|
||||
{
|
||||
rlc_ue_t *ue = _ue;
|
||||
int i;
|
||||
int is_srb;
|
||||
int rb_id;
|
||||
MessageDef *msg;
|
||||
int is_enb;
|
||||
|
||||
/* is it SRB? */
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (entity == ue->srb[i]) {
|
||||
is_srb = 1;
|
||||
rb_id = i+1;
|
||||
goto rb_found;
|
||||
}
|
||||
}
|
||||
|
||||
/* maybe DRB? */
|
||||
for (i = 0; i < 5; i++) {
|
||||
if (entity == ue->drb[i]) {
|
||||
is_srb = 0;
|
||||
rb_id = i+1;
|
||||
goto rb_found;
|
||||
}
|
||||
}
|
||||
|
||||
LOG_E(RLC, "%s:%d:%s: fatal, no RB found for ue %d\n",
|
||||
__FILE__, __LINE__, __FUNCTION__, ue->rnti);
|
||||
exit(1);
|
||||
|
||||
rb_found:
|
||||
LOG_D(RLC, "sdu %d was successfully delivered on %s %d\n",
|
||||
sdu_id,
|
||||
is_srb ? "SRB" : "DRB",
|
||||
rb_id);
|
||||
|
||||
/* TODO: do something for DRBs? */
|
||||
if (is_srb == 0)
|
||||
return;
|
||||
|
||||
is_enb = rlc_manager_get_enb_flag(rlc_ue_manager);
|
||||
if (!is_enb)
|
||||
return;
|
||||
|
||||
msg = itti_alloc_new_message(TASK_RLC_ENB, RLC_SDU_INDICATION);
|
||||
RLC_SDU_INDICATION(msg).rnti = ue->rnti;
|
||||
RLC_SDU_INDICATION(msg).is_successful = 1;
|
||||
RLC_SDU_INDICATION(msg).srb_id = rb_id;
|
||||
RLC_SDU_INDICATION(msg).message_id = sdu_id;
|
||||
/* TODO: accept more than 1 instance? here we send to instance id 0 */
|
||||
itti_send_msg_to_task(TASK_RRC_ENB, 0, msg);
|
||||
}
|
||||
|
||||
static void max_retx_reached(void *_ue, rlc_entity_t *entity)
|
||||
{
|
||||
rlc_ue_t *ue = _ue;
|
||||
int i;
|
||||
int is_srb;
|
||||
int rb_id;
|
||||
MessageDef *msg;
|
||||
int is_enb;
|
||||
|
||||
/* is it SRB? */
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (entity == ue->srb[i]) {
|
||||
is_srb = 1;
|
||||
rb_id = i+1;
|
||||
goto rb_found;
|
||||
}
|
||||
}
|
||||
|
||||
/* maybe DRB? */
|
||||
for (i = 0; i < 5; i++) {
|
||||
if (entity == ue->drb[i]) {
|
||||
is_srb = 0;
|
||||
rb_id = i+1;
|
||||
goto rb_found;
|
||||
}
|
||||
}
|
||||
|
||||
LOG_E(RLC, "%s:%d:%s: fatal, no RB found for ue %d\n",
|
||||
__FILE__, __LINE__, __FUNCTION__, ue->rnti);
|
||||
exit(1);
|
||||
|
||||
rb_found:
|
||||
LOG_D(RLC, "max RETX reached on %s %d\n",
|
||||
is_srb ? "SRB" : "DRB",
|
||||
rb_id);
|
||||
|
||||
/* TODO: do something for DRBs? */
|
||||
if (is_srb == 0)
|
||||
return;
|
||||
|
||||
is_enb = rlc_manager_get_enb_flag(rlc_ue_manager);
|
||||
if (!is_enb)
|
||||
return;
|
||||
|
||||
msg = itti_alloc_new_message(TASK_RLC_ENB, RLC_SDU_INDICATION);
|
||||
RLC_SDU_INDICATION(msg).rnti = ue->rnti;
|
||||
RLC_SDU_INDICATION(msg).is_successful = 0;
|
||||
RLC_SDU_INDICATION(msg).srb_id = rb_id;
|
||||
RLC_SDU_INDICATION(msg).message_id = -1;
|
||||
/* TODO: accept more than 1 instance? here we send to instance id 0 */
|
||||
itti_send_msg_to_task(TASK_RRC_ENB, 0, msg);
|
||||
}
|
||||
|
||||
static void add_srb(int rnti, struct LTE_SRB_ToAddMod *s)
|
||||
{
|
||||
rlc_entity_t *rlc_am;
|
||||
rlc_ue_t *ue;
|
||||
|
||||
struct LTE_SRB_ToAddMod__rlc_Config *r = s->rlc_Config;
|
||||
struct LTE_SRB_ToAddMod__logicalChannelConfig *l = s->logicalChannelConfig;
|
||||
int srb_id = s->srb_Identity;
|
||||
int logical_channel_group;
|
||||
|
||||
int t_reordering;
|
||||
int t_status_prohibit;
|
||||
int t_poll_retransmit;
|
||||
int poll_pdu;
|
||||
int poll_byte;
|
||||
int max_retx_threshold;
|
||||
|
||||
if (srb_id != 1 && srb_id != 2) {
|
||||
LOG_E(RLC, "%s:%d:%s: fatal, bad srb id %d\n",
|
||||
__FILE__, __LINE__, __FUNCTION__, srb_id);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
switch (l->present) {
|
||||
case LTE_SRB_ToAddMod__logicalChannelConfig_PR_explicitValue:
|
||||
logical_channel_group = *l->choice.explicitValue.ul_SpecificParameters->logicalChannelGroup;
|
||||
break;
|
||||
case LTE_SRB_ToAddMod__logicalChannelConfig_PR_defaultValue:
|
||||
/* default value from 36.331 9.2.1 */
|
||||
logical_channel_group = 0;
|
||||
break;
|
||||
default:
|
||||
LOG_E(RLC, "%s:%d:%s: fatal error\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* TODO: accept other values? */
|
||||
if (logical_channel_group != 0) {
|
||||
LOG_E(RLC, "%s:%d:%s: fatal error\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
switch (r->present) {
|
||||
case LTE_SRB_ToAddMod__rlc_Config_PR_explicitValue: {
|
||||
struct LTE_RLC_Config__am *am;
|
||||
if (r->choice.explicitValue.present != LTE_RLC_Config_PR_am) {
|
||||
LOG_E(RLC, "%s:%d:%s: fatal error, must be RLC AM\n",
|
||||
__FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
am = &r->choice.explicitValue.choice.am;
|
||||
t_reordering = decode_t_reordering(am->dl_AM_RLC.t_Reordering);
|
||||
t_status_prohibit = decode_t_status_prohibit(am->dl_AM_RLC.t_StatusProhibit);
|
||||
t_poll_retransmit = decode_t_poll_retransmit(am->ul_AM_RLC.t_PollRetransmit);
|
||||
poll_pdu = decode_poll_pdu(am->ul_AM_RLC.pollPDU);
|
||||
poll_byte = decode_poll_byte(am->ul_AM_RLC.pollByte);
|
||||
max_retx_threshold = decode_max_retx_threshold(am->ul_AM_RLC.maxRetxThreshold);
|
||||
break;
|
||||
}
|
||||
case LTE_SRB_ToAddMod__rlc_Config_PR_defaultValue:
|
||||
/* default values from 36.331 9.2.1 */
|
||||
t_reordering = 35;
|
||||
t_status_prohibit = 0;
|
||||
t_poll_retransmit = 45;
|
||||
poll_pdu = -1;
|
||||
poll_byte = -1;
|
||||
max_retx_threshold = 4;
|
||||
break;
|
||||
default:
|
||||
LOG_E(RLC, "%s:%d:%s: fatal error\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
rlc_manager_lock(rlc_ue_manager);
|
||||
ue = rlc_manager_get_ue(rlc_ue_manager, rnti);
|
||||
if (ue->srb[srb_id-1] != NULL) {
|
||||
LOG_D(RLC, "%s:%d:%s: warning SRB %d already exist for ue %d, do nothing\n",
|
||||
__FILE__, __LINE__, __FUNCTION__, srb_id, rnti);
|
||||
} else {
|
||||
rlc_am = new_rlc_entity_am(100000,
|
||||
100000,
|
||||
deliver_sdu, ue,
|
||||
successful_delivery, ue,
|
||||
max_retx_reached, ue,
|
||||
t_reordering, t_status_prohibit,
|
||||
t_poll_retransmit,
|
||||
poll_pdu, poll_byte, max_retx_threshold);
|
||||
rlc_ue_add_srb_rlc_entity(ue, srb_id, rlc_am);
|
||||
|
||||
LOG_D(RLC, "%s:%d:%s: added srb %d to ue %d\n",
|
||||
__FILE__, __LINE__, __FUNCTION__, srb_id, rnti);
|
||||
}
|
||||
rlc_manager_unlock(rlc_ue_manager);
|
||||
}
|
||||
|
||||
static void add_drb_am(int rnti, struct LTE_DRB_ToAddMod *s)
|
||||
{
|
||||
rlc_entity_t *rlc_am;
|
||||
rlc_ue_t *ue;
|
||||
|
||||
struct LTE_RLC_Config *r = s->rlc_Config;
|
||||
struct LTE_LogicalChannelConfig *l = s->logicalChannelConfig;
|
||||
int drb_id = s->drb_Identity;
|
||||
int channel_id = *s->logicalChannelIdentity;
|
||||
int logical_channel_group;
|
||||
|
||||
int t_reordering;
|
||||
int t_status_prohibit;
|
||||
int t_poll_retransmit;
|
||||
int poll_pdu;
|
||||
int poll_byte;
|
||||
int max_retx_threshold;
|
||||
|
||||
if (!(drb_id >= 1 && drb_id <= 5)) {
|
||||
LOG_E(RLC, "%s:%d:%s: fatal, bad srb id %d\n",
|
||||
__FILE__, __LINE__, __FUNCTION__, drb_id);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (channel_id != drb_id + 2) {
|
||||
LOG_E(RLC, "%s:%d:%s: todo, remove this limitation\n",
|
||||
__FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
logical_channel_group = *l->ul_SpecificParameters->logicalChannelGroup;
|
||||
|
||||
/* TODO: accept other values? */
|
||||
if (logical_channel_group != 1) {
|
||||
LOG_E(RLC, "%s:%d:%s: fatal error\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
switch (r->present) {
|
||||
case LTE_RLC_Config_PR_am: {
|
||||
struct LTE_RLC_Config__am *am;
|
||||
am = &r->choice.am;
|
||||
t_reordering = decode_t_reordering(am->dl_AM_RLC.t_Reordering);
|
||||
t_status_prohibit = decode_t_status_prohibit(am->dl_AM_RLC.t_StatusProhibit);
|
||||
t_poll_retransmit = decode_t_poll_retransmit(am->ul_AM_RLC.t_PollRetransmit);
|
||||
poll_pdu = decode_poll_pdu(am->ul_AM_RLC.pollPDU);
|
||||
poll_byte = decode_poll_byte(am->ul_AM_RLC.pollByte);
|
||||
max_retx_threshold = decode_max_retx_threshold(am->ul_AM_RLC.maxRetxThreshold);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
LOG_E(RLC, "%s:%d:%s: fatal error\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
rlc_manager_lock(rlc_ue_manager);
|
||||
ue = rlc_manager_get_ue(rlc_ue_manager, rnti);
|
||||
if (ue->drb[drb_id-1] != NULL) {
|
||||
LOG_D(RLC, "%s:%d:%s: warning DRB %d already exist for ue %d, do nothing\n",
|
||||
__FILE__, __LINE__, __FUNCTION__, drb_id, rnti);
|
||||
} else {
|
||||
rlc_am = new_rlc_entity_am(1000000,
|
||||
1000000,
|
||||
deliver_sdu, ue,
|
||||
successful_delivery, ue,
|
||||
max_retx_reached, ue,
|
||||
t_reordering, t_status_prohibit,
|
||||
t_poll_retransmit,
|
||||
poll_pdu, poll_byte, max_retx_threshold);
|
||||
rlc_ue_add_drb_rlc_entity(ue, drb_id, rlc_am);
|
||||
|
||||
LOG_D(RLC, "%s:%d:%s: added drb %d to ue %d\n",
|
||||
__FILE__, __LINE__, __FUNCTION__, drb_id, rnti);
|
||||
}
|
||||
rlc_manager_unlock(rlc_ue_manager);
|
||||
}
|
||||
|
||||
static void add_drb_um(int rnti, struct LTE_DRB_ToAddMod *s)
|
||||
{
|
||||
rlc_entity_t *rlc_um;
|
||||
rlc_ue_t *ue;
|
||||
|
||||
struct LTE_RLC_Config *r = s->rlc_Config;
|
||||
struct LTE_LogicalChannelConfig *l = s->logicalChannelConfig;
|
||||
int drb_id = s->drb_Identity;
|
||||
int channel_id = *s->logicalChannelIdentity;
|
||||
int logical_channel_group;
|
||||
|
||||
int t_reordering;
|
||||
int sn_field_length;
|
||||
|
||||
if (!(drb_id >= 1 && drb_id <= 5)) {
|
||||
LOG_E(RLC, "%s:%d:%s: fatal, bad srb id %d\n",
|
||||
__FILE__, __LINE__, __FUNCTION__, drb_id);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (channel_id != drb_id + 2) {
|
||||
LOG_E(RLC, "%s:%d:%s: todo, remove this limitation\n",
|
||||
__FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
logical_channel_group = *l->ul_SpecificParameters->logicalChannelGroup;
|
||||
|
||||
/* TODO: accept other values? */
|
||||
if (logical_channel_group != 1) {
|
||||
LOG_E(RLC, "%s:%d:%s: fatal error\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
switch (r->present) {
|
||||
case LTE_RLC_Config_PR_um_Bi_Directional: {
|
||||
struct LTE_RLC_Config__um_Bi_Directional *um;
|
||||
um = &r->choice.um_Bi_Directional;
|
||||
t_reordering = decode_t_reordering(um->dl_UM_RLC.t_Reordering);
|
||||
if (um->dl_UM_RLC.sn_FieldLength != um->ul_UM_RLC.sn_FieldLength) {
|
||||
LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
sn_field_length = decode_sn_field_length(um->dl_UM_RLC.sn_FieldLength);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
LOG_E(RLC, "%s:%d:%s: fatal error\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
rlc_manager_lock(rlc_ue_manager);
|
||||
ue = rlc_manager_get_ue(rlc_ue_manager, rnti);
|
||||
if (ue->drb[drb_id-1] != NULL) {
|
||||
LOG_D(RLC, "%s:%d:%s: warning DRB %d already exist for ue %d, do nothing\n",
|
||||
__FILE__, __LINE__, __FUNCTION__, drb_id, rnti);
|
||||
} else {
|
||||
rlc_um = new_rlc_entity_um(1000000,
|
||||
1000000,
|
||||
deliver_sdu, ue,
|
||||
t_reordering,
|
||||
sn_field_length);
|
||||
rlc_ue_add_drb_rlc_entity(ue, drb_id, rlc_um);
|
||||
|
||||
LOG_D(RLC, "%s:%d:%s: added drb %d to ue %d\n",
|
||||
__FILE__, __LINE__, __FUNCTION__, drb_id, rnti);
|
||||
}
|
||||
rlc_manager_unlock(rlc_ue_manager);
|
||||
}
|
||||
|
||||
static void add_drb(int rnti, struct LTE_DRB_ToAddMod *s)
|
||||
{
|
||||
switch (s->rlc_Config->present) {
|
||||
case LTE_RLC_Config_PR_am:
|
||||
add_drb_am(rnti, s);
|
||||
break;
|
||||
case LTE_RLC_Config_PR_um_Bi_Directional:
|
||||
add_drb_um(rnti, s);
|
||||
break;
|
||||
default:
|
||||
LOG_E(RLC, "%s:%d:%s: fatal: unhandled DRB type\n",
|
||||
__FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t * const ctxt_pP,
|
||||
const LTE_SRB_ToAddModList_t * const srb2add_listP,
|
||||
const LTE_DRB_ToAddModList_t * const drb2add_listP,
|
||||
const LTE_DRB_ToReleaseList_t * const drb2release_listP
|
||||
#if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0))
|
||||
,const LTE_PMCH_InfoList_r9_t * const pmch_InfoList_r9_pP
|
||||
,const uint32_t sourceL2Id
|
||||
,const uint32_t destinationL2Id
|
||||
#endif
|
||||
)
|
||||
{
|
||||
int rnti = ctxt_pP->rnti;
|
||||
int i;
|
||||
|
||||
if (/*ctxt_pP->enb_flag != 1 ||*/ ctxt_pP->module_id != 0 /*||
|
||||
ctxt_pP->instance != 0 || ctxt_pP->eNB_index != 0 ||
|
||||
ctxt_pP->configured != 1 || ctxt_pP->brOption != 0 */) {
|
||||
LOG_E(RLC, "%s: ctxt_pP not handled (%d %d %d %d %d %d)\n", __FUNCTION__,
|
||||
ctxt_pP->enb_flag , ctxt_pP->module_id, ctxt_pP->instance,
|
||||
ctxt_pP->eNB_index, ctxt_pP->configured, ctxt_pP->brOption);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (pmch_InfoList_r9_pP != NULL) {
|
||||
LOG_E(RLC, "%s: pmch_InfoList_r9_pP not handled\n", __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (drb2release_listP != NULL) {
|
||||
LOG_E(RLC, "%s:%d:%s: TODO\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (srb2add_listP != NULL) {
|
||||
for (i = 0; i < srb2add_listP->list.count; i++) {
|
||||
add_srb(rnti, srb2add_listP->list.array[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (drb2add_listP != NULL) {
|
||||
for (i = 0; i < drb2add_listP->list.count; i++) {
|
||||
add_drb(rnti, drb2add_listP->list.array[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return RLC_OP_STATUS_OK;
|
||||
}
|
||||
|
||||
rlc_op_status_t rrc_rlc_config_req (
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
const srb_flag_t srb_flagP,
|
||||
const MBMS_flag_t mbms_flagP,
|
||||
const config_action_t actionP,
|
||||
const rb_id_t rb_idP,
|
||||
const rlc_info_t rlc_infoP)
|
||||
{
|
||||
rlc_ue_t *ue;
|
||||
int i;
|
||||
|
||||
if (mbms_flagP) {
|
||||
LOG_E(RLC, "%s:%d:%s: todo (mbms not supported)\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
if (actionP != CONFIG_ACTION_REMOVE) {
|
||||
LOG_E(RLC, "%s:%d:%s: todo (only CONFIG_ACTION_REMOVE supported)\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
if (ctxt_pP->module_id) {
|
||||
LOG_E(RLC, "%s:%d:%s: todo (only module_id 0 supported)\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
if ((srb_flagP && !(rb_idP >= 1 && rb_idP <= 2)) ||
|
||||
(!srb_flagP && !(rb_idP >= 1 && rb_idP <= 5))) {
|
||||
LOG_E(RLC, "%s:%d:%s: bad rb_id (%d) (is_srb %d)\n", __FILE__, __LINE__, __FUNCTION__, rb_idP, srb_flagP);
|
||||
exit(1);
|
||||
}
|
||||
rlc_manager_lock(rlc_ue_manager);
|
||||
LOG_D(RLC, "%s:%d:%s: remove rb %d (is_srb %d) for UE %d\n", __FILE__, __LINE__, __FUNCTION__, rb_idP, srb_flagP, ctxt_pP->rnti);
|
||||
ue = rlc_manager_get_ue(rlc_ue_manager, ctxt_pP->rnti);
|
||||
if (srb_flagP) {
|
||||
if (ue->srb[rb_idP-1] != NULL) {
|
||||
ue->srb[rb_idP-1]->delete(ue->srb[rb_idP-1]);
|
||||
ue->srb[rb_idP-1] = NULL;
|
||||
} else
|
||||
LOG_W(RLC, "removing non allocated SRB %d, do nothing\n", rb_idP);
|
||||
} else {
|
||||
if (ue->drb[rb_idP-1] != NULL) {
|
||||
ue->drb[rb_idP-1]->delete(ue->drb[rb_idP-1]);
|
||||
ue->drb[rb_idP-1] = NULL;
|
||||
} else
|
||||
LOG_W(RLC, "removing non allocated DRB %d, do nothing\n", rb_idP);
|
||||
}
|
||||
/* remove UE if it has no more RB configured */
|
||||
for (i = 0; i < 2; i++)
|
||||
if (ue->srb[i] != NULL)
|
||||
break;
|
||||
if (i == 2) {
|
||||
for (i = 0; i < 5; i++)
|
||||
if (ue->drb[i] != NULL)
|
||||
break;
|
||||
if (i == 5)
|
||||
rlc_manager_remove_ue(rlc_ue_manager, ctxt_pP->rnti);
|
||||
}
|
||||
rlc_manager_unlock(rlc_ue_manager);
|
||||
return RLC_OP_STATUS_OK;
|
||||
}
|
||||
|
||||
void rrc_rlc_register_rrc (rrc_data_ind_cb_t rrc_data_indP, rrc_data_conf_cb_t rrc_data_confP)
|
||||
{
|
||||
/* nothing to do */
|
||||
}
|
||||
|
||||
rlc_op_status_t rrc_rlc_remove_ue (const protocol_ctxt_t* const x)
|
||||
{
|
||||
LOG_D(RLC, "%s:%d:%s: remove UE %d\n", __FILE__, __LINE__, __FUNCTION__, x->rnti);
|
||||
rlc_manager_lock(rlc_ue_manager);
|
||||
rlc_manager_remove_ue(rlc_ue_manager, x->rnti);
|
||||
rlc_manager_unlock(rlc_ue_manager);
|
||||
|
||||
return RLC_OP_STATUS_OK;
|
||||
}
|
||||
266
openair2/LAYER2/rlc_v2/rlc_pdu.c
Normal file
266
openair2/LAYER2/rlc_v2/rlc_pdu.c
Normal file
@@ -0,0 +1,266 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#include "rlc_pdu.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "LOG/log.h"
|
||||
|
||||
/**************************************************************************/
|
||||
/* RX PDU segment and segment list */
|
||||
/**************************************************************************/
|
||||
|
||||
rlc_rx_pdu_segment_t *rlc_rx_new_pdu_segment(int sn, int so, int size,
|
||||
int is_last, char *data, int data_offset)
|
||||
{
|
||||
rlc_rx_pdu_segment_t *ret = malloc(sizeof(rlc_rx_pdu_segment_t));
|
||||
if (ret == NULL) {
|
||||
LOG_E(RLC, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
ret->sn = sn;
|
||||
ret->so = so;
|
||||
ret->size = size;
|
||||
ret->is_last = is_last;
|
||||
ret->next = NULL;
|
||||
|
||||
ret->data = malloc(size);
|
||||
if (ret->data == NULL) {
|
||||
LOG_E(RLC, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
memcpy(ret->data, data, size);
|
||||
|
||||
ret->data_offset = data_offset;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void rlc_rx_free_pdu_segment(rlc_rx_pdu_segment_t *pdu_segment)
|
||||
{
|
||||
free(pdu_segment->data);
|
||||
free(pdu_segment);
|
||||
}
|
||||
|
||||
rlc_rx_pdu_segment_t *rlc_rx_pdu_segment_list_add(
|
||||
int (*sn_compare)(void *, int, int), void *sn_compare_data,
|
||||
rlc_rx_pdu_segment_t *list, rlc_rx_pdu_segment_t *pdu_segment)
|
||||
{
|
||||
rlc_rx_pdu_segment_t head;
|
||||
rlc_rx_pdu_segment_t *cur;
|
||||
rlc_rx_pdu_segment_t *prev;
|
||||
|
||||
head.next = list;
|
||||
cur = list;
|
||||
prev = &head;
|
||||
|
||||
/* order is by 'sn', if 'sn' is the same then order is by 'so' */
|
||||
while (cur != NULL) {
|
||||
/* check if 'pdu_segment' is before 'cur' in the list */
|
||||
if (sn_compare(sn_compare_data, cur->sn, pdu_segment->sn) > 0 ||
|
||||
(cur->sn == pdu_segment->sn && cur->so > pdu_segment->so)) {
|
||||
break;
|
||||
}
|
||||
prev = cur;
|
||||
cur = cur->next;
|
||||
}
|
||||
prev->next = pdu_segment;
|
||||
pdu_segment->next = cur;
|
||||
return head.next;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/* TX PDU management */
|
||||
/**************************************************************************/
|
||||
|
||||
rlc_tx_pdu_segment_t *rlc_tx_new_pdu(void)
|
||||
{
|
||||
rlc_tx_pdu_segment_t *ret = calloc(1, sizeof(rlc_tx_pdu_segment_t));
|
||||
if (ret == NULL) {
|
||||
LOG_E(RLC, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
ret->retx_count = -1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void rlc_tx_free_pdu(rlc_tx_pdu_segment_t *pdu)
|
||||
{
|
||||
free(pdu);
|
||||
}
|
||||
|
||||
rlc_tx_pdu_segment_t *rlc_tx_pdu_list_append(rlc_tx_pdu_segment_t *list,
|
||||
rlc_tx_pdu_segment_t *pdu)
|
||||
{
|
||||
rlc_tx_pdu_segment_t head;
|
||||
rlc_tx_pdu_segment_t *cur;
|
||||
|
||||
head.next = list;
|
||||
|
||||
cur = &head;
|
||||
while (cur->next != NULL) {
|
||||
cur = cur->next;
|
||||
}
|
||||
cur->next = pdu;
|
||||
|
||||
return head.next;
|
||||
}
|
||||
|
||||
rlc_tx_pdu_segment_t *rlc_tx_pdu_list_add(
|
||||
int (*sn_compare)(void *, int, int), void *sn_compare_data,
|
||||
rlc_tx_pdu_segment_t *list, rlc_tx_pdu_segment_t *pdu_segment)
|
||||
{
|
||||
rlc_tx_pdu_segment_t head;
|
||||
rlc_tx_pdu_segment_t *cur;
|
||||
rlc_tx_pdu_segment_t *prev;
|
||||
|
||||
head.next = list;
|
||||
cur = list;
|
||||
prev = &head;
|
||||
|
||||
/* order is by 'sn', if 'sn' is the same then order is by 'so' */
|
||||
while (cur != NULL) {
|
||||
/* check if 'pdu_segment' is before 'cur' in the list */
|
||||
if (sn_compare(sn_compare_data, cur->sn, pdu_segment->sn) > 0 ||
|
||||
(cur->sn == pdu_segment->sn && cur->so > pdu_segment->so)) {
|
||||
break;
|
||||
}
|
||||
prev = cur;
|
||||
cur = cur->next;
|
||||
}
|
||||
prev->next = pdu_segment;
|
||||
pdu_segment->next = cur;
|
||||
return head.next;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/* PDU decoder */
|
||||
/**************************************************************************/
|
||||
|
||||
void rlc_pdu_decoder_init(rlc_pdu_decoder_t *decoder, char *buffer, int size)
|
||||
{
|
||||
decoder->error = 0;
|
||||
decoder->byte = 0;
|
||||
decoder->bit = 0;
|
||||
decoder->buffer = buffer;
|
||||
decoder->size = size;
|
||||
}
|
||||
|
||||
static int get_bit(rlc_pdu_decoder_t *decoder)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (decoder->byte >= decoder->size) {
|
||||
decoder->error = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = (decoder->buffer[decoder->byte] >> (7 - decoder->bit)) & 1;
|
||||
|
||||
decoder->bit++;
|
||||
if (decoder->bit == 8) {
|
||||
decoder->bit = 0;
|
||||
decoder->byte++;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int rlc_pdu_decoder_get_bits(rlc_pdu_decoder_t *decoder, int count)
|
||||
{
|
||||
int ret = 0;
|
||||
int i;
|
||||
|
||||
if (count > 31) {
|
||||
LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
ret <<= 1;
|
||||
ret |= get_bit(decoder);
|
||||
if (decoder->error) return -1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void rlc_pdu_decoder_align(rlc_pdu_decoder_t *decoder)
|
||||
{
|
||||
if (decoder->bit) {
|
||||
decoder->bit = 0;
|
||||
decoder->byte++;
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/* PDU encoder */
|
||||
/**************************************************************************/
|
||||
|
||||
void rlc_pdu_encoder_init(rlc_pdu_encoder_t *encoder, char *buffer, int size)
|
||||
{
|
||||
encoder->byte = 0;
|
||||
encoder->bit = 0;
|
||||
encoder->buffer = buffer;
|
||||
encoder->size = size;
|
||||
}
|
||||
|
||||
static void put_bit(rlc_pdu_encoder_t *encoder, int bit)
|
||||
{
|
||||
if (encoder->byte == encoder->size) {
|
||||
LOG_E(RLC, "%s:%d:%s: fatal, buffer full\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
encoder->buffer[encoder->byte] <<= 1;
|
||||
if (bit)
|
||||
encoder->buffer[encoder->byte] |= 1;
|
||||
|
||||
encoder->bit++;
|
||||
if (encoder->bit == 8) {
|
||||
encoder->bit = 0;
|
||||
encoder->byte++;
|
||||
}
|
||||
}
|
||||
|
||||
void rlc_pdu_encoder_put_bits(rlc_pdu_encoder_t *encoder, int value, int count)
|
||||
{
|
||||
int i;
|
||||
int x;
|
||||
|
||||
if (count > 31) {
|
||||
LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
x = 1 << (count - 1);
|
||||
for (i = 0; i < count; i++, x >>= 1)
|
||||
put_bit(encoder, value & x);
|
||||
}
|
||||
|
||||
void rlc_pdu_encoder_align(rlc_pdu_encoder_t *encoder)
|
||||
{
|
||||
while (encoder->bit)
|
||||
put_bit(encoder, 0);
|
||||
}
|
||||
109
openair2/LAYER2/rlc_v2/rlc_pdu.h
Normal file
109
openair2/LAYER2/rlc_v2/rlc_pdu.h
Normal file
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#ifndef _RLC_PDU_H_
|
||||
#define _RLC_PDU_H_
|
||||
|
||||
/**************************************************************************/
|
||||
/* RX PDU segment and segment list */
|
||||
/**************************************************************************/
|
||||
|
||||
typedef struct rlc_rx_pdu_segment_t {
|
||||
int sn;
|
||||
int so;
|
||||
int size;
|
||||
int is_last;
|
||||
char *data;
|
||||
int data_offset;
|
||||
struct rlc_rx_pdu_segment_t *next;
|
||||
} rlc_rx_pdu_segment_t;
|
||||
|
||||
rlc_rx_pdu_segment_t *rlc_rx_new_pdu_segment(int sn, int so, int size,
|
||||
int is_last, char *data, int data_offset);
|
||||
|
||||
void rlc_rx_free_pdu_segment(rlc_rx_pdu_segment_t *pdu_segment);
|
||||
|
||||
rlc_rx_pdu_segment_t *rlc_rx_pdu_segment_list_add(
|
||||
int (*sn_compare)(void *, int, int), void *sn_compare_data,
|
||||
rlc_rx_pdu_segment_t *list, rlc_rx_pdu_segment_t *pdu_segment);
|
||||
|
||||
/**************************************************************************/
|
||||
/* TX PDU management */
|
||||
/**************************************************************************/
|
||||
|
||||
typedef struct rlc_tx_pdu_segment_t {
|
||||
int sn;
|
||||
void *start_sdu; /* real type is rlc_sdu_t * */
|
||||
int sdu_start_byte; /* starting byte in 'start_sdu' */
|
||||
int so; /* starting byte of the segment in full PDU */
|
||||
int data_size; /* number of data bytes (exclude header) */
|
||||
int is_segment;
|
||||
int is_last;
|
||||
int retx_count;
|
||||
struct rlc_tx_pdu_segment_t *next;
|
||||
} rlc_tx_pdu_segment_t;
|
||||
|
||||
rlc_tx_pdu_segment_t *rlc_tx_new_pdu(void);
|
||||
void rlc_tx_free_pdu(rlc_tx_pdu_segment_t *pdu);
|
||||
rlc_tx_pdu_segment_t *rlc_tx_pdu_list_append(rlc_tx_pdu_segment_t *list,
|
||||
rlc_tx_pdu_segment_t *pdu);
|
||||
rlc_tx_pdu_segment_t *rlc_tx_pdu_list_add(
|
||||
int (*sn_compare)(void *, int, int), void *sn_compare_data,
|
||||
rlc_tx_pdu_segment_t *list, rlc_tx_pdu_segment_t *pdu_segment);
|
||||
|
||||
/**************************************************************************/
|
||||
/* PDU decoder */
|
||||
/**************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
int error;
|
||||
int byte; /* next byte to decode */
|
||||
int bit; /* next bit in next byte to decode */
|
||||
char *buffer;
|
||||
int size;
|
||||
} rlc_pdu_decoder_t;
|
||||
|
||||
void rlc_pdu_decoder_init(rlc_pdu_decoder_t *decoder, char *buffer, int size);
|
||||
|
||||
#define rlc_pdu_decoder_in_error(d) ((d)->error == 1)
|
||||
|
||||
int rlc_pdu_decoder_get_bits(rlc_pdu_decoder_t *decoder, int count);
|
||||
|
||||
void rlc_pdu_decoder_align(rlc_pdu_decoder_t *decoder);
|
||||
|
||||
/**************************************************************************/
|
||||
/* PDU encoder */
|
||||
/**************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
int byte; /* next byte to encode */
|
||||
int bit; /* next bit in next byte to encode */
|
||||
char *buffer;
|
||||
int size;
|
||||
} rlc_pdu_encoder_t;
|
||||
|
||||
void rlc_pdu_encoder_init(rlc_pdu_encoder_t *encoder, char *buffer, int size);
|
||||
|
||||
void rlc_pdu_encoder_put_bits(rlc_pdu_encoder_t *encoder, int value, int count);
|
||||
|
||||
void rlc_pdu_encoder_align(rlc_pdu_encoder_t *encoder);
|
||||
|
||||
#endif /* _RLC_PDU_H_ */
|
||||
68
openair2/LAYER2/rlc_v2/rlc_sdu.c
Normal file
68
openair2/LAYER2/rlc_v2/rlc_sdu.c
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#include "rlc_sdu.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "LOG/log.h"
|
||||
|
||||
rlc_sdu_t *rlc_new_sdu(char *buffer, int size, int upper_layer_id)
|
||||
{
|
||||
rlc_sdu_t *ret = calloc(1, sizeof(rlc_sdu_t));
|
||||
if (ret == NULL)
|
||||
goto oom;
|
||||
|
||||
ret->upper_layer_id = upper_layer_id;
|
||||
|
||||
ret->data = malloc(size);
|
||||
if (ret->data == NULL)
|
||||
goto oom;
|
||||
|
||||
memcpy(ret->data, buffer, size);
|
||||
|
||||
ret->size = size;
|
||||
|
||||
return ret;
|
||||
|
||||
oom:
|
||||
LOG_E(RLC, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void rlc_free_sdu(rlc_sdu_t *sdu)
|
||||
{
|
||||
free(sdu->data);
|
||||
free(sdu);
|
||||
}
|
||||
|
||||
void rlc_sdu_list_add(rlc_sdu_t **list, rlc_sdu_t **end, rlc_sdu_t *sdu)
|
||||
{
|
||||
if (*list == NULL) {
|
||||
*list = sdu;
|
||||
*end = sdu;
|
||||
return;
|
||||
}
|
||||
|
||||
(*end)->next = sdu;
|
||||
*end = sdu;
|
||||
}
|
||||
39
openair2/LAYER2/rlc_v2/rlc_sdu.h
Normal file
39
openair2/LAYER2/rlc_v2/rlc_sdu.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#ifndef _RLC_SDU_H_
|
||||
#define _RLC_SDU_H_
|
||||
|
||||
typedef struct rlc_sdu_t {
|
||||
int upper_layer_id;
|
||||
char *data;
|
||||
int size;
|
||||
/* next_byte indicates the starting byte to use to construct a new PDU */
|
||||
int next_byte;
|
||||
int acked_bytes;
|
||||
struct rlc_sdu_t *next;
|
||||
} rlc_sdu_t;
|
||||
|
||||
rlc_sdu_t *rlc_new_sdu(char *buffer, int size, int upper_layer_id);
|
||||
void rlc_free_sdu(rlc_sdu_t *sdu);
|
||||
void rlc_sdu_list_add(rlc_sdu_t **list, rlc_sdu_t **end, rlc_sdu_t *sdu);
|
||||
|
||||
#endif /* _RLC_SDU_H_ */
|
||||
190
openair2/LAYER2/rlc_v2/rlc_ue_manager.c
Normal file
190
openair2/LAYER2/rlc_v2/rlc_ue_manager.c
Normal file
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#include "rlc_ue_manager.h"
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "LOG/log.h"
|
||||
|
||||
typedef struct {
|
||||
pthread_mutex_t lock;
|
||||
rlc_ue_t **ue_list;
|
||||
int ue_count;
|
||||
int enb_flag;
|
||||
} rlc_ue_manager_internal_t;
|
||||
|
||||
rlc_ue_manager_t *new_rlc_ue_manager(int enb_flag)
|
||||
{
|
||||
rlc_ue_manager_internal_t *ret;
|
||||
|
||||
ret = calloc(1, sizeof(rlc_ue_manager_internal_t));
|
||||
if (ret == NULL) {
|
||||
LOG_E(RLC, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (pthread_mutex_init(&ret->lock, NULL)) abort();
|
||||
ret->enb_flag = enb_flag;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int rlc_manager_get_enb_flag(rlc_ue_manager_t *_m)
|
||||
{
|
||||
rlc_ue_manager_internal_t *m = _m;
|
||||
return m->enb_flag;
|
||||
}
|
||||
|
||||
void rlc_manager_lock(rlc_ue_manager_t *_m)
|
||||
{
|
||||
rlc_ue_manager_internal_t *m = _m;
|
||||
if (pthread_mutex_lock(&m->lock)) {
|
||||
LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void rlc_manager_unlock(rlc_ue_manager_t *_m)
|
||||
{
|
||||
rlc_ue_manager_internal_t *m = _m;
|
||||
if (pthread_mutex_unlock(&m->lock)) {
|
||||
LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* must be called with lock acquired */
|
||||
rlc_ue_t *rlc_manager_get_ue(rlc_ue_manager_t *_m, int rnti)
|
||||
{
|
||||
/* TODO: optimze */
|
||||
rlc_ue_manager_internal_t *m = _m;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < m->ue_count; i++)
|
||||
if (m->ue_list[i]->rnti == rnti)
|
||||
return m->ue_list[i];
|
||||
|
||||
LOG_D(RLC, "%s:%d:%s: new UE %d\n", __FILE__, __LINE__, __FUNCTION__, rnti);
|
||||
|
||||
m->ue_count++;
|
||||
m->ue_list = realloc(m->ue_list, sizeof(rlc_ue_t *) * m->ue_count);
|
||||
if (m->ue_list == NULL) {
|
||||
LOG_E(RLC, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
m->ue_list[m->ue_count-1] = calloc(1, sizeof(rlc_ue_t));
|
||||
if (m->ue_list[m->ue_count-1] == NULL) {
|
||||
LOG_E(RLC, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
m->ue_list[m->ue_count-1]->rnti = rnti;
|
||||
|
||||
return m->ue_list[m->ue_count-1];
|
||||
}
|
||||
|
||||
/* must be called with lock acquired */
|
||||
void rlc_manager_remove_ue(rlc_ue_manager_t *_m, int rnti)
|
||||
{
|
||||
rlc_ue_manager_internal_t *m = _m;
|
||||
rlc_ue_t *ue;
|
||||
int i;
|
||||
int j;
|
||||
|
||||
for (i = 0; i < m->ue_count; i++)
|
||||
if (m->ue_list[i]->rnti == rnti)
|
||||
break;
|
||||
|
||||
if (i == m->ue_count) {
|
||||
LOG_D(RLC, "%s:%d:%s: warning: ue %d not found\n",
|
||||
__FILE__, __LINE__, __FUNCTION__,
|
||||
rnti);
|
||||
return;
|
||||
}
|
||||
|
||||
ue = m->ue_list[i];
|
||||
|
||||
for (j = 0; j < 2; j++)
|
||||
if (ue->srb[j] != NULL)
|
||||
ue->srb[j]->delete(ue->srb[j]);
|
||||
|
||||
for (j = 0; j < 5; j++)
|
||||
if (ue->drb[j] != NULL)
|
||||
ue->drb[j]->delete(ue->drb[j]);
|
||||
|
||||
free(ue);
|
||||
|
||||
m->ue_count--;
|
||||
if (m->ue_count == 0) {
|
||||
free(m->ue_list);
|
||||
m->ue_list = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
memmove(&m->ue_list[i], &m->ue_list[i+1],
|
||||
(m->ue_count - i) * sizeof(rlc_ue_t *));
|
||||
m->ue_list = realloc(m->ue_list, m->ue_count * sizeof(rlc_ue_t *));
|
||||
if (m->ue_list == NULL) {
|
||||
LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* must be called with lock acquired */
|
||||
void rlc_ue_add_srb_rlc_entity(rlc_ue_t *ue, int srb_id, rlc_entity_t *entity)
|
||||
{
|
||||
if (srb_id < 1 || srb_id > 2) {
|
||||
LOG_E(RLC, "%s:%d:%s: fatal, bad srb id\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
srb_id--;
|
||||
|
||||
if (ue->srb[srb_id] != NULL) {
|
||||
LOG_E(RLC, "%s:%d:%s: fatal, srb already present\n",
|
||||
__FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ue->srb[srb_id] = entity;
|
||||
}
|
||||
|
||||
/* must be called with lock acquired */
|
||||
void rlc_ue_add_drb_rlc_entity(rlc_ue_t *ue, int drb_id, rlc_entity_t *entity)
|
||||
{
|
||||
if (drb_id < 1 || drb_id > 5) {
|
||||
LOG_E(RLC, "%s:%d:%s: fatal, bad drb id\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
drb_id--;
|
||||
|
||||
if (ue->drb[drb_id] != NULL) {
|
||||
LOG_E(RLC, "%s:%d:%s: fatal, drb already present\n",
|
||||
__FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ue->drb[drb_id] = entity;
|
||||
}
|
||||
60
openair2/LAYER2/rlc_v2/rlc_ue_manager.h
Normal file
60
openair2/LAYER2/rlc_v2/rlc_ue_manager.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#ifndef _RLC_UE_MANAGER_H_
|
||||
#define _RLC_UE_MANAGER_H_
|
||||
|
||||
#include "rlc_entity.h"
|
||||
|
||||
typedef void rlc_ue_manager_t;
|
||||
|
||||
typedef struct rlc_ue_t {
|
||||
int rnti;
|
||||
/* due to openair calling status_ind/data_req, we need to keep this.
|
||||
* To be considered 'hackish'.
|
||||
*/
|
||||
int saved_status_ind_tb_size[2+5];
|
||||
rlc_entity_t *srb[2];
|
||||
rlc_entity_t *drb[5];
|
||||
} rlc_ue_t;
|
||||
|
||||
/***********************************************************************/
|
||||
/* manager functions */
|
||||
/***********************************************************************/
|
||||
|
||||
rlc_ue_manager_t *new_rlc_ue_manager(int enb_flag);
|
||||
|
||||
int rlc_manager_get_enb_flag(rlc_ue_manager_t *m);
|
||||
|
||||
void rlc_manager_lock(rlc_ue_manager_t *m);
|
||||
void rlc_manager_unlock(rlc_ue_manager_t *m);
|
||||
|
||||
rlc_ue_t *rlc_manager_get_ue(rlc_ue_manager_t *m, int rnti);
|
||||
void rlc_manager_remove_ue(rlc_ue_manager_t *m, int rnti);
|
||||
|
||||
/***********************************************************************/
|
||||
/* ue functions */
|
||||
/***********************************************************************/
|
||||
|
||||
void rlc_ue_add_srb_rlc_entity(rlc_ue_t *ue, int srb_id, rlc_entity_t *entity);
|
||||
void rlc_ue_add_drb_rlc_entity(rlc_ue_t *ue, int drb_id, rlc_entity_t *entity);
|
||||
|
||||
#endif /* _RLC_UE_MANAGER_H_ */
|
||||
10
openair2/LAYER2/rlc_v2/tests/LOG/log.h
Normal file
10
openair2/LAYER2/rlc_v2/tests/LOG/log.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#ifndef _LOG_H_
|
||||
#define _LOG_H_
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define LOG_E(x, ...) printf(__VA_ARGS__)
|
||||
#define LOG_D(x, ...) printf(__VA_ARGS__)
|
||||
#define LOG_W(x, ...) printf(__VA_ARGS__)
|
||||
|
||||
#endif /* _LOG_H_ */
|
||||
32
openair2/LAYER2/rlc_v2/tests/Makefile
Normal file
32
openair2/LAYER2/rlc_v2/tests/Makefile
Normal file
@@ -0,0 +1,32 @@
|
||||
CC=gcc
|
||||
CFLAGS=-Wall -g --coverage -I.
|
||||
|
||||
LIB=rlc_entity.o rlc_entity_am.o rlc_entity_um.o rlc_pdu.o rlc_sdu.o
|
||||
|
||||
tests:
|
||||
@./run_tests.sh
|
||||
|
||||
all: clean_run $(TEST).run
|
||||
|
||||
%.run: $(TEST).bin
|
||||
#valgrind ./$(TEST).bin > $(TEST).run_pre 2> $(TEST).valgrind
|
||||
./$(TEST).bin > $(TEST).run_pre
|
||||
grep ^TEST $(TEST).run_pre > $(TEST).run
|
||||
gunzip -c $(TEST).txt.gz > $(TEST).txt
|
||||
diff -q $(TEST).txt $(TEST).run
|
||||
|
||||
$(TEST).bin: $(TEST).o $(LIB)
|
||||
$(CC) $(CFLAGS) -o $@ $^
|
||||
|
||||
%.o: ../%.c
|
||||
$(CC) $(CFLAGS) -I.. -c -o $@ $<
|
||||
|
||||
$(TEST).o: test.c
|
||||
$(CC) $(CFLAGS) -c -o $@ $< -DTEST='"$(TEST).h"'
|
||||
|
||||
clean_run:
|
||||
rm -f $(TEST).run $(TEST).bin $(TEST).o
|
||||
|
||||
clean:
|
||||
rm -f *.o *.bin *.run *.run_pre *.gcov *.gcda *.gcno test*.txt a.out \
|
||||
*.valgrind
|
||||
38
openair2/LAYER2/rlc_v2/tests/README
Normal file
38
openair2/LAYER2/rlc_v2/tests/README
Normal file
@@ -0,0 +1,38 @@
|
||||
To run tests, simply type: make
|
||||
|
||||
Each test is made of:
|
||||
testXX.h definition of the test
|
||||
testXX.txt.gz compressed expected output of the test
|
||||
|
||||
At runtime, we generate:
|
||||
testXX.run actual output of the test
|
||||
|
||||
test.c is the test driving program.
|
||||
|
||||
Only the output lines of the test program starting with "TEST" are
|
||||
stored into testXX.txt and testXX.run.
|
||||
|
||||
A test is considered a success if testXX.txt and testXX.run are equal.
|
||||
|
||||
Only failed tests are reported.
|
||||
|
||||
How to define a new test?
|
||||
|
||||
1 - get the ID
|
||||
|
||||
Look in the file run_tests.sh, the variable test_count gives you
|
||||
the number of existing tests. The ID of your test has to be
|
||||
test_count + 1.
|
||||
|
||||
2 - create files
|
||||
|
||||
Create the file test<ID>.h containing the test, then generate test<ID>.run
|
||||
by running 'make all TEST=test<ID>' and copy test<ID>.run to test<ID>.txt.
|
||||
Then compress this file (gzip -9 test<ID>.txt). Be sure that the output
|
||||
is correct, of course.
|
||||
|
||||
For the file names, replace <ID> by the actual number of the test.
|
||||
For example, if your test ID is 47, then name the files test47.h and
|
||||
test47.txt. And run 'make all TEST=test47' to generate test47.run.
|
||||
|
||||
The available instructions for a test are described at the top of test.c.
|
||||
29
openair2/LAYER2/rlc_v2/tests/make_pdu.c
Normal file
29
openair2/LAYER2/rlc_v2/tests/make_pdu.c
Normal file
@@ -0,0 +1,29 @@
|
||||
/* gcc -Wall make_pdu.c -I.. ../rlc_pdu.c */
|
||||
|
||||
#include "rlc_pdu.h"
|
||||
#include <stdio.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
char out[100];
|
||||
rlc_pdu_encoder_t e;
|
||||
int i;
|
||||
|
||||
rlc_pdu_encoder_init(&e, out, 100);
|
||||
|
||||
rlc_pdu_encoder_put_bits(&e, 0, 1); // D/C
|
||||
rlc_pdu_encoder_put_bits(&e, 0, 3); // CPT
|
||||
rlc_pdu_encoder_put_bits(&e, 0, 10); // ack_sn
|
||||
rlc_pdu_encoder_put_bits(&e, 1, 1); // e1
|
||||
rlc_pdu_encoder_put_bits(&e, 10, 10); // nack_sn
|
||||
rlc_pdu_encoder_put_bits(&e, 0, 1); // e1
|
||||
rlc_pdu_encoder_put_bits(&e, 0, 1); // e2
|
||||
|
||||
rlc_pdu_encoder_align(&e);
|
||||
|
||||
for (i = 0; i < e.byte; i++) printf(" %2.2x", (unsigned char)e.buffer[i]);
|
||||
|
||||
printf("\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
12
openair2/LAYER2/rlc_v2/tests/run_tests.sh
Executable file
12
openair2/LAYER2/rlc_v2/tests/run_tests.sh
Executable file
@@ -0,0 +1,12 @@
|
||||
#!/bin/sh
|
||||
|
||||
test_count=45
|
||||
|
||||
for i in `seq $test_count`
|
||||
do
|
||||
make all TEST=test$i >/dev/null 2>/dev/null
|
||||
if [ $? != 0 ]
|
||||
then
|
||||
echo TEST $i FAILURE
|
||||
fi
|
||||
done
|
||||
433
openair2/LAYER2/rlc_v2/tests/test.c
Normal file
433
openair2/LAYER2/rlc_v2/tests/test.c
Normal file
@@ -0,0 +1,433 @@
|
||||
#include "../rlc_entity.h"
|
||||
#include "../rlc_entity_am.h"
|
||||
#include "../rlc_entity_um.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/*
|
||||
* ENB_AM <rx_maxsize> <tx_maxsize> <t_reordering> <t_status_prohibit>
|
||||
* <t_poll_retransmit> <poll_pdu> <poll_byte> <max_retx_threshold>
|
||||
* create the eNB RLC AM entity with given parameters
|
||||
*
|
||||
* UE_AM <rx_maxsize> <tx_maxsize> <t_reordering> <t_status_prohibit>
|
||||
* <t_poll_retransmit> <poll_pdu> <poll_byte> <max_retx_threshold>
|
||||
* create the UE RLC AM entity with given parameters
|
||||
*
|
||||
* ENB_UM <rx_maxsize> <tx_maxsize> <t_reordering> <sn_field_length>
|
||||
* create the eNB RLC UM entity with given parameters
|
||||
*
|
||||
* UE_UM <rx_maxsize> <tx_maxsize> <t_reordering> <sn_field_length>
|
||||
* create the UE RLC UM entity with given parameters
|
||||
*
|
||||
* TIME <time>
|
||||
* following actions to be performed at time <time>
|
||||
* <time> starts at 1
|
||||
* You must end your test definition with a line 'TIME, -1'.
|
||||
*
|
||||
* ENB_SDU <id> <size>
|
||||
* send an SDU to eNB with id <i> and size <size>
|
||||
* the SDU is [00 01 ... ff 01 ...]
|
||||
* (ie. start byte is 00 then we increment for each byte, loop if needed)
|
||||
*
|
||||
* UE_SDU <id> <size>
|
||||
* same as ENB_SDU but the SDU is sent to the UE
|
||||
*
|
||||
* ENB_PDU <size> <'size' bytes>
|
||||
* send a custom PDU from eNB to UE (eNB does not see this PDU at all)
|
||||
*
|
||||
* UE_PDU <size> <'size' bytes>
|
||||
* send a custom PDU from UE to eNB (UE does not see this PDU at all)
|
||||
*
|
||||
* ENB_PDU_SIZE <size>
|
||||
* set 'enb_pdu_size'
|
||||
*
|
||||
* UE_PDU_SIZE <size>
|
||||
* set 'ue_pdu_size'
|
||||
*
|
||||
* ENB_RECV_FAILS <fails>
|
||||
* set the 'enb_recv_fails' flag to <fails>
|
||||
* (1: recv will fail, 0: recv will succeed)
|
||||
*
|
||||
* UE_RECV_FAILS <fails>
|
||||
* same as ENB_RECV_FAILS but for 'ue_recv_fails'
|
||||
*
|
||||
* MUST_FAIL
|
||||
* to be used as first command after the first TIME to indicate
|
||||
* that the test must fail (ie. exit with non zero, crash not allowed)
|
||||
*
|
||||
* ENB_BUFFER_STATUS
|
||||
* call buffer_status for eNB and print result
|
||||
*
|
||||
* UE_BUFFER_STATUS
|
||||
* call buffer_status for UE and print result
|
||||
*
|
||||
* ENB_DISCARD_SDU <sdu ID>
|
||||
* discards given SDU
|
||||
*
|
||||
* UE_DISCARD_SDU <sdu ID>
|
||||
* discards given SDU
|
||||
*
|
||||
* RE_ESTABLISH
|
||||
* re-establish both eNB and UE
|
||||
*/
|
||||
|
||||
enum action {
|
||||
ENB_AM, UE_AM,
|
||||
ENB_UM, UE_UM,
|
||||
TIME, ENB_SDU, UE_SDU, ENB_PDU, UE_PDU,
|
||||
ENB_PDU_SIZE, UE_PDU_SIZE,
|
||||
ENB_RECV_FAILS, UE_RECV_FAILS,
|
||||
MUST_FAIL,
|
||||
ENB_BUFFER_STATUS, UE_BUFFER_STATUS,
|
||||
ENB_DISCARD_SDU, UE_DISCARD_SDU,
|
||||
RE_ESTABLISH
|
||||
};
|
||||
|
||||
int test[] = {
|
||||
/* TEST is defined at compilation time */
|
||||
#include TEST
|
||||
};
|
||||
|
||||
void deliver_sdu_enb_am(void *deliver_sdu_data, struct rlc_entity_t *_entity,
|
||||
char *buf, int size)
|
||||
{
|
||||
rlc_entity_am_t *entity = (rlc_entity_am_t *)_entity;
|
||||
printf("TEST: ENB: %"PRIu64": deliver SDU size %d [",
|
||||
entity->t_current, size);
|
||||
for (int i = 0; i < size; i++) printf(" %2.2x", (unsigned char)buf[i]);
|
||||
printf("]\n");
|
||||
}
|
||||
|
||||
void deliver_sdu_enb_um(void *deliver_sdu_data, struct rlc_entity_t *_entity,
|
||||
char *buf, int size)
|
||||
{
|
||||
rlc_entity_um_t *entity = (rlc_entity_um_t *)_entity;
|
||||
printf("TEST: ENB: %"PRIu64": deliver SDU size %d [",
|
||||
entity->t_current, size);
|
||||
for (int i = 0; i < size; i++) printf(" %2.2x", (unsigned char)buf[i]);
|
||||
printf("]\n");
|
||||
}
|
||||
|
||||
void successful_delivery_enb(void *successful_delivery_data,
|
||||
rlc_entity_t *_entity, int sdu_id)
|
||||
{
|
||||
rlc_entity_am_t *entity = (rlc_entity_am_t *)_entity;
|
||||
printf("TEST: ENB: %"PRIu64": SDU %d was successfully delivered.\n",
|
||||
entity->t_current, sdu_id);
|
||||
}
|
||||
|
||||
void max_retx_reached_enb(void *max_retx_reached_data, rlc_entity_t *_entity)
|
||||
{
|
||||
rlc_entity_am_t *entity = (rlc_entity_am_t *)_entity;
|
||||
printf("TEST: ENB: %"PRIu64": max RETX reached! radio link failure!\n",
|
||||
entity->t_current);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void deliver_sdu_ue_am(void *deliver_sdu_data, struct rlc_entity_t *_entity,
|
||||
char *buf, int size)
|
||||
{
|
||||
rlc_entity_am_t *entity = (rlc_entity_am_t *)_entity;
|
||||
printf("TEST: UE: %"PRIu64": deliver SDU size %d [",
|
||||
entity->t_current, size);
|
||||
for (int i = 0; i < size; i++) printf(" %2.2x", (unsigned char)buf[i]);
|
||||
printf("]\n");
|
||||
}
|
||||
|
||||
void deliver_sdu_ue_um(void *deliver_sdu_data, struct rlc_entity_t *_entity,
|
||||
char *buf, int size)
|
||||
{
|
||||
rlc_entity_um_t *entity = (rlc_entity_um_t *)_entity;
|
||||
printf("TEST: UE: %"PRIu64": deliver SDU size %d [",
|
||||
entity->t_current, size);
|
||||
for (int i = 0; i < size; i++) printf(" %2.2x", (unsigned char)buf[i]);
|
||||
printf("]\n");
|
||||
}
|
||||
|
||||
void successful_delivery_ue(void *successful_delivery_data,
|
||||
rlc_entity_t *_entity, int sdu_id)
|
||||
{
|
||||
rlc_entity_am_t *entity = (rlc_entity_am_t *)_entity;
|
||||
printf("TEST: UE: %"PRIu64": SDU %d was successfully delivered.\n",
|
||||
entity->t_current, sdu_id);
|
||||
}
|
||||
|
||||
void max_retx_reached_ue(void *max_retx_reached_data, rlc_entity_t *_entity)
|
||||
{
|
||||
rlc_entity_am_t *entity = (rlc_entity_am_t *)_entity;
|
||||
printf("TEST: UE: %"PRIu64", max RETX reached! radio link failure!\n",
|
||||
entity->t_current);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int test_main(void)
|
||||
{
|
||||
rlc_entity_t *enb = NULL;
|
||||
rlc_entity_t *ue = NULL;
|
||||
int i;
|
||||
int k;
|
||||
char *sdu;
|
||||
char *pdu;
|
||||
rlc_entity_buffer_status_t buffer_status;
|
||||
int enb_do_buffer_status = 0;
|
||||
int ue_do_buffer_status = 0;
|
||||
int size;
|
||||
int pos;
|
||||
int next_byte_enb = 0;
|
||||
int next_byte_ue = 0;
|
||||
int enb_recv_fails = 0;
|
||||
int ue_recv_fails = 0;
|
||||
int enb_pdu_size = 1000;
|
||||
int ue_pdu_size = 1000;
|
||||
|
||||
sdu = malloc(16001);
|
||||
pdu = malloc(3000);
|
||||
if (sdu == NULL || pdu == NULL) {
|
||||
printf("out of memory\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (i = 0; i < 16001; i++)
|
||||
sdu[i] = i & 255;
|
||||
|
||||
pos = 0;
|
||||
if (test[pos] != TIME) {
|
||||
printf("%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (i = 1; i < 1000; i++) {
|
||||
if (i == test[pos+1]) {
|
||||
pos += 2;
|
||||
while (test[pos] != TIME)
|
||||
switch (test[pos]) {
|
||||
default: printf("fatal: unknown action\n"); exit(1);
|
||||
case ENB_AM:
|
||||
enb = new_rlc_entity_am(test[pos+1], test[pos+2],
|
||||
deliver_sdu_enb_am, NULL,
|
||||
successful_delivery_enb, NULL,
|
||||
max_retx_reached_enb, NULL,
|
||||
test[pos+3], test[pos+4], test[pos+5],
|
||||
test[pos+6], test[pos+7], test[pos+8]);
|
||||
pos += 9;
|
||||
break;
|
||||
case UE_AM:
|
||||
ue = new_rlc_entity_am(test[pos+1], test[pos+2],
|
||||
deliver_sdu_ue_am, NULL,
|
||||
successful_delivery_ue, NULL,
|
||||
max_retx_reached_ue, NULL,
|
||||
test[pos+3], test[pos+4], test[pos+5],
|
||||
test[pos+6], test[pos+7], test[pos+8]);
|
||||
pos += 9;
|
||||
break;
|
||||
case ENB_UM:
|
||||
enb = new_rlc_entity_um(test[pos+1], test[pos+2],
|
||||
deliver_sdu_enb_um, NULL,
|
||||
test[pos+3], test[pos+4]);
|
||||
pos += 5;
|
||||
break;
|
||||
case UE_UM:
|
||||
ue = new_rlc_entity_um(test[pos+1], test[pos+2],
|
||||
deliver_sdu_ue_um, NULL,
|
||||
test[pos+3], test[pos+4]);
|
||||
pos += 5;
|
||||
break;
|
||||
case ENB_SDU:
|
||||
for (k = 0; k < test[pos+2]; k++, next_byte_enb++)
|
||||
sdu[k] = next_byte_enb;
|
||||
printf("TEST: ENB: %d: recv_sdu (id %d): size %d: [",
|
||||
i, test[pos+1], test[pos+2]);
|
||||
for (k = 0; k < test[pos+2]; k++)
|
||||
printf(" %2.2x", (unsigned char)sdu[k]);
|
||||
printf("]\n");
|
||||
enb->recv_sdu(enb, sdu, test[pos+2], test[pos+1]);
|
||||
pos += 3;
|
||||
break;
|
||||
case UE_SDU:
|
||||
for (k = 0; k < test[pos+2]; k++, next_byte_ue++)
|
||||
sdu[k] = next_byte_ue;
|
||||
printf("TEST: UE: %d: recv_sdu (id %d): size %d: [",
|
||||
i, test[pos+1], test[pos+2]);
|
||||
for (k = 0; k < test[pos+2]; k++)
|
||||
printf(" %2.2x", (unsigned char)sdu[k]);
|
||||
printf("]\n");
|
||||
ue->recv_sdu(ue, sdu, test[pos+2], test[pos+1]);
|
||||
pos += 3;
|
||||
break;
|
||||
case ENB_PDU:
|
||||
for (k = 0; k < test[pos+1]; k++)
|
||||
pdu[k] = test[pos+2+k];
|
||||
printf("TEST: ENB: %d: custom PDU: size %d: [", i, test[pos+1]);
|
||||
for (k = 0; k < test[pos+1]; k++) printf(" %2.2x", (unsigned char)pdu[k]);
|
||||
printf("]\n");
|
||||
if (!ue_recv_fails)
|
||||
ue->recv_pdu(ue, pdu, test[pos+1]);
|
||||
pos += 2 + test[pos+1];
|
||||
break;
|
||||
case UE_PDU:
|
||||
for (k = 0; k < test[pos+1]; k++)
|
||||
pdu[k] = test[pos+2+k];
|
||||
printf("TEST: UE: %d: custom PDU: size %d: [", i, test[pos+1]);
|
||||
for (k = 0; k < test[pos+1]; k++) printf(" %2.2x", (unsigned char)pdu[k]);
|
||||
printf("]\n");
|
||||
if (!enb_recv_fails)
|
||||
enb->recv_pdu(enb, pdu, test[pos+1]);
|
||||
pos += 2 + test[pos+1];
|
||||
break;
|
||||
case ENB_PDU_SIZE:
|
||||
enb_pdu_size = test[pos+1];
|
||||
pos += 2;
|
||||
break;
|
||||
case UE_PDU_SIZE:
|
||||
ue_pdu_size = test[pos+1];
|
||||
pos += 2;
|
||||
break;
|
||||
case ENB_RECV_FAILS:
|
||||
enb_recv_fails = test[pos+1];
|
||||
pos += 2;
|
||||
break;
|
||||
case UE_RECV_FAILS:
|
||||
ue_recv_fails = test[pos+1];
|
||||
pos += 2;
|
||||
break;
|
||||
case MUST_FAIL:
|
||||
/* do nothing, only used by caller */
|
||||
pos++;
|
||||
break;
|
||||
case ENB_BUFFER_STATUS:
|
||||
enb_do_buffer_status = 1;
|
||||
pos++;
|
||||
break;
|
||||
case UE_BUFFER_STATUS:
|
||||
ue_do_buffer_status = 1;
|
||||
pos++;
|
||||
break;
|
||||
case ENB_DISCARD_SDU:
|
||||
printf("TEST: ENB: %d: discard SDU %d\n", i, test[pos+1]);
|
||||
enb->discard_sdu(enb, test[pos+1]);
|
||||
pos += 2;
|
||||
break;
|
||||
case UE_DISCARD_SDU:
|
||||
printf("TEST: UE: %d: discard SDU %d\n", i, test[pos+1]);
|
||||
ue->discard_sdu(ue, test[pos+1]);
|
||||
pos += 2;
|
||||
break;
|
||||
case RE_ESTABLISH:
|
||||
printf("TEST: %d: re-establish eNB and UE\n", i);
|
||||
enb->reestablishment(enb);
|
||||
ue->reestablishment(ue);
|
||||
pos++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
enb->set_time(enb, i);
|
||||
ue->set_time(ue, i);
|
||||
|
||||
if (enb_do_buffer_status) {
|
||||
enb_do_buffer_status = 0;
|
||||
buffer_status = enb->buffer_status(enb, enb_pdu_size);
|
||||
printf("TEST: ENB: %d: buffer_status: status_size %d tx_size %d retx_size %d\n",
|
||||
i,
|
||||
buffer_status.status_size,
|
||||
buffer_status.tx_size,
|
||||
buffer_status.retx_size);
|
||||
}
|
||||
|
||||
size = enb->generate_pdu(enb, pdu, enb_pdu_size);
|
||||
if (size) {
|
||||
printf("TEST: ENB: %d: generate_pdu: size %d: [", i, size);
|
||||
for (k = 0; k < size; k++) printf(" %2.2x", (unsigned char)pdu[k]);
|
||||
printf("]\n");
|
||||
if (!ue_recv_fails)
|
||||
ue->recv_pdu(ue, pdu, size);
|
||||
}
|
||||
|
||||
if (ue_do_buffer_status) {
|
||||
ue_do_buffer_status = 0;
|
||||
buffer_status = ue->buffer_status(ue, ue_pdu_size);
|
||||
printf("TEST: UE: %d: buffer_status: status_size %d tx_size %d retx_size %d\n",
|
||||
i,
|
||||
buffer_status.status_size,
|
||||
buffer_status.tx_size,
|
||||
buffer_status.retx_size);
|
||||
}
|
||||
|
||||
size = ue->generate_pdu(ue, pdu, ue_pdu_size);
|
||||
if (size) {
|
||||
printf("TEST: UE: %d: generate_pdu: size %d: [", i, size);
|
||||
for (k = 0; k < size; k++) printf(" %2.2x", (unsigned char)pdu[k]);
|
||||
printf("]\n");
|
||||
if (!enb_recv_fails)
|
||||
enb->recv_pdu(enb, pdu, size);
|
||||
}
|
||||
}
|
||||
|
||||
enb->delete(enb);
|
||||
ue->delete(ue);
|
||||
|
||||
free(sdu);
|
||||
free(pdu);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void usage(void)
|
||||
{
|
||||
printf("options:\n");
|
||||
printf(" -no-fork\n");
|
||||
printf(" don't fork (to ease debugging with gdb)\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
int main(int n, char **v)
|
||||
{
|
||||
int must_fail = 0;
|
||||
int son;
|
||||
int status;
|
||||
int i;
|
||||
int no_fork = 0;
|
||||
|
||||
for (i = 1; i < n; i++) {
|
||||
if (!strcmp(v[i], "-no-fork")) { no_fork = 1; continue; }
|
||||
usage();
|
||||
}
|
||||
|
||||
if (test[2] == MUST_FAIL)
|
||||
must_fail = 1;
|
||||
|
||||
if (no_fork) return test_main();
|
||||
|
||||
son = fork();
|
||||
if (son == -1) {
|
||||
perror("fork");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (son == 0)
|
||||
return test_main();
|
||||
|
||||
if (wait(&status) == -1) {
|
||||
perror("wait");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* child must quit properly */
|
||||
if (!WIFEXITED(status))
|
||||
return 1;
|
||||
|
||||
/* child must fail if expected to */
|
||||
if (must_fail && WEXITSTATUS(status) == 0)
|
||||
return 1;
|
||||
|
||||
/* child must not fail if not expected to */
|
||||
if (!must_fail && WEXITSTATUS(status))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
14
openair2/LAYER2/rlc_v2/tests/test1.h
Normal file
14
openair2/LAYER2/rlc_v2/tests/test1.h
Normal file
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* basic am test:
|
||||
* at time 1, eNB receives an SDU of 10 bytes
|
||||
* at time 10, UE receives an SDU of 5 bytes
|
||||
*/
|
||||
|
||||
TIME, 1,
|
||||
ENB_AM, 100000, 100000, 35, 0, 45, -1, -1, 4,
|
||||
UE_AM, 100000, 100000, 35, 0, 45, -1, -1, 4,
|
||||
ENB_SDU, 0, 10,
|
||||
UE_BUFFER_STATUS,
|
||||
TIME, 10,
|
||||
UE_SDU, 0, 5,
|
||||
TIME, -1
|
||||
BIN
openair2/LAYER2/rlc_v2/tests/test1.txt.gz
Normal file
BIN
openair2/LAYER2/rlc_v2/tests/test1.txt.gz
Normal file
Binary file not shown.
23
openair2/LAYER2/rlc_v2/tests/test10.h
Normal file
23
openair2/LAYER2/rlc_v2/tests/test10.h
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* rlc am test resegmentation of PDU segment with several SDUs
|
||||
* eNB sends 3 SDUs [1..10] [11.20] [21..30], not received
|
||||
* eNB retx with smaller PDUs, not received
|
||||
* eNB retx with still smaller PDUs, not received
|
||||
* then reception on, all passes
|
||||
*/
|
||||
TIME, 1,
|
||||
ENB_AM, 100000, 100000, 35, 0, 45, -1, -1, 4,
|
||||
UE_AM, 100000, 100000, 35, 0, 45, -1, -1, 4,
|
||||
UE_RECV_FAILS, 1,
|
||||
ENB_RECV_FAILS, 1,
|
||||
ENB_SDU, 0, 10,
|
||||
ENB_SDU, 1, 10,
|
||||
ENB_SDU, 2, 10,
|
||||
TIME, 2,
|
||||
ENB_PDU_SIZE, 25,
|
||||
TIME, 48,
|
||||
ENB_PDU_SIZE, 15,
|
||||
TIME, 100,
|
||||
UE_RECV_FAILS, 0,
|
||||
ENB_RECV_FAILS, 0,
|
||||
TIME, -1
|
||||
BIN
openair2/LAYER2/rlc_v2/tests/test10.txt.gz
Normal file
BIN
openair2/LAYER2/rlc_v2/tests/test10.txt.gz
Normal file
Binary file not shown.
37
openair2/LAYER2/rlc_v2/tests/test11.h
Normal file
37
openair2/LAYER2/rlc_v2/tests/test11.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* rlc am test function rlc_am_reassemble_next_segment
|
||||
* in r->pdu_byte >= r->so + (r->sdu_offset - r->start->data_offset)
|
||||
* + r->sdu_len
|
||||
* when case 'if (r->e)' is false
|
||||
* eNB sends 3 SDUs [1..10] [11.20] [21..30], not received
|
||||
* eNB retx with smaller PDUs, not received
|
||||
* eNB retx with still smaller PDUs, not received
|
||||
* then UE reception on
|
||||
* then custom PDUs, first a small part of head of original PDU
|
||||
* then a bigger part, covering the first part
|
||||
* so that the beginning of this part triggers the 'while'
|
||||
* then eNB reception on, all passes
|
||||
*/
|
||||
TIME, 1,
|
||||
ENB_AM, 100000, 100000, 35, 0, 45, -1, -1, 4,
|
||||
UE_AM, 100000, 100000, 35, 0, 45, -1, -1, 4,
|
||||
UE_RECV_FAILS, 1,
|
||||
ENB_RECV_FAILS, 1,
|
||||
ENB_SDU, 0, 10,
|
||||
ENB_SDU, 1, 10,
|
||||
ENB_SDU, 2, 10,
|
||||
TIME, 2,
|
||||
ENB_PDU_SIZE, 25,
|
||||
TIME, 48,
|
||||
ENB_PDU_SIZE, 15,
|
||||
TIME, 95,
|
||||
ENB_BUFFER_STATUS,
|
||||
TIME, 99,
|
||||
UE_RECV_FAILS, 0,
|
||||
ENB_PDU, 14, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
|
||||
ENB_PDU, 25, 0xec, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12,
|
||||
TIME, 100,
|
||||
ENB_RECV_FAILS, 0,
|
||||
TIME, 134,
|
||||
UE_BUFFER_STATUS,
|
||||
TIME, -1
|
||||
BIN
openair2/LAYER2/rlc_v2/tests/test11.txt.gz
Normal file
BIN
openair2/LAYER2/rlc_v2/tests/test11.txt.gz
Normal file
Binary file not shown.
34
openair2/LAYER2/rlc_v2/tests/test12.h
Normal file
34
openair2/LAYER2/rlc_v2/tests/test12.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* rlc am test function rlc_am_reassemble_next_segment
|
||||
* in r->pdu_byte >= r->so + (r->sdu_offset - r->start->data_offset)
|
||||
* + r->sdu_len
|
||||
* when case 'if (r->e)' is true
|
||||
* eNB sends 4 SDUs [1..5] [6..10] [11.20] [21..30], not received
|
||||
* eNB retx with smaller PDUs, not received
|
||||
* eNB retx with still smaller PDUs, not received
|
||||
* then UE reception on
|
||||
* then custom PDUs, first a small part of head of original PDU
|
||||
* then a bigger part, covering the first part
|
||||
* so that the beginning of this part triggers the 'while'
|
||||
* then eNB reception on, all passes
|
||||
*/
|
||||
TIME, 1,
|
||||
ENB_AM, 100000, 100000, 35, 0, 45, -1, -1, 4,
|
||||
UE_AM, 100000, 100000, 35, 0, 45, -1, -1, 4,
|
||||
UE_RECV_FAILS, 1,
|
||||
ENB_RECV_FAILS, 1,
|
||||
ENB_SDU, 0, 5,
|
||||
ENB_SDU, 1, 5,
|
||||
ENB_SDU, 2, 10,
|
||||
ENB_SDU, 3, 10,
|
||||
TIME, 2,
|
||||
ENB_PDU_SIZE, 25,
|
||||
TIME, 48,
|
||||
ENB_PDU_SIZE, 15,
|
||||
TIME, 99,
|
||||
UE_RECV_FAILS, 0,
|
||||
ENB_PDU, 15, 0xec, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
|
||||
ENB_PDU, 25, 0xec, 0x00, 0x00, 0x00, 0x80, 0x50, 0x05, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
|
||||
TIME, 100,
|
||||
ENB_RECV_FAILS, 0,
|
||||
TIME, -1
|
||||
BIN
openair2/LAYER2/rlc_v2/tests/test12.txt.gz
Normal file
BIN
openair2/LAYER2/rlc_v2/tests/test12.txt.gz
Normal file
Binary file not shown.
30
openair2/LAYER2/rlc_v2/tests/test13.h
Normal file
30
openair2/LAYER2/rlc_v2/tests/test13.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* rlc am test function process_received_ack with something in
|
||||
* the retransmit_list to put in the ack_list
|
||||
* eNB sends 4 PDUs, not received
|
||||
* eNB retransmits 4th PDU, received, ACKed with NACKs for PDU 1, 2, 3
|
||||
* UE receives custom PDU for 1, 2, 3, 4 (they are not sent by eNB)
|
||||
* (4 resent to have the P bit set)
|
||||
* UE sends ACK for all, eNB puts from retransmit_list to ack_list
|
||||
*
|
||||
* Maybe not very realistic (custom PDUs).
|
||||
*/
|
||||
TIME, 1,
|
||||
ENB_AM, 100000, 100000, 35, 0, 45, -1, -1, 4,
|
||||
UE_AM, 100000, 100000, 35, 0, 45, -1, -1, 4,
|
||||
UE_RECV_FAILS, 1,
|
||||
ENB_RECV_FAILS, 1,
|
||||
ENB_PDU_SIZE, 12,
|
||||
ENB_SDU, 0, 10,
|
||||
ENB_SDU, 1, 10,
|
||||
ENB_SDU, 2, 10,
|
||||
ENB_SDU, 3, 10,
|
||||
TIME, 10,
|
||||
UE_RECV_FAILS, 0,
|
||||
ENB_RECV_FAILS, 0,
|
||||
TIME, 87,
|
||||
ENB_PDU, 12, 0x80, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
|
||||
ENB_PDU, 12, 0x80, 0x01, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13,
|
||||
ENB_PDU, 12, 0x80, 0x02, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
|
||||
ENB_PDU, 12, 0xa0, 0x03, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
|
||||
TIME, -1
|
||||
BIN
openair2/LAYER2/rlc_v2/tests/test13.txt.gz
Normal file
BIN
openair2/LAYER2/rlc_v2/tests/test13.txt.gz
Normal file
Binary file not shown.
12
openair2/LAYER2/rlc_v2/tests/test14.h
Normal file
12
openair2/LAYER2/rlc_v2/tests/test14.h
Normal file
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* rlc am test max_retx_reached
|
||||
* eNB sends PDU, never received
|
||||
*/
|
||||
TIME, 1,
|
||||
MUST_FAIL,
|
||||
ENB_AM, 100000, 100000, 35, 0, 45, -1, -1, 4,
|
||||
UE_AM, 100000, 100000, 35, 0, 45, -1, -1, 4,
|
||||
UE_RECV_FAILS, 1,
|
||||
ENB_RECV_FAILS, 1,
|
||||
ENB_SDU, 0, 10,
|
||||
TIME, -1
|
||||
BIN
openair2/LAYER2/rlc_v2/tests/test14.txt.gz
Normal file
BIN
openair2/LAYER2/rlc_v2/tests/test14.txt.gz
Normal file
Binary file not shown.
42
openair2/LAYER2/rlc_v2/tests/test15.h
Normal file
42
openair2/LAYER2/rlc_v2/tests/test15.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* rlc am test so_overlap
|
||||
* eNB sends PDU, not received
|
||||
* then PDU is segmented in 3 parts, part 1 & 3 not received,
|
||||
* then we generate a fake control PDU from UE to eNB that
|
||||
* contains NACK with so_start/so_end being inside part 2.
|
||||
*
|
||||
* code to generate fake control PDU:
|
||||
* rlc_pdu_encoder_init(&e, out, 100);
|
||||
* rlc_pdu_encoder_put_bits(&e, 0, 1); // D/C
|
||||
* rlc_pdu_encoder_put_bits(&e, 0, 3); // CPT
|
||||
* rlc_pdu_encoder_put_bits(&e, 2, 10); // ack_sn
|
||||
* rlc_pdu_encoder_put_bits(&e, 1, 1); // e1
|
||||
* rlc_pdu_encoder_put_bits(&e, 1, 10); // nack_sn
|
||||
* rlc_pdu_encoder_put_bits(&e, 0, 1); // e1
|
||||
* rlc_pdu_encoder_put_bits(&e, 1, 1); // e2
|
||||
* rlc_pdu_encoder_put_bits(&e, 14, 15); // so_start
|
||||
* rlc_pdu_encoder_put_bits(&e, 16, 15); // so_end
|
||||
* rlc_pdu_encoder_align(&e);
|
||||
*/
|
||||
TIME, 1,
|
||||
ENB_AM, 100000, 100000, 35, 0, 45, -1, -1, 4,
|
||||
UE_AM, 100000, 100000, 35, 0, 45, -1, -1, 4,
|
||||
ENB_SDU, 0, 8,
|
||||
ENB_RECV_FAILS, 1,
|
||||
TIME, 2,
|
||||
UE_RECV_FAILS, 1,
|
||||
ENB_SDU, 1, 30,
|
||||
TIME, 20,
|
||||
ENB_PDU_SIZE, 14,
|
||||
TIME, 48,
|
||||
UE_RECV_FAILS, 0,
|
||||
TIME, 49,
|
||||
UE_RECV_FAILS, 1,
|
||||
TIME, 50,
|
||||
UE_RECV_FAILS, 0,
|
||||
TIME, 60,
|
||||
ENB_RECV_FAILS, 0,
|
||||
UE_PDU, 8, 0x00, 0x0a, 0x00, 0xa0, 0x03, 0x80, 0x08, 0x00,
|
||||
TIME, 70,
|
||||
UE_RECV_FAILS, 0,
|
||||
TIME, -1
|
||||
BIN
openair2/LAYER2/rlc_v2/tests/test15.txt.gz
Normal file
BIN
openair2/LAYER2/rlc_v2/tests/test15.txt.gz
Normal file
Binary file not shown.
48
openair2/LAYER2/rlc_v2/tests/test16.h
Normal file
48
openair2/LAYER2/rlc_v2/tests/test16.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* rlc am test process_received_nack
|
||||
* Same events as for test15 except the fake control PDU
|
||||
* does not ACK anything (ack_sn = 0) so that PDU in the
|
||||
* wait_list are not transfered into the ack_list and
|
||||
* we cover the case:
|
||||
* } else {
|
||||
* prev = cur;
|
||||
* cur = cur->next;
|
||||
* }
|
||||
* for the wait_list case.
|
||||
*
|
||||
* code to generate fake control PDU:
|
||||
* rlc_pdu_encoder_init(&e, out, 100);
|
||||
* rlc_pdu_encoder_put_bits(&e, 0, 1); // D/C
|
||||
* rlc_pdu_encoder_put_bits(&e, 0, 3); // CPT
|
||||
* rlc_pdu_encoder_put_bits(&e, 0, 10); // ack_sn
|
||||
* rlc_pdu_encoder_put_bits(&e, 1, 1); // e1
|
||||
* rlc_pdu_encoder_put_bits(&e, 1, 10); // nack_sn
|
||||
* rlc_pdu_encoder_put_bits(&e, 0, 1); // e1
|
||||
* rlc_pdu_encoder_put_bits(&e, 1, 1); // e2
|
||||
* rlc_pdu_encoder_put_bits(&e, 14, 15); // so_start
|
||||
* rlc_pdu_encoder_put_bits(&e, 16, 15); // so_end
|
||||
* rlc_pdu_encoder_align(&e);
|
||||
*/
|
||||
|
||||
TIME, 1,
|
||||
ENB_AM, 100000, 100000, 35, 0, 45, -1, -1, 4,
|
||||
UE_AM, 100000, 100000, 35, 0, 45, -1, -1, 4,
|
||||
ENB_SDU, 0, 8,
|
||||
ENB_RECV_FAILS, 1,
|
||||
TIME, 2,
|
||||
UE_RECV_FAILS, 1,
|
||||
ENB_SDU, 1, 30,
|
||||
TIME, 20,
|
||||
ENB_PDU_SIZE, 14,
|
||||
TIME, 48,
|
||||
UE_RECV_FAILS, 0,
|
||||
TIME, 49,
|
||||
UE_RECV_FAILS, 1,
|
||||
TIME, 50,
|
||||
UE_RECV_FAILS, 0,
|
||||
TIME, 60,
|
||||
ENB_RECV_FAILS, 0,
|
||||
UE_PDU, 8, 0x00, 0x02, 0x00, 0xa0, 0x03, 0x80, 0x08, 0x00,
|
||||
TIME, 70,
|
||||
UE_RECV_FAILS, 0,
|
||||
TIME, -1
|
||||
BIN
openair2/LAYER2/rlc_v2/tests/test16.txt.gz
Normal file
BIN
openair2/LAYER2/rlc_v2/tests/test16.txt.gz
Normal file
Binary file not shown.
30
openair2/LAYER2/rlc_v2/tests/test17.h
Normal file
30
openair2/LAYER2/rlc_v2/tests/test17.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* rlc am test function process_received_nack
|
||||
* case 'check that VT(A) <= sn < VT(S)'
|
||||
* eNB sends PDU, not received, resends segmented
|
||||
* we generate a fake control PDU containing nack_sn == 10,
|
||||
* to fail the 'check ...' and cover the return.
|
||||
*
|
||||
* code to generate fake control PDU:
|
||||
* rlc_pdu_encoder_init(&e, out, 100);
|
||||
* rlc_pdu_encoder_put_bits(&e, 0, 1); // D/C
|
||||
* rlc_pdu_encoder_put_bits(&e, 0, 3); // CPT
|
||||
* rlc_pdu_encoder_put_bits(&e, 0, 10); // ack_sn
|
||||
* rlc_pdu_encoder_put_bits(&e, 1, 1); // e1
|
||||
* rlc_pdu_encoder_put_bits(&e, 10, 10); // nack_sn
|
||||
* rlc_pdu_encoder_put_bits(&e, 0, 1); // e1
|
||||
* rlc_pdu_encoder_put_bits(&e, 0, 1); // e2
|
||||
* rlc_pdu_encoder_align(&e);
|
||||
*/
|
||||
|
||||
TIME, 1,
|
||||
ENB_AM, 100000, 100000, 35, 0, 45, -1, -1, 4,
|
||||
UE_AM, 100000, 100000, 35, 0, 45, -1, -1, 4,
|
||||
ENB_SDU, 0, 30,
|
||||
ENB_RECV_FAILS, 1,
|
||||
TIME, 20,
|
||||
ENB_PDU_SIZE, 14,
|
||||
TIME, 60,
|
||||
ENB_RECV_FAILS, 0,
|
||||
UE_PDU, 4, 0x00, 0x02, 0x05, 0x00,
|
||||
TIME, -1
|
||||
BIN
openair2/LAYER2/rlc_v2/tests/test17.txt.gz
Normal file
BIN
openair2/LAYER2/rlc_v2/tests/test17.txt.gz
Normal file
Binary file not shown.
10
openair2/LAYER2/rlc_v2/tests/test18.h
Normal file
10
openair2/LAYER2/rlc_v2/tests/test18.h
Normal file
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
* test rlc am simulate rx pdu buffer full
|
||||
* eNB sends too big PDU to UE, rejected because buffer full
|
||||
*/
|
||||
TIME, 1,
|
||||
MUST_FAIL,
|
||||
ENB_AM, 100000, 100000, 35, 0, 45, -1, -1, 4,
|
||||
UE_AM, 10, 10, 35, 0, 45, -1, -1, 4,
|
||||
ENB_SDU, 0, 10,
|
||||
TIME, -1
|
||||
BIN
openair2/LAYER2/rlc_v2/tests/test18.txt.gz
Normal file
BIN
openair2/LAYER2/rlc_v2/tests/test18.txt.gz
Normal file
Binary file not shown.
54
openair2/LAYER2/rlc_v2/tests/test19.h
Normal file
54
openair2/LAYER2/rlc_v2/tests/test19.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* test rlc am bad PDU
|
||||
* eNB sends custom PDUs to UE, all of them are wrong for a reason or another
|
||||
*/
|
||||
TIME, 1,
|
||||
ENB_AM, 100000, 100000, 35, 0, 45, -1, -1, 4,
|
||||
UE_AM, 100000, 100000, 35, 0, 45, -1, -1, 4,
|
||||
/* data PDU, LI == 0
|
||||
* rlc_pdu_encoder_put_bits(&e, 1, 1); // D/C
|
||||
* rlc_pdu_encoder_put_bits(&e, 0, 1); // RF
|
||||
* rlc_pdu_encoder_put_bits(&e, 0, 1); // P
|
||||
* rlc_pdu_encoder_put_bits(&e, 0, 2); // FI
|
||||
* rlc_pdu_encoder_put_bits(&e, 1, 1); // E
|
||||
* rlc_pdu_encoder_put_bits(&e, 0, 10); // SN
|
||||
* rlc_pdu_encoder_put_bits(&e, 0, 1); // E
|
||||
* rlc_pdu_encoder_put_bits(&e, 0, 11); // LI
|
||||
*/
|
||||
ENB_PDU, 4, 0x84, 0x00, 0x00, 0x00,
|
||||
/* data PDU, no data
|
||||
* rlc_pdu_encoder_put_bits(&e, 1, 1); // D/C
|
||||
* rlc_pdu_encoder_put_bits(&e, 0, 1); // RF
|
||||
* rlc_pdu_encoder_put_bits(&e, 0, 1); // P
|
||||
* rlc_pdu_encoder_put_bits(&e, 0, 2); // FI
|
||||
* rlc_pdu_encoder_put_bits(&e, 0, 1); // E
|
||||
* rlc_pdu_encoder_put_bits(&e, 0, 10); // SN
|
||||
*/
|
||||
ENB_PDU, 2, 0x80, 0x00,
|
||||
/* data PDU, LI == 2 > data size == 1
|
||||
* rlc_pdu_encoder_put_bits(&e, 1, 1); // D/C
|
||||
* rlc_pdu_encoder_put_bits(&e, 0, 1); // RF
|
||||
* rlc_pdu_encoder_put_bits(&e, 0, 1); // P
|
||||
* rlc_pdu_encoder_put_bits(&e, 0, 2); // FI
|
||||
* rlc_pdu_encoder_put_bits(&e, 1, 1); // E
|
||||
* rlc_pdu_encoder_put_bits(&e, 0, 10); // SN
|
||||
* rlc_pdu_encoder_put_bits(&e, 0, 1); // E
|
||||
* rlc_pdu_encoder_put_bits(&e, 2, 11); // LI
|
||||
* rlc_pdu_encoder_align(&e);
|
||||
* rlc_pdu_encoder_put_bits(&e, 0, 8); // 1 byte of data
|
||||
*/
|
||||
ENB_PDU, 5, 0x84, 0x00, 0x00, 0x20, 0x00,
|
||||
/* control PDU, CPT != 0
|
||||
* rlc_pdu_encoder_put_bits(&e, 0, 1); // D/C
|
||||
* rlc_pdu_encoder_put_bits(&e, 2, 3); // CPT
|
||||
*/
|
||||
ENB_PDU, 1, 0x20,
|
||||
/* data PDU, but only 1 byte
|
||||
* rlc_pdu_encoder_put_bits(&e, 1, 1); // D/C
|
||||
* rlc_pdu_encoder_put_bits(&e, 0, 1); // RF
|
||||
* rlc_pdu_encoder_put_bits(&e, 0, 1); // P
|
||||
* rlc_pdu_encoder_put_bits(&e, 0, 2); // FI
|
||||
* rlc_pdu_encoder_put_bits(&e, 1, 1); // E
|
||||
*/
|
||||
ENB_PDU, 1, 0x84,
|
||||
TIME, -1
|
||||
BIN
openair2/LAYER2/rlc_v2/tests/test19.txt.gz
Normal file
BIN
openair2/LAYER2/rlc_v2/tests/test19.txt.gz
Normal file
Binary file not shown.
10
openair2/LAYER2/rlc_v2/tests/test2.h
Normal file
10
openair2/LAYER2/rlc_v2/tests/test2.h
Normal file
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
* basic am test:
|
||||
* at time 1, eNB receives an SDU of 16000 bytes
|
||||
*/
|
||||
|
||||
TIME, 1,
|
||||
ENB_AM, 100000, 100000, 35, 0, 45, -1, -1, 4,
|
||||
UE_AM, 100000, 100000, 35, 0, 45, -1, -1, 4,
|
||||
ENB_SDU, 0, 16000,
|
||||
TIME, -1
|
||||
BIN
openair2/LAYER2/rlc_v2/tests/test2.txt.gz
Normal file
BIN
openair2/LAYER2/rlc_v2/tests/test2.txt.gz
Normal file
Binary file not shown.
28
openair2/LAYER2/rlc_v2/tests/test20.h
Normal file
28
openair2/LAYER2/rlc_v2/tests/test20.h
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* rlc am test full tx window
|
||||
* for that eNB sends a lot of small PDUs
|
||||
*/
|
||||
TIME, 1,
|
||||
ENB_AM, 100000, 100000, 35, 0, 45, -1, -1, 4,
|
||||
UE_AM, 100000, 100000, 35, 0, 45, -1, -1, 4,
|
||||
ENB_SDU, 0, 513,
|
||||
ENB_PDU_SIZE, 3,
|
||||
ENB_RECV_FAILS, 1,
|
||||
ENB_BUFFER_STATUS,
|
||||
TIME, 511,
|
||||
UE_BUFFER_STATUS,
|
||||
TIME, 512,
|
||||
UE_BUFFER_STATUS,
|
||||
TIME, 513,
|
||||
UE_BUFFER_STATUS,
|
||||
TIME, 557,
|
||||
ENB_BUFFER_STATUS,
|
||||
TIME, 558,
|
||||
ENB_BUFFER_STATUS,
|
||||
TIME, 559,
|
||||
ENB_BUFFER_STATUS,
|
||||
TIME, 600,
|
||||
ENB_BUFFER_STATUS,
|
||||
ENB_RECV_FAILS, 0,
|
||||
TIME, -1
|
||||
|
||||
BIN
openair2/LAYER2/rlc_v2/tests/test20.txt.gz
Normal file
BIN
openair2/LAYER2/rlc_v2/tests/test20.txt.gz
Normal file
Binary file not shown.
18
openair2/LAYER2/rlc_v2/tests/test21.h
Normal file
18
openair2/LAYER2/rlc_v2/tests/test21.h
Normal file
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* rlc am test big SDU (size > 2047)
|
||||
* first generate SDU with exactly 2047 bytes
|
||||
* later on generate SDU with exactly 2048 bytes
|
||||
*/
|
||||
TIME, 1,
|
||||
ENB_AM, 100000, 100000, 35, 0, 45, -1, -1, 4,
|
||||
UE_AM, 100000, 100000, 35, 0, 45, -1, -1, 4,
|
||||
ENB_SDU, 0, 20,
|
||||
ENB_SDU, 1, 2047,
|
||||
ENB_SDU, 2, 20,
|
||||
ENB_PDU_SIZE, 2200,
|
||||
TIME, 10,
|
||||
ENB_SDU, 3, 20,
|
||||
ENB_SDU, 4, 2048,
|
||||
ENB_SDU, 5, 20,
|
||||
TIME, -1
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user