From 3d5170f6a08dca0e58931b09cc8fa0f0699c072b Mon Sep 17 00:00:00 2001 From: Raphael Defosseux Date: Fri, 2 Apr 2021 11:35:02 +0200 Subject: [PATCH 01/12] [CI][Docker] adding no-cache options to make to take executables from Merge Requests Signed-off-by: Raphael Defosseux --- ci-scripts/cls_containerize.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py index 0debe42468..d576ccaa2a 100644 --- a/ci-scripts/cls_containerize.py +++ b/ci-scripts/cls_containerize.py @@ -83,6 +83,7 @@ class Containerize(): self.flexranCtrlDeployed = False self.flexranCtrlIpAddress = '' self.cli = '' + self.cliBuildOptions = '' self.dockerfileprefix = '' self.host = '' self.allImagesSize = {} @@ -124,9 +125,11 @@ class Containerize(): if self.host == 'Ubuntu': self.cli = 'docker' self.dockerfileprefix = '.ubuntu18' + self.cliBuildOptions = '--no-cache' elif self.host == 'Red Hat': self.cli = 'sudo podman' self.dockerfileprefix = '.rhel8.2' + self.cliBuildOptions = '--no-cache --disable-compression' imageNames = [] result = re.search('eNB', self.imageKind) @@ -201,7 +204,7 @@ class Containerize(): # Build the shared image only on Push Events (not on Merge Requests) if (not self.ranAllowMerge): - mySSH.command(self.cli + ' build --target ' + sharedimage + ' --tag ' + sharedimage + ':' + sharedTag + ' --file docker/Dockerfile.ran' + self.dockerfileprefix + ' --build-arg NEEDED_GIT_PROXY="http://proxy.eurecom.fr:8080" . > cmake_targets/log/ran-build.log 2>&1', '\$', 1600) + mySSH.command(self.cli + ' build ' + self.cliBuildOptions + ' --target ' + sharedimage + ' --tag ' + sharedimage + ':' + sharedTag + ' --file docker/Dockerfile.ran' + self.dockerfileprefix + ' --build-arg NEEDED_GIT_PROXY="http://proxy.eurecom.fr:8080" . > cmake_targets/log/ran-build.log 2>&1', '\$', 1600) # First verify if the shared image was properly created. status = True mySSH.command(self.cli + ' image inspect --format=\'Size = {{.Size}} bytes\' ' + sharedimage + ':' + sharedTag, '\$', 5) @@ -249,7 +252,7 @@ class Containerize(): # the archived Dockerfiles have "ran-build:latest" as base image # we need to update them with proper tag mySSH.command('sed -i -e "s#' + sharedimage + ':latest#' + sharedimage + ':' + sharedTag + '#" docker/Dockerfile.' + pattern + self.dockerfileprefix, '\$', 5) - mySSH.command(self.cli + ' build --target ' + image + ' --tag ' + image + ':' + imageTag + ' --file docker/Dockerfile.' + pattern + self.dockerfileprefix + ' . > cmake_targets/log/' + image + '.log 2>&1', '\$', 1200) + mySSH.command(self.cli + ' build ' + self.cliBuildOptions + ' --target ' + image + ' --tag ' + image + ':' + imageTag + ' --file docker/Dockerfile.' + pattern + self.dockerfileprefix + ' . > cmake_targets/log/' + image + '.log 2>&1', '\$', 1200) # split the log mySSH.command('mkdir -p cmake_targets/log/' + image, '\$', 5) mySSH.command('python3 ci-scripts/docker_log_split.py --logfilename=cmake_targets/log/' + image + '.log', '\$', 5) From 1a5f10be90bf9dac9c7d42c645f28c1df642b822 Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Tue, 6 Apr 2021 10:38:28 +0200 Subject: [PATCH 02/12] bugfix: nr: free RA process when UE is removed The bug was: connect a phone, disconnect, repeat five times. The fifth time the phone does not reconnect because there is no free RA process. When an UE is removed, we have to free associated RA processes. --- .../LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 94524795f3..9db78244ba 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -1705,6 +1705,7 @@ void mac_remove_nr_ue(module_id_t mod_id, rnti_t rnti) { int UE_id; int i; + int cc_id; NR_UE_info_t *UE_info = &RC.nrmac[mod_id]->UE_info; for (i = 0; i < MAX_MOBILES_PER_GNB; i++) { @@ -1741,6 +1742,20 @@ void mac_remove_nr_ue(module_id_t mod_id, rnti_t rnti) rnti_to_remove_count++; if (pthread_mutex_unlock(&rnti_to_remove_mutex)) exit(1); } + + /* clear RA process(es?) associated to the UE */ + for (cc_id = 0; cc_id < NFAPI_CC_MAX; cc_id++) { + NR_COMMON_channels_t *cc = &RC.nrmac[mod_id]->common_channels[cc_id]; + for (i = 0; i < NR_NB_RA_PROC_MAX; i++) { + if (cc->ra[i].rnti == rnti) { + LOG_D(MAC, "free RA process %d for rnti %d\n", i, rnti); + /* is it enough? */ + cc->ra[i].cfra = false; + cc->ra[i].rnti = 0; + cc->ra[i].crnti = 0; + } + } + } } uint8_t nr_get_tpc(int target, uint8_t cqi, int incr) { From b263ff15ec55a40418cf2da41f331061f5a7cea7 Mon Sep 17 00:00:00 2001 From: Raphael Defosseux Date: Fri, 2 Apr 2021 14:43:54 +0200 Subject: [PATCH 03/12] [CI] fix the email generation Signed-off-by: Raphael Defosseux --- ci-scripts/Jenkinsfile-GitLab-Container | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/ci-scripts/Jenkinsfile-GitLab-Container b/ci-scripts/Jenkinsfile-GitLab-Container index fbf9ba8f4b..1bd86f2a8e 100644 --- a/ci-scripts/Jenkinsfile-GitLab-Container +++ b/ci-scripts/Jenkinsfile-GitLab-Container @@ -27,6 +27,9 @@ def nodeExecutor = params.nodeExecutor def doMandatoryTests = false def doFullTestsuite = false +// +def gitCommitAuthorEmailAddr + pipeline { agent { label nodeExecutor @@ -158,15 +161,15 @@ pipeline { post { always { script { + def eSubject = JOB_NAME + ' - Build # ' + BUILD_ID + ' - ' + currentBuild.result + '!' + def eBody = "Hi,\n\n" + eBody += "Here are attached HTML report files for " + JOB_NAME + " - Build # " + BUILD_ID + " - " + currentBuild.result + "!\n\n" + eBody += "Regards,\n" + eBody += "OAI CI Team" emailext attachmentsPattern: '*results*.html', - body: '''Hi, - -Here are attached HTML report files for $PROJECT_NAME - Build # $BUILD_NUMBER - $BUILD_STATUS! - -Regards, -OAI CI Team''', + body: eBody, replyTo: 'no-reply@openairinterface.org', - subject: '$PROJECT_NAME - Build # $BUILD_NUMBER - $BUILD_STATUS!', + subject: eSubject, to: gitCommitAuthorEmailAddr if (fileExists('.git/CI_COMMIT_MSG')) { From 2cfc1a6cdbf3cec91f1f053e8a5856e45aa0d42e Mon Sep 17 00:00:00 2001 From: Raphael Defosseux Date: Tue, 6 Apr 2021 17:08:03 +0200 Subject: [PATCH 04/12] [CI] adding new cppcheck docker for container CI operations Signed-off-by: Raphael Defosseux --- ci-scripts/docker/Dockerfile.cppcheck.xenial | 31 ++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 ci-scripts/docker/Dockerfile.cppcheck.xenial diff --git a/ci-scripts/docker/Dockerfile.cppcheck.xenial b/ci-scripts/docker/Dockerfile.cppcheck.xenial new file mode 100644 index 0000000000..0aecc62037 --- /dev/null +++ b/ci-scripts/docker/Dockerfile.cppcheck.xenial @@ -0,0 +1,31 @@ +FROM ubuntu:xenial AS oai-cppcheck + +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update && \ + DEBIAN_FRONTEND=noninteractive apt-get upgrade --yes && \ + DEBIAN_FRONTEND=noninteractive apt-get install --yes \ + build-essential \ + vim \ + cppcheck + +WORKDIR /oai-ran +COPY . . + +WORKDIR /oai-ran/common/utils/T +RUN make + +WORKDIR /oai-ran +RUN mkdir -p cmake_targets/log && \ + cppcheck --enable=warning --force --xml --xml-version=2 \ + -i openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c \ + --suppressions-list=ci-scripts/cppcheck_suppressions.list \ + -I common/utils \ + -I openair3/NAS/COMMON/UTIL \ + -j`nproc` . 2> cmake_targets/log/cppcheck.xml 1> cmake_targets/log/cppcheck_build.txt + +RUN egrep -c 'severity="error' cmake_targets/log/cppcheck.xml + +RUN egrep -c 'severity="warning' cmake_targets/log/cppcheck.xml + +RUN cat cmake_targets/log/cppcheck.xml From d0578d77c8ab1fb2021a923d7da94b70fda834a8 Mon Sep 17 00:00:00 2001 From: Raphael Defosseux Date: Wed, 7 Apr 2021 11:13:17 +0200 Subject: [PATCH 05/12] [CI] cppcheck analysis in the python framework Signed-off-by: Raphael Defosseux --- ci-scripts/args_parse.py | 11 +- ci-scripts/cls_static_code_analysis.py | 192 +++++++++++++++++++++++++ ci-scripts/html.py | 85 +++++++++++ ci-scripts/main.py | 14 +- ci-scripts/xml_class_list.yml | 1 + ci-scripts/xml_files/cppcheck.xml | 37 +++++ 6 files changed, 334 insertions(+), 6 deletions(-) create mode 100644 ci-scripts/cls_static_code_analysis.py create mode 100644 ci-scripts/xml_files/cppcheck.xml diff --git a/ci-scripts/args_parse.py b/ci-scripts/args_parse.py index 248e873cdd..288e0b4885 100644 --- a/ci-scripts/args_parse.py +++ b/ci-scripts/args_parse.py @@ -41,7 +41,7 @@ import constants as CONST #----------------------------------------------------------- -def ArgsParse(argvs,CiTestObj,RAN,HTML,EPC,ldpc,CONTAINERS,HELP): +def ArgsParse(argvs,CiTestObj,RAN,HTML,EPC,ldpc,CONTAINERS,HELP,SCA): py_param_file_present = False @@ -80,6 +80,7 @@ def ArgsParse(argvs,CiTestObj,RAN,HTML,EPC,ldpc,CONTAINERS,HELP): HTML.ranRepository=matchReg.group(1) ldpc.ranRepository=matchReg.group(1) CONTAINERS.ranRepository=matchReg.group(1) + SCA.ranRepository=matchReg.group(1) elif re.match('^\-\-eNB_AllowMerge=(.+)$|^\-\-ranAllowMerge=(.+)$', myArgv, re.IGNORECASE): if re.match('^\-\-eNB_AllowMerge=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNB_AllowMerge=(.+)$', myArgv, re.IGNORECASE) @@ -92,6 +93,7 @@ def ArgsParse(argvs,CiTestObj,RAN,HTML,EPC,ldpc,CONTAINERS,HELP): RAN.ranAllowMerge=True HTML.ranAllowMerge=True CONTAINERS.ranAllowMerge=True + SCA.ranAllowMerge=True elif re.match('^\-\-eNBBranch=(.+)$|^\-\-ranBranch=(.+)$', myArgv, re.IGNORECASE): if re.match('^\-\-eNBBranch=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNBBranch=(.+)$', myArgv, re.IGNORECASE) @@ -102,6 +104,7 @@ def ArgsParse(argvs,CiTestObj,RAN,HTML,EPC,ldpc,CONTAINERS,HELP): HTML.ranBranch=matchReg.group(1) ldpc.ranBranch=matchReg.group(1) CONTAINERS.ranBranch=matchReg.group(1) + SCA.ranBranch=matchReg.group(1) elif re.match('^\-\-eNBCommitID=(.*)$|^\-\-ranCommitID=(.*)$', myArgv, re.IGNORECASE): if re.match('^\-\-eNBCommitID=(.*)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNBCommitID=(.*)$', myArgv, re.IGNORECASE) @@ -112,6 +115,7 @@ def ArgsParse(argvs,CiTestObj,RAN,HTML,EPC,ldpc,CONTAINERS,HELP): HTML.ranCommitID=matchReg.group(1) ldpc.ranCommitID=matchReg.group(1) CONTAINERS.ranCommitID=matchReg.group(1) + SCA.ranCommitID=matchReg.group(1) elif re.match('^\-\-eNBTargetBranch=(.*)$|^\-\-ranTargetBranch=(.*)$', myArgv, re.IGNORECASE): if re.match('^\-\-eNBTargetBranch=(.*)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNBTargetBranch=(.*)$', myArgv, re.IGNORECASE) @@ -122,12 +126,14 @@ def ArgsParse(argvs,CiTestObj,RAN,HTML,EPC,ldpc,CONTAINERS,HELP): HTML.ranTargetBranch=matchReg.group(1) ldpc.ranTargetBranch=matchReg.group(1) CONTAINERS.ranTargetBranch=matchReg.group(1) + SCA.ranTargetBranch=matchReg.group(1) elif re.match('^\-\-eNBIPAddress=(.+)$|^\-\-eNB[1-2]IPAddress=(.+)$', myArgv, re.IGNORECASE): if re.match('^\-\-eNBIPAddress=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNBIPAddress=(.+)$', myArgv, re.IGNORECASE) RAN.eNBIPAddress=matchReg.group(1) ldpc.eNBIpAddr=matchReg.group(1) CONTAINERS.eNBIPAddress=matchReg.group(1) + SCA.eNBIPAddress=matchReg.group(1) elif re.match('^\-\-eNB1IPAddress=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNB1IPAddress=(.+)$', myArgv, re.IGNORECASE) RAN.eNB1IPAddress=matchReg.group(1) @@ -142,6 +148,7 @@ def ArgsParse(argvs,CiTestObj,RAN,HTML,EPC,ldpc,CONTAINERS,HELP): RAN.eNBUserName=matchReg.group(1) ldpc.eNBUserName=matchReg.group(1) CONTAINERS.eNBUserName=matchReg.group(1) + SCA.eNBUserName=matchReg.group(1) elif re.match('^\-\-eNB1UserName=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNB1UserName=(.+)$', myArgv, re.IGNORECASE) RAN.eNB1UserName=matchReg.group(1) @@ -156,6 +163,7 @@ def ArgsParse(argvs,CiTestObj,RAN,HTML,EPC,ldpc,CONTAINERS,HELP): RAN.eNBPassword=matchReg.group(1) ldpc.eNBPassWord=matchReg.group(1) CONTAINERS.eNBPassword=matchReg.group(1) + SCA.eNBPassword=matchReg.group(1) elif re.match('^\-\-eNB1Password=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNB1Password=(.+)$', myArgv, re.IGNORECASE) RAN.eNB1Password=matchReg.group(1) @@ -170,6 +178,7 @@ def ArgsParse(argvs,CiTestObj,RAN,HTML,EPC,ldpc,CONTAINERS,HELP): RAN.eNBSourceCodePath=matchReg.group(1) ldpc.eNBSourceCodePath=matchReg.group(1) CONTAINERS.eNBSourceCodePath=matchReg.group(1) + SCA.eNBSourceCodePath=matchReg.group(1) elif re.match('^\-\-eNB1SourceCodePath=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNB1SourceCodePath=(.+)$', myArgv, re.IGNORECASE) RAN.eNB1SourceCodePath=matchReg.group(1) diff --git a/ci-scripts/cls_static_code_analysis.py b/ci-scripts/cls_static_code_analysis.py new file mode 100644 index 0000000000..521afbffce --- /dev/null +++ b/ci-scripts/cls_static_code_analysis.py @@ -0,0 +1,192 @@ +#/* +# * 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 +# */ +#--------------------------------------------------------------------- +# Python for CI of OAI-eNB + COTS-UE +# +# Required Python Version +# Python 3.x +# +# Required Python Package +# pexpect +#--------------------------------------------------------------------- + +#----------------------------------------------------------- +# Import +#----------------------------------------------------------- +import sys # arg +import re # reg +import logging +import os +import time + +#----------------------------------------------------------- +# OAI Testing modules +#----------------------------------------------------------- +import sshconnection as SSH +import helpreadme as HELP +import constants as CONST + +#----------------------------------------------------------- +# Class Declaration +#----------------------------------------------------------- +class CppCheckResults(): + + def __init__(self): + + self.variants = ['xenial', 'bionic'] + self.versions = ['',''] + self.nbErrors = [0,0] + self.nbWarnings = [0,0] + self.nbNullPtrs = [0,0] + self.nbMemLeaks = [0,0] + self.nbUninitVars = [0,0] + self.nbInvalidPrintf = [0,0] + self.nbModuloAlways = [0,0] + self.nbTooManyBitsShift = [0,0] + self.nbIntegerOverflow = [0,0] + self.nbWrongScanfArg = [0,0] + self.nbPtrAddNotNull = [0,0] + self.nbOppoInnerCondition = [0,0] + +class StaticCodeAnalysis(): + + def __init__(self): + + self.ranRepository = '' + self.ranBranch = '' + self.ranAllowMerge = False + self.ranCommitID = '' + self.ranTargetBranch = '' + self.eNBIPAddress = '' + self.eNBUserName = '' + self.eNBPassword = '' + self.eNBSourceCodePath = '' + + def CppCheckAnalysis(self, HTML): +# if self.ranRepository == '' or self.ranBranch == '' or self.ranCommitID == '': +# HELP.GenericHelp(CONST.Version) +# sys.exit('Insufficient Parameter') +# lIpAddr = self.eNBIPAddress +# lUserName = self.eNBUserName +# lPassWord = self.eNBPassword +# lSourcePath = self.eNBSourceCodePath +# +# if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': +# HELP.GenericHelp(CONST.Version) +# sys.exit('Insufficient Parameter') +# logging.debug('Building on server: ' + lIpAddr) +# mySSH = SSH.SSHConnection() +# mySSH.open(lIpAddr, lUserName, lPassWord) +# +# self.testCase_id = HTML.testCase_id +# +# # on RedHat/CentOS .git extension is mandatory +# result = re.search('([a-zA-Z0-9\:\-\.\/])+\.git', self.ranRepository) +# if result is not None: +# full_ran_repo_name = self.ranRepository +# else: +# full_ran_repo_name = self.ranRepository + '.git' +# mySSH.command('mkdir -p ' + lSourcePath, '\$', 5) +# mySSH.command('cd ' + lSourcePath, '\$', 5) +# mySSH.command('if [ ! -e .git ]; then stdbuf -o0 git clone ' + full_ran_repo_name + ' .; else stdbuf -o0 git fetch --prune; fi', '\$', 600) +# # Raphael: here add a check if git clone or git fetch went smoothly +# mySSH.command('git config user.email "jenkins@openairinterface.org"', '\$', 5) +# mySSH.command('git config user.name "OAI Jenkins"', '\$', 5) +# +# mySSH.command('echo ' + lPassWord + ' | sudo -S git clean -x -d -ff', '\$', 30) +# mySSH.command('mkdir -p cmake_targets/log', '\$', 5) +# # if the commit ID is provided use it to point to it +# if self.ranCommitID != '': +# mySSH.command('git checkout -f ' + self.ranCommitID, '\$', 5) +# +# mySSH.command('docker image rm oai-cppcheck:bionic oai-cppcheck:xenial || true', '\$', 60) +# mySSH.command('docker build --tag oai-cppcheck:xenial --file ci-scripts/docker/Dockerfile.cppcheck.xenial . > cmake_targets/log/cppcheck-xenial.txt 2>&1', '\$', 600) +# mySSH.command('sed -e "s@xenial@bionic@" ci-scripts/docker/Dockerfile.cppcheck.xenial > ci-scripts/docker/Dockerfile.cppcheck.bionic', '\$', 6) +# mySSH.command('docker build --tag oai-cppcheck:bionic --file ci-scripts/docker/Dockerfile.cppcheck.bionic . > cmake_targets/log/cppcheck-bionic.txt 2>&1', '\$', 600) +# mySSH.command('docker image rm oai-cppcheck:bionic oai-cppcheck:xenial || true', '\$', 60) +# +# # Analyzing the logs +# mySSH.command('cd ' + lSourcePath + '/cmake_targets', '\$', 5) +# mySSH.command('mkdir -p build_log_' + self.testCase_id, '\$', 5) +# mySSH.command('mv log/* ' + 'build_log_' + self.testCase_id, '\$', 5) +# mySSH.close() +# +# mySSH.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/build_log_' + self.testCase_id + '/*', '.') + CCR = CppCheckResults() + vId = 0 + for variant in CCR.variants: + if (os.path.isfile('./cppcheck-'+ variant + '.txt')): + xmlStart = False + with open('./cppcheck-'+ variant + '.txt', 'r') as logfile: + for line in logfile: + ret = re.search('Unpacking cppcheck \((?P[0-9\.]+)', str(line)) + if ret is not None: + CCR.versions[vId] = ret.group('version') + if re.search('RUN cat cmake_targets/log/cppcheck.xml', str(line)) is not None: + xmlStart = True + if xmlStart: + if re.search('severity="error"', str(line)) is not None: + CCR.nbErrors[vId] += 1 + if re.search('severity="warning"', str(line)) is not None: + CCR.nbWarnings[vId] += 1 + if re.search('id="memleak"', str(line)) is not None: + CCR.nbMemLeaks[vId] += 1 + if re.search('id="nullPointer"', str(line)) is not None: + CCR.nbNullPtrs[vId] += 1 + if re.search('id="uninitvar"', str(line)) is not None: + CCR.nbUninitVars[vId] += 1 + if re.search('id="invalidPrintfArgType_sint"|id="invalidPrintfArgType_uint"', str(line)) is not None: + CCR.nbInvalidPrintf[vId] += 1 + if re.search('id="moduloAlwaysTrueFalse"', str(line)) is not None: + CCR.nbModuloAlways[vId] += 1 + if re.search('id="shiftTooManyBitsSigned"', str(line)) is not None: + CCR.nbTooManyBitsShift[vId] += 1 + if re.search('id="integerOverflow"', str(line)) is not None: + CCR.nbIntegerOverflow[vId] += 1 + if re.search('id="wrongPrintfScanfArgNum"|id="invalidScanfArgType_int"', str(line)) is not None: + CCR.nbWrongScanfArg[vId] += 1 + if re.search('id="pointerAdditionResultNotNull"', str(line)) is not None: + CCR.nbPtrAddNotNull[vId] += 1 + if re.search('id="oppositeInnerCondition"', str(line)) is not None: + CCR.nbOppoInnerCondition[vId] += 1 + logging.debug('======== Variant ' + variant + ' - ' + CCR.versions[vId] + ' ========') + logging.debug(' ' + str(CCR.nbErrors[vId]) + ' errors') + logging.debug(' ' + str(CCR.nbWarnings[vId]) + ' warnings') + logging.debug(' -- Details --') + logging.debug(' Memory leak: ' + str(CCR.nbMemLeaks[vId])) + logging.debug(' Possible null pointer deference: ' + str(CCR.nbNullPtrs[vId])) + logging.debug(' Uninitialized variable: ' + str(CCR.nbUninitVars[vId])) + logging.debug(' Undefined behaviour shifting: ' + str(CCR.nbTooManyBitsShift[vId])) + logging.debug(' Signed integer overflow: ' + str(CCR.nbIntegerOverflow[vId])) + logging.debug('') + logging.debug(' Printf formatting issue: ' + str(CCR.nbInvalidPrintf[vId])) + logging.debug(' Modulo result is predetermined: ' + str(CCR.nbModuloAlways[vId])) + logging.debug(' Opposite Condition -> dead code: ' + str(CCR.nbOppoInnerCondition[vId])) + logging.debug(' Wrong Scanf Nb Args: ' + str(CCR.nbWrongScanfArg[vId])) + logging.debug('') + vId += 1 + + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) + HTML.CreateHtmlTestRowCppCheckResults(CCR) + logging.info('\u001B[1m Static Code Analysis Pass\u001B[0m') + + return 0 + diff --git a/ci-scripts/html.py b/ci-scripts/html.py index b3ee00e7dc..a0ac638573 100644 --- a/ci-scripts/html.py +++ b/ci-scripts/html.py @@ -479,3 +479,88 @@ class HTMLManagement(): self.htmlFile.write(' \n') self.htmlFile.close() + def CreateHtmlTestRowCppCheckResults(self, CCR): + if (self.htmlFooterCreated or (not self.htmlHeaderCreated)): + return + self.htmlFile = open('test_results.html', 'a') + vId = 0 + for version in CCR.versions: + self.htmlFile.write(' \n') + self.htmlFile.write(' Results for cppcheck v ' + version + ' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' NB ERRORS\n') + if CCR.nbErrors[vId] == 0: + myColor = 'lightgreen' + elif CCR.nbErrors[vId] < 20: + myColor = 'orange' + else: + myColor = 'lightcoral' + self.htmlFile.write(' ' + str(CCR.nbErrors[vId]) + '\n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' NB WARNINGS\n') + if CCR.nbWarnings[vId] == 0: + myColor = 'lightgreen' + elif CCR.nbWarnings[vId] < 20: + myColor = 'orange' + else: + myColor = 'lightcoral' + self.htmlFile.write(' ' + str(CCR.nbWarnings[vId]) + '\n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' ----------------- \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' Memory leak\n') + self.htmlFile.write(' ' + str(CCR.nbMemLeaks[vId]) + '\n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' Possible null pointer deference\n') + self.htmlFile.write(' ' + str(CCR.nbNullPtrs[vId]) + '\n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' Uninitialized variable\n') + self.htmlFile.write(' ' + str(CCR.nbUninitVars[vId]) + '\n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' Undefined behaviour shifting\n') + self.htmlFile.write(' ' + str(CCR.nbTooManyBitsShift[vId]) + '\n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' Signed integer overflow\n') + self.htmlFile.write(' ' + str(CCR.nbIntegerOverflow[vId]) + '\n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' Printf formatting issues\n') + self.htmlFile.write(' ' + str(CCR.nbInvalidPrintf[vId]) + '\n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' Modulo result is predetermined\n') + self.htmlFile.write(' ' + str(CCR.nbModuloAlways[vId]) + '\n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' Opposite Condition -> dead code\n') + self.htmlFile.write(' ' + str(CCR.nbOppoInnerCondition[vId]) + '\n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' Wrong Scanf Nb Args\n') + self.htmlFile.write(' ' + str(CCR.nbWrongScanfArg[vId]) + '\n') + self.htmlFile.write(' \n') + vId += 1 + + self.htmlFile.close() diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 3094197c54..f13df9beb5 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -38,10 +38,11 @@ import helpreadme as HELP import constants as CONST -import cls_oaicitest #main class for OAI CI test framework -import cls_physim #class PhySim for physical simulators build and test -import cls_cots_ue #class CotsUe for Airplane mode control -import cls_containerize #class Containerize for all container-based operations on RAN/UE objects +import cls_oaicitest #main class for OAI CI test framework +import cls_physim #class PhySim for physical simulators build and test +import cls_cots_ue #class CotsUe for Airplane mode control +import cls_containerize #class Containerize for all container-based operations on RAN/UE objects +import cls_static_code_analysis #class for static code analysis import sshconnection @@ -378,6 +379,7 @@ EPC = epc.EPCManagement() RAN = ran.RANManagement() HTML = html.HTMLManagement() CONTAINERS = cls_containerize.Containerize() +SCA = cls_static_code_analysis.StaticCodeAnalysis() ldpc=cls_physim.PhySim() #create an instance for LDPC test using GPU or CPU build @@ -388,7 +390,7 @@ ldpc=cls_physim.PhySim() #create an instance for LDPC test using GPU or CPU b #----------------------------------------------------------- import args_parse -py_param_file_present, py_params, mode = args_parse.ArgsParse(sys.argv,CiTestObj,RAN,HTML,EPC,ldpc,CONTAINERS,HELP) +py_param_file_present, py_params, mode = args_parse.ArgsParse(sys.argv,CiTestObj,RAN,HTML,EPC,ldpc,CONTAINERS,HELP,SCA) @@ -741,6 +743,8 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re CONTAINERS.DeployObject(HTML, EPC) elif action == 'Undeploy_Object': CONTAINERS.UndeployObject(HTML, RAN) + elif action == 'Cppcheck_Analysis': + SCA.CppCheckAnalysis(HTML) else: sys.exit('Invalid class (action) from xml') if not RAN.prematureExit: diff --git a/ci-scripts/xml_class_list.yml b/ci-scripts/xml_class_list.yml index 0e00a2e7d4..de16116124 100755 --- a/ci-scripts/xml_class_list.yml +++ b/ci-scripts/xml_class_list.yml @@ -37,3 +37,4 @@ - Build_Image - Deploy_Object - Undeploy_Object + - Cppcheck_Analysis diff --git a/ci-scripts/xml_files/cppcheck.xml b/ci-scripts/xml_files/cppcheck.xml new file mode 100644 index 0000000000..dd90d88f7e --- /dev/null +++ b/ci-scripts/xml_files/cppcheck.xml @@ -0,0 +1,37 @@ + + + build-tab + CPPCHECK Analysis + wrench + + 000001 + + + + + Cppcheck_Analysis + Static Code Analysis with cppcheck + + + From 6b6df21d35135c0acb366b8b242e47836107abdc Mon Sep 17 00:00:00 2001 From: Raphael Defosseux Date: Wed, 7 Apr 2021 11:35:04 +0200 Subject: [PATCH 06/12] [CI] triggering child pipeline Signed-off-by: Raphael Defosseux --- ci-scripts/Jenkinsfile-GitLab-Container | 19 +++++ ci-scripts/cls_static_code_analysis.py | 98 ++++++++++++------------- 2 files changed, 68 insertions(+), 49 deletions(-) diff --git a/ci-scripts/Jenkinsfile-GitLab-Container b/ci-scripts/Jenkinsfile-GitLab-Container index fbf9ba8f4b..e35fd15fe5 100644 --- a/ci-scripts/Jenkinsfile-GitLab-Container +++ b/ci-scripts/Jenkinsfile-GitLab-Container @@ -152,6 +152,25 @@ pipeline { } } } + stage ("CppCheck Analysis") { + steps { + script { + triggerSlaveJob ('RAN-cppcheck', 'CppCheck Analysis') + } + } + post { + always { + script { + finalizeSlaveJob('RAN-cppcheck') + } + } + failure { + script { + currentBuild.result = 'FAILURE' + } + } + } + } } } } diff --git a/ci-scripts/cls_static_code_analysis.py b/ci-scripts/cls_static_code_analysis.py index 521afbffce..980efb4f8a 100644 --- a/ci-scripts/cls_static_code_analysis.py +++ b/ci-scripts/cls_static_code_analysis.py @@ -81,55 +81,55 @@ class StaticCodeAnalysis(): self.eNBSourceCodePath = '' def CppCheckAnalysis(self, HTML): -# if self.ranRepository == '' or self.ranBranch == '' or self.ranCommitID == '': -# HELP.GenericHelp(CONST.Version) -# sys.exit('Insufficient Parameter') -# lIpAddr = self.eNBIPAddress -# lUserName = self.eNBUserName -# lPassWord = self.eNBPassword -# lSourcePath = self.eNBSourceCodePath -# -# if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': -# HELP.GenericHelp(CONST.Version) -# sys.exit('Insufficient Parameter') -# logging.debug('Building on server: ' + lIpAddr) -# mySSH = SSH.SSHConnection() -# mySSH.open(lIpAddr, lUserName, lPassWord) -# -# self.testCase_id = HTML.testCase_id -# -# # on RedHat/CentOS .git extension is mandatory -# result = re.search('([a-zA-Z0-9\:\-\.\/])+\.git', self.ranRepository) -# if result is not None: -# full_ran_repo_name = self.ranRepository -# else: -# full_ran_repo_name = self.ranRepository + '.git' -# mySSH.command('mkdir -p ' + lSourcePath, '\$', 5) -# mySSH.command('cd ' + lSourcePath, '\$', 5) -# mySSH.command('if [ ! -e .git ]; then stdbuf -o0 git clone ' + full_ran_repo_name + ' .; else stdbuf -o0 git fetch --prune; fi', '\$', 600) -# # Raphael: here add a check if git clone or git fetch went smoothly -# mySSH.command('git config user.email "jenkins@openairinterface.org"', '\$', 5) -# mySSH.command('git config user.name "OAI Jenkins"', '\$', 5) -# -# mySSH.command('echo ' + lPassWord + ' | sudo -S git clean -x -d -ff', '\$', 30) -# mySSH.command('mkdir -p cmake_targets/log', '\$', 5) -# # if the commit ID is provided use it to point to it -# if self.ranCommitID != '': -# mySSH.command('git checkout -f ' + self.ranCommitID, '\$', 5) -# -# mySSH.command('docker image rm oai-cppcheck:bionic oai-cppcheck:xenial || true', '\$', 60) -# mySSH.command('docker build --tag oai-cppcheck:xenial --file ci-scripts/docker/Dockerfile.cppcheck.xenial . > cmake_targets/log/cppcheck-xenial.txt 2>&1', '\$', 600) -# mySSH.command('sed -e "s@xenial@bionic@" ci-scripts/docker/Dockerfile.cppcheck.xenial > ci-scripts/docker/Dockerfile.cppcheck.bionic', '\$', 6) -# mySSH.command('docker build --tag oai-cppcheck:bionic --file ci-scripts/docker/Dockerfile.cppcheck.bionic . > cmake_targets/log/cppcheck-bionic.txt 2>&1', '\$', 600) -# mySSH.command('docker image rm oai-cppcheck:bionic oai-cppcheck:xenial || true', '\$', 60) -# -# # Analyzing the logs -# mySSH.command('cd ' + lSourcePath + '/cmake_targets', '\$', 5) -# mySSH.command('mkdir -p build_log_' + self.testCase_id, '\$', 5) -# mySSH.command('mv log/* ' + 'build_log_' + self.testCase_id, '\$', 5) -# mySSH.close() -# -# mySSH.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/build_log_' + self.testCase_id + '/*', '.') + if self.ranRepository == '' or self.ranBranch == '' or self.ranCommitID == '': + HELP.GenericHelp(CONST.Version) + sys.exit('Insufficient Parameter') + lIpAddr = self.eNBIPAddress + lUserName = self.eNBUserName + lPassWord = self.eNBPassword + lSourcePath = self.eNBSourceCodePath + + if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': + HELP.GenericHelp(CONST.Version) + sys.exit('Insufficient Parameter') + logging.debug('Building on server: ' + lIpAddr) + mySSH = SSH.SSHConnection() + mySSH.open(lIpAddr, lUserName, lPassWord) + + self.testCase_id = HTML.testCase_id + + # on RedHat/CentOS .git extension is mandatory + result = re.search('([a-zA-Z0-9\:\-\.\/])+\.git', self.ranRepository) + if result is not None: + full_ran_repo_name = self.ranRepository + else: + full_ran_repo_name = self.ranRepository + '.git' + mySSH.command('mkdir -p ' + lSourcePath, '\$', 5) + mySSH.command('cd ' + lSourcePath, '\$', 5) + mySSH.command('if [ ! -e .git ]; then stdbuf -o0 git clone ' + full_ran_repo_name + ' .; else stdbuf -o0 git fetch --prune; fi', '\$', 600) + # Raphael: here add a check if git clone or git fetch went smoothly + mySSH.command('git config user.email "jenkins@openairinterface.org"', '\$', 5) + mySSH.command('git config user.name "OAI Jenkins"', '\$', 5) + + mySSH.command('echo ' + lPassWord + ' | sudo -S git clean -x -d -ff', '\$', 30) + mySSH.command('mkdir -p cmake_targets/log', '\$', 5) + # if the commit ID is provided use it to point to it + if self.ranCommitID != '': + mySSH.command('git checkout -f ' + self.ranCommitID, '\$', 5) + + mySSH.command('docker image rm oai-cppcheck:bionic oai-cppcheck:xenial || true', '\$', 60) + mySSH.command('docker build --tag oai-cppcheck:xenial --file ci-scripts/docker/Dockerfile.cppcheck.xenial . > cmake_targets/log/cppcheck-xenial.txt 2>&1', '\$', 600) + mySSH.command('sed -e "s@xenial@bionic@" ci-scripts/docker/Dockerfile.cppcheck.xenial > ci-scripts/docker/Dockerfile.cppcheck.bionic', '\$', 6) + mySSH.command('docker build --tag oai-cppcheck:bionic --file ci-scripts/docker/Dockerfile.cppcheck.bionic . > cmake_targets/log/cppcheck-bionic.txt 2>&1', '\$', 600) + mySSH.command('docker image rm oai-cppcheck:bionic oai-cppcheck:xenial || true', '\$', 60) + + # Analyzing the logs + mySSH.command('cd ' + lSourcePath + '/cmake_targets', '\$', 5) + mySSH.command('mkdir -p build_log_' + self.testCase_id, '\$', 5) + mySSH.command('mv log/* ' + 'build_log_' + self.testCase_id, '\$', 5) + mySSH.close() + + mySSH.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/build_log_' + self.testCase_id + '/*', '.') CCR = CppCheckResults() vId = 0 for variant in CCR.variants: From a4b836ac216f067610f439ddf0085a852291e8c8 Mon Sep 17 00:00:00 2001 From: Raphael Defosseux Date: Wed, 7 Apr 2021 11:39:59 +0200 Subject: [PATCH 07/12] [CI] disabling cppcheck on the old pipeline Signed-off-by: Raphael Defosseux --- ci-scripts/buildOnVM.sh | 2 +- ci-scripts/waitBuildOnVM.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ci-scripts/buildOnVM.sh b/ci-scripts/buildOnVM.sh index 2b1a5e0c71..31e9653769 100755 --- a/ci-scripts/buildOnVM.sh +++ b/ci-scripts/buildOnVM.sh @@ -62,7 +62,7 @@ function build_on_vm { echo "ARCHIVES_LOC = $ARCHIVES_LOC" echo "BUILD_OPTIONS = $BUILD_OPTIONS" - if [[ "$VM_NAME" == *"-enb-usrp"* ]] + if [[ "$VM_NAME" == *"-enb-usrp"* ]] || [[ "$VM_NAME" == *"-cppcheck"* ]] then echo "This VM type is no longer supported in the pipeline framework" return diff --git a/ci-scripts/waitBuildOnVM.sh b/ci-scripts/waitBuildOnVM.sh index ff2129a187..11762f6f4f 100755 --- a/ci-scripts/waitBuildOnVM.sh +++ b/ci-scripts/waitBuildOnVM.sh @@ -47,7 +47,7 @@ function wait_on_vm_build { echo "ARCHIVES_LOC = $ARCHIVES_LOC" echo "BUILD_OPTIONS = $BUILD_OPTIONS" - if [[ "$VM_NAME" == *"-enb-usrp"* ]] + if [[ "$VM_NAME" == *"-enb-usrp"* ]] || [[ "$VM_NAME" == *"-cppcheck"* ]] then echo "This VM type is no longer supported in the pipeline framework" return From 45f6266b5f58000c5121b218b4b70e93459f5259 Mon Sep 17 00:00:00 2001 From: Raphael Defosseux Date: Wed, 7 Apr 2021 12:20:55 +0200 Subject: [PATCH 08/12] [CI] fix Signed-off-by: Raphael Defosseux --- ci-scripts/buildOnRH.sh | 216 ------------------------------------ ci-scripts/createVM.sh | 2 +- ci-scripts/waitBuildOnVM.sh | 5 +- 3 files changed, 5 insertions(+), 218 deletions(-) delete mode 100755 ci-scripts/buildOnRH.sh diff --git a/ci-scripts/buildOnRH.sh b/ci-scripts/buildOnRH.sh deleted file mode 100755 index eaff097c88..0000000000 --- a/ci-scripts/buildOnRH.sh +++ /dev/null @@ -1,216 +0,0 @@ -#!/bin/bash -#/* -# * 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 -# */ - -function usage { - echo "OAI RedHat Build Check script" - echo " Original Author: Raphael Defosseux" - - echo "" - echo "Usage:" - echo "------" - echo " buildOnRH.sh [OPTIONS]" - echo "" - echo "Options:" - echo "--------" - echo " --job-name #### OR -jn ####" - echo " Specify the name of the Jenkins job." - echo "" - echo " --build-id #### OR -id ####" - echo " Specify the build ID of the Jenkins job." - echo "" - echo " --workspace #### OR -ws ####" - echo " Specify the workspace." - echo "" - echo " --remote-host #### OR -rh ####" - echo " Specify the RedHat remote server." - echo "" - echo " --remote-user-name #### OR -ru ####" - echo " Specify the RedHat remote server username." - echo "" - echo " --remote-password #### OR -rp ####" - echo " Specify the RedHat remote server password." - echo "" - echo " --remote-path #### OR -ra ####" - echo " Specify the RedHat remote server path to work on." - echo "" -} - -if [ $# -lt 1 ] || [ $# -gt 14 ] -then - echo "Syntax Error: not the correct number of arguments" - echo "" - usage - exit 1 -fi - -RH_HOST=XX -RH_USER=XX -RH_PASSWD=XX -RH_PATH=XX -JOB_NAME=XX -BUILD_ID=XX - -while [[ $# -gt 0 ]] -do -key="$1" - -case $key in - -h|--help) - shift - usage - exit 0 - ;; - -jn|--job-name) - JOB_NAME="$2" - shift - shift - ;; - -id|--build-id) - BUILD_ID="$2" - shift - shift - ;; - -ws|--workspace) - JENKINS_WKSP="$2" - shift - shift - ;; - -rh|--remote-host) - RH_HOST="$2" - shift - shift - ;; - -ru|--remote-user-name) - RH_USER="$2" - shift - shift - ;; - -rp|--remote-password) - RH_PASSWD="$2" - shift - shift - ;; - -ra|--remote-path) - RH_PATH="$2" - shift - shift - ;; - *) - echo "Syntax Error: unknown option: $key" - echo "" - usage - exit 1 -esac -done - -if [ ! -f $JENKINS_WKSP/localZip.zip ] -then - echo "Missing localZip.zip file!" - exit 1 -fi - -if [ "$JOB_NAME" == "XX" ] || [ "$BUILD_ID" == "XX" ] || [ "$RH_HOST" == "XX" ] || [ "$RH_USER" == "XX" ] || [ "$RH_PASSWD" == "XX" ] || [ "$RH_PATH" == "XX" ] -then - echo "Missing options" - usage - exit 1 -fi - -echo "############################################################" -echo "Copying GIT repo into RedHat Server" -echo "############################################################" -echo "rm -Rf ${RH_PATH}" >> rh-cmd.txt -echo "mkdir -p ${RH_PATH}" >> rh-cmd.txt - -sshpass -p ${RH_PASSWD} ssh -o 'StrictHostKeyChecking no' ${RH_USER}@${RH_HOST} < rh-cmd.txt -rm -f rh-cmd.txt - -echo "############################################################" -echo "Running install and build script on RedHat Server" -echo "############################################################" -sshpass -p ${RH_PASSWD} scp -o 'StrictHostKeyChecking no' $JENKINS_WKSP/localZip.zip ${RH_USER}@${RH_HOST}:${RH_PATH} - -echo "cd ${RH_PATH}" > rh-cmd.txt -echo "unzip -qq localZip.zip" >> rh-cmd.txt -echo "source oaienv" >> rh-cmd.txt -echo "cd cmake_targets" >> rh-cmd.txt -echo "mkdir -p log" >> rh-cmd.txt -echo "./build_oai -I -w USRP --eNB > log/install-build.txt 2>&1" >> rh-cmd.txt -sshpass -p ${RH_PASSWD} ssh -o 'StrictHostKeyChecking no' ${RH_USER}@${RH_HOST} < rh-cmd.txt - -rm -f rh-cmd.txt - -echo "############################################################" -echo "Creating a tmp folder to store results and artifacts" -echo "############################################################" -if [ ! -d $JENKINS_WKSP/archives ] -then - mkdir -p $JENKINS_WKSP/archives -fi - -ARCHIVES_LOC=$JENKINS_WKSP/archives/red_hat -if [ ! -d $ARCHIVES_LOC ] -then - mkdir -p $ARCHIVES_LOC -fi - -sshpass -p ${RH_PASSWD} scp -o 'StrictHostKeyChecking no' ${RH_USER}@${RH_HOST}:${RH_PATH}/cmake_targets/log/*.txt $ARCHIVES_LOC - -echo "############################################################" -echo "Checking build status" -echo "############################################################" - -LOG_PATTERN=.Rel15.txt -NB_PATTERN_FILES=7 - -LOG_FILES=`ls $ARCHIVES_LOC/*.txt` -STATUS=0 -NB_FOUND_FILES=0 - -for FULLFILE in $LOG_FILES -do - if [[ $FULLFILE == *"$LOG_PATTERN"* ]] - then - filename=$(basename -- "$FULLFILE") - PASS_PATTERN=`echo $filename | sed -e "s#$LOG_PATTERN##"` - LOCAL_STAT=`egrep -c "Built target $PASS_PATTERN" $FULLFILE` - if [ $LOCAL_STAT -eq 0 ]; then STATUS=-1; fi - NB_FOUND_FILES=$((NB_FOUND_FILES + 1)) - fi -done - -if [ $NB_PATTERN_FILES -ne $NB_FOUND_FILES ] -then - echo "Expecting $NB_PATTERN_FILES log files and found $NB_FOUND_FILES" - STATUS=-1 -fi - -echo "COMMAND: build_oai -I -w USRP --eNB" > $ARCHIVES_LOC/build_final_status.log -if [ $STATUS -eq 0 ] -then - echo "BUILD_OK" >> $ARCHIVES_LOC/build_final_status.log - echo "STATUS seems OK" -else - echo "BUILD_KO" >> $ARCHIVES_LOC/build_final_status.log - echo "STATUS failed?" -fi -exit $STATUS diff --git a/ci-scripts/createVM.sh b/ci-scripts/createVM.sh index b67668f0bc..ab859c10d7 100755 --- a/ci-scripts/createVM.sh +++ b/ci-scripts/createVM.sh @@ -87,7 +87,7 @@ function create_vm { echo "VM_CPU = $VM_CPU" echo "VM_DISK = $VM_DISK GBytes" - if [[ "$VM_NAME" == *"-enb-usrp"* ]] + if [[ "$VM_NAME" == *"-enb-usrp"* ]] || [[ "$VM_NAME" == *"-cppcheck"* ]] then echo "This VM type is no longer supported in the pipeline framework" return diff --git a/ci-scripts/waitBuildOnVM.sh b/ci-scripts/waitBuildOnVM.sh index 11762f6f4f..f7e300edf4 100755 --- a/ci-scripts/waitBuildOnVM.sh +++ b/ci-scripts/waitBuildOnVM.sh @@ -73,6 +73,9 @@ function wait_on_vm_build { echo "############################################################" echo "Waiting build process to end on VM ($VM_NAME)" echo "############################################################" + # Since the last VM was cppcheck and is removed + # we are going too fast in wait and the build_oai is not yet started + sleep 120 if [[ "$VM_NAME" == *"-cppcheck"* ]] then @@ -90,7 +93,7 @@ function wait_on_vm_build { } function check_on_vm_build { - if [[ "$VM_NAME" == *"-enb-usrp"* ]] + if [[ "$VM_NAME" == *"-enb-usrp"* ]] || [[ "$VM_NAME" == *"-cppcheck"* ]] then echo "This VM type is no longer supported in the pipeline framework" return From 3b187925e8deb672e2c59d7fe3fd817833a8fef5 Mon Sep 17 00:00:00 2001 From: Raphael Defosseux Date: Wed, 7 Apr 2021 13:55:01 +0200 Subject: [PATCH 09/12] [CI] fix cppcheck reporting Signed-off-by: Raphael Defosseux --- ci-scripts/reportBuildLocally.sh | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/ci-scripts/reportBuildLocally.sh b/ci-scripts/reportBuildLocally.sh index 19a486303f..b46ade903f 100755 --- a/ci-scripts/reportBuildLocally.sh +++ b/ci-scripts/reportBuildLocally.sh @@ -568,17 +568,20 @@ function report_build { echo "

Ubuntu 16.04 LTS -- Summary

" >> ./build_results.html - sca_summary_table_header ./archives/cppcheck/cppcheck.xml "OAI Static Code Analysis with CPPCHECK" - sca_summary_table_row ./archives/cppcheck/cppcheck.xml "Uninitialized variable" uninitvar - sca_summary_table_row ./archives/cppcheck/cppcheck.xml "Uninitialized struct member" uninitStructMember - sca_summary_table_row ./archives/cppcheck/cppcheck.xml "Memory leak" memleak - sca_summary_table_row ./archives/cppcheck/cppcheck.xml "Memory is freed twice" doubleFree - sca_summary_table_row ./archives/cppcheck/cppcheck.xml "Resource leak" resourceLeak - sca_summary_table_row ./archives/cppcheck/cppcheck.xml "Possible null pointer dereference" nullPointer - sca_summary_table_row ./archives/cppcheck/cppcheck.xml "Array access out of bounds" arrayIndexOutOfBounds - sca_summary_table_row ./archives/cppcheck/cppcheck.xml "Buffer is accessed out of bounds" bufferAccessOutOfBounds - sca_summary_table_row ./archives/cppcheck/cppcheck.xml "Expression depends on order of evaluation of side effects" unknownEvaluationOrder - sca_summary_table_footer ./archives/cppcheck/cppcheck.xml + if [ -f ./archives/cppcheck/cppcheck.xml ] + then + sca_summary_table_header ./archives/cppcheck/cppcheck.xml "OAI Static Code Analysis with CPPCHECK" + sca_summary_table_row ./archives/cppcheck/cppcheck.xml "Uninitialized variable" uninitvar + sca_summary_table_row ./archives/cppcheck/cppcheck.xml "Uninitialized struct member" uninitStructMember + sca_summary_table_row ./archives/cppcheck/cppcheck.xml "Memory leak" memleak + sca_summary_table_row ./archives/cppcheck/cppcheck.xml "Memory is freed twice" doubleFree + sca_summary_table_row ./archives/cppcheck/cppcheck.xml "Resource leak" resourceLeak + sca_summary_table_row ./archives/cppcheck/cppcheck.xml "Possible null pointer dereference" nullPointer + sca_summary_table_row ./archives/cppcheck/cppcheck.xml "Array access out of bounds" arrayIndexOutOfBounds + sca_summary_table_row ./archives/cppcheck/cppcheck.xml "Buffer is accessed out of bounds" bufferAccessOutOfBounds + sca_summary_table_row ./archives/cppcheck/cppcheck.xml "Expression depends on order of evaluation of side effects" unknownEvaluationOrder + sca_summary_table_footer ./archives/cppcheck/cppcheck.xml + fi # summary_table_header "OAI Build: 4G LTE eNB -- USRP option" ./archives/enb_usrp # summary_table_row "LTE SoftModem - Release 15" ./archives/enb_usrp/lte-softmodem.Rel15.txt "Built target lte-softmodem" ./enb_usrp_row1.html From 25d7eb6c8878b7bcea38b17237a3db97cd4bf6a4 Mon Sep 17 00:00:00 2001 From: Mohammed Ismail Date: Wed, 7 Apr 2021 14:05:54 +0200 Subject: [PATCH 10/12] CI: adding physim imgae build Signed-off-by: Mohammed Ismail --- ci-scripts/cls_containerize.py | 2 + docker/Dockerfile.phySim.rhel8.2 | 123 +++++++++++++++++++++++++++++++ 2 files changed, 125 insertions(+) create mode 100644 docker/Dockerfile.phySim.rhel8.2 diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py index 0debe42468..a835ee01c3 100644 --- a/ci-scripts/cls_containerize.py +++ b/ci-scripts/cls_containerize.py @@ -144,6 +144,8 @@ class Containerize(): imageNames.append(('oai-gnb', 'gNB')) imageNames.append(('oai-lte-ue', 'lteUE')) imageNames.append(('oai-nr-ue', 'nrUE')) + if self.host == 'Red Hat': + imageNames.append(('oai-physim', 'phySim')) if len(imageNames) == 0: imageNames.append(('oai-enb', 'eNB')) diff --git a/docker/Dockerfile.phySim.rhel8.2 b/docker/Dockerfile.phySim.rhel8.2 new file mode 100644 index 0000000000..4472ece363 --- /dev/null +++ b/docker/Dockerfile.phySim.rhel8.2 @@ -0,0 +1,123 @@ +#/* +# * 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 +# */ +#--------------------------------------------------------------------- +# +# Dockerfile for the Open-Air-Interface BUILD service +# Valid for RHEL8 +# +#--------------------------------------------------------------------- + +FROM localhost/ran-build:develop AS phy-sim-build + +RUN rm -Rf /oai-ran +WORKDIR /oai-ran +COPY . . + +#run build_oai to build the target image +RUN /bin/sh oaienv && \ + cd cmake_targets && \ + mkdir -p log && \ + ./build_oai --phy_simulators --ninja --verbose-ci + + +#start from scratch for target executable +FROM registry.access.redhat.com/ubi8/ubi:latest as oai-physim + +RUN yum update -y && \ + yum install -y --enablerepo="ubi-8-codeready-builder" \ + lksctp-tools \ + nettle \ + atlas \ + hostname \ + sudo \ + procps-ng \ + net-tools \ + iputils \ + bc \ + iproute \ + libyaml && \ + echo "/usr/local/lib" > /etc/ld.so.conf.d/local-lib.conf && \ + echo "/usr/local/lib64" >> /etc/ld.so.conf.d/local-lib.conf + +WORKDIR /opt/oai-physim/targets/bin +COPY --from=phy-sim-build /oai-ran/targets/bin/dlsim.Rel15 . +COPY --from=phy-sim-build /oai-ran/targets/bin/nr_dlsim.Rel15 . +COPY --from=phy-sim-build /oai-ran/targets/bin/nr_prachsim.Rel15 . +COPY --from=phy-sim-build /oai-ran/targets/bin/nr_ulschsim.Rel15 . +COPY --from=phy-sim-build /oai-ran/targets/bin/polartest.Rel15 . +COPY --from=phy-sim-build /oai-ran/targets/bin/ulsim.Rel15 . +COPY --from=phy-sim-build /oai-ran/targets/bin/ldpctest.Rel15 . +COPY --from=phy-sim-build /oai-ran/targets/bin/nr_dlschsim.Rel15 . +COPY --from=phy-sim-build /oai-ran/targets/bin/nr_pbchsim.Rel15 . +COPY --from=phy-sim-build /oai-ran/targets/bin/nr_pucchsim.Rel15 . +COPY --from=phy-sim-build /oai-ran/targets/bin/nr_ulsim.Rel15 . +COPY --from=phy-sim-build /oai-ran/targets/bin/smallblocktest.Rel15 . + +WORKDIR /usr/local/lib/ +COPY --from=phy-sim-build /oai-ran/targets/bin/libcoding.so . +COPY --from=phy-sim-build /lib64/liblapacke.so.3 . +COPY --from=phy-sim-build /lib64/libX11.so.6 . +COPY --from=phy-sim-build /lib64/libXpm.so.4 . +COPY --from=phy-sim-build /lib64/libxcb.so.1 . +COPY --from=phy-sim-build /lib64/libXau.so.6 . +COPY --from=phy-sim-build /lib64/libforms.so.2 . +COPY --from=phy-sim-build /lib64/libblas.so.3 . +COPY --from=phy-sim-build /lib64/liblapack.so.3 . +COPY --from=phy-sim-build /lib64/libexslt.so.0 . +COPY --from=phy-sim-build /lib64/libxslt.so.1 . +COPY --from=phy-sim-build /oai-ran/cmake_targets/phy_simulators/build/libdfts.so . +COPY --from=phy-sim-build /oai-ran/cmake_targets/phy_simulators/build/libSIMU.so . +COPY --from=phy-sim-build /oai-ran/cmake_targets/phy_simulators/build/libldpc.so . +COPY --from=phy-sim-build /oai-ran/cmake_targets/phy_simulators/build/libldpc_orig.so . + +RUN ldconfig + +#debug +#RUN ldd /opt/oai-physim/targets/bin/dlsim.Rel15 +#RUN ldd /opt/oai-physim/targets/bin/nr_dlsim.Rel15 +#RUN ldd /opt/oai-physim/targets/bin/nr_prachsim.Rel15 +#RUN ldd /opt/oai-physim/targets/bin/nr_ulschsim.Rel15 +#RUN ldd /opt/oai-physim/targets/bin/polartest.Rel15 +#RUN ldd /opt/oai-physim/targets/bin/ulsim.Rel15 +#RUN ldd /opt/oai-physim/targets/bin/ldpctest.Rel15 +#RUN ldd /opt/oai-physim/targets/bin/nr_dlschsim.Rel15 +#RUN ldd /opt/oai-physim/targets/bin/nr_pbchsim.Rel15 +#RUN ldd /opt/oai-physim/targets/bin/nr_pucchsim.Rel15 +#RUN ldd /opt/oai-physim/targets/bin/nr_ulsim.Rel15 +#RUN ldd /opt/oai-physim/targets/bin/smallblocktest.Rel15 + +# Copy some executables +WORKDIR /usr/bin/ + +COPY --from=phy-sim-build /usr/bin/killall . +COPY --from=phy-sim-build /usr/bin/xmlstarlet . +COPY --from=phy-sim-build /usr/bin/svn . + +# Copy the relevant configuration files for phySim +WORKDIR /opt/oai-physim/ + +COPY --from=phy-sim-build /oai-ran/cmake_targets/autotests/run_exec_autotests.bash /opt/oai-physim/cmake_targets/autotests/ +COPY --from=phy-sim-build /oai-ran/cmake_targets/autotests/test_case_list.xml /opt/oai-physim/cmake_targets/autotests/ +COPY --from=phy-sim-build /oai-ran/cmake_targets/autotests/tools/free_mem.bash /opt/oai-physim/cmake_targets/autotests/tools/ +COPY --from=phy-sim-build /oai-ran/cmake_targets/tools/build_helper /opt/oai-physim/cmake_targets/tools/ +COPY --from=phy-sim-build /oai-ran/cmake_targets/tools/test_helper /opt/oai-physim/cmake_targets/tools/ + +#CMD ["sleep", "infinity"] From 650645f8833be5fd1207b02e05e5e1dc9b132a38 Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Wed, 7 Apr 2021 14:20:10 +0000 Subject: [PATCH 11/12] NR_UE: send tick to RLC and PDCP every ms --- executables/nr-ue.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/executables/nr-ue.c b/executables/nr-ue.c index 47ddd7896e..2adf373196 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -332,6 +332,14 @@ void processSlotRX( PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc) { protocol_ctxt_t ctxt; PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, UE->Mod_id, ENB_FLAG_NO, mac->crnti, proc->frame_rx, proc->nr_slot_rx, 0); pdcp_run(&ctxt); + + /* send tick to RLC and PDCP every ms */ + if (proc->nr_slot_rx % UE->frame_parms.slots_per_subframe == 0) { + void nr_rlc_tick(int frame, int subframe); + void nr_pdcp_tick(int frame, int subframe); + nr_rlc_tick(proc->frame_rx, proc->nr_slot_rx / UE->frame_parms.slots_per_subframe); + nr_pdcp_tick(proc->frame_rx, proc->nr_slot_rx / UE->frame_parms.slots_per_subframe); + } } } From 5c2a5fd74d3fcfc61a06135c0ca3effda44f93e4 Mon Sep 17 00:00:00 2001 From: Raphael Defosseux Date: Thu, 8 Apr 2021 10:30:03 +0200 Subject: [PATCH 12/12] [CI]: removing the cppcheck stages from the old pipeline Signed-off-by: Raphael Defosseux --- ci-scripts/Jenkinsfile-gitlab | 33 ++------------------------------- 1 file changed, 2 insertions(+), 31 deletions(-) diff --git a/ci-scripts/Jenkinsfile-gitlab b/ci-scripts/Jenkinsfile-gitlab index de49275b7e..2f06216101 100644 --- a/ci-scripts/Jenkinsfile-gitlab +++ b/ci-scripts/Jenkinsfile-gitlab @@ -226,27 +226,8 @@ pipeline { } } - stage ("Start VM -- cppcheck") { - steps { - lock (vmResource) { - timeout (time: 7, unit: 'MINUTES') { - sh "./ci-scripts/oai-ci-vm-tool build --workspace $WORKSPACE --variant cppcheck --job-name ${JOB_NAME} --build-id ${BUILD_ID} --daemon" - } - } - } - } - stage ("Variant Builds") { parallel { - stage ("Analysis with cppcheck") { - steps { - gitlabCommitStatus(name: "Analysis with cppcheck") { - timeout (time: 30, unit: 'MINUTES') { - sh "./ci-scripts/oai-ci-vm-tool wait --workspace $WORKSPACE --variant cppcheck --job-name ${JOB_NAME} --build-id ${BUILD_ID}" - } - } - } - } stage ("Build basic simulator") { steps { gitlabCommitStatus(name: "Build basic-sim") { @@ -315,9 +296,9 @@ pipeline { script { dir ('archives') { if (fileExists('red_hat')) { - sh "zip -r -qq vm_build_logs.zip basic_sim enb_usrp phy_sim cppcheck enb_eth ue_eth gnb_usrp nr_ue_usrp red_hat" + sh "zip -r -qq vm_build_logs.zip basic_sim phy_sim enb_eth ue_eth gnb_usrp nr_ue_usrp red_hat" } else { - sh "zip -r -qq vm_build_logs.zip basic_sim enb_usrp phy_sim cppcheck enb_eth ue_eth gnb_usrp nr_ue_usrp" + sh "zip -r -qq vm_build_logs.zip basic_sim phy_sim enb_eth ue_eth gnb_usrp nr_ue_usrp" } } if(fileExists('archives/vm_build_logs.zip')) { @@ -325,16 +306,6 @@ pipeline { } if ("MERGE".equals(env.gitlabActionType)) { sh "./ci-scripts/oai-ci-vm-tool report-build --workspace $WORKSPACE --git-url ${GIT_URL} --job-name ${JOB_NAME} --build-id ${BUILD_ID} --trigger merge-request --src-branch ${env.gitlabSourceBranch} --src-commit ${env.gitlabMergeRequestLastCommit} --target-branch ${env.gitlabTargetBranch} --target-commit ${GIT_COMMIT}" - // If the merge request has introduced more CPPCHECK errors or warnings, notifications in GitLab - if (fileExists('oai_cppcheck_added_errors.txt')) { - def ret=readFile('./oai_cppcheck_added_errors.txt').trim(); - if ("0".equals(ret)) { - echo "No added cppcheck warnings/errors in this merge request" - } else { - def message = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): Some modified files in Merge Request MAY have INTRODUCED up to " + ret + " CPPCHECK errors/warnings" - addGitLabMRComment comment: message - } - } // If the merge request has introduced compilation warnings, notifications in GitLab sh "./ci-scripts/checkAddedWarnings.sh --src-branch ${env.gitlabSourceBranch} --target-branch ${env.gitlabTargetBranch}" def res=readFile('./oai_warning_files.txt').trim();