├── .gitignore ├── docs ├── images │ ├── oai_final_logo.png │ ├── OAICN-Network-Deployment-Explanation.png │ └── OAI-MAGMA-NSA-Demo-Network-configuration.png ├── DEPLOY_HOME_MAGMA_MME.md ├── GENERATE_TRAFFIC.md ├── RETRIEVE_OFFICIAL_IMAGES_MAGMA.md ├── DEPLOY_PRE_REQUESITES_MAGMA.md ├── CONFIGURE_NETWORKS_MAGMA.md ├── BUILD_IMAGES.md ├── NSA_SUPPORT_OAI_RAN.md └── BUILD_IMAGES_MAGMA_MME.md ├── ci-scripts ├── dsTesterDockerCompose │ ├── .gitignore │ ├── spgwc-healthy-check.sh │ ├── spgwu-healthy-check.sh │ ├── hss-healthy-check.sh │ ├── mme-healthy-check.sh │ ├── redis_extern.conf │ ├── mme-cfg.sh │ ├── mme.conf.tplt │ ├── docker-compose.tplt │ └── mme_fd.sprint.conf ├── oai-ran-sanity-check │ ├── ue.env │ ├── hss.env │ ├── spgwu.env │ ├── mme.env │ ├── spgwc.env │ ├── enb.env │ ├── redis-extern.conf │ ├── mme-old.env │ └── mme-entrypoint.sh ├── fail.sh ├── Jenkinsfile-Magma-OAI-Check-Master ├── Dockerfile.traffic.generator.ubuntu18.04 ├── Dockerfile.traffic.generator.rhel8 ├── jenkinsStats.py ├── pcap_check.py ├── Jenkinsfile-Magma-OAI-DsTester └── Jenkinsfile-Magma-Sanity-Check ├── .gitmodules ├── NOTICE ├── docker-compose ├── magma-mme-demo │ ├── redis_extern.conf │ ├── mme-cfg.sh │ ├── mme.conf │ ├── docker-compose.yml │ ├── mme_fd.sprint.conf │ └── README.md └── inria-oai-mme-legacy │ └── docker-compose.yml ├── LICENSE ├── CHANGELOG.md ├── CONTRIBUTING.md ├── scripts └── syncComponents.sh └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | DS-TEST-RESULTS 2 | archives 3 | fed_docker_logs.zip 4 | test_results_oai_epc.html 5 | -------------------------------------------------------------------------------- /docs/images/oai_final_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OPENAIRINTERFACE/openair-epc-fed/HEAD/docs/images/oai_final_logo.png -------------------------------------------------------------------------------- /ci-scripts/dsTesterDockerCompose/.gitignore: -------------------------------------------------------------------------------- 1 | docker-compose.yml 2 | hss-entrypoint-sleep.sh 3 | oai_db.cql 4 | spgwc-entrypoint-sleep.sh 5 | spgwu-entrypoint-sleep.sh 6 | -------------------------------------------------------------------------------- /docs/images/OAICN-Network-Deployment-Explanation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OPENAIRINTERFACE/openair-epc-fed/HEAD/docs/images/OAICN-Network-Deployment-Explanation.png -------------------------------------------------------------------------------- /docs/images/OAI-MAGMA-NSA-Demo-Network-configuration.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OPENAIRINTERFACE/openair-epc-fed/HEAD/docs/images/OAI-MAGMA-NSA-Demo-Network-configuration.png -------------------------------------------------------------------------------- /ci-scripts/dsTesterDockerCompose/spgwc-healthy-check.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | STATUS=0 4 | NB_UNREPLACED_AT=`cat /openair-spgwc/etc/*.conf | grep -v contact@openairinterface.org | grep -c @ || true` 5 | if [ $NB_UNREPLACED_AT -ne 0 ] 6 | then 7 | STATUS=-1 8 | fi 9 | 10 | exit $STATUS 11 | -------------------------------------------------------------------------------- /ci-scripts/dsTesterDockerCompose/spgwu-healthy-check.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | STATUS=0 4 | NB_UNREPLACED_AT=`cat /openair-spgwc/etc/*.conf | grep -v contact@openairinterface.org | grep -c @ || true` 5 | if [ $NB_UNREPLACED_AT -ne 0 ] 6 | then 7 | STATUS=-1 8 | fi 9 | 10 | exit $STATUS 11 | -------------------------------------------------------------------------------- /ci-scripts/oai-ran-sanity-check/ue.env: -------------------------------------------------------------------------------- 1 | TZ=Europe/Paris 2 | RFSIMULATOR=192.168.61.80 3 | MCC=208 4 | MNC=96 5 | SHORT_IMSI=0100000001 6 | LTE_KEY=fec86ba6eb707ed08905757b1bb44b8f 7 | OPC=c42449363bbad02b66d16bc975d77cc1 8 | MSISDN=001011234561010 9 | HPLMN=20896 10 | USE_ADDITIONAL_OPTIONS=--rfsim -C 2680000000 -r 25 --ue-rxgain 140 --ue-txgain 120 --nokrnmod 1 11 | -------------------------------------------------------------------------------- /ci-scripts/oai-ran-sanity-check/hss.env: -------------------------------------------------------------------------------- 1 | TZ=Europe/Paris 2 | REALM=openairinterface.org 3 | HSS_FQDN=hss.openairinterface.org 4 | PREFIX=/openair-hss/etc 5 | cassandra_Server_IP=192.168.61.66 6 | OP_KEY=1006020f0a478bf6b699f15c062e42b3 7 | LTE_K=fec86ba6eb707ed08905757b1bb44b8f 8 | APN1=oai.ipv4 9 | APN2=internet 10 | FIRST_IMSI=208960100000001 11 | NB_USERS=10 12 | 13 | -------------------------------------------------------------------------------- /ci-scripts/oai-ran-sanity-check/spgwu.env: -------------------------------------------------------------------------------- 1 | TZ=Europe/Paris 2 | PID_DIRECTORY=/var/run 3 | INSTANCE=1 4 | SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP=eth0 5 | PGW_INTERFACE_NAME_FOR_SGI=eth0 6 | SGW_INTERFACE_NAME_FOR_SX=eth0 7 | SPGWC0_IP_ADDRESS=192.168.61.70 8 | NETWORK_UE_IP=12.0.0.0/24 9 | NETWORK_UE_NAT_OPTION=yes 10 | MCC=208 11 | MNC=96 12 | MNC03=096 13 | TAC=1 14 | GW_ID=1 15 | REALM=openairinterface.org 16 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "component/oai-hss"] 2 | path = component/oai-hss 3 | url = https://github.com/OPENAIRINTERFACE/openair-hss.git 4 | [submodule "component/oai-spgwc"] 5 | path = component/oai-spgwc 6 | url = https://github.com/OPENAIRINTERFACE/openair-spgwc.git 7 | [submodule "component/oai-spgwu-tiny"] 8 | path = component/oai-spgwu-tiny 9 | url = https://github.com/OPENAIRINTERFACE/openair-spgwu-tiny.git 10 | -------------------------------------------------------------------------------- /ci-scripts/oai-ran-sanity-check/mme.env: -------------------------------------------------------------------------------- 1 | TZ=Europe/Paris 2 | REALM=openairinterface.org 3 | PREFIX=/magma-mme/etc 4 | HSS_HOSTNAME=hss 5 | HSS_FQDN=hss.openairinterface.org 6 | HSS_REALM=openairinterface.org 7 | MME_FQDN=mme.openairinterface.org 8 | FEATURES=mme_oai 9 | MCC=208 10 | MNC=96 11 | TAC0=1 12 | HSS_IP_ADDR=192.168.61.67 13 | REDIS_IP_ADDR=192.168.61.69 14 | MME_S1_IP_ADDR=192.168.61.68 15 | SPGWC0_IP_ADDR=192.168.61.70 16 | -------------------------------------------------------------------------------- /ci-scripts/oai-ran-sanity-check/spgwc.env: -------------------------------------------------------------------------------- 1 | TZ=Europe/Paris 2 | SGW_INTERFACE_NAME_FOR_S11=eth0 3 | PGW_INTERFACE_NAME_FOR_SX=eth0 4 | DEFAULT_DNS_IPV4_ADDRESS=192.168.18.129 5 | DEFAULT_DNS_SEC_IPV4_ADDRESS=8.8.4.4 6 | PUSH_PROTOCOL_OPTION=true 7 | APN_NI_1=oai.ipv4 8 | APN_NI_2=oai.ipv4_2 9 | DEFAULT_APN_NI_1=oai.ipv4 10 | UE_IP_ADDRESS_POOL_1=12.0.0.2 - 12.0.0.254 11 | UE_IP_ADDRESS_POOL_2=12.1.1.2 - 12.1.1.254 12 | MCC=208 13 | MNC=96 14 | MNC03=096 15 | TAC=1 16 | GW_ID=1 17 | REALM=openairinterface.org 18 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Openair-epc-fed is distributed under 3-Clause BSD License 2 | 3 | However, it also includes third party-software indicated below. 4 | 5 | - component/oai-spgwc is distributed under OAI Public License V1.0. 6 | see component/oai-spgwc/LICENSE for more details 7 | 8 | - component/oai-spgwu-tiny is distributed under OAI Public License V1.0. 9 | see component/oai-spgwu-tiny/LICENSE for more details 10 | 11 | Also each component may use also 3rd party-software. Check in each component the NOTICE file. 12 | -------------------------------------------------------------------------------- /ci-scripts/dsTesterDockerCompose/hss-healthy-check.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | STATUS=0 4 | NB_UNREPLACED_AT=`cat /openair-hss/etc/*.json /openair-hss/etc/*.conf | grep -v contact@openairinterface.org | grep -c @ || true` 5 | if [ $NB_UNREPLACED_AT -ne 0 ] 6 | then 7 | STATUS=-1 8 | fi 9 | 10 | NB_GENERATED_CERTIFICATES=`ls /openair-hss/etc/cacert.pem /openair-hss/etc/hss.cert.pem /openair-hss/etc/hss.key.pem | grep -c pem || true` 11 | if [ $NB_GENERATED_CERTIFICATES -ne 3 ] 12 | then 13 | STATUS=-1 14 | fi 15 | 16 | exit $STATUS 17 | -------------------------------------------------------------------------------- /ci-scripts/oai-ran-sanity-check/enb.env: -------------------------------------------------------------------------------- 1 | TZ=Europe/Paris 2 | USE_FDD_MONO=yes 3 | RFSIMULATOR=enb 4 | ENB_NAME=eNB-rf-sim 5 | MCC=208 6 | MNC=96 7 | MNC_LENGTH=2 8 | TAC=1 9 | UTRA_BAND_ID=7 10 | DL_FREQUENCY_IN_MHZ=2680 11 | UL_FREQUENCY_OFFSET_IN_MHZ=120 12 | NID_CELL=10 13 | NB_PRB=25 14 | MME_S1C_IP_ADDRESS=192.168.61.68 15 | ENB_S1C_IF_NAME=eth0 16 | ENB_S1C_IP_ADDRESS=192.168.61.80 17 | ENB_S1U_IF_NAME=eth0 18 | ENB_S1U_IP_ADDRESS=192.168.61.80 19 | ENB_X2_IP_ADDRESS=192.168.61.80 20 | FLEXRAN_ENABLED=no 21 | FLEXRAN_INTERFACE_NAME=eth0 22 | FLEXRAN_IPV4_ADDRESS=192.168.61.68 23 | USE_ADDITIONAL_OPTIONS=--rfsim 24 | -------------------------------------------------------------------------------- /ci-scripts/dsTesterDockerCompose/mme-healthy-check.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | STATUS=0 4 | NB_UNREPLACED_AT=`cat /magma-mme/etc/*.conf | grep -c @ || true` 5 | if [ $NB_UNREPLACED_AT -ne 0 ] 6 | then 7 | STATUS=-1 8 | fi 9 | 10 | NB_GENERATED_CERTIFICATES=`ls /magma-mme/etc/mme.cacert.pem /magma-mme/etc/mme.cakey.pem /magma-mme/etc/mme.cert.pem /magma-mme/etc/mme.key.pem | grep -c pem || true` 11 | if [ $NB_GENERATED_CERTIFICATES -ne 4 ] 12 | then 13 | STATUS=-1 14 | fi 15 | 16 | NB_NOT_FOUND_PACKAGES=`ldd /magma-mme/bin/oai_mme /magma-mme/bin/sctpd | egrep -c "not found" || true` 17 | if [ $NB_NOT_FOUND_PACKAGES -ne 0 ] 18 | then 19 | STATUS=-1 20 | fi 21 | 22 | exit $STATUS 23 | -------------------------------------------------------------------------------- /docker-compose/magma-mme-demo/redis_extern.conf: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2016-present, Facebook, Inc. 3 | # All rights reserved. 4 | # 5 | # This source code is licensed under the BSD-style license found in the 6 | # LICENSE file in the root directory of this source tree. An additional grant 7 | # of patent rights can be found in the PATENTS file in the same directory. 8 | 9 | # Jinja template for Redis configuration 10 | # See the default config file for options and explanations: 11 | # https://github.com/antirez/redis/blob/unstable/redis.conf 12 | 13 | # TODO: make sensible, production-aware config decisions 14 | 15 | bind 192.168.61.148 16 | port 6380 17 | 18 | daemonize no 19 | loglevel notice 20 | 21 | timeout 0 22 | databases 1 23 | 24 | dbfilename redis_dump.rdb 25 | dir /data 26 | 27 | # Save the DB on disk 28 | 29 | save 900 1 30 | 31 | save 300 10 32 | 33 | save 60 1000 34 | -------------------------------------------------------------------------------- /ci-scripts/dsTesterDockerCompose/redis_extern.conf: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2016-present, Facebook, Inc. 3 | # All rights reserved. 4 | # 5 | # This source code is licensed under the BSD-style license found in the 6 | # LICENSE file in the root directory of this source tree. An additional grant 7 | # of patent rights can be found in the PATENTS file in the same directory. 8 | 9 | # Jinja template for Redis configuration 10 | # See the default config file for options and explanations: 11 | # https://github.com/antirez/redis/blob/unstable/redis.conf 12 | 13 | # TODO: make sensible, production-aware config decisions 14 | 15 | bind 192.168.61.195 16 | port 6380 17 | 18 | daemonize no 19 | loglevel notice 20 | 21 | timeout 0 22 | databases 1 23 | 24 | dbfilename redis_dump.rdb 25 | dir /data 26 | 27 | # Save the DB on disk 28 | 29 | save 900 1 30 | 31 | save 300 10 32 | 33 | save 60 1000 34 | -------------------------------------------------------------------------------- /ci-scripts/oai-ran-sanity-check/redis-extern.conf: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2016-present, Facebook, Inc. 3 | # All rights reserved. 4 | # 5 | # This source code is licensed under the BSD-style license found in the 6 | # LICENSE file in the root directory of this source tree. An additional grant 7 | # of patent rights can be found in the PATENTS file in the same directory. 8 | 9 | # Jinja template for Redis configuration 10 | # See the default config file for options and explanations: 11 | # https://github.com/antirez/redis/blob/unstable/redis.conf 12 | 13 | # TODO: make sensible, production-aware config decisions 14 | 15 | bind 192.168.61.69 16 | port 6380 17 | 18 | daemonize no 19 | loglevel notice 20 | 21 | timeout 0 22 | databases 1 23 | 24 | dbfilename redis_dump.rdb 25 | dir /data 26 | 27 | # Save the DB on disk 28 | 29 | save 900 1 30 | 31 | save 300 10 32 | 33 | save 60 1000 34 | -------------------------------------------------------------------------------- /ci-scripts/fail.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #/* 3 | # * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more 4 | # * contributor license agreements. See the NOTICE file distributed with 5 | # * this work for additional information regarding copyright ownership. 6 | # * The OpenAirInterface Software Alliance licenses this file to You under 7 | # * the OAI Public License, Version 1.1 (the "License"); you may not use this file 8 | # * except in compliance with the License. 9 | # * You may obtain a copy of the License at 10 | # * 11 | # * http://www.openairinterface.org/?page_id=698 12 | # * 13 | # * Unless required by applicable law or agreed to in writing, software 14 | # * distributed under the License is distributed on an "AS IS" BASIS, 15 | # * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # * See the License for the specific language governing permissions and 17 | # * limitations under the License. 18 | # *------------------------------------------------------------------------------- 19 | # * For more information about the OpenAirInterface (OAI) Software Alliance: 20 | # * contact@openairinterface.org 21 | # */ 22 | 23 | exit -1 24 | -------------------------------------------------------------------------------- /ci-scripts/dsTesterDockerCompose/mme-cfg.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -x 4 | cd /magma-mme/scripts 5 | 6 | INSTANCE=1 7 | PREFIX='/magma-mme/etc' 8 | MY_REALM='openairinterface.org' 9 | 10 | declare -A MME_CONF 11 | 12 | pushd $PREFIX 13 | cp mme_fd.conf.tmplt mme_fd.conf 14 | 15 | MME_CONF[@MME_S6A_IP_ADDR@]="192.168.61.196" 16 | MME_CONF[@INSTANCE@]=$INSTANCE 17 | MME_CONF[@PREFIX@]=$PREFIX 18 | MME_CONF[@REALM@]=$MY_REALM 19 | MME_CONF[@MME_FQDN@]="mme.${MME_CONF[@REALM@]}" 20 | MME_CONF[@HSS_HOSTNAME@]='hss' 21 | MME_CONF[@HSS_FQDN@]="${MME_CONF[@HSS_HOSTNAME@]}.${MME_CONF[@REALM@]}" 22 | MME_CONF[@HSS_REALM@]=$MY_REALM 23 | MME_CONF[@HSS_IP_ADDR@]="192.168.61.194" 24 | 25 | for K in "${!MME_CONF[@]}"; do 26 | egrep -lRZ "$K" $PREFIX/mme_fd.conf | xargs -0 -l sed -i -e "s|$K|${MME_CONF[$K]}|g" 27 | ret=$?;[[ ret -ne 0 ]] && echo "Tried to replace $K with ${MME_CONF[$K]}" 28 | done 29 | 30 | sed -i -e "s@etc/freeDiameter@etc@" /magma-mme/etc/mme_fd.conf 31 | sed -i -e "s@bind: 127.0.0.1@bind: 192.168.61.195@" /etc/magma/redis.yml 32 | # Generate freeDiameter certificate 33 | popd 34 | ./check_mme_s6a_certificate $PREFIX mme.${MME_CONF[@REALM@]} 35 | set +x 36 | 37 | sleep infinity 38 | -------------------------------------------------------------------------------- /docker-compose/magma-mme-demo/mme-cfg.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | INSTANCE=1 4 | PREFIX='/magma-mme/etc' 5 | MY_REALM='openairinterface.org' 6 | 7 | declare -A MME_CONF 8 | 9 | pushd $PREFIX 10 | MME_CONF[@MME_S6A_IP_ADDR@]="192.168.61.149" 11 | MME_CONF[@INSTANCE@]=$INSTANCE 12 | MME_CONF[@PREFIX@]=$PREFIX 13 | MME_CONF[@REALM@]=$MY_REALM 14 | MME_CONF[@MME_FQDN@]="mme.${MME_CONF[@REALM@]}" 15 | MME_CONF[@HSS_HOSTNAME@]='hss' 16 | MME_CONF[@HSS_FQDN@]="${MME_CONF[@HSS_HOSTNAME@]}.${MME_CONF[@REALM@]}" 17 | MME_CONF[@HSS_IP_ADDR@]="192.168.61.130" 18 | 19 | cp mme_fd.conf.tmplt $PREFIX/mme_fd.conf 20 | 21 | for K in "${!MME_CONF[@]}"; do 22 | egrep -lRZ "$K" $PREFIX/mme_fd.conf | xargs -0 -l sed -i -e "s|$K|${MME_CONF[$K]}|g" 23 | ret=$?;[[ ret -ne 0 ]] && echo "Tried to replace $K with ${MME_CONF[$K]}" 24 | done 25 | 26 | sed -i -e "s@etc/freeDiameter@etc@" /magma-mme/etc/mme_fd.conf 27 | sed -i -e "s@bind: 127.0.0.1@bind: 192.168.61.148@" /etc/magma/redis.yml 28 | # Generate freeDiameter certificate 29 | popd 30 | ./check_mme_s6a_certificate $PREFIX mme.${MME_CONF[@REALM@]} 31 | 32 | cd /magma-mme 33 | nohup /magma-mme/bin/sctpd > /var/log/sctpd.log 2>&1 & 34 | sleep 5 35 | /magma-mme/bin/oai_mme -c /magma-mme/etc/mme.conf 36 | -------------------------------------------------------------------------------- /ci-scripts/oai-ran-sanity-check/mme-old.env: -------------------------------------------------------------------------------- 1 | TZ=Europe/Paris 2 | REALM=openairinterface.org 3 | PREFIX=/openair-mme/etc 4 | HSS_HOSTNAME=hss 5 | HSS_FQDN=hss.openairinterface.org 6 | HSS_REALM=openairinterface.org 7 | MME_FQDN=mme.openairinterface.org 8 | MCC=208 9 | MNC=96 10 | HSS_IP_ADDR=192.168.61.67 11 | MME_S1_IP_ADDR=192.168.61.68 12 | SPGWC0_IP_ADDR=192.168.61.70 13 | INSTANCE=1 14 | PID_DIRECTORY=/var/run 15 | MME_GID=32768 16 | MME_CODE=3 17 | TAC_0=1 18 | TAC_1=2 19 | TAC_2=3 20 | MME_S6A_IP_ADDR=192.168.61.68 21 | MME_INTERFACE_NAME_FOR_S1_MME=eth0 22 | MME_IPV4_ADDRESS_FOR_S1_MME=192.168.61.68 23 | MME_INTERFACE_NAME_FOR_S11=eth0 24 | MME_IPV4_ADDRESS_FOR_S11=192.168.61.68 25 | MME_INTERFACE_NAME_FOR_S10=lo 26 | MME_IPV4_ADDRESS_FOR_S10=127.0.0.10 27 | OUTPUT=CONSOLE 28 | SGW_IPV4_ADDRESS_FOR_S11_0=192.168.61.70 29 | PEER_MME_IPV4_ADDRESS_FOR_S10_0=0.0.0.0 30 | PEER_MME_IPV4_ADDRESS_FOR_S10_1=0.0.0.0 31 | MCC_SGW_0=208 32 | MNC3_SGW_0=096 33 | TAC_LB_SGW_0=01 34 | TAC_HB_SGW_0=00 35 | MCC_MME_0=208 36 | MNC3_MME_0=096 37 | TAC_LB_MME_0=02 38 | TAC_HB_MME_0=00 39 | MCC_MME_1=208 40 | MNC3_MME_1=096 41 | TAC_LB_MME_1=03 42 | TAC_HB_MME_1=00 43 | TAC_LB_SGW_TEST_0=03 44 | TAC_HB_SGW_TEST_0=00 45 | SGW_IPV4_ADDRESS_FOR_S11_TEST_0=0.0.0.0 46 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | For OpenAir-HSS software 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation and/or 13 | other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its contributors 16 | may be used to endorse or promote products derived from this software without 17 | specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 23 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 26 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | -------------------------------------------------------------------------------- /docs/DEPLOY_HOME_MAGMA_MME.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 12 | 13 |
4 | 5 | 6 | 7 | 8 | 10 | OpenAirInterface Core Network : MAGMA MME based Deployment 11 |
14 | 15 | # Why you should use this deployment? # 16 | 17 | - You want the latest updates: 18 | - the `master` branch on the `magma` project is updated every day with new features, bug fixes... 19 | - You expect the whole EPC to be running for hours and days without any restart 20 | 21 | **2021/07/28 Update: you have now the choice to either pull images or build your-self.** 22 | 23 | **2022/02/25 Update: MAGMA-MME can now be used with a full OAI stack to perform OAI RF simulation.** 24 | 25 | **Table of Contents** 26 | 27 | 1. [Pre-requisites](./DEPLOY_PRE_REQUESITES_MAGMA.md) 28 | 2. Getting the images 29 | 1. [Retrieving the Container Images](./RETRIEVE_OFFICIAL_IMAGES_MAGMA.md) 30 | 2. [Building the Container Images](./BUILD_IMAGES_MAGMA_MME.md) 31 | 3. [Deploying with MAGMA-MME using docker-compose](../docker-compose/magma-mme-demo/README.md) 32 | 4. [Verify/Correct your network environment](./CONFIGURE_NETWORKS_MAGMA.md) 33 | 5. [Demo made during 2021 MAGMA-dev conference](./NSA_SUPPORT_OAI_RAN.md) 34 | -------------------------------------------------------------------------------- /ci-scripts/Jenkinsfile-Magma-OAI-Check-Master: -------------------------------------------------------------------------------- 1 | #!/bin/groovy 2 | /* 3 | * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more 4 | * contributor license agreements. See the NOTICE file distributed with 5 | * this work for additional information regarding copyright ownership. 6 | * The OpenAirInterface Software Alliance licenses this file to You under 7 | * the OAI Public License, Version 1.1 (the "License"); you may not use this file 8 | * except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.openairinterface.org/?page_id=698 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | *------------------------------------------------------------------------------- 19 | * For more information about the OpenAirInterface (OAI) Software Alliance: 20 | * contact@openairinterface.org 21 | */ 22 | 23 | def magma_job = params.magma_job_name 24 | 25 | pipeline { 26 | agent { 27 | label 'master' 28 | } 29 | stages { 30 | stage ('Trigger MAGMA pipeline') { 31 | steps { 32 | script { 33 | localStatus = build job: magma_job, 34 | parameters: [ 35 | booleanParam(name: 'REGRESSION_TEST', value: true) 36 | ], propagate: false 37 | localResult = localStatus.getResult() 38 | echo "${magma_job} Slave Job status is ${localResult}" 39 | if (localStatus.resultIsBetterOrEqualTo('SUCCESS')) { 40 | echo "${magma_job} Slave Job is OK" 41 | } else { 42 | error "${magma_job} Slave Job is OK" 43 | } 44 | } 45 | } 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # RELEASE NOTES: # 2 | 3 | ## v1.2.0 -- February 2022 ## 4 | 5 | * `FEDERATION LEVEL`: 6 | - Obsolescence of Legacy OAI-MME 7 | * `HSS`: 8 | - Build fixes 9 | - Docker image layer optimization 10 | * `SPGWC`: 11 | - Build fixes 12 | - Docker image layer optimization 13 | - Association trigger 14 | - Sanitize leak and UE configurable MTU 15 | - IE NWI dotted formatting 16 | - IE UPF Features 17 | - Custom UPF FQDN support 18 | * `SPGWU-TINY`: 19 | - Build fixes 20 | - Docker image layer optimization 21 | 22 | ## v1.1.5 -- December 2021 ## 23 | 24 | * `SPGWU-TINY`: 25 | - Disable association request if NF registration is enabled 26 | 27 | ## v1.1.4 -- October 2021 ## 28 | 29 | * `SPGWU-TINY`: 30 | - Fix build issue 31 | - Fix GTPU DL encapsulation: 8 extraneous bytes 32 | 33 | ## v1.1.3 -- October 2021 ## 34 | 35 | * `HSS`: 36 | - Fix build on external git sub-modules that are using `main` as master branch name 37 | - Code clean-up with no more cppcheck errors 38 | * `SPGWU-TINY`: 39 | - Adding 5G features 40 | - HTTP2 support 41 | 42 | ## v1.1.2 -- July 2021 ## 43 | 44 | * `FEDERATION LEVEL`: 45 | - DOC: cleanup, update and fixes on tutorials 46 | * `HSS`: 47 | - Enable Dual-Registration- 5G-Indicator flag in S6a/ULR 48 | - Fix users' provision in case of multi-pdn 49 | - Adding correct TZ env var to dockerfiles 50 | - Improved Continuous Integration 51 | * `SPGWC`: 52 | - Sanitize leak fixes 53 | - Adding correct TZ env var to dockerfiles 54 | - Improved Continuous Integration 55 | * `SPGWU-TINY`: 56 | - Adding 5G features 57 | - NRF discovery and FQDN support 58 | 59 | ## v1.1.1 -- February 2021 ## 60 | 61 | * `HSS`: 62 | - Cloud-native support 63 | - RHEL8 support 64 | - Proper build in release mode 65 | * `SPGWC`: 66 | - Cloud-native support 67 | - RHEL8 support 68 | - A lot of bug fixes 69 | - UE MTU 70 | - CSR Collision fix 71 | - ... 72 | - Last release before change to a JSON-based configuration file and Multi-SPGW-U-instance support 73 | * `SPGWU-TINY`: 74 | - GTP-U extension headers for 5G support 75 | - disabled by default for 4G usage 76 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to OpenAir-CN # 2 | 3 | We want to make contributing to this project as easy and transparent as possible. 4 | 5 | Please refer to the steps described on our website: [How to contribute to OAI](https://www.openairinterface.org/?page_id=112) 6 | 7 | 1. Sign and return a Contributor License Agreement to OAI team. 8 | 2. Create an account on [GitHub](https://github.com). 9 | 3. Provide the identifiant of this account to the OAI team (mailto:contact@openairinterface.org) so you have developer rights on this repository. 10 | 4. The policies are described in these wiki pages: [OAI Policies](https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/oai-policies-home) 11 | - You can fork onto another hosting system. But we will **NOT** accept a pull request from a forked repository. 12 | * This decision was made for the license reasons. 13 | * The Continuous Integration will reject your pull request. 14 | - All pull requests SHALL have **`develop`** branch as target branch. 15 | 16 | ## License ## 17 | 18 | By contributing to OpenAirInterface, you agree that your contributions will be licensed under the [LICENSE](LICENSE) file in the root directory of this source tree. 19 | 20 | ## Continuous Integration process ## 21 | 22 | 1. You push your modified code with the new branch onto our [official GitHub repository](https://github.com/OPENAIRINTERFACE/openair-epd-fed). 23 | - Please make the name of the branch explicit and short. 24 | 2. You create a pull request from the [dedicated web page](https://github.com/OPENAIRINTERFACE/openair-epd-fed/pulls). 25 | - The `target` (`base` in the web-page) branch **SHALL be `develop`**. 26 | - The `source` (`compare` in the web-page) branch is your branch. 27 | 3. Our Continuous Integration (CI) process will be triggered automatically on your proposed modified code and check the validity. 28 | - Check build 29 | - Check some formatting rules 30 | - Run a bunch of tests 31 | 4. If at least one of these steps fails, you will have to push corrections onto your source branch. 32 | - The step 3. will be again automatically triggered on this new commit. 33 | - Please wait that your run is finished before committing and pushing new modifications on your source branch. 34 | - That will allow fairness on the CI usage to other contributors. 35 | 4. When this automated process passes, one of our CI administrators will review your changes or assign a senior contributor 36 | to do a peer-review. 37 | 5. Once the peer reviewer accepts your modification, one of our CI administrators will accept and merge your pull request 38 | - The CI will run again on the new `develop` branch commit. 39 | - The source branch WILL be deleted by one of our CI administrators. 40 | 41 | -------------------------------------------------------------------------------- /ci-scripts/Dockerfile.traffic.generator.ubuntu18.04: -------------------------------------------------------------------------------- 1 | #/* 2 | # * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more 3 | # * contributor license agreements. See the NOTICE file distributed with 4 | # * this work for additional information regarding copyright ownership. 5 | # * The OpenAirInterface Software Alliance licenses this file to You under 6 | # * the OAI Public License, Version 1.1 (the "License"); you may not use this file 7 | # * except in compliance with the License. 8 | # * You may obtain a copy of the License at 9 | # * 10 | # * http://www.openairinterface.org/?page_id=698 11 | # * 12 | # * Unless required by applicable law or agreed to in writing, software 13 | # * distributed under the License is distributed on an "AS IS" BASIS, 14 | # * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # * See the License for the specific language governing permissions and 16 | # * limitations under the License. 17 | # *------------------------------------------------------------------------------- 18 | # * For more information about the OpenAirInterface (OAI) Software Alliance: 19 | # * contact@openairinterface.org 20 | # */ 21 | #--------------------------------------------------------------------- 22 | # 23 | # Dockerfile for the Open-Air-Interface SMF service 24 | # Valid for Ubuntu-18.04 (bionic) 25 | # 26 | #--------------------------------------------------------------------- 27 | 28 | #--------------------------------------------------------------------- 29 | # BUILDER IMAGE 30 | #--------------------------------------------------------------------- 31 | FROM ubuntu:bionic as trf-gen-builder 32 | 33 | ENV DEBIAN_FRONTEND=noninteractive 34 | ENV TZ=Europe/Paris 35 | RUN apt-get update && \ 36 | DEBIAN_FRONTEND=noninteractive apt-get upgrade --yes && \ 37 | DEBIAN_FRONTEND=noninteractive apt-get install --yes \ 38 | build-essential \ 39 | git \ 40 | wget \ 41 | libpthread-stubs0-dev \ 42 | && rm -rf /var/lib/apt/lists/* 43 | 44 | WORKDIR / 45 | RUN wget --tries=3 https://iperf.fr/download/source/iperf-2.0.5-source.tar.gz && \ 46 | gzip -cd iperf-2.0.5-source.tar.gz | tar -xvf - 47 | 48 | WORKDIR /iperf-2.0.5 49 | RUN sed -i -e "s@#include 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | OpenAirInterface Core Network Docker Deployment : Generating Traffic 11 | 12 | 13 | 14 | 15 | I will not explain here: 16 | 17 | - how to start/stop EPC nor 18 | - how to start/stop eNB or gNb nor 19 | - how to attach an UE 20 | 21 | Once your UE is attached, you can either see if you have internet connection. 22 | 23 | # 0. Common issues if your UE is connected but without any access to Internet # 24 | 25 | ## 0.1. Have you properly configured the DNS in SPGW-C ? ## 26 | 27 | **YOUR_DNS_IP_ADDRESS** shall have a correct value. 28 | 29 | from your EPC **Docker Host**: 30 | 31 | ```bash 32 | $ route -n 33 | Kernel IP routing table 34 | Destination Gateway Genmask Flags Metric Ref Use Iface 35 | 0.0.0.0 192.168.21.179 0.0.0.0 UG 300 0 0 ens3 36 | ... 37 | ``` 38 | 39 | In this example, the DNS IP address is `192.168.21.179`. 40 | 41 | In the `docker-compose.yml` file: 42 | 43 | ```yml 44 | DEFAULT_DNS_IPV4_ADDRESS: 192.168.21.179 45 | DEFAULT_DNS_SEC_IPV4_ADDRESS: 8.8.4.4 46 | ``` 47 | 48 | ## 0.2. May you need to enable "NATTING" on the UE pool ## 49 | 50 | In the `docker-compose.yml` file: 51 | 52 | ```yml 53 | NETWORK_UE_NAT_OPTION: 'yes' 54 | ``` 55 | 56 | ## 0.3. Last trick: enable PUSH-PROTOCOL on SPGW-C. ## 57 | 58 | In the `docker-compose.yml` file: 59 | 60 | ```yml 61 | PUSH_PROTOCOL_OPTION: 'yes' 62 | ``` 63 | 64 | **But us for testing purposes (not use our Internet bandwidth) we prefer to manage traffic internally.** 65 | 66 | # 1. Build a traffic generator image # 67 | 68 | ```bash 69 | $ cd openair-epc-fed 70 | $ cd ci-scripts 71 | $ docker build --target trf-gen --tag trf-gen:production --file Dockerfile.traffic.generator.ubuntu18.04 . 72 | $ docker image prune --force 73 | $ docker image ls 74 | trf-gen production bfdfe4e7ac51 1 minute ago 217MB 75 | ``` 76 | 77 | # 2. Instantiate a container # 78 | 79 | ```bash 80 | $ docker run --privileged --name prod-trf-gen --network prod-oai-public-net -d trf-gen:production 81 | ``` 82 | 83 | # 3. Redirect the traffic from the UE Allocation pool(s) to SPGW-U container # 84 | 85 | ```bash 86 | $ SPGWU_IP=`docker inspect --format="{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}" prod-oai-spgwu-tiny` 87 | $ docker exec -it prod-trf-gen /bin/bash -c "ip route add 12.1.1.0/24 via ${SPGWU_IP} dev eth0" 88 | ``` 89 | 90 | # 4. Ping an attached UE # 91 | 92 | ```bash 93 | $ docker exec -it prod-trf-gen /bin/bash -c "ping -c 20 12.1.1.2" 94 | ``` 95 | 96 | # 5. Iperf versions # 97 | 98 | Depending on the `iperf` version that is installed on your UE, use: 99 | 100 | ```bash 101 | $ docker exec -it prod-trf-gen /bin/bash -c "iperf --version" 102 | iperf version 2.0.10 (2 June 2018) pthreads 103 | $ docker exec -it prod-trf-gen /bin/bash -c "/iperf-2.0.5/bin/iperf --version" 104 | iperf version 2.0.5 (08 Jul 2010) pthreads 105 | ``` 106 | 107 | -------------------------------------------------------------------------------- /docs/RETRIEVE_OFFICIAL_IMAGES_MAGMA.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 12 | 13 |
4 | 5 | 6 | 7 | 8 | 10 | OpenAirInterface 4G Core Network Deployment : Pulling Container Images in a MAGMA MME env 11 |
14 | 15 | This page is only valid for an `Ubuntu18` host. 16 | 17 | If you are using any other distributions, please refer to [Build your own images](./BUILD_IMAGES_MAGMA_MME.md). 18 | 19 | If you want to the up-to-date new features, please refer to [Build your own images](./BUILD_IMAGES_MAGMA_MME.md). 20 | 21 | # Pulling the images from Docker Hub # 22 | 23 | Currently the images are hosted under the `oaisoftwarealliance` organization. 24 | 25 | This may change in the future. 26 | 27 | Once again you may need to log on [docker-hub](https://hub.docker.com/) if your organization has reached pulling limit as `anonymous`. 28 | 29 | ```bash 30 | $ docker login 31 | Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one. 32 | Username: 33 | Password: 34 | ``` 35 | 36 | Now pull images. 37 | 38 | ```bash 39 | $ docker pull oaisoftwarealliance/oai-hss:latest 40 | $ docker pull oaisoftwarealliance/oai-spgwc:latest 41 | $ docker pull oaisoftwarealliance/oai-spgwu-tiny:latest 42 | $ docker pull oaisoftwarealliance/magma-mme:latest 43 | ``` 44 | 45 | And **re-tag** them for tutorials' docker-compose file to work. 46 | 47 | ```bash 48 | $ docker image tag oaisoftwarealliance/oai-hss:latest oai-hss:production 49 | $ docker image tag oaisoftwarealliance/oai-spgwc:latest oai-spgwc:production 50 | $ docker image tag oaisoftwarealliance/oai-spgwu-tiny:latest oai-spgwu-tiny:production 51 | $ docker image tag oaisoftwarealliance/magma-mme:latest magma-mme:master 52 | ``` 53 | 54 | **CAUTION: The `MAGMA-MME` image is not updated as frequently as the other images and does not have any hack.** 55 | 56 | **We still recommend that you build yourselves the MAGMA-MME image as described [here](./BUILD_IMAGES_MAGMA_MME.md).** 57 | 58 | # Synchronizing the tutorials # 59 | 60 | **CAUTION: PLEASE READ THIS SECTION VERY CAREFULLY!** 61 | 62 | This repository only has tutorials and Continuous Integration scripts. 63 | 64 | **At the time of writing (2022/02/25), the release tag is `v1.2.0`.** 65 | 66 | | CNF Name | Branch Name | Tag | Ubuntu 18.04 | RHEL8 (UBI8) | 67 | | ----------- | ----------- | ---------- | ------------ | ----------------| 68 | | FED REPO | N/A | `v1.2.0` | | | 69 | | HSS | `master` | `v1.2.0` | X | X | 70 | | SPWG-C | `master` | `v1.2.0` | X | X | 71 | | SPGW-U-TINY | `master` | `v1.2.0` | X | X | 72 | 73 | ```bash 74 | # Clone directly on the latest release tag 75 | $ git clone --branch v1.2.0 https://github.com/OPENAIRINTERFACE/openair-epc-fed.git 76 | $ cd openair-epc-fed 77 | # If you forgot to clone directly to the latest release tag 78 | $ git checkout -f v1.2.0 79 | 80 | # Synchronize all git submodules 81 | $ ./scripts/syncComponents.sh 82 | --------------------------------------------------------- 83 | OAI-HSS component branch : master 84 | OAI-SPGW-C component branch : master 85 | OAI-SPGW-U component branch : master 86 | --------------------------------------------------------- 87 | git submodule deinit --all --force 88 | git submodule init 89 | git submodule update 90 | ``` 91 | 92 | Later versions of the `master` branch may not work with the pulled images. 93 | 94 | To deploy: 95 | 96 | * See [Deploy with MAGMA-MME](../docker-compose/magma-mme-demo/README.md). 97 | 98 | 99 | -------------------------------------------------------------------------------- /ci-scripts/Dockerfile.traffic.generator.rhel8: -------------------------------------------------------------------------------- 1 | #/* 2 | # * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more 3 | # * contributor license agreements. See the NOTICE file distributed with 4 | # * this work for additional information regarding copyright ownership. 5 | # * The OpenAirInterface Software Alliance licenses this file to You under 6 | # * the OAI Public License, Version 1.1 (the "License"); you may not use this file 7 | # * except in compliance with the License. 8 | # * You may obtain a copy of the License at 9 | # * 10 | # * http://www.openairinterface.org/?page_id=698 11 | # * 12 | # * Unless required by applicable law or agreed to in writing, software 13 | # * distributed under the License is distributed on an "AS IS" BASIS, 14 | # * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # * See the License for the specific language governing permissions and 16 | # * limitations under the License. 17 | # *------------------------------------------------------------------------------- 18 | # * For more information about the OpenAirInterface (OAI) Software Alliance: 19 | # * contact@openairinterface.org 20 | # */ 21 | #--------------------------------------------------------------------- 22 | # 23 | # 24 | #--------------------------------------------------------------------- 25 | 26 | #--------------------------------------------------------------------- 27 | # BUILDER IMAGE 28 | #--------------------------------------------------------------------- 29 | FROM registry.access.redhat.com/ubi8/ubi:latest as trf-gen-builder 30 | 31 | COPY tmp/ca/redhat-uep.pem /etc/rhsm/ca 32 | COPY tmp/entitlement/*.pem /etc/pki/entitlement 33 | 34 | RUN rm /etc/rhsm-host && \ 35 | # Initialize /etc/yum.repos.d/redhat.repo 36 | # See https://access.redhat.com/solutions/1443553 37 | yum repolist --disablerepo=* && \ 38 | subscription-manager repos --enable codeready-builder-for-rhel-8-x86_64-rpms && \ 39 | yum update -y && \ 40 | yum -y install --enablerepo="codeready-builder-for-rhel-8-x86_64-rpms" \ 41 | # diff, cmp and file are not in the ubi??? 42 | gcc gcc-c++ \ 43 | git \ 44 | make \ 45 | psmisc \ 46 | traceroute \ 47 | wget && \ 48 | echo "/usr/local/lib" > /etc/ld.so.conf.d/local-lib.conf && \ 49 | echo "/usr/local/lib64" >> /etc/ld.so.conf.d/local-lib.conf 50 | 51 | WORKDIR / 52 | RUN wget --tries=3 https://iperf.fr/download/source/iperf-2.0.5-source.tar.gz && \ 53 | gzip -cd iperf-2.0.5-source.tar.gz | tar -xvf - 54 | 55 | WORKDIR /iperf-2.0.5 56 | RUN sed -i -e "s@#include /etc/ld.so.conf.d/local-lib.conf && \ 89 | yum clean all -y && \ 90 | rm -rf /var/cache/yum 91 | 92 | WORKDIR /iperf-2.0.5/bin 93 | COPY --from=trf-gen-builder /iperf-2.0.5/src/iperf . 94 | 95 | WORKDIR /iperf-2.0.10/bin 96 | COPY --from=trf-gen-builder /iperf-2.0.10/src/iperf . 97 | 98 | WORKDIR /iperf-2.0.13/bin 99 | COPY --from=trf-gen-builder /iperf-2.0.13/src/iperf . 100 | 101 | CMD ["sleep", "infinity"] 102 | -------------------------------------------------------------------------------- /scripts/syncComponents.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #/* 3 | # * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more 4 | # * contributor license agreements. See the NOTICE file distributed with 5 | # * this work for additional information regarding copyright ownership. 6 | # * The OpenAirInterface Software Alliance licenses this file to You under 7 | # * the OAI Public License, Version 1.1 (the "License"); you may not use this file 8 | # * except in compliance with the License. 9 | # * You may obtain a copy of the License at 10 | # * 11 | # * http://www.openairinterface.org/?page_id=698 12 | # * 13 | # * Unless required by applicable law or agreed to in writing, software 14 | # * distributed under the License is distributed on an "AS IS" BASIS, 15 | # * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # * See the License for the specific language governing permissions and 17 | # * limitations under the License. 18 | # *------------------------------------------------------------------------------- 19 | # * For more information about the OpenAirInterface (OAI) Software Alliance: 20 | # * contact@openairinterface.org 21 | # */ 22 | 23 | function usage { 24 | echo "Openair-CN components synchronization" 25 | echo " Original Author: Raphael Defosseux" 26 | echo "" 27 | echo " Requirement: git shall be installed" 28 | echo "" 29 | echo " By default (no options) all components will be synchronized to" 30 | echo " the 'develop' branch." 31 | echo " Each component can be synchronized a dedicated branch." 32 | echo "" 33 | echo "Usage:" 34 | echo "------" 35 | echo " syncComponents.sh [OPTIONS]" 36 | echo "" 37 | echo "Options:" 38 | echo "--------" 39 | echo " --hss-branch ####" 40 | echo " Specify the source branch for the OAI-HSS component" 41 | echo "" 42 | echo " --spgwc-branch ####" 43 | echo " Specify the source branch for the OAI-SPGW-C component" 44 | echo "" 45 | echo " --spgwu-tiny-branch ####" 46 | echo " Specify the source branch for the OAI-SPGW-U-TINY component" 47 | echo "" 48 | echo " --help OR -h" 49 | echo " Print this help message." 50 | echo "" 51 | } 52 | 53 | HSS_BRANCH='master' 54 | SPGWC_BRANCH='master' 55 | SPGWU_BRANCH='master' 56 | 57 | doDefault=1 58 | 59 | while [[ $# -gt 0 ]] 60 | do 61 | key="$1" 62 | 63 | case $key in 64 | -h|--help) 65 | shift 66 | usage 67 | exit 0 68 | ;; 69 | --hss-branch) 70 | HSS_BRANCH="$2" 71 | doDefault=0 72 | shift 73 | shift 74 | ;; 75 | --spgwc-branch) 76 | SPGWC_BRANCH="$2" 77 | doDefault=0 78 | shift 79 | shift 80 | ;; 81 | --spgwu-tiny-branch) 82 | SPGWU_BRANCH="$2" 83 | doDefault=0 84 | shift 85 | shift 86 | ;; 87 | *) 88 | echo "Syntax Error: unknown option: $key" 89 | echo "" 90 | usage 91 | exit 1 92 | esac 93 | 94 | done 95 | 96 | echo "---------------------------------------------------------" 97 | echo "OAI-HSS component branch : ${HSS_BRANCH}" 98 | echo "OAI-SPGW-C component branch : ${SPGWC_BRANCH}" 99 | echo "OAI-SPGW-U component branch : ${SPGWU_BRANCH}" 100 | echo "---------------------------------------------------------" 101 | 102 | # First do a clean-up 103 | echo "git submodule deinit --all --force" 104 | git submodule deinit --all --force > /dev/null 2>&1 105 | 106 | echo "git submodule init" 107 | git submodule init > /dev/null 2>&1 108 | echo "git submodule update" 109 | git submodule update > /dev/null 2>&1 110 | 111 | if [ $doDefault -eq 1 ] 112 | then 113 | git submodule foreach 'git fetch --prune && git branch -D master && git checkout -b master origin/master' > /dev/null 2>&1 114 | else 115 | pushd component/oai-hss 116 | git fetch --prune > /dev/null 2>&1 117 | git branch -D $HSS_BRANCH > /dev/null 2>&1 118 | if [[ $? -ne 0 ]]; then 119 | git checkout $HSS_BRANCH > /dev/null 2>&1 120 | else 121 | git checkout -b $HSS_BRANCH origin/$HSS_BRANCH > /dev/null 2>&1 122 | fi 123 | popd 124 | pushd component/oai-spgwc 125 | git fetch --prune > /dev/null 2>&1 126 | git branch -D $SPGWC_BRANCH > /dev/null 2>&1 127 | if [[ $? -ne 0 ]]; then 128 | git checkout $SPGWC_BRANCH > /dev/null 2>&1 129 | else 130 | git checkout -b $SPGWC_BRANCH origin/$SPGWC_BRANCH > /dev/null 2>&1 131 | fi 132 | popd 133 | pushd component/oai-spgwu-tiny 134 | git fetch --prune > /dev/null 2>&1 135 | git branch -D $SPGWU_BRANCH > /dev/null 2>&1 136 | if [[ $? -ne 0 ]]; then 137 | git checkout $SPGWU_BRANCH > /dev/null 2>&1 138 | else 139 | git checkout -b $SPGWU_BRANCH origin/$SPGWU_BRANCH > /dev/null 2>&1 140 | fi 141 | popd 142 | fi 143 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | OAI 3 |

4 | 5 | 6 | ------------------------------------------------------------------------------ 7 | 8 | OPENAIR-CN 9 | An implementation of the Evolved Packet Core network. 10 | 11 | ------------------------------------------------------------------------------ 12 | 13 |

14 | License 15 | License 16 | Release 17 |

18 | 19 |

20 | 21 | 22 | 23 | 24 |

25 | 26 |

27 | Docker Pulls 28 | Docker Pulls 29 | Docker Pulls 30 | Docker Pulls 31 |

32 | 33 | Openair-cn is an implementation of the 3GPP specifications concerning the 34 | Evolved Packet Core Networks, that means it contains the implementation of the 35 | following network elements: 36 | 37 | * MME, 38 | * HSS, 39 | * S-GW+P-GW. 40 | 41 | Each element implementation has its own repository. This repository is a federation of components. 42 | 43 | Currently the purpose of this repository is mainly for CI activities and documentation. 44 | 45 | **AS OF 2022/02/25, WE HAVE OBSOLETED OUR LEGACY OAI-MME. THE ONLY RECOMMENDED AND SUPPORTED MME IS MAGMA-MME.** 46 | 47 | It is also hosting some tutorials: 48 | 49 | - [Deploying a whole EPC with MAGMA MME image](docs/DEPLOY_HOME_MAGMA_MME.md) 50 | 51 | # Licence info 52 | 53 | The source code in this repository is mainly written under the [3-Clause BSD License](https://opensource.org/licenses/BSD-3-Clause). 54 | 55 | The text for 3-Clause BSD License is also available under [LICENSE](LICENSE) file in the same directory. 56 | 57 | This repository is just an aggregation of git repositories as sub-modules. Each repository has its own LICENSE file. 58 | 59 | - OAI-HSS --> **3-Clause BSD License** 60 | - MAGMA-MME --> **3-Clause BSD License** 61 | - OAI-SPGWC --> **OAI Public License V1.1** 62 | - OAI-SPGWU-TINY --> **OAI Public License V1.1** 63 | 64 | For more details on third party software, please read the [NOTICE](NOTICE) file in the same directory. 65 | 66 | # Collaborative work 67 | 68 | This source code is managed through a GITHUB, a collaborative development platform 69 | 70 | * URL: [https://github.com/OPENAIRINTERFACE/openair-epc-fed](https://github.com/OPENAIRINTERFACE/openair-epc-fed). 71 | 72 | Process is explained in [CONTRIBUTING](CONTRIBUTING.md) file. 73 | 74 | # Contribution requests 75 | 76 | In a general way, anybody who is willing can contribute on any part of the 77 | code in any network component. 78 | 79 | Contributions can be simple bugfixes, advices and remarks on the design, 80 | architecture, coding/implementation. 81 | 82 | # Release Notes 83 | 84 | They are available on the [CHANGELOG](CHANGELOG.md) file. 85 | -------------------------------------------------------------------------------- /docs/DEPLOY_PRE_REQUESITES_MAGMA.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 12 | 13 |
4 | 5 | 6 | 7 | 8 | 10 | OpenAirInterface Core Network Docker Deployment : Pre-Requisites for MAGMA-MME + OAI CN 11 |
14 | 15 | # 1. Install the proper version of Docker # 16 | 17 | At time of writing (2021 / 02 / 01): 18 | 19 | ```bash 20 | $ dpkg --list | grep docker 21 | ii docker-ce 5:20.10.2~3-0~ubuntu-bionic amd64 Docker: the open-source application container engine 22 | ii docker-ce-cli 5:20.10.2~3-0~ubuntu-bionic amd64 Docker CLI: the open-source application container engine 23 | ii docker-ce-rootless-extras 5:20.10.2~3-0~ubuntu-bionic amd64 Rootless support for Docker. 24 | ``` 25 | 26 | **CAUTION: do not forget to add your username to the `docker` group** 27 | 28 | Otherwise you will have to run in `sudo` mode. 29 | 30 | ```bash 31 | $ sudo usermod -a -G docker myusername 32 | ``` 33 | 34 | **CAUTION: At time of writing (2021 / 02 / 01), we only support Ubuntu18.04 deployment.** 35 | 36 | Please refer to the official [docker engine installation guide page](https://docs.docker.com/engine/install/). 37 | 38 | You will get more details than here. 39 | 40 | ## 1.1. Install a recent version of `docker-compose` ## 41 | 42 | Official [installation guide](https://docs.docker.com/compose/install/). 43 | 44 | We recommend a version newer than `1.27`. 45 | 46 | # 2. Create an account on Docker Hub # 47 | 48 | Go to [https://hub.docker.com/](https://hub.docker.com/) website and create an account. 49 | 50 | # 3. Pull base images # 51 | 52 | * Ubuntu version: We need 3 base images: `ubuntu:bionic`, `cassandra:2.1` and `redis:6.0.5` 53 | 54 | First log with your Docker Hub credentials. This is required if your organization has reached pulling limit as `anonymous`. 55 | 56 | ```bash 57 | $ docker login 58 | Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one. 59 | Username: 60 | Password: 61 | ``` 62 | 63 | Then pull base images. 64 | 65 | On a Ubuntu18.04 host: 66 | 67 | ```bash 68 | $ docker pull ubuntu:bionic 69 | $ docker pull cassandra:2.1 70 | $ docker pull redis:6.0.5 71 | ``` 72 | 73 | If the `redis` tag is not available, pick the newest available `6.0.x` tag at [Docker Hub Redis Tags](https://hub.docker.com/_/redis?tab=tags). 74 | 75 | Finally you may logoff --> your token is stored in plain text.. 76 | 77 | ```bash 78 | $ docker logout 79 | ``` 80 | 81 | # 4. Network Configuration # 82 | 83 | **CAUTION: THIS FIRST STEP IS MANDATORY** 84 | 85 | Based on this [recommendation](https://docs.docker.com/network/bridge/#enable-forwarding-from-docker-containers-to-the-outside-world): 86 | 87 | ```bash 88 | $ sudo sysctl net.ipv4.conf.all.forwarding=1 89 | $ sudo iptables -P FORWARD ACCEPT 90 | ``` 91 | 92 | **CAUTION: THIS SECOND STEP MAY NOT BE NEEDED IN YOUR ENVIRONMENT.** 93 | 94 | * The default docker network (ie "bridge") is on "172.17.0.0/16" range. 95 | * In our Eurecom private network, this IP address range is already in use. 96 | - We have to change it to another IP range is free in our private network configuration. 97 | - We picked a **new/IDLE** IP range by adding a `/etc/docker/daemon.json` file: 98 | 99 | ```json 100 | { 101 | "bip": "192.168.17.1/24" 102 | } 103 | ``` 104 | 105 | Restart the docker daemon: 106 | 107 | ```bash 108 | $ sudo service docker restart 109 | $ docker info 110 | ``` 111 | 112 | Check the new network configuration: 113 | 114 | ```bash 115 | $ docker network inspect bridge 116 | [ 117 | { 118 | "Name": "bridge", 119 | .... 120 | "Scope": "local", 121 | "Driver": "bridge", 122 | "EnableIPv6": false, 123 | "IPAM": { 124 | "Driver": "default", 125 | "Options": null, 126 | "Config": [ 127 | { 128 | "Subnet": "192.168.17.1/24", 129 | "Gateway": "192.168.17.1" 130 | } 131 | ] 132 | }, 133 | .... 134 | ``` 135 | 136 | Here you have 2 choices: 137 | 138 | * You can pull official images from Docker Hub like [this](./RETRIEVE_OFFICIAL_IMAGES_MAGMA.md). 139 | * You are ready to [build yourself the images (including MAGMA-MME)](./BUILD_IMAGES_MAGMA_MME.md). 140 | 141 | -------------------------------------------------------------------------------- /docs/CONFIGURE_NETWORKS_MAGMA.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 12 | 13 |
4 | 5 | 6 | 7 | 8 | 10 | OpenAirInterface Core Network Docker Deployment : Configure Networking 11 |
14 | 15 | 16 | **TABLE OF CONTENTS** 17 | 18 | 1. [Networking](#1-networking) 19 | 2. [After Deployment](#2-after-deploying-your-cnf-containers) 20 | 21 | 22 | # 1. Networking # 23 | 24 | Accessing a Docker container from the server you've deployed it on is easy. 25 | 26 | Accessing a Docker container from another server is NOT. 27 | 28 | Here is a picture of what we will be doing: 29 | 30 | ![Block Diagram](./images/OAICN-Network-Deployment-Explanation.png) 31 | 32 | **The objective is to be able to ping the MME and SPGW-U containers from the eNB server(s)**. 33 | 34 | 35 | ## Step 1 : create a docker network on your EPC docker host. ## 36 | 37 | By just deploying the Cassandra container(s), you will create 2 docker networks: 38 | 39 | ```bash 40 | $ cd docker-compose/magma-mme-demo 41 | $ docker-compose up -d db_init 42 | Creating network "demo-oai-private-net" with the default driver 43 | Creating network "demo-oai-public-net" with the default driver 44 | Creating demo-cassandra ... done 45 | Creating demo-db-init ... done 46 | $ docker network ls 47 | NETWORK ID NAME DRIVER SCOPE 48 | db9d51755702 bridge bridge local 49 | c3605ce9dbf6 host host local 50 | 3dffd2ec9ad2 none null local 51 | a2774c5b14ee demo-oai-private-net bridge local 52 | 4a2fc2f18d63 demo-oai-public-net bridge local 53 | $ docker network inspect demo-oai-public-net 54 | [ 55 | { 56 | "Name": "demo-oai-public-net", 57 | ... 58 | "IPAM": { 59 | "Driver": "default", 60 | "Options": null, 61 | "Config": [ 62 | { 63 | "Subnet": "192.168.61.128/26" 64 | } 65 | ] 66 | }, 67 | "Internal": false, 68 | "Attachable": true, 69 | ... 70 | } 71 | ] 72 | ``` 73 | 74 | As you can see, the public network (`demo-oai-public-net`) is using the range `192.168.61.128/26`. 75 | 76 | If this IP range **DOES NOT** suit your network environment, you have a lot of editing. 77 | 78 | ## Step 2: create a route on your eNB/gNB server(s) ## 79 | 80 | In the servers that are hosting the eNB(s) and/or gNB(s), create IP route(s): 81 | 82 | The following are examples. **PLEASE ADAPT TO YOUR ENVIRONMENT.** 83 | 84 | ```bash 85 | # On minimassive 86 | sudo ip route add 192.168.61.128/26 via 192.168.18.197 dev bond0 87 | 88 | # On mozart 89 | sudo ip route add 192.168.61.128/26 via 192.168.18.197 dev nm-bond 90 | 91 | # On caracal 92 | sudo ip route add 192.168.61.128/26 via 192.168.18.197 dev nm-bond 93 | ``` 94 | 95 | - Where `192.168.18.197` is the IP address of the **Docker Host** 96 | - Where `bond0` is the **Network Interface Controller(NIC)** of the eNB server (minimassive in our case). 97 | - Where `nm-bond` is the **NIC** of the gNB server (mozart/caracal in our case). 98 | 99 | # 2. After deploying your cNF containers # 100 | 101 | Normally you did: 102 | 103 | ```bash 104 | $ docker-compose up -d oai_spgwu 105 | ``` 106 | 107 | ## Verify your network configuration ## 108 | 109 | Let make sure your routing on the eNB server is correct. 110 | 111 | **On your EPC Docker Host:** recover the MME IP address: 112 | 113 | ```bash 114 | $ docker inspect --format="{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}" demo-magma-mme 115 | 192.168.61.149 116 | ``` 117 | 118 | You can also find in the `docker-compose.yml` file. 119 | 120 | **On your eNB server:** 121 | 122 | ```bash 123 | $ ping -c 5 192.168.61.149 124 | PING 192.168.61.149 (192.168.61.149) 56(84) bytes of data. 125 | 64 bytes from 192.168.61.149: icmp_seq=1 ttl=63 time=0.306 ms 126 | 64 bytes from 192.168.61.149: icmp_seq=2 ttl=63 time=0.269 ms 127 | 64 bytes from 192.168.61.149: icmp_seq=3 ttl=63 time=0.234 ms 128 | 64 bytes from 192.168.61.149: icmp_seq=4 ttl=63 time=0.266 ms 129 | 64 bytes from 192.168.61.149: icmp_seq=5 ttl=63 time=0.233 ms 130 | 131 | --- 192.168.61.149 ping statistics --- 132 | 5 packets transmitted, 5 received, 0% packet loss, time 129ms 133 | rtt min/avg/max/mdev = 0.233/0.261/0.306/0.032 ms 134 | ``` 135 | 136 | Same thing for SPGW-U IP address: 137 | 138 | ```bash 139 | $ ping -c 5 192.168.61.133 140 | ... 141 | 5 packets transmitted, 5 received, 0% packet loss, time 129ms 142 | ... 143 | ``` 144 | 145 | **NOTE: YOU CAN TRY TO PING THE HSS CONTAINER BUT IT WON'T WORK.** 146 | 147 | You are ready to [generate some traffic](./GENERATE_TRAFFIC.md). 148 | -------------------------------------------------------------------------------- /docker-compose/magma-mme-demo/mme.conf: -------------------------------------------------------------------------------- 1 | # generated by generate_mme_config_script.py 2 | MME : 3 | { 4 | REALM = "openairinterface.org" 5 | PID_DIRECTORY = "/var/run"; 6 | MAXENB = 8; # power of 2 7 | MAXUE = 16; # power of 2 8 | RELATIVE_CAPACITY = 10; 9 | 10 | EMERGENCY_ATTACH_SUPPORTED = "no"; 11 | UNAUTHENTICATED_IMSI_SUPPORTED = "no"; 12 | 13 | # EPS network feature support 14 | EPS_NETWORK_FEATURE_SUPPORT_IMS_VOICE_OVER_PS_SESSION_IN_S1 = "no"; # DO NOT CHANGE 15 | EPS_NETWORK_FEATURE_SUPPORT_EMERGENCY_BEARER_SERVICES_IN_S1_MODE = "no"; # DO NOT CHANGE 16 | EPS_NETWORK_FEATURE_SUPPORT_LOCATION_SERVICES_VIA_EPC = "no"; # DO NOT CHANGE 17 | EPS_NETWORK_FEATURE_SUPPORT_EXTENDED_SERVICE_REQUEST = "no"; # DO NOT CHANGE 18 | 19 | # Display statistics about whole system (expressed in seconds) 20 | MME_STATISTIC_TIMER = 10; 21 | IP_CAPABILITY = "IPV4"; # UE PDN_TYPE 22 | USE_STATELESS = ""; 23 | 24 | INTERTASK_INTERFACE : 25 | { 26 | # max queue size per task 27 | ITTI_QUEUE_SIZE = 2000000; 28 | }; 29 | 30 | S6A : 31 | { 32 | S6A_CONF = "/magma-mme/etc/mme_fd.conf"; # YOUR MME freeDiameter config file path 33 | HSS_HOSTNAME = "hss.openairinterface.org"; 34 | HSS_REALM = "openairinterface.org"; 35 | }; 36 | 37 | # ------- SCTP definitions 38 | SCTP : 39 | { 40 | # Number of streams to use in input/output 41 | SCTP_INSTREAMS = 8; 42 | SCTP_OUTSTREAMS = 8; 43 | }; 44 | 45 | # ------- S1AP definitions 46 | S1AP : 47 | { 48 | # outcome drop timer value (seconds) 49 | S1AP_OUTCOME_TIMER = 10; 50 | }; 51 | 52 | # ------- MME served GUMMEIs 53 | GUMMEI_LIST = ( 54 | { MCC="222" ; MNC="01"; MME_GID="32768" ; MME_CODE="3"; } 55 | ); 56 | 57 | # ------- MME served TAIs 58 | TAI_LIST = ( 59 | {MCC="222" ; MNC="01"; TAC = "1"; }, 60 | {MCC="222" ; MNC="01"; TAC = "2"; }, 61 | {MCC="222" ; MNC="01"; TAC = "3"; } 62 | ); 63 | 64 | TAC_LIST = ( 65 | {MCC="222" ; MNC="01"; TAC = "1"; } 66 | ); 67 | 68 | CSFB : 69 | { 70 | NON_EPS_SERVICE_CONTROL = "OFF"; 71 | CSFB_MCC = "222"; 72 | CSFB_MNC = "01"; 73 | LAC = "1"; 74 | }; 75 | NAS : 76 | { 77 | ORDERED_SUPPORTED_INTEGRITY_ALGORITHM_LIST = [ "EIA2" , "EIA1" , "EIA0" ]; 78 | ORDERED_SUPPORTED_CIPHERING_ALGORITHM_LIST = [ "EEA0" , "EEA1" , "EEA2" ]; 79 | T3402 = 1 # in minutes (default is 12 minutes) 80 | T3412 = 54 # in minutes (default is 54 minutes, network dependent) 81 | T3422 = 6 # in seconds (default is 6s) 82 | T3450 = 6 # in seconds (default is 6s) 83 | T3460 = 6 # in seconds (default is 6s) 84 | T3470 = 6 # in seconds (default is 6s) 85 | T3485 = 8 # UNUSED in seconds (default is 8s) 86 | T3486 = 8 # UNUSED in seconds (default is 8s) 87 | T3489 = 4 # UNUSED in seconds (default is 4s) 88 | T3495 = 8 # UNUSED in seconds (default is 8s) 89 | }; 90 | 91 | SGS : 92 | { 93 | TS6_1 = 10 # in seconds (default is 10s) 94 | TS8 = 4 # in seconds (default is 4s) 95 | TS9 = 2 # in seconds (default is 4s) 96 | TS10 = 4 # in seconds (default is 4s) 97 | TS13 = 4 # in seconds (default is 4s) 98 | }; 99 | 100 | NETWORK_INTERFACES : 101 | { 102 | MME_INTERFACE_NAME_FOR_S1_MME = "eth0"; 103 | MME_IPV4_ADDRESS_FOR_S1_MME = "192.168.61.149/24"; 104 | MME_INTERFACE_NAME_FOR_S11_MME = "eth0"; 105 | MME_IPV4_ADDRESS_FOR_S11_MME = "192.168.61.149/24"; 106 | MME_PORT_FOR_S11_MME = 2123; 107 | }; 108 | 109 | LOGGING : 110 | { 111 | OUTPUT = "CONSOLE"; 112 | THREAD_SAFE = "no"; 113 | COLOR = "no"; 114 | 115 | SCTP_LOG_LEVEL = "ERROR"; 116 | GTPV1U_LOG_LEVEL = "INFO"; 117 | SPGW_APP_LOG_LEVEL = "INFO"; 118 | UDP_LOG_LEVEL = "INFO"; 119 | S1AP_LOG_LEVEL = "DEBUG"; 120 | NAS_LOG_LEVEL = "INFO"; 121 | MME_APP_LOG_LEVEL = "DEBUG"; 122 | GTPV2C_LOG_LEVEL = "INFO"; 123 | S11_LOG_LEVEL = "DEBUG"; 124 | S6A_LOG_LEVEL = "DEBUG"; 125 | UTIL_LOG_LEVEL = "INFO"; 126 | MSC_LOG_LEVEL = "ERROR"; 127 | ITTI_LOG_LEVEL = "ERROR"; 128 | MME_SCENARIO_PLAYER_LOG_LEVEL = "ERROR"; 129 | ASN1_VERBOSITY = "INFO"; 130 | }; 131 | 132 | S-GW : 133 | { 134 | SGW_IPV4_ADDRESS_FOR_S11 = "192.168.61.132"; 135 | }; 136 | }; 137 | -------------------------------------------------------------------------------- /ci-scripts/dsTesterDockerCompose/mme.conf.tplt: -------------------------------------------------------------------------------- 1 | # generated by generate_mme_config_script.py 2 | MME : 3 | { 4 | REALM = "openairinterface.org" 5 | PID_DIRECTORY = "/var/run"; 6 | MAXENB = 8; # power of 2 7 | MAXUE = 16; # power of 2 8 | RELATIVE_CAPACITY = 10; 9 | 10 | EMERGENCY_ATTACH_SUPPORTED = "no"; 11 | UNAUTHENTICATED_IMSI_SUPPORTED = "no"; 12 | 13 | # EPS network feature support 14 | EPS_NETWORK_FEATURE_SUPPORT_IMS_VOICE_OVER_PS_SESSION_IN_S1 = "no"; # DO NOT CHANGE 15 | EPS_NETWORK_FEATURE_SUPPORT_EMERGENCY_BEARER_SERVICES_IN_S1_MODE = "no"; # DO NOT CHANGE 16 | EPS_NETWORK_FEATURE_SUPPORT_LOCATION_SERVICES_VIA_EPC = "no"; # DO NOT CHANGE 17 | EPS_NETWORK_FEATURE_SUPPORT_EXTENDED_SERVICE_REQUEST = "no"; # DO NOT CHANGE 18 | 19 | # Display statistics about whole system (expressed in seconds) 20 | MME_STATISTIC_TIMER = 10; 21 | IP_CAPABILITY = "IPV4"; # UE PDN_TYPE 22 | USE_STATELESS = ""; 23 | 24 | INTERTASK_INTERFACE : 25 | { 26 | # max queue size per task 27 | ITTI_QUEUE_SIZE = 2000000; 28 | }; 29 | 30 | S6A : 31 | { 32 | S6A_CONF = "/magma-mme/etc/mme_fd.conf"; # YOUR MME freeDiameter config file path 33 | HSS_HOSTNAME = "hss.openairinterface.org"; 34 | HSS_REALM = "openairinterface.org"; 35 | }; 36 | 37 | # ------- SCTP definitions 38 | SCTP : 39 | { 40 | # Number of streams to use in input/output 41 | SCTP_INSTREAMS = 8; 42 | SCTP_OUTSTREAMS = 8; 43 | }; 44 | 45 | # ------- S1AP definitions 46 | S1AP : 47 | { 48 | # outcome drop timer value (seconds) 49 | S1AP_OUTCOME_TIMER = 10; 50 | }; 51 | 52 | # ------- MME served GUMMEIs 53 | GUMMEI_LIST = ( 54 | { MCC="320" ; MNC="230"; MME_GID="455" ; MME_CODE="5"; } 55 | ); 56 | 57 | # ------- MME served TAIs 58 | TAI_LIST = ( 59 | {MCC="320" ; MNC="230"; TAC = "5556"; }, 60 | {MCC="506" ; MNC="301"; TAC = "5556"; }, 61 | {MCC="505" ; MNC="300"; TAC = "5556"; }, 62 | {MCC="320" ; MNC="230"; TAC = "1235"; }, 63 | {MCC="203" ; MNC="101"; TAC = "1235"; }, 64 | {MCC="202" ; MNC="100"; TAC = "1235"; }, 65 | {MCC="506" ; MNC="301"; TAC = "5557"; }, 66 | {MCC="505" ; MNC="300"; TAC = "5557"; }, 67 | {MCC="203" ; MNC="101"; TAC = "1236"; }, 68 | {MCC="202" ; MNC="100"; TAC = "1236"; } 69 | ); 70 | 71 | TAC_LIST = ( 72 | {MCC="320" ; MNC="230"; TAC = "5556"; } 73 | ); 74 | 75 | CSFB : 76 | { 77 | NON_EPS_SERVICE_CONTROL = "OFF"; 78 | CSFB_MCC = "320"; 79 | CSFB_MNC = "230"; 80 | LAC = "1"; 81 | }; 82 | NAS : 83 | { 84 | ORDERED_SUPPORTED_INTEGRITY_ALGORITHM_LIST = [ "EIA2" , "EIA1" , "EIA0" ]; 85 | ORDERED_SUPPORTED_CIPHERING_ALGORITHM_LIST = [ "EEA0" , "EEA1" , "EEA2" ]; 86 | T3402 = 1 # in minutes (default is 12 minutes) 87 | T3412 = 54 # in minutes (default is 54 minutes, network dependent) 88 | T3422 = 6 # in seconds (default is 6s) 89 | T3450 = 6 # in seconds (default is 6s) 90 | T3460 = 6 # in seconds (default is 6s) 91 | T3470 = 6 # in seconds (default is 6s) 92 | T3485 = 8 # UNUSED in seconds (default is 8s) 93 | T3486 = 8 # UNUSED in seconds (default is 8s) 94 | T3489 = 4 # UNUSED in seconds (default is 4s) 95 | T3495 = 8 # UNUSED in seconds (default is 8s) 96 | }; 97 | 98 | SGS : 99 | { 100 | TS6_1 = 10 # in seconds (default is 10s) 101 | TS8 = 4 # in seconds (default is 4s) 102 | TS9 = 2 # in seconds (default is 4s) 103 | TS10 = 4 # in seconds (default is 4s) 104 | TS13 = 4 # in seconds (default is 4s) 105 | }; 106 | 107 | NETWORK_INTERFACES : 108 | { 109 | MME_INTERFACE_NAME_FOR_S1_MME = "eth0"; 110 | MME_IPV4_ADDRESS_FOR_S1_MME = "192.168.61.196/24"; 111 | MME_INTERFACE_NAME_FOR_S11_MME = "eth0"; 112 | MME_IPV4_ADDRESS_FOR_S11_MME = "192.168.61.196/24"; 113 | MME_PORT_FOR_S11_MME = 2123; 114 | }; 115 | 116 | LOGGING : 117 | { 118 | OUTPUT = "CONSOLE"; 119 | THREAD_SAFE = "no"; 120 | COLOR = "no"; 121 | 122 | SCTP_LOG_LEVEL = "ERROR"; 123 | GTPV1U_LOG_LEVEL = "INFO"; 124 | SPGW_APP_LOG_LEVEL = "INFO"; 125 | UDP_LOG_LEVEL = "INFO"; 126 | S1AP_LOG_LEVEL = "DEBUG"; 127 | NAS_LOG_LEVEL = "DEBUG"; 128 | MME_APP_LOG_LEVEL = "DEBUG"; 129 | GTPV2C_LOG_LEVEL = "DEBUG"; 130 | S11_LOG_LEVEL = "DEBUG"; 131 | S6A_LOG_LEVEL = "DEBUG"; 132 | UTIL_LOG_LEVEL = "INFO"; 133 | MSC_LOG_LEVEL = "ERROR"; 134 | ITTI_LOG_LEVEL = "ERROR"; 135 | MME_SCENARIO_PLAYER_LOG_LEVEL = "ERROR"; 136 | ASN1_VERBOSITY = "INFO"; 137 | }; 138 | 139 | S-GW : 140 | { 141 | SGW_IPV4_ADDRESS_FOR_S11 = "192.168.61.197"; 142 | }; 143 | }; 144 | -------------------------------------------------------------------------------- /docker-compose/magma-mme-demo/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.8' 2 | 3 | services: 4 | cassandra: 5 | image: cassandra:2.1 6 | container_name: demo-cassandra 7 | networks: 8 | private_net: 9 | ipv4_address: 192.168.68.130 10 | environment: 11 | CASSANDRA_CLUSTER_NAME: "OAI HSS Cluster" 12 | CASSANDRA_ENDPOINT_SNITCH: GossipingPropertyFileSnitch 13 | healthcheck: 14 | test: /bin/bash -c "nodetool status" 15 | interval: 10s 16 | timeout: 5s 17 | retries: 5 18 | 19 | db_init: 20 | image: cassandra:2.1 21 | container_name: demo-db-init 22 | depends_on: [cassandra] 23 | deploy: 24 | restart_policy: 25 | condition: on-failure 26 | max_attempts: 10 27 | networks: 28 | private_net: 29 | ipv4_address: 192.168.68.132 30 | volumes: 31 | - ../../component/oai-hss/src/hss_rel14/db/oai_db.cql:/home/oai_db.cql 32 | entrypoint: /bin/bash -c "cqlsh --file /home/oai_db.cql 192.168.68.130 && echo 'OK'" 33 | 34 | oai_hss: 35 | image: oai-hss:production 36 | container_name: demo-oai-hss 37 | privileged: true 38 | depends_on: [cassandra] 39 | networks: 40 | private_net: 41 | ipv4_address: 192.168.68.131 42 | public_net: 43 | ipv4_address: 192.168.61.130 44 | environment: 45 | TZ: Europe/Paris 46 | REALM: openairinterface.org 47 | HSS_FQDN: hss.openairinterface.org 48 | PREFIX: /openair-hss/etc 49 | cassandra_Server_IP: 192.168.68.130 50 | OP_KEY: 1006020f0a478bf6b699f15c062e42b3 51 | LTE_K: fec86ba6eb707ed08905757b1bb44b8f 52 | APN1: oai.ipv4 53 | APN2: oai2.ipv4 54 | FIRST_IMSI: 222010100001120 55 | NB_USERS: 30 56 | healthcheck: 57 | test: /bin/bash -c "pgrep oai_hss" 58 | interval: 10s 59 | timeout: 5s 60 | retries: 5 61 | 62 | redis: 63 | image: redis:6.0.5 64 | container_name: demo-redis 65 | privileged: true 66 | networks: 67 | public_net: 68 | ipv4_address: 192.168.61.148 69 | volumes: 70 | - ./redis_extern.conf:/usr/local/etc/redis/redis.conf 71 | entrypoint: /bin/bash -c "redis-server /usr/local/etc/redis/redis.conf" 72 | healthcheck: 73 | test: /bin/bash -c "redis-cli -h 192.168.61.148 -p 6380 ping" 74 | interval: 10s 75 | timeout: 5s 76 | retries: 5 77 | 78 | magma_mme: 79 | image: magma-mme:master 80 | container_name: demo-magma-mme 81 | hostname: mme 82 | privileged: true 83 | depends_on: [oai_hss, redis] 84 | networks: 85 | public_net: 86 | ipv4_address: 192.168.61.149 87 | environment: 88 | TZ: Europe/Paris 89 | REALM: openairinterface.org 90 | PREFIX: /openair-mme/etc 91 | HSS_HOSTNAME: hss 92 | HSS_FQDN: hss.openairinterface.org 93 | HSS_REALM: openairinterface.org 94 | MME_FQDN: mme.openairinterface.org 95 | FEATURES: mme_oai 96 | volumes: 97 | - ./mme_fd.sprint.conf:/magma-mme/etc/mme_fd.conf.tmplt 98 | - ./mme.conf:/magma-mme/etc/mme.conf 99 | - ./mme-cfg.sh:/magma-mme/scripts/mme-cfg.sh 100 | entrypoint: /bin/bash -c "cd /magma-mme/scripts; ./mme-cfg.sh" 101 | healthcheck: 102 | test: /bin/bash -c "pgrep oai_mme" 103 | interval: 10s 104 | timeout: 5s 105 | retries: 5 106 | 107 | oai_spgwc: 108 | image: oai-spgwc:production 109 | privileged: true 110 | depends_on: [magma_mme] 111 | container_name: demo-oai-spgwc 112 | networks: 113 | public_net: 114 | ipv4_address: 192.168.61.132 115 | environment: 116 | TZ: Europe/Paris 117 | SGW_INTERFACE_NAME_FOR_S11: eth0 118 | PGW_INTERFACE_NAME_FOR_SX: eth0 119 | DEFAULT_DNS_IPV4_ADDRESS: 192.168.18.129 120 | DEFAULT_DNS_SEC_IPV4_ADDRESS: 8.8.4.4 121 | PUSH_PROTOCOL_OPTION: 'true' 122 | APN_NI_1: oai.ipv4 123 | APN_NI_2: oai2.ipv4 124 | DEFAULT_APN_NI_1: oai.ipv4 125 | UE_IP_ADDRESS_POOL_1: '12.1.1.2 - 12.1.1.254' 126 | UE_IP_ADDRESS_POOL_2: '12.0.0.2 - 12.0.0.254' 127 | UE_MTU_IPV4: 1500 128 | MCC: '222' 129 | MNC: '01' 130 | MNC03: '001' 131 | TAC: 1 132 | GW_ID: 1 133 | REALM: openairinterface.org 134 | healthcheck: 135 | test: /bin/bash -c "pgrep oai_spgwc" 136 | interval: 10s 137 | timeout: 5s 138 | retries: 5 139 | 140 | oai_spgwu: 141 | image: oai-spgwu-tiny:production 142 | privileged: true 143 | container_name: demo-oai-spgwu-tiny 144 | depends_on: [oai_spgwc] 145 | networks: 146 | public_net: 147 | ipv4_address: 192.168.61.133 148 | environment: 149 | TZ: Europe/Paris 150 | PID_DIRECTORY: /var/run 151 | INSTANCE: 1 152 | SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP: eth0 153 | PGW_INTERFACE_NAME_FOR_SGI: eth0 154 | SGW_INTERFACE_NAME_FOR_SX: eth0 155 | SPGWC0_IP_ADDRESS: 192.168.61.132 156 | NETWORK_UE_IP: '12.1.1.0/24' 157 | NETWORK_UE_NAT_OPTION: 'yes' 158 | MCC: '222' 159 | MNC: '01' 160 | MNC03: '001' 161 | TAC: 1 162 | GW_ID: 1 163 | REALM: openairinterface.org 164 | healthcheck: 165 | test: /bin/bash -c "pgrep oai_spgwu" 166 | interval: 10s 167 | timeout: 5s 168 | retries: 5 169 | 170 | trf_gen: 171 | image: trf-gen:production 172 | privileged: true 173 | container_name: demo-trf-gen 174 | networks: 175 | public_net: 176 | ipv4_address: 192.168.61.139 177 | entrypoint: /bin/bash -c "ip route add 12.1.1.0/24 via 192.168.61.133 dev eth0; sleep infinity" 178 | healthcheck: 179 | test: /bin/bash -c "ping -c 2 192.168.61.133" 180 | interval: 10s 181 | timeout: 5s 182 | retries: 5 183 | 184 | networks: 185 | private_net: 186 | name: demo-oai-private-net 187 | ipam: 188 | config: 189 | - subnet: 192.168.68.128/26 190 | public_net: 191 | name: demo-oai-public-net 192 | ipam: 193 | config: 194 | - subnet: 192.168.61.128/26 195 | -------------------------------------------------------------------------------- /ci-scripts/jenkinsStats.py: -------------------------------------------------------------------------------- 1 | import sys # arg 2 | import re # reg 3 | import time # sleep 4 | import os 5 | import subprocess 6 | import time 7 | 8 | class JenkinsStats: 9 | def __init__(self): 10 | self.url = '' 11 | self.jobName = '' 12 | self.nbDays = 1 13 | 14 | def doStatsOnJob(self): 15 | lastBuildId = subprocess.check_output('curl --silent ' + self.url + '/job/' + self.jobName + '/api/json | jq .lastBuild.number', shell=True, universal_newlines=True) 16 | lastBuildId = int(lastBuildId.strip()) 17 | print('Last job ID was ' + str(lastBuildId)) 18 | 19 | doLoop = True 20 | jobId = lastBuildId 21 | foundTodayMasterRun = False 22 | foundYesterdayMasterRun = False 23 | nbPullRequestJobs = 0 24 | nbSuccessFull = 0 25 | nbFailed = 0 26 | nbBypassJobs = 0 27 | duration = 0 28 | bypassDuration = 0 29 | fullDuration = 0 30 | waitLockDuration = 0 31 | todayMasterStatus = False 32 | todayMasterDuration = 0 33 | masterCount = 0 34 | masterDuration = 0 35 | 36 | while doLoop: 37 | print('Stats on job #' + str(jobId)) 38 | subprocess.run('curl --silent ' + self.url + '/job/' + self.jobName + '/' + str(jobId) + '/api/json | jq . > jobsStats.json', shell=True) 39 | buildCause = subprocess.check_output('cat jobsStats.json | jq .actions[0].causes', shell=True, universal_newlines=True) 40 | if re.search('UpstreamCause', str(buildCause)) is not None: 41 | if not foundTodayMasterRun: 42 | foundTodayMasterRun = True 43 | status = subprocess.check_output('cat jobsStats.json | jq .result', shell=True, universal_newlines=True) 44 | if re.search('SUCCESS', str(status)) is not None: 45 | todayMasterStatus = True 46 | jobDuration = subprocess.check_output('cat jobsStats.json | jq .duration', shell=True, universal_newlines=True) 47 | jobDuration = int(jobDuration.strip()) 48 | todayMasterDuration = jobDuration / 1000 49 | masterDuration = jobDuration / 1000 50 | elif not foundYesterdayMasterRun: 51 | masterCount += 1 52 | if masterCount == self.nbDays: 53 | foundYesterdayMasterRun = True 54 | doLoop = False 55 | else: 56 | jobDuration = subprocess.check_output('cat jobsStats.json | jq .duration', shell=True, universal_newlines=True) 57 | jobDuration = int(jobDuration.strip()) 58 | masterDuration += jobDuration / 1000 59 | elif (re.search('GhprbCause', str(buildCause)) is not None) and foundTodayMasterRun: 60 | nbPullRequestJobs +=1 61 | status = subprocess.check_output('cat jobsStats.json | jq .result', shell=True, universal_newlines=True) 62 | if re.search('SUCCESS', str(status)) is not None: 63 | nbSuccessFull += 1 64 | else: 65 | nbFailed += 1 66 | jobDuration = subprocess.check_output('cat jobsStats.json | jq .duration', shell=True, universal_newlines=True) 67 | jobDuration = int(jobDuration.strip()) 68 | duration += (jobDuration / 1000) 69 | lockTime = subprocess.check_output('curl --silent ' + self.url + '/job/' + self.jobName + '/' + str(jobId) + '/console | grep CI-Orion-Build-Sanity-Check-Deploy-Test', shell=True, universal_newlines=True) 70 | for lockLine in str(lockTime).split('\n'): 71 | if re.search('Trying to acquire lock on', lockLine) is not None: 72 | ret = re.search('(?P[0-9:]+)', lockLine) 73 | if ret is not None: 74 | timestamp = ret.group('timestamp') 75 | lockStart = time.strptime(timestamp, "%H:%M:%S") 76 | if re.search('Lock acquired on', lockLine) is not None: 77 | ret = re.search('(?P[0-9:]+)', lockLine) 78 | if ret is not None: 79 | timestamp = ret.group('timestamp') 80 | lockEnd = time.strptime(timestamp, "%H:%M:%S") 81 | lockDuration = time.mktime(lockEnd) - time.mktime(lockStart) 82 | waitLockDuration += lockDuration 83 | jobDuration -= (lockDuration * 1000) 84 | # if job ran for less than 90 seconds, it is certainly a bypass 85 | if jobDuration < 90000: 86 | nbBypassJobs += 1 87 | bypassDuration += (jobDuration / 1000) 88 | else: 89 | fullDuration += (jobDuration / 1000) 90 | jobId = subprocess.check_output('cat jobsStats.json | jq .previousBuild.number', shell=True, universal_newlines=True) 91 | jobId = int(jobId.strip()) 92 | 93 | print ('---------------------------------------------------------') 94 | print ('Statistics on = ' + str(self.nbDays) + ' last day(s)') 95 | print ('---------------------------------------------------------') 96 | print ('nbPullRequestJobs = ' + str(nbPullRequestJobs)) 97 | print ('nbSuccessFul = ' + str(nbSuccessFull)) 98 | print ('nbFailed = ' + str(nbFailed)) 99 | print ('nbBypassJobs = ' + str(nbBypassJobs)) 100 | print ('---------------------------------------------------------') 101 | duration = duration + masterDuration 102 | print ('Full Usage = ' + ('%.1f' % duration) + ' seconds (' + ('%.1f' % (duration/3600)) + ' hours)') 103 | print ('Wait Usage = ' + ('%.1f' % waitLockDuration) + ' seconds (' + ('%.1f' % (waitLockDuration/3600)) + ' hours)') 104 | waitLockDuration = int(waitLockDuration) 105 | print ('Real Usage = ' + ('%.1f' % ((duration-waitLockDuration)/(3600))) + ' hours (Rate = ' + ('%.1f' % ((100*(duration-waitLockDuration))/(3600*24*self.nbDays))) + '%)') 106 | print ('---------------------------------------------------------') 107 | print ('Bypass Avg Duration = ' + ('%.1f' % (bypassDuration/nbBypassJobs)) + ' seconds') 108 | print ('Full Avg Duration = ' + ('%.1f' % (fullDuration/(nbPullRequestJobs-nbBypassJobs))) + ' seconds') 109 | print (' = ' + ('%.1f' % (fullDuration/((nbPullRequestJobs-nbBypassJobs)*60))) + ' minutes') 110 | print ('---------------------------------------------------------') 111 | if todayMasterStatus: 112 | print ('Today Master Check = SUCCESS') 113 | else: 114 | print ('Today Master Check = FAILURE') 115 | print ('Today Master Time = ' + ('%.1f' % (todayMasterDuration/60)) + ' minutes') 116 | 117 | #-------------------------------------------------------------------------------------------------------- 118 | # 119 | # Start of main 120 | # 121 | #-------------------------------------------------------------------------------------------------------- 122 | 123 | STATS = JenkinsStats() 124 | STATS.url = 'https://jenkins-oai.eurecom.fr' 125 | STATS.jobName = 'MAGMA-MME-production' 126 | 127 | STATS.doStatsOnJob() 128 | -------------------------------------------------------------------------------- /ci-scripts/dsTesterDockerCompose/docker-compose.tplt: -------------------------------------------------------------------------------- 1 | version: '3.8' 2 | 3 | services: 4 | cicd_cassandra: 5 | image: cassandra:2.1 6 | container_name: cicd-cassandra 7 | networks: 8 | cicd_private_net: 9 | ipv4_address: 192.168.68.2 10 | environment: 11 | CASSANDRA_CLUSTER_NAME: "OAI HSS Cluster" 12 | CASSANDRA_ENDPOINT_SNITCH: GossipingPropertyFileSnitch 13 | healthcheck: 14 | test: /bin/bash -c "nodetool status" 15 | interval: 10s 16 | timeout: 5s 17 | retries: 5 18 | 19 | cicd_db_init: 20 | image: cassandra:2.1 21 | container_name: cicd-db-init 22 | depends_on: [cicd_cassandra] 23 | deploy: 24 | restart_policy: 25 | condition: on-failure 26 | max_attempts: 10 27 | networks: 28 | cicd_private_net: 29 | ipv4_address: 192.168.68.4 30 | volumes: 31 | - ./oai_db.cql:/home/oai_db.cql 32 | entrypoint: /bin/bash -c "cqlsh --file /home/oai_db.cql 192.168.68.2 && echo 'OK'" 33 | 34 | cicd_oai_hss: 35 | image: oai-hss:HSS_IMAGE_TAG 36 | container_name: cicd-oai-hss 37 | privileged: true 38 | depends_on: [cicd_cassandra] 39 | networks: 40 | cicd_private_net: 41 | ipv4_address: 192.168.68.3 42 | cicd_public_net: 43 | ipv4_address: 192.168.61.194 44 | environment: 45 | TZ: Europe/Paris 46 | REALM: openairinterface.org 47 | HSS_FQDN: hss.openairinterface.org 48 | PREFIX: /openair-hss/etc 49 | cassandra_Server_IP: 192.168.68.2 50 | OP_KEY: 63bfa50ee6523365ff14c1f45f88737d 51 | LTE_K: 0c0a34601d4f07677303652c0462535b 52 | APN1: apn1.carrier.com 53 | APN2: apn2.carrier.com 54 | FIRST_IMSI: 100000000000001 55 | NB_USERS: 200 56 | volumes: 57 | - ./hss-entrypoint-sleep.sh:/openair-hss/bin/hss-entrypoint-sleep.sh 58 | - ./hss-healthy-check.sh:/openair-hss/bin/hss-healthy-check.sh 59 | entrypoint: /bin/bash -c "/openair-hss/bin/hss-entrypoint-sleep.sh" 60 | healthcheck: 61 | test: /bin/bash -c "/openair-hss/bin/hss-healthy-check.sh" 62 | interval: 10s 63 | timeout: 5s 64 | retries: 5 65 | 66 | cicd_redis: 67 | image: redis:6.0.5 68 | container_name: cicd-redis 69 | privileged: true 70 | networks: 71 | cicd_public_net: 72 | ipv4_address: 192.168.61.195 73 | volumes: 74 | - ./redis_extern.conf:/usr/local/etc/redis/redis.conf 75 | entrypoint: /bin/bash -c "redis-server /usr/local/etc/redis/redis.conf" 76 | healthcheck: 77 | test: /bin/bash -c "redis-cli -h 192.168.61.195 -p 6380 ping" 78 | interval: 10s 79 | timeout: 5s 80 | retries: 5 81 | 82 | cicd_magma_mme: 83 | image: magma-mme:MAGMA_MME_IMAGE_TAG 84 | container_name: cicd-oai-mme 85 | hostname: mme 86 | privileged: true 87 | depends_on: [cicd_oai_hss, cicd_redis] 88 | networks: 89 | cicd_public_net: 90 | ipv4_address: 192.168.61.196 91 | environment: 92 | TZ: Europe/Paris 93 | REALM: openairinterface.org 94 | PREFIX: /openair-mme/etc 95 | HSS_HOSTNAME: hss 96 | HSS_FQDN: hss.openairinterface.org 97 | HSS_REALM: openairinterface.org 98 | MME_FQDN: mme.openairinterface.org 99 | FEATURES: mme_oai 100 | volumes: 101 | - ./mme_fd.sprint.conf:/magma-mme/etc/mme_fd.conf.tmplt 102 | - ./mme.conf:/magma-mme/etc/mme.conf 103 | - ./mme-cfg.sh:/magma-mme/scripts/mme-cfg.sh 104 | - ./mme-healthy-check.sh:/magma-mme/bin/mme-healthy-check.sh 105 | entrypoint: /bin/bash -c "cd /magma-mme/scripts; ./mme-cfg.sh" 106 | healthcheck: 107 | test: /bin/bash -c "/magma-mme/bin/mme-healthy-check.sh" 108 | interval: 10s 109 | timeout: 5s 110 | retries: 5 111 | 112 | cicd_oai_spgwc: 113 | image: oai-spgwc:SPGWC_IMAGE_TAG 114 | privileged: true 115 | depends_on: [cicd_magma_mme] 116 | container_name: cicd-oai-spgwc 117 | networks: 118 | cicd_public_net: 119 | ipv4_address: 192.168.61.197 120 | environment: 121 | TZ: Europe/Paris 122 | SGW_INTERFACE_NAME_FOR_S11: eth0 123 | PGW_INTERFACE_NAME_FOR_SX: eth0 124 | DEFAULT_DNS_IPV4_ADDRESS: 192.168.18.129 125 | DEFAULT_DNS_SEC_IPV4_ADDRESS: 8.8.4.4 126 | PUSH_PROTOCOL_OPTION: 'true' 127 | APN_NI_1: apn1.carrier.com 128 | APN_NI_2: apn2.carrier.com 129 | DEFAULT_APN_NI_1: apn1.carrier.com 130 | UE_IP_ADDRESS_POOL_1: '12.0.0.2 - 12.0.0.254' 131 | UE_IP_ADDRESS_POOL_2: '12.1.1.2 - 12.1.1.254' 132 | MCC: 320 133 | MNC: 230 134 | MNC03: '230' 135 | TAC: 5556 136 | GW_ID: 1 137 | REALM: openairinterface.org 138 | volumes: 139 | - ./spgwc-entrypoint-sleep.sh:/openair-spgwc/bin/spgwc-entrypoint-sleep.sh 140 | - ./spgwc-healthy-check.sh:/openair-spgwc/bin/spgwc-healthy-check.sh 141 | entrypoint: /bin/bash -c "/openair-spgwc/bin/spgwc-entrypoint-sleep.sh" 142 | healthcheck: 143 | test: /bin/bash -c "/openair-spgwc/bin/spgwc-healthy-check.sh" 144 | interval: 10s 145 | timeout: 5s 146 | retries: 5 147 | 148 | cicd_oai_spgwu: 149 | image: oai-spgwu-tiny:SPGWU_IMAGE_TAG 150 | privileged: true 151 | container_name: cicd-oai-spgwu-tiny 152 | depends_on: [cicd_oai_spgwc] 153 | networks: 154 | cicd_public_net: 155 | ipv4_address: 192.168.61.198 156 | environment: 157 | TZ: Europe/Paris 158 | PID_DIRECTORY: /var/run 159 | INSTANCE: 1 160 | SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP: eth0 161 | PGW_INTERFACE_NAME_FOR_SGI: eth0 162 | SGW_INTERFACE_NAME_FOR_SX: eth0 163 | SPGWC0_IP_ADDRESS: 192.168.61.197 164 | NETWORK_UE_IP: '12.0.0.0/24' 165 | NETWORK_UE_NAT_OPTION: 'yes' 166 | MCC: 320 167 | MNC: 230 168 | MNC03: '230' 169 | TAC: 5556 170 | GW_ID: 1 171 | REALM: openairinterface.org 172 | volumes: 173 | - ./spgwu-entrypoint-sleep.sh:/openair-spgwu-tiny/bin/spgwu-entrypoint-sleep.sh 174 | - ./spgwu-healthy-check.sh:/openair-spgwu-tiny/bin/spgwu-healthy-check.sh 175 | entrypoint: /bin/bash -c "/openair-spgwu-tiny/bin/spgwu-entrypoint-sleep.sh" 176 | healthcheck: 177 | test: /bin/bash -c "/openair-spgwu-tiny/bin/spgwu-healthy-check.sh" 178 | interval: 10s 179 | timeout: 5s 180 | retries: 5 181 | 182 | networks: 183 | cicd_private_net: 184 | name: cicd-oai-private-net 185 | ipam: 186 | config: 187 | - subnet: 192.168.68.0/26 188 | cicd_public_net: 189 | name: cicd-oai-public-net 190 | ipam: 191 | config: 192 | - subnet: 192.168.61.192/26 193 | -------------------------------------------------------------------------------- /docker-compose/inria-oai-mme-legacy/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.8' 2 | 3 | services: 4 | cassandra: 5 | image: cassandra:2.1 6 | container_name: prod-cassandra 7 | networks: 8 | private_net: 9 | ipv4_address: 192.168.68.2 10 | environment: 11 | CASSANDRA_CLUSTER_NAME: "OAI HSS Cluster" 12 | CASSANDRA_ENDPOINT_SNITCH: GossipingPropertyFileSnitch 13 | healthcheck: 14 | test: /bin/bash -c "nodetool status" 15 | interval: 10s 16 | timeout: 5s 17 | retries: 5 18 | 19 | db_init: 20 | image: cassandra:2.1 21 | container_name: prod-db-init 22 | depends_on: [cassandra] 23 | deploy: 24 | restart_policy: 25 | condition: on-failure 26 | max_attempts: 10 27 | networks: 28 | private_net: 29 | ipv4_address: 192.168.68.4 30 | volumes: 31 | - ../../component/oai-hss/src/hss_rel14/db/oai_db.cql:/home/oai_db.cql 32 | entrypoint: /bin/bash -c "cqlsh --file /home/oai_db.cql prod-cassandra && echo 'OK'" 33 | 34 | oai_hss: 35 | image: oai-hss:production 36 | container_name: prod-oai-hss 37 | privileged: true 38 | depends_on: [cassandra] 39 | networks: 40 | private_net: 41 | ipv4_address: 192.168.68.3 42 | public_net: 43 | ipv4_address: 192.168.61.194 44 | environment: 45 | REALM: openairinterface.org 46 | HSS_FQDN: hss.openairinterface.org 47 | PREFIX: /openair-hss/etc 48 | cassandra_Server_IP: prod-cassandra 49 | OP_KEY: 11111111111111111111111111111111 50 | LTE_K: 8baf473f2f8fd09487cccbd7097c6862 51 | APN1: oai.ipv4 52 | APN2: internet 53 | FIRST_IMSI: 208950000000002 54 | NB_USERS: 10 55 | healthcheck: 56 | test: /bin/bash -c "pgrep oai_hss" 57 | interval: 10s 58 | timeout: 5s 59 | retries: 5 60 | 61 | oai_mme: 62 | image: oai-mme:production 63 | container_name: prod-oai-mme 64 | privileged: true 65 | depends_on: [oai_hss] 66 | networks: 67 | public_net: 68 | ipv4_address: 192.168.61.195 69 | environment: 70 | REALM: openairinterface.org 71 | PREFIX: /openair-mme/etc 72 | INSTANCE: 1 73 | PID_DIRECTORY: /var/run 74 | HSS_IP_ADDR: 192.168.61.194 75 | HSS_HOSTNAME: hss 76 | HSS_FQDN: hss.openairinterface.org 77 | HSS_REALM: openairinterface.org 78 | MCC: '208' 79 | MNC: '95' 80 | MME_GID: 32768 81 | MME_CODE: 3 82 | TAC_0: 1 83 | TAC_1: 2 84 | TAC_2: 3 85 | MME_FQDN: mme.openairinterface.org 86 | MME_S6A_IP_ADDR: 192.168.61.195 87 | MME_INTERFACE_NAME_FOR_S1_MME: eth0 88 | MME_IPV4_ADDRESS_FOR_S1_MME: 192.168.61.195 89 | MME_INTERFACE_NAME_FOR_S11: eth0 90 | MME_IPV4_ADDRESS_FOR_S11: 192.168.61.195 91 | MME_INTERFACE_NAME_FOR_S10: lo 92 | MME_IPV4_ADDRESS_FOR_S10: 127.0.0.10 93 | OUTPUT: CONSOLE 94 | SGW_IPV4_ADDRESS_FOR_S11_0: 192.168.61.196 95 | PEER_MME_IPV4_ADDRESS_FOR_S10_0: 0.0.0.0 96 | PEER_MME_IPV4_ADDRESS_FOR_S10_1: 0.0.0.0 97 | MCC_SGW_0: '208' 98 | MNC3_SGW_0: '095' 99 | TAC_LB_SGW_0: '01' 100 | TAC_HB_SGW_0: '00' 101 | MCC_MME_0: '208' 102 | MNC3_MME_0: '095' 103 | TAC_LB_MME_0: '02' 104 | TAC_HB_MME_0: '00' 105 | MCC_MME_1: '208' 106 | MNC3_MME_1: '095' 107 | TAC_LB_MME_1: '03' 108 | TAC_HB_MME_1: '00' 109 | TAC_LB_SGW_TEST_0: '03' 110 | TAC_HB_SGW_TEST_0: '00' 111 | SGW_IPV4_ADDRESS_FOR_S11_TEST_0: 0.0.0.0 112 | healthcheck: 113 | test: /bin/bash -c "pgrep oai_mme" 114 | interval: 10s 115 | timeout: 5s 116 | retries: 5 117 | 118 | oai_spgwc: 119 | image: oai-spgwc:2021.w40 120 | privileged: true 121 | depends_on: [oai_mme] 122 | container_name: prod-oai-spgwc 123 | networks: 124 | public_net: 125 | ipv4_address: 192.168.61.196 126 | environment: 127 | TZ: Europe/Paris 128 | SGW_INTERFACE_NAME_FOR_S11: eth0 129 | PGW_INTERFACE_NAME_FOR_SX: eth0 130 | DEFAULT_DNS_IPV4_ADDRESS: 193.51.196.138 131 | DEFAULT_DNS_SEC_IPV4_ADDRESS: 138.96.0.210 132 | PUSH_PROTOCOL_OPTION: 'true' 133 | APN_NI_1: oai.ipv4 134 | APN_NI_2: oai2.ipv4 135 | DEFAULT_APN_NI_1: oai.ipv4 136 | UE_IP_ADDRESS_POOL_1: '12.1.1.2 - 12.1.1.254' 137 | UE_IP_ADDRESS_POOL_2: '12.0.0.2 - 12.0.0.254' 138 | UE_MTU_IPV4: 1500 139 | MCC: '208' 140 | MNC: '95' 141 | MNC03: '095' 142 | TAC: 1 143 | GW_ID: 1 144 | REALM: openairinterface.org 145 | healthcheck: 146 | test: /bin/bash -c "pgrep oai_spgwc" 147 | interval: 10s 148 | timeout: 5s 149 | retries: 5 150 | 151 | oai_spgwu: 152 | image: oai-spgwu-tiny:2021.w40 153 | privileged: true 154 | container_name: prod-oai-spgwu-tiny 155 | depends_on: [oai_spgwc] 156 | networks: 157 | public_net: 158 | ipv4_address: 192.168.61.197 159 | environment: 160 | TZ: Europe/Paris 161 | PID_DIRECTORY: /var/run 162 | INSTANCE: 1 163 | SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP: eth0 164 | PGW_INTERFACE_NAME_FOR_SGI: eth0 165 | SGW_INTERFACE_NAME_FOR_SX: eth0 166 | SPGWC0_IP_ADDRESS: 192.168.61.196 167 | NETWORK_UE_IP: '12.1.1.0/24' 168 | NETWORK_UE_NAT_OPTION: 'yes' 169 | MCC: '208' 170 | MNC: '95' 171 | MNC03: '095' 172 | TAC: 1 173 | GW_ID: 1 174 | REALM: openairinterface.org 175 | healthcheck: 176 | test: /bin/bash -c "pgrep oai_spgwu" 177 | interval: 10s 178 | timeout: 5s 179 | retries: 5 180 | 181 | trf_gen: 182 | image: trf-gen:production 183 | privileged: true 184 | container_name: prod-trf-gen 185 | networks: 186 | public_net: 187 | ipv4_address: 192.168.61.198 188 | entrypoint: /bin/bash -c "ip route add 12.1.1.0/24 via 192.168.61.197 dev eth0; sleep infinity" 189 | healthcheck: 190 | #test: /bin/bash -c "ping -c 2 192.168.61.197" 191 | test: /bin/bash -c "ip route | grep -c 12.1.1.0/24" 192 | interval: 10s 193 | timeout: 5s 194 | retries: 5 195 | 196 | networks: 197 | private_net: 198 | name: prod-oai-private-net 199 | ipam: 200 | config: 201 | - subnet: 192.168.68.0/26 202 | driver_opts: 203 | com.docker.network.bridge.name: "cn4g-priv" 204 | public_net: 205 | name: prod-oai-public-net 206 | ipam: 207 | config: 208 | - subnet: 192.168.61.192/26 209 | driver_opts: 210 | com.docker.network.bridge.name: "cn4g-public" 211 | 212 | -------------------------------------------------------------------------------- /docs/BUILD_IMAGES.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 12 | 13 |
4 | 5 | 6 | 7 | 8 | 10 | OpenAirInterface Core Network Docker Deployment : Building the Images 11 |
14 | 15 | # 1. Retrieve the proper code version # 16 | 17 | **CAUTION: PLEASE READ THIS SECTION VERY CAREFULLY!** 18 | 19 | This repository only has tutorials and Continuous Integration scripts. 20 | 21 | Each 4G Network Function source code is managed in its own repository. 22 | 23 | They are called as git sub-modules in the component folder. 24 | 25 | Before doing anything, you SHALL retrieve the code for each git sub-module. 26 | 27 | ## 1.1. You are interested on a very stable version. ## 28 | 29 | We recommend to synchronize with the master branches on all git sub-modules. 30 | 31 | We also recommend that you synchronize this "tutorial" repository with a provided tag. By doing so, the `docker-compose` files will be aligned with feature sets of each NF. 32 | 33 | **At the time of writing (2022/02/25), the release tag is v1.2.0.** 34 | 35 | | CNF Name | Branch Name | Tag | Ubuntu 18.04 | RHEL8 (UBI8) | 36 | | ----------- | ----------- | ---------- | ------------ | ----------------| 37 | | FED REPO | N/A | `v1.1.2` | | | 38 | | HSS | `master` | `v1.1.2` | X | X | 39 | | SPWG-C | `master` | `v1.1.2` | X | X | 40 | | SPGW-U-TINY | `master` | `v1.1.2` | X | X | 41 | | MAGMA-MME | `master` | `N/A` | X | X | 42 | 43 | ```bash 44 | # Clone directly on the latest release tag 45 | $ git clone --branch v1.2.0 https://github.com/OPENAIRINTERFACE/openair-epc-fed.git 46 | $ cd openair-epc-fed 47 | # If you forgot to clone directly to the latest release tag 48 | $ git checkout -f v1.2.0 49 | 50 | # Synchronize all git submodules 51 | $ ./scripts/syncComponents.sh 52 | --------------------------------------------------------- 53 | OAI-HSS component branch : master 54 | OAI-SPGW-C component branch : master 55 | OAI-SPGW-U component branch : master 56 | --------------------------------------------------------- 57 | git submodule deinit --all --force 58 | git submodule init 59 | git submodule update 60 | ``` 61 | 62 | ## 1.2. You are interested on the latest features. ## 63 | 64 | All the latest features are somehow pushed to the `develop` branches of each NF repository. 65 | 66 | It means that we/you are able to build and the Continuous Integration test suite makes sure it 67 | does NOT break any existing tested feature. 68 | 69 | Anyhow, the tutorials' docker-compose files on the latest commit of the `master` branch of 70 | `openair-epc-fed` repository SHALL support any additional un-tested feature. 71 | 72 | ```bash 73 | # Clone 74 | $ git clone https://gitlab.eurecom.fr/oai/cn5g/oai-cn5g-fed.git 75 | $ cd oai-cn5g-fed 76 | # On an existing repository, resync to the last `master` commit 77 | $ git fetch --prune 78 | $ git checkout master 79 | $ git rebase origin/master 80 | 81 | # Synchronize all git submodules 82 | $ ./scripts/syncComponents.sh --hss-branch develop \ 83 | --spgwc-branch develop --spgwu-tiny-branch develop 84 | --------------------------------------------------------- 85 | OAI-HSS component branch : develop 86 | OAI-SPGW-C component branch : develop 87 | OAI-SPGW-U component branch : develop 88 | --------------------------------------------------------- 89 | git submodule deinit --all --force 90 | git submodule init 91 | git submodule update 92 | ``` 93 | 94 | **CAUTION: At the time of writing (2020 / 10 / 26), only HSS and MME have a full CentOS-7 support.** 95 | 96 | It means that if you are on a CentOS 7 host, you will need to build a CentOS8 image of SPGW-C / SPGW-U-TINY. 97 | 98 | **CAUTION: (2021 / 07 / 28): CentOS dockerfiles are not part of the OAI CI process. They are certainly in need of maintenance.** 99 | 100 | # 2. Generic Parameters # 101 | 102 | Here in our network configuration, we need to pass the "GIT PROXY" configuration. 103 | 104 | * If you do not need, remove the `--build-arg EURECOM_PROXY=".."` option. 105 | * If you do need it, change with your proxy value. 106 | 107 | If you have re-building CN4G images, be careful that `docker` or `podman` may re-use `cached` blobs 108 | to construct the intermediate layers. 109 | 110 | We recommend to add the `--no-cache` option in that case. 111 | 112 | **CAUTION: the location of the dockerfiles HAVE CHANGED.** 113 | 114 | # 3. Build HSS Image # 115 | 116 | ## 3.1 On a Ubuntu 18.04 Host ## 117 | 118 | ```bash 119 | $ docker build --target oai-hss --tag oai-hss:production \ 120 | --file component/oai-hss/docker/Dockerfile.ubuntu18.04 \ 121 | # The following line about proxy is certainly not needed in your env \ 122 | --build-arg EURECOM_PROXY="http://proxy.eurecom.fr:8080" \ 123 | component/oai-hss 124 | $ docker image prune --force 125 | $ docker image ls 126 | oai-hss production f478bafd7a06 1 minute ago 341MB 127 | ... 128 | ``` 129 | 130 | ## 3.2 On a CentOS 7 Host ## 131 | 132 | ```bash 133 | $ docker build --target oai-hss --tag oai-hss:production \ 134 | --file component/oai-hss/docker/Dockerfile.centos7 component/oai-hss 135 | $ docker image prune --force 136 | $ docker image ls 137 | oai-hss production 5b277bf98abe 1 minute ago 527MB 138 | ... 139 | ``` 140 | 141 | ## 3.3 On a CentOS 8 Host ## 142 | 143 | ```bash 144 | $ docker build --target oai-hss --tag oai-hss:production \ 145 | --file component/oai-hss/docker/Dockerfile.centos8 component/oai-hss 146 | $ docker image prune --force 147 | $ docker image ls 148 | oai-hss production 5fa77e2b6b94 1 minute ago 517MB 149 | ... 150 | ``` 151 | 152 | # 4. Build SPGW-C Image # 153 | 154 | ## 4.1 On a Ubuntu 18.04 Host ## 155 | 156 | ```bash 157 | $ docker build --target oai-spgwc --tag oai-spgwc:production \ 158 | --file component/oai-spgwc/docker/Dockerfile.ubuntu18.04 \ 159 | # The following line about proxy is certainly not needed in your env \ 160 | --build-arg EURECOM_PROXY="http://proxy.eurecom.fr:8080" \ 161 | component/oai-spgwc 162 | $ docker image prune --force 163 | $ docker image ls 164 | oai-spgwc production b1ba7dd16bc5 1 minute ago 218MB 165 | ... 166 | ``` 167 | 168 | ## 4.2 On a CentOS 7/8 Host ## 169 | 170 | **Even if we are on a CentOS7 host, we build the SPGW-C image using the CentOS-8 dockerfile.** 171 | 172 | ```bash 173 | $ docker build --target oai-spgwc --tag oai-spgwc:production \ 174 | --file component/oai-spgwc/docker/Dockerfile.centos8 component/oai-spgwc 175 | $ docker image prune --force 176 | $ docker image ls 177 | oai-spgwc production 15ad64676b1f 1 minute ago 379MB 178 | ... 179 | ``` 180 | 181 | # 5. Build SPGW-U Image # 182 | 183 | ## 5.1 On a Ubuntu 18.04 Host ## 184 | 185 | ```bash 186 | $ docker build --target oai-spgwu-tiny --tag oai-spgwu-tiny:production \ 187 | --file component/oai-spgwu-tiny/docker/Dockerfile.ubuntu18.04 \ 188 | # The following line about proxy is certainly not needed in your env \ 189 | --build-arg EURECOM_PROXY="http://proxy.eurecom.fr:8080" \ 190 | component/oai-spgwu-tiny 191 | $ docker image prune --force 192 | $ docker image ls 193 | oai-spgwu-tiny production 588e14481f2b 1 minute ago 220MB 194 | ... 195 | ``` 196 | 197 | ## 5.2 On a CentOS 7/8 Host ## 198 | 199 | **Even if we are on a CentOS7 host, we build the SPGW-U image using the CentOS-8 dockerfile.** 200 | 201 | ```bash 202 | $ docker build --target oai-spgwu-tiny --tag oai-spgwu-tiny:production \ 203 | --file component/oai-spgwu-tiny/docker/Dockerfile.centos8 component/oai-spgwu-tiny 204 | $ docker image prune --force 205 | $ docker image ls 206 | oai-spgwu-tiny production f2d0a07fba2c 1 minute ago 378MB 207 | ... 208 | ``` 209 | 210 | # 6. Build MAGMA-MME image # 211 | 212 | It is possible to build it on a RHEL8 Base image. 213 | -------------------------------------------------------------------------------- /docs/NSA_SUPPORT_OAI_RAN.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 12 | 13 |
4 | 5 | 6 | 7 | 8 | 10 | OpenAirInterface 5G MAGMA NSA SUPPORT demo 11 |
14 | 15 | 16 | **TABLE OF CONTENTS** 17 | 18 | 1. [Verify your connectivity on all servers](#1-verify-your-connectivity-on-all-servers) 19 | 1. [Between eNB and the EPC containers](#11-between-enb-and-the-epc-containers) 20 | 2. [Between gNB and the EPC containers](#12-between-gnb-and-the-epc-containers) 21 | 3. [Between eNB and gNB](#13-between-enb-and-gnb) 22 | 2. [Configuring your eNB and gNB](#2-configuring-your-enb-and-gnb) 23 | 24 | Here is a picture of what we will be doing: 25 | 26 | ![Block Diagram](./images/OAI-MAGMA-NSA-Demo-Network-configuration.png) 27 | 28 | 29 | # 1. Verify your connectivity on all servers # 30 | 31 | ## 1.1. Between eNB and the EPC containers ## 32 | 33 | The eNB server **SHALL** see the MME and the SPGW-U containers. 34 | 35 | The `demo-oai-public-net` docker network shall be reachable from the eNB server. 36 | 37 | We need to add a IP route (based on the subnet defined in the docker-compose.yml file). 38 | 39 | ```bash 40 | $ sudo ip route add 192.168.61.128/26 via EPC_DOCKER_HOST_IP_ADDR dev NIC1_NAME 41 | ``` 42 | 43 | where: 44 | 45 | - EPC_DOCKER_HOST_IP_ADDR is the IP address of the server that hosts all EPC containers 46 | - NIC1_NAME is the name of the default network interface (use `ifconfig` to retrieve it) 47 | 48 | Verify with a ping: 49 | 50 | ```bash 51 | $ ping -c 5 192.168.61.149 52 | PING 192.168.61.149 (192.168.61.149) 56(84) bytes of data. 53 | 64 bytes from 192.168.61.149: icmp_seq=1 ttl=63 time=0.306 ms 54 | 64 bytes from 192.168.61.149: icmp_seq=2 ttl=63 time=0.269 ms 55 | 64 bytes from 192.168.61.149: icmp_seq=3 ttl=63 time=0.234 ms 56 | 64 bytes from 192.168.61.149: icmp_seq=4 ttl=63 time=0.266 ms 57 | 64 bytes from 192.168.61.149: icmp_seq=5 ttl=63 time=0.233 ms 58 | 59 | --- 192.168.61.149 ping statistics --- 60 | 5 packets transmitted, 5 received, 0% packet loss, time 129ms 61 | rtt min/avg/max/mdev = 0.233/0.261/0.306/0.032 ms 62 | ``` 63 | 64 | You can also verify the **SCTP** connection using a tool such as [sctp_test](https://manpages.debian.org/testing/lksctp-tools/sctp_test.1.en.html). 65 | 66 | ```bash 67 | # On the EPC HOST server (no need to be in containers) 68 | $ sudo sctp_test -H EPC_DOCKER_HOST_IP_ADDR -P 36412 -l 69 | local:addr=EPC_DOCKER_HOST_IP_ADDR, port=36412, family=2 70 | seed = 1612270835 71 | 72 | Starting tests... 73 | socket(SOCK_SEQPACKET, IPPROTO_SCTP) -> sk=3 74 | bind(sk=3, [a:EPC_DOCKER_HOST_IP_ADDR,p:36412]) -- attempt 1/10 75 | listen(sk=3,backlog=100) 76 | Server: Receiving packets. 77 | recvmsg(sk=3) 78 | ... 79 | ``` 80 | 81 | ```bash 82 | # On the eNB server 83 | $ sudo sctp_test -H ENB_IP_ADDR -P 36412 -h EPC_DOCKER_HOST_IP_ADDR -p 36412 -s 84 | remote:addr=EPC_DOCKER_HOST_IP_ADDR, port=36412, family=2 85 | local:addr=ENB_IP_ADDR, port=36412, family=2 86 | seed = 1612271200 87 | 88 | Starting tests... 89 | socket(SOCK_SEQPACKET, IPPROTO_SCTP) -> sk=3 90 | bind(sk=3, [a:192.168.18.199,p:36412]) -- attempt 1/10 91 | Client: Sending packets.(1/10) 92 | .... 93 | ``` 94 | ## 1.2. Between gNB and the EPC containers ## 95 | 96 | The gNB server **SHALL** see the SPGW-U containers. 97 | 98 | ```bash 99 | $ sudo ip route add 192.168.61.128/26 via EPC_DOCKER_HOST_IP_ADDR dev NIC2_NAME 100 | ``` 101 | 102 | Verify with a ping: 103 | 104 | ```bash 105 | $ ping -c 5 192.168.61.133 106 | PING 192.168.61.133 (192.168.61.133) 56(84) bytes of data. 107 | 64 bytes from 192.168.61.133: icmp_seq=1 ttl=63 time=0.306 ms 108 | 64 bytes from 192.168.61.133: icmp_seq=2 ttl=63 time=0.269 ms 109 | 64 bytes from 192.168.61.133: icmp_seq=3 ttl=63 time=0.234 ms 110 | 64 bytes from 192.168.61.133: icmp_seq=4 ttl=63 time=0.266 ms 111 | 64 bytes from 192.168.61.133: icmp_seq=5 ttl=63 time=0.233 ms 112 | 113 | --- 192.168.61.133 ping statistics --- 114 | 5 packets transmitted, 5 received, 0% packet loss, time 129ms 115 | rtt min/avg/max/mdev = 0.233/0.261/0.306/0.032 ms 116 | ``` 117 | 118 | ## 1.3. Between eNB and gNB ## 119 | 120 | The gNB server **SHALL** also see the eNB through a **SCTP** connection. 121 | 122 | I strongly recommend to do this, especially if you are using CentOS/RHEL servers for eNB and gNB. 123 | 124 | ```bash 125 | # on such machines, after a reboot, we do this: 126 | sudo setenforce 0 127 | sudo iptables -t nat -F 128 | sudo iptables -t filter -F 129 | sudo iptables -t mangle -F 130 | sudo iptables -t raw -F 131 | sudo iptables -t security -F 132 | ``` 133 | 134 | ```bash 135 | # on the eNB server 136 | $ sudo sctp_test -H ENB_IP_ADDR -P 36422 -l 137 | local:addr=ENB_IP_ADDR, port=36422, family=2 138 | seed = 1612271429 139 | 140 | Starting tests... 141 | socket(SOCK_SEQPACKET, IPPROTO_SCTP) -> sk=3 142 | bind(sk=3, [a:ENB_IP_ADDR,p:36422]) -- attempt 1/10 143 | listen(sk=3,backlog=100) 144 | Server: Receiving packets. 145 | ... 146 | ``` 147 | 148 | ```bash 149 | # on the gNB server 150 | $ sudo sctp_test -H GNB_IP_ADDR -P 36422 -h ENB_IP_ADDR -p 36422 -s 151 | remote:addr=ENB_IP_ADDR, port=36422, family=2 152 | local:addr=GNB_IP_ADDR, port=36422, family=2 153 | seed = 1612271431 154 | 155 | Starting tests... 156 | socket(SOCK_SEQPACKET, IPPROTO_SCTP) -> sk=3 157 | bind(sk=3, [a:GNB_IP_ADDR,p:36422]) -- attempt 1/10 158 | Client: Sending packets.(1/10) 159 | ... 160 | ``` 161 | 162 | # 2. Configuring your eNB and gNB # 163 | 164 | I will not explain how to compile or install. There are a lot of documentations [here](https://gitlab.eurecom.fr/oai/openairinterface5g/-/tree/develop/doc). 165 | 166 | ## 2.1. eNB Configuration file ## 167 | 168 | The one we use for the demo is the one used by the [OAI RAN CI for NSA FR1 setup](https://gitlab.eurecom.fr/oai/openairinterface5g/-/blob/develop/ci-scripts/conf_files/enb.band7.tm1.fr1.25PRB.usrpb210.conf) 169 | 170 | The modifications we made: 171 | 172 | We changed the name of the eNB. Cosmetic change! 173 | 174 | ```bash 175 | Active_eNBs = ( "eNB-OAI-MAGMA-NSA"); 176 | # Asn1_verbosity, choice in: none, info, annoying 177 | Asn1_verbosity = "none"; 178 | 179 | eNBs = 180 | ( 181 | { 182 | # real_time choice in {hard, rt-preempt, no} 183 | real_time = "no"; 184 | ////////// Identification parameters: 185 | eNB_ID = 0xe01; 186 | cell_type = "CELL_MACRO_ENB"; 187 | eNB_name = "eNB-OAI-MAGMA-NSA"; 188 | ``` 189 | 190 | And more important: the **MME_IP_ADDRESS** 191 | 192 | ```bash 193 | enable_measurement_reports = "yes"; 194 | 195 | ////////// MME parameters: 196 | mme_ip_address = ( { ipv4 = "192.168.61.149"; 197 | ipv6 = "192:168:30::17"; 198 | port = 36412 ; 199 | active = "yes"; 200 | preference = "ipv4"; 201 | } 202 | ); 203 | 204 | ///X2 205 | enable_x2 = "yes"; 206 | ``` 207 | 208 | **CAUTION: `enable_measurement_reports` and `enable_x2` SHALL be set to Yes** 209 | 210 | ## 2.2. gNB Configuration file ## 211 | 212 | Once again the one used by the [OAI RAN CI for NSA FR1 setup](https://gitlab.eurecom.fr/oai/openairinterface5g/-/blob/develop/ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpb210.conf). 213 | 214 | No particular changes. 215 | 216 | ## 2.3. Tags we used. ## 217 | 218 | We used `2020.w51_2` at the time of writing, but any newer tag would be better. Since this part is quickly evolving with bug fixes and feature enhancements. 219 | 220 | ### UPDATE: 2021/06/17 ### 221 | 222 | I made an update on all tutorials and I used the latest possible commits/tags on every component: 223 | 224 | Component | Branch | Commit | Date 225 | --- | --- | --- | --- 226 | `MAGMA` | `master` | `01135cd333c51431b3fcece8ba09b2b62d6711a4` | 2021/06/13 227 | `HSS` | `develop` | `0e0d12e140294c7fd14fd187887e434c2273a012` | 2021/05/21 228 | `SPGW-C` | `develop` | `b523f660ee0bc5dc06e73aba3d39c4ede65b99ab` | 2021/05/31 229 | `SPGW-U-TINY` | `develop` | `8b39dcad77fa96edcff135a318ea3a59ed33923e` | 2021/06/01 230 | `eNB/gNB` | `develop` | `2021.w23` | 2021/06/14 231 | 232 | **Last point:** Compared to the recorded video (link below), on 2021/06/17, I used another COTS-UE: 233 | 234 | * an `USB-powered` modem (not a smartphone), **Quectel RM500Q-GL** module. 235 | 236 | # 3. Link to video # 237 | 238 | A video is available on [Youtube](https://youtu.be/bnhguk6CfOk). 239 | 240 | -------------------------------------------------------------------------------- /docker-compose/magma-mme-demo/mme_fd.sprint.conf: -------------------------------------------------------------------------------- 1 | # -------- Local --------- 2 | 3 | # Uncomment if the framework cannot resolv it. 4 | Identity = "@MME_FQDN@"; 5 | Realm = "@REALM@"; 6 | 7 | # TLS configuration (see previous section) 8 | TLS_Cred = "@PREFIX@/freeDiameter/mme.cert.pem", 9 | "@PREFIX@/freeDiameter/mme.key.pem"; 10 | TLS_CA = "@PREFIX@/freeDiameter/mme.cacert.pem"; 11 | 12 | # Disable use of TCP protocol (only listen and connect in SCTP) 13 | # Default : TCP enabled 14 | No_SCTP; 15 | 16 | # This option is ignored if freeDiameter is compiled with DISABLE_SCTP option. 17 | # Prefer TCP instead of SCTP for establishing new connections. 18 | # This setting may be overwritten per peer in peer configuration blocs. 19 | # Default : SCTP is attempted first. 20 | Prefer_TCP; 21 | 22 | 23 | No_IPv6; 24 | 25 | # Overwrite the number of SCTP streams. This value should be kept low, 26 | # especially if you are using TLS over SCTP, because it consumes a lot of 27 | # resources in that case. See tickets 19 and 27 for some additional details on 28 | # this. 29 | # Limit the number of SCTP streams 30 | SCTP_streams = 3; 31 | 32 | 33 | # By default, freeDiameter acts as a Diameter Relay Agent by forwarding all 34 | # messages it cannot handle locally. This parameter disables this behavior. 35 | NoRelay; 36 | 37 | # Use RFC3588 method for TLS protection, where TLS is negociated after CER/CEA exchange is completed 38 | # on the unsecure connection. The alternative is RFC6733 mechanism, where TLS protects also the 39 | # CER/CEA exchange on a dedicated secure port. 40 | # This parameter only affects outgoing connections. 41 | # The setting can be also defined per-peer (see Peers configuration section). 42 | # Default: use RFC6733 method with separate port for TLS. 43 | 44 | #TLS_old_method; 45 | 46 | AppServThreads = 4; 47 | 48 | # Specify the addresses on which to bind the listening server. This must be 49 | # specified if the framework is unable to auto-detect these addresses, or if the 50 | # auto-detected values are incorrect. Note that the list of addresses is sent 51 | # in CER or CEA message, so one should pay attention to this parameter if some 52 | # adresses should be kept hidden. 53 | ListenOn = "@MME_S6A_IP_ADDR@"; 54 | 55 | Port = 3870; 56 | SecPort = 5870; 57 | 58 | # -------- Extensions --------- 59 | 60 | # Uncomment (and create rtd.conf) to specify routing table for this peer. 61 | #LoadExtension = "/usr/local/lib/freeDiameter/rt_default.fdx" : "rtd.conf"; 62 | 63 | #LoadExtension = "/usr/local/lib/freeDiameter/_sample.fdx"; 64 | #LoadExtension = "/usr/local/lib/freeDiameter/app_acct.fdx"; 65 | #LoadExtension = "/usr/local/lib/freeDiameter/app_diameap.fdx"; 66 | #LoadExtension = "/usr/local/lib/freeDiameter/app_radgw.fdx"; 67 | #LoadExtension = "/usr/local/lib/freeDiameter/app_redirect.fdx"; 68 | #LoadExtension = "/usr/local/lib/freeDiameter/app_sip.fdx"; 69 | #LoadExtension = "/usr/local/lib/freeDiameter/dbg_interactive.fdx"; 70 | #LoadExtension = "/usr/local/lib/freeDiameter/dbg_monitor.fdx"; 71 | #LoadExtension = "/usr/local/lib/freeDiameter/dbg_msg_dumps.fdx"; 72 | #LoadExtension = "/usr/local/lib/freeDiameter/dbg_msg_timings.fdx"; 73 | #LoadExtension = "/usr/local/lib/freeDiameter/dbg_rt.fdx"; 74 | LoadExtension = "/usr/local/lib/freeDiameter/dict_3gpp2_avps.fdx"; 75 | #LoadExtension = "/usr/local/lib/freeDiameter/dict_CreditControl.fdx"; 76 | #LoadExtension = "/usr/local/lib/freeDiameter/dict_CxDx.fdx"; 77 | #LoadExtension = "/usr/local/lib/freeDiameter/dict_Gx.fdx"; 78 | #LoadExtension = "/usr/local/lib/freeDiameter/dict_NAS.fdx"; 79 | #LoadExtension = "/usr/local/lib/freeDiameter/dict_Ro.fdx"; 80 | #LoadExtension = "/usr/local/lib/freeDiameter/dict_Rx.fdx"; 81 | #LoadExtension = "/usr/local/lib/freeDiameter/dict_S6mS6n.fdx"; 82 | #LoadExtension = "/usr/local/lib/freeDiameter/dict_SGd.fdx"; 83 | #LoadExtension = "/usr/local/lib/freeDiameter/dict_SLh.fdx"; 84 | #LoadExtension = "/usr/local/lib/freeDiameter/dict_Sd.fdx"; 85 | #LoadExtension = "/usr/local/lib/freeDiameter/dict_Sh.fdx"; 86 | #LoadExtension = "/usr/local/lib/freeDiameter/dict_T4.fdx"; 87 | #LoadExtension = "/usr/local/lib/freeDiameter/dict_T6aT6bT7.fdx"; 88 | #LoadExtension = "/usr/local/lib/freeDiameter/dict_Tsp.fdx"; 89 | #LoadExtension = "/usr/local/lib/freeDiameter/dict_dcca.fdx"; 90 | #LoadExtension = "/usr/local/lib/freeDiameter/dict_dcca_3gpp.fdx"; 91 | #LoadExtension = "/usr/local/lib/freeDiameter/dict_dcca_starent.fdx"; 92 | LoadExtension = "/usr/local/lib/freeDiameter/dict_draftload_avps.fdx"; 93 | #LoadExtension = "/usr/local/lib/freeDiameter/dict_eap.fdx"; 94 | LoadExtension = "/usr/local/lib/freeDiameter/dict_etsi283034_avps.fdx"; 95 | #LoadExtension = "/usr/local/lib/freeDiameter/dict_legacy_xml.fdx"; 96 | #LoadExtension = "/usr/local/lib/freeDiameter/dict_mip6a.fdx"; 97 | #LoadExtension = "/usr/local/lib/freeDiameter/dict_mip6i.fdx"; 98 | #LoadExtension = "/usr/local/lib/freeDiameter/dict_nas_mipv6.fdx"; 99 | #LoadExtension = "/usr/local/lib/freeDiameter/dict_nasreq.fdx"; 100 | LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc4004_avps.fdx"; 101 | LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc4006bis_avps.fdx"; 102 | LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc4072_avps.fdx"; 103 | LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc4590_avps.fdx"; 104 | LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc5447_avps.fdx"; 105 | LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc5580_avps.fdx"; 106 | LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc5777_avps.fdx"; 107 | LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc5778_avps.fdx"; 108 | LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc6734_avps.fdx"; 109 | LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc6942_avps.fdx"; 110 | LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc7155_avps.fdx"; 111 | LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc7683_avps.fdx"; 112 | LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc7944_avps.fdx"; 113 | #LoadExtension = "/usr/local/lib/freeDiameter/dict_sip.fdx"; 114 | LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29061_avps.fdx"; 115 | LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29128_avps.fdx"; 116 | LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29154_avps.fdx"; 117 | LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29173_avps.fdx"; 118 | LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29212_avps.fdx"; 119 | LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29214_avps.fdx"; 120 | LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29215_avps.fdx"; 121 | LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29217_avps.fdx"; 122 | LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29229_avps.fdx"; 123 | LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29272_avps.fdx"; 124 | LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29273_avps.fdx"; 125 | LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29329_avps.fdx"; 126 | LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29336_avps.fdx"; 127 | LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29337_avps.fdx"; 128 | LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29338_avps.fdx"; 129 | LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29343_avps.fdx"; 130 | LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29344_avps.fdx"; 131 | LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29345_avps.fdx"; 132 | LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29368_avps.fdx"; 133 | LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29468_avps.fdx"; 134 | LoadExtension = "/usr/local/lib/freeDiameter/dict_ts32299_avps.fdx"; 135 | #LoadExtension = "/usr/local/lib/freeDiameter/rt_busypeers.fdx"; 136 | #LoadExtension = "/usr/local/lib/freeDiameter/rt_default.fdx"; 137 | #LoadExtension = "/usr/local/lib/freeDiameter/rt_ereg.fdx"; 138 | #LoadExtension = "/usr/local/lib/freeDiameter/rt_ignore_dh.fdx"; 139 | #LoadExtension = "/usr/local/lib/freeDiameter/rt_load_balance.fdx"; 140 | #LoadExtension = "/usr/local/lib/freeDiameter/rt_randomize.fdx"; 141 | #LoadExtension = "/usr/local/lib/freeDiameter/rt_redirect.fdx"; 142 | #LoadExtension = "/usr/local/lib/freeDiameter/test_acct.fdx"; 143 | #LoadExtension = "/usr/local/lib/freeDiameter/test_app.fdx"; 144 | #LoadExtension = "/usr/local/lib/freeDiameter/test_hss.fdx"; 145 | #LoadExtension = "/usr/local/lib/freeDiameter/test_netemul.fdx"; 146 | #LoadExtension = "/usr/local/lib/freeDiameter/test_rt_any.fdx"; 147 | #LoadExtension = "/usr/local/lib/freeDiameter/test_sip.fdx"; 148 | #LoadExtension = "/usr/local/lib/freeDiameter/dict_Rf.fdx"; 149 | LoadExtension = "/usr/local/lib/freeDiameter/dict_S6as6d.fdx"; 150 | LoadExtension = "/usr/local/lib/freeDiameter/dict_S6t.fdx"; 151 | LoadExtension = "/usr/local/lib/freeDiameter/dict_S6c.fdx"; 152 | 153 | 154 | # -------- Peers --------- 155 | 156 | # The framework will actively attempt to establish and maintain a connection 157 | # with the peers listed here. 158 | # For only accepting incoming connections, see the acl_wl.fx extension. 159 | 160 | # ConnectPeer 161 | # Declare a remote peer to which this peer must maintain a connection. 162 | # In addition, this allows specifying non-default parameters for this peer only 163 | # (for example disable SCTP with this peer, or use RFC3588-flavour TLS). 164 | # Note that by default, if a peer is not listed as a ConnectPeer entry, an 165 | # incoming connection from this peer will be rejected. If you want to accept 166 | # incoming connections from other peers, see the acl_wl.fdx? extension which 167 | # allows exactly this. 168 | 169 | ConnectPeer= "@HSS_FQDN@" { ConnectTo = "@HSS_IP_ADDR@"; No_SCTP ; No_IPv6; Prefer_TCP; No_TLS; port = 3868;}; 170 | -------------------------------------------------------------------------------- /ci-scripts/dsTesterDockerCompose/mme_fd.sprint.conf: -------------------------------------------------------------------------------- 1 | # -------- Local --------- 2 | 3 | # Uncomment if the framework cannot resolv it. 4 | Identity = "@MME_FQDN@"; 5 | Realm = "@REALM@"; 6 | 7 | # TLS configuration (see previous section) 8 | TLS_Cred = "@PREFIX@/freeDiameter/mme.cert.pem", 9 | "@PREFIX@/freeDiameter/mme.key.pem"; 10 | TLS_CA = "@PREFIX@/freeDiameter/mme.cacert.pem"; 11 | 12 | # Disable use of TCP protocol (only listen and connect in SCTP) 13 | # Default : TCP enabled 14 | No_SCTP; 15 | 16 | # This option is ignored if freeDiameter is compiled with DISABLE_SCTP option. 17 | # Prefer TCP instead of SCTP for establishing new connections. 18 | # This setting may be overwritten per peer in peer configuration blocs. 19 | # Default : SCTP is attempted first. 20 | Prefer_TCP; 21 | 22 | 23 | No_IPv6; 24 | 25 | # Overwrite the number of SCTP streams. This value should be kept low, 26 | # especially if you are using TLS over SCTP, because it consumes a lot of 27 | # resources in that case. See tickets 19 and 27 for some additional details on 28 | # this. 29 | # Limit the number of SCTP streams 30 | SCTP_streams = 3; 31 | 32 | 33 | # By default, freeDiameter acts as a Diameter Relay Agent by forwarding all 34 | # messages it cannot handle locally. This parameter disables this behavior. 35 | NoRelay; 36 | 37 | # Use RFC3588 method for TLS protection, where TLS is negociated after CER/CEA exchange is completed 38 | # on the unsecure connection. The alternative is RFC6733 mechanism, where TLS protects also the 39 | # CER/CEA exchange on a dedicated secure port. 40 | # This parameter only affects outgoing connections. 41 | # The setting can be also defined per-peer (see Peers configuration section). 42 | # Default: use RFC6733 method with separate port for TLS. 43 | 44 | #TLS_old_method; 45 | 46 | AppServThreads = 4; 47 | 48 | # Specify the addresses on which to bind the listening server. This must be 49 | # specified if the framework is unable to auto-detect these addresses, or if the 50 | # auto-detected values are incorrect. Note that the list of addresses is sent 51 | # in CER or CEA message, so one should pay attention to this parameter if some 52 | # adresses should be kept hidden. 53 | ListenOn = "@MME_S6A_IP_ADDR@"; 54 | 55 | Port = 3870; 56 | SecPort = 5870; 57 | 58 | # -------- Extensions --------- 59 | 60 | # Uncomment (and create rtd.conf) to specify routing table for this peer. 61 | #LoadExtension = "/usr/local/lib/freeDiameter/rt_default.fdx" : "rtd.conf"; 62 | 63 | #LoadExtension = "/usr/local/lib/freeDiameter/_sample.fdx"; 64 | #LoadExtension = "/usr/local/lib/freeDiameter/app_acct.fdx"; 65 | #LoadExtension = "/usr/local/lib/freeDiameter/app_diameap.fdx"; 66 | #LoadExtension = "/usr/local/lib/freeDiameter/app_radgw.fdx"; 67 | #LoadExtension = "/usr/local/lib/freeDiameter/app_redirect.fdx"; 68 | #LoadExtension = "/usr/local/lib/freeDiameter/app_sip.fdx"; 69 | #LoadExtension = "/usr/local/lib/freeDiameter/dbg_interactive.fdx"; 70 | #LoadExtension = "/usr/local/lib/freeDiameter/dbg_monitor.fdx"; 71 | #LoadExtension = "/usr/local/lib/freeDiameter/dbg_msg_dumps.fdx"; 72 | #LoadExtension = "/usr/local/lib/freeDiameter/dbg_msg_timings.fdx"; 73 | #LoadExtension = "/usr/local/lib/freeDiameter/dbg_rt.fdx"; 74 | LoadExtension = "/usr/local/lib/freeDiameter/dict_3gpp2_avps.fdx"; 75 | #LoadExtension = "/usr/local/lib/freeDiameter/dict_CreditControl.fdx"; 76 | #LoadExtension = "/usr/local/lib/freeDiameter/dict_CxDx.fdx"; 77 | #LoadExtension = "/usr/local/lib/freeDiameter/dict_Gx.fdx"; 78 | #LoadExtension = "/usr/local/lib/freeDiameter/dict_NAS.fdx"; 79 | #LoadExtension = "/usr/local/lib/freeDiameter/dict_Ro.fdx"; 80 | #LoadExtension = "/usr/local/lib/freeDiameter/dict_Rx.fdx"; 81 | #LoadExtension = "/usr/local/lib/freeDiameter/dict_S6mS6n.fdx"; 82 | #LoadExtension = "/usr/local/lib/freeDiameter/dict_SGd.fdx"; 83 | #LoadExtension = "/usr/local/lib/freeDiameter/dict_SLh.fdx"; 84 | #LoadExtension = "/usr/local/lib/freeDiameter/dict_Sd.fdx"; 85 | #LoadExtension = "/usr/local/lib/freeDiameter/dict_Sh.fdx"; 86 | #LoadExtension = "/usr/local/lib/freeDiameter/dict_T4.fdx"; 87 | #LoadExtension = "/usr/local/lib/freeDiameter/dict_T6aT6bT7.fdx"; 88 | #LoadExtension = "/usr/local/lib/freeDiameter/dict_Tsp.fdx"; 89 | #LoadExtension = "/usr/local/lib/freeDiameter/dict_dcca.fdx"; 90 | #LoadExtension = "/usr/local/lib/freeDiameter/dict_dcca_3gpp.fdx"; 91 | #LoadExtension = "/usr/local/lib/freeDiameter/dict_dcca_starent.fdx"; 92 | LoadExtension = "/usr/local/lib/freeDiameter/dict_draftload_avps.fdx"; 93 | #LoadExtension = "/usr/local/lib/freeDiameter/dict_eap.fdx"; 94 | LoadExtension = "/usr/local/lib/freeDiameter/dict_etsi283034_avps.fdx"; 95 | #LoadExtension = "/usr/local/lib/freeDiameter/dict_legacy_xml.fdx"; 96 | #LoadExtension = "/usr/local/lib/freeDiameter/dict_mip6a.fdx"; 97 | #LoadExtension = "/usr/local/lib/freeDiameter/dict_mip6i.fdx"; 98 | #LoadExtension = "/usr/local/lib/freeDiameter/dict_nas_mipv6.fdx"; 99 | #LoadExtension = "/usr/local/lib/freeDiameter/dict_nasreq.fdx"; 100 | LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc4004_avps.fdx"; 101 | LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc4006bis_avps.fdx"; 102 | LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc4072_avps.fdx"; 103 | LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc4590_avps.fdx"; 104 | LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc5447_avps.fdx"; 105 | LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc5580_avps.fdx"; 106 | LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc5777_avps.fdx"; 107 | LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc5778_avps.fdx"; 108 | LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc6734_avps.fdx"; 109 | LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc6942_avps.fdx"; 110 | LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc7155_avps.fdx"; 111 | LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc7683_avps.fdx"; 112 | LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc7944_avps.fdx"; 113 | #LoadExtension = "/usr/local/lib/freeDiameter/dict_sip.fdx"; 114 | LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29061_avps.fdx"; 115 | LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29128_avps.fdx"; 116 | LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29154_avps.fdx"; 117 | LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29173_avps.fdx"; 118 | LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29212_avps.fdx"; 119 | LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29214_avps.fdx"; 120 | LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29215_avps.fdx"; 121 | LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29217_avps.fdx"; 122 | LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29229_avps.fdx"; 123 | LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29272_avps.fdx"; 124 | LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29273_avps.fdx"; 125 | LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29329_avps.fdx"; 126 | LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29336_avps.fdx"; 127 | LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29337_avps.fdx"; 128 | LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29338_avps.fdx"; 129 | LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29343_avps.fdx"; 130 | LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29344_avps.fdx"; 131 | LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29345_avps.fdx"; 132 | LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29368_avps.fdx"; 133 | LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29468_avps.fdx"; 134 | LoadExtension = "/usr/local/lib/freeDiameter/dict_ts32299_avps.fdx"; 135 | #LoadExtension = "/usr/local/lib/freeDiameter/rt_busypeers.fdx"; 136 | #LoadExtension = "/usr/local/lib/freeDiameter/rt_default.fdx"; 137 | #LoadExtension = "/usr/local/lib/freeDiameter/rt_ereg.fdx"; 138 | #LoadExtension = "/usr/local/lib/freeDiameter/rt_ignore_dh.fdx"; 139 | #LoadExtension = "/usr/local/lib/freeDiameter/rt_load_balance.fdx"; 140 | #LoadExtension = "/usr/local/lib/freeDiameter/rt_randomize.fdx"; 141 | #LoadExtension = "/usr/local/lib/freeDiameter/rt_redirect.fdx"; 142 | #LoadExtension = "/usr/local/lib/freeDiameter/test_acct.fdx"; 143 | #LoadExtension = "/usr/local/lib/freeDiameter/test_app.fdx"; 144 | #LoadExtension = "/usr/local/lib/freeDiameter/test_hss.fdx"; 145 | #LoadExtension = "/usr/local/lib/freeDiameter/test_netemul.fdx"; 146 | #LoadExtension = "/usr/local/lib/freeDiameter/test_rt_any.fdx"; 147 | #LoadExtension = "/usr/local/lib/freeDiameter/test_sip.fdx"; 148 | #LoadExtension = "/usr/local/lib/freeDiameter/dict_Rf.fdx"; 149 | LoadExtension = "/usr/local/lib/freeDiameter/dict_S6as6d.fdx"; 150 | LoadExtension = "/usr/local/lib/freeDiameter/dict_S6t.fdx"; 151 | LoadExtension = "/usr/local/lib/freeDiameter/dict_S6c.fdx"; 152 | 153 | 154 | # -------- Peers --------- 155 | 156 | # The framework will actively attempt to establish and maintain a connection 157 | # with the peers listed here. 158 | # For only accepting incoming connections, see the acl_wl.fx extension. 159 | 160 | # ConnectPeer 161 | # Declare a remote peer to which this peer must maintain a connection. 162 | # In addition, this allows specifying non-default parameters for this peer only 163 | # (for example disable SCTP with this peer, or use RFC3588-flavour TLS). 164 | # Note that by default, if a peer is not listed as a ConnectPeer entry, an 165 | # incoming connection from this peer will be rejected. If you want to accept 166 | # incoming connections from other peers, see the acl_wl.fdx? extension which 167 | # allows exactly this. 168 | 169 | ConnectPeer= "@HSS_FQDN@" { ConnectTo = "@HSS_IP_ADDR@"; No_SCTP ; No_IPv6; Prefer_TCP; No_TLS; port = 3868;}; 170 | -------------------------------------------------------------------------------- /docs/BUILD_IMAGES_MAGMA_MME.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 12 | 13 |
4 | 5 | 6 | 7 | 8 | 10 | OpenAirInterface Core Network Docker Deployment : Building the Images 11 |
14 | 15 | **Table of Contents** 16 | 17 | 1. [Retrieve the proper code version on the OAI-CN part](#1-retrieve-the-proper-code-version-on-the-oai-cn-part) 18 | 2. [Generic Parameters](#2-generic-parameters) 19 | 3. [Build OAI-HSS Image](#3-build-hss-image) 20 | 4. [Build OAI-SPGW-C Image](#4-build-spgw-c-image) 21 | 5. [Build OAI-SPGW-U Image](#5-build-spgw-u-image) 22 | 6. [Retrieve the MAGMA source code](#6-retrieve-the-magma-source-code) 23 | 1. [Get the NSA-Support source code](#61-get-the-nsa-support-source-code) 24 | 2. [Prepare the source code for a MAGMA-MME Docker Image build](#62-prepare-the-source-code-for-a-magma-mme-docker-image-build) 25 | 3. [Build the MAGMA-MME Ubuntu18 Docker image](#63-build-the-magma-mme-ubuntu18-docker-image) 26 | 27 | 28 | This page is only for `Ubuntu18` builds. For other distributions, see [here](./BUILD_IMAGES.md). 29 | 30 | # 1. Retrieve the proper code version on the OAI-CN part # 31 | 32 | **CAUTION: PLEASE READ THIS SECTION VERY CAREFULLY!** 33 | 34 | This repository only has tutorials and Continuous Integration scripts. 35 | 36 | Each 4G Network Function source code is managed in its own repository. 37 | 38 | They are called as git sub-modules in the component folder. 39 | 40 | Before doing anything, you SHALL retrieve the code for each git sub-module. 41 | 42 | ## 1.1. You are interested on a very stable version. ## 43 | 44 | We recommend to synchronize with the master branches on all git sub-modules. 45 | 46 | We also recommend that you synchronize this "tutorial" repository with a provided tag. By doing so, the `docker-compose` files will be aligned with feature sets of each NF. 47 | 48 | **At the time of writing (2022/02/25), the release tag is v1.2.0.** 49 | 50 | | CNF Name | Branch Name | Tag | Ubuntu 18.04 | RHEL8 (UBI8) | 51 | | ----------- | ----------- | ---------- | ------------ | ----------------| 52 | | FED REPO | N/A | `v1.2.0` | | | 53 | | HSS | `master` | `v1.2.0` | X | X | 54 | | SPWG-C | `master` | `v1.2.0` | X | X | 55 | | SPGW-U-TINY | `master` | `v1.2.0` | X | X | 56 | | MAGMA-MME | `master` | `N/A` | X | X | 57 | 58 | ```bash 59 | # Clone directly on the latest release tag 60 | $ git clone --branch v1.2.0 https://github.com/OPENAIRINTERFACE/openair-epc-fed.git 61 | $ cd openair-epc-fed 62 | # If you forgot to clone directly to the latest release tag 63 | $ git checkout -f v1.2.0 64 | 65 | # Synchronize all git submodules 66 | $ ./scripts/syncComponents.sh 67 | --------------------------------------------------------- 68 | OAI-HSS component branch : master 69 | OAI-SPGW-C component branch : master 70 | OAI-SPGW-U component branch : master 71 | ``` 72 | 73 | ## 1.2. You are interested on the latest features. ## 74 | 75 | All the latest features are somehow pushed to the `develop` branches of each NF repository. 76 | 77 | It means that we/you are able to build and the Continuous Integration test suite makes sure it 78 | does NOT break any existing tested feature. 79 | 80 | Anyhow, the tutorials' docker-compose files on the latest commit of the `master` branch of 81 | `openair-epc-fed` repository SHALL support any additional un-tested feature. 82 | 83 | ```bash 84 | # Clone 85 | $ git clone https://gitlab.eurecom.fr/oai/cn5g/oai-cn5g-fed.git 86 | $ cd oai-cn5g-fed 87 | # On an existing repository, resync to the last `master` commit 88 | $ git fetch --prune 89 | $ git checkout master 90 | $ git rebase origin/master 91 | 92 | # Synchronize all git submodules 93 | $ ./scripts/syncComponentsLegacy.sh --hss-branch develop --spgwc-branch develop --spgwu-tiny-branch develop 94 | --------------------------------------------------------- 95 | OAI-HSS component branch : develop 96 | OAI-SPGW-C component branch : develop 97 | OAI-SPGW-U component branch : develop 98 | --------------------------------------------------------- 99 | git submodule deinit --all --force 100 | git submodule init 101 | git submodule update 102 | ``` 103 | 104 | # 2. Generic Parameters # 105 | 106 | Here in our network configuration, we need to pass the "GIT PROXY" configuration. 107 | 108 | * If you do not need, remove the `--build-arg EURECOM_PROXY=".."` option. 109 | * If you do need it, change with your proxy value. 110 | 111 | # 3. Build HSS Image # 112 | 113 | ## 3.1 On a Ubuntu 18.04 Host ## 114 | 115 | On our CI server (a 48-CPU server), this operation takes around **13 minutes**. Please be patient. 116 | 117 | ```bash 118 | $ docker build --target oai-hss --tag oai-hss:production \ 119 | --file component/oai-hss/docker/Dockerfile.ubuntu18.04 \ 120 | # The following line about proxy is certainly not needed in your env \ 121 | --build-arg EURECOM_PROXY="http://proxy.eurecom.fr:8080" \ 122 | component/oai-hss 123 | $ docker image prune --force 124 | $ docker image ls 125 | oai-hss production f478bafd7a06 1 minute ago 341MB 126 | ... 127 | ``` 128 | 129 | # 4. Build SPGW-C Image # 130 | 131 | ## 4.1 On a Ubuntu 18.04 Host ## 132 | 133 | On our CI server (a 48-CPU server), this operation takes around **10 minutes**. Please be patient. 134 | 135 | ```bash 136 | $ docker build --target oai-spgwc --tag oai-spgwc:production \ 137 | --file component/oai-spgwc/docker/Dockerfile.ubuntu18.04 \ 138 | # The following line about proxy is certainly not needed in your env \ 139 | --build-arg EURECOM_PROXY="http://proxy.eurecom.fr:8080" \ 140 | component/oai-spgwc 141 | $ docker image prune --force 142 | $ docker image ls 143 | oai-spgwc production b1ba7dd16bc5 1 minute ago 218MB 144 | ... 145 | ``` 146 | 147 | # 5. Build SPGW-U Image # 148 | 149 | ## 5.1 On a Ubuntu 18.04 Host ## 150 | 151 | On our CI server (a 48-CPU server), this operation takes around **9 minutes**. Please be patient. 152 | 153 | ```bash 154 | $ docker build --target oai-spgwu-tiny --tag oai-spgwu-tiny:production \ 155 | --file component/oai-spgwu-tiny/docker/Dockerfile.ubuntu18.04 \ 156 | # The following line about proxy is certainly not needed in your env \ 157 | --build-arg EURECOM_PROXY="http://proxy.eurecom.fr:8080" \ 158 | component/oai-spgwu-tiny 159 | $ docker image prune --force 160 | $ docker image ls 161 | oai-spgwu-tiny production 588e14481f2b 1 minute ago 220MB 162 | ... 163 | ``` 164 | 165 | # 6. Retrieve the MAGMA source code # 166 | 167 | ## 6.1. Get the NSA-Support source code ## 168 | 169 | **Important Update (2021 / 03 / 20), the NSA Support was merged into `master`.** 170 | 171 | ```bash 172 | $ cd ~ 173 | $ git clone https://github.com/magma/magma.git 174 | $ cd magma 175 | $ git log | grep -i NSA 176 | ``` 177 | 178 | You should see Mohit's Pull request being merged (`[Converged MME]NSA-Addition (#4513)`). 179 | 180 | ## 6.2. Prepare the source code for a MAGMA-MME Docker Image build ## 181 | 182 | The `.dockerignore` file is meant for the image building on the Orchestrator. 183 | 184 | **It is NOT suitable for the MAGMA-MME image building. If you don't remove/rename, build won't complete.** 185 | 186 | ```bash 187 | $ rm .dockerignore 188 | ``` 189 | 190 | During the UE attachment, we have seen that when UE receives the `EMM-Information` NAS packet, the UE disconnects. 191 | 192 | **So at the time of writing (2021 / 02 / 01), we are disabling the sending of EMM-INFO packet.** 193 | 194 | ```bash 195 | $ git diff lte/gateway/c/core/oai/tasks/nas/emm/Attach.c 196 | diff --git a/lte/gateway/c/core/oai/tasks/nas/emm/Attach.c b/lte/gateway/c/core/oai/tasks/nas/emm/Attach.c 197 | index 34f353a88..b354b18b7 100644 198 | --- a/lte/gateway/c/core/oai/tasks/nas/emm/Attach.c 199 | +++ b/lte/gateway/c/core/oai/tasks/nas/emm/Attach.c 200 | @@ -840,7 +840,7 @@ int emm_proc_attach_complete( 201 | LOG_NAS_EMM, 202 | " Sending EMM INFORMATION for ue_id = " MME_UE_S1AP_ID_FMT "\n", 203 | ue_id); 204 | - emm_proc_emm_informtion(ue_mm_context); 205 | + //emm_proc_emm_informtion(ue_mm_context); 206 | increment_counter("ue_attach", 1, 1, "result", "attach_proc_successful"); 207 | attach_success_event(ue_mm_context->emm_context._imsi64); 208 | } 209 | ``` 210 | 211 | This issue is in our **TODO** list and we are still investigating. 212 | 213 | Another known issue is if the UE send a `TAU request` to the MME. Currently the MAGMA MME with an OAI eNB 214 | does not handle it well. We are also working on providing a fix for this issue. 215 | 216 | **Update (2021/11/22): Implementation of `TAU request` response in the MME has been merged in September in MAGMA `master` branch.** 217 | We validated it on our RAN CI bench. 218 | 219 | ## 6.3. Build the MAGMA-MME Ubuntu18 Docker image ## 220 | 221 | On our CI server (a 48-CPU server), this operation takes around **30-35 minutes**. Please be patient. 222 | 223 | The reason: a lot of needed packages/libraries are installed from source for a very specific version. 224 | 225 | Once again, if you need a proxy, add your proxy URL. If not, remove the option. 226 | 227 | ```bash 228 | $ docker build --target magma-mme --tag magma-mme:master \ 229 | --file lte/gateway/docker/mme/Dockerfile.ubuntu18.04 \ 230 | # The following line about proxy is certainly not needed in your env \ 231 | --build-arg GIT_PROXY="http://proxy.eurecom.fr:8080" \ 232 | . 233 | $ docker image ls 234 | magma-mme nsa-support b6fb01eb0d07 1 minute ago 492MB 235 | ... 236 | ``` 237 | 238 | If you are planning to re-build MAGMA-MME Docker image, here is is a trick: 239 | 240 | Normally after the 35 minutes, you should get the MME image but also a dangling image that should 241 | be quite large (5+ GBytes). 242 | 243 | ```bash 244 | $ docker image ls 245 | magma-mme nsa-support b6fb01eb0d07 1 minute ago 492MB 246 | 91259fd827ee 5 minutes ago 5.24GB 247 | ... 248 | ``` 249 | 250 | Re-tag the dangling image: 251 | 252 | ```bash 253 | $ docker image tag 91259fd827ee magma-dev-mme:ci-base-image 254 | ``` 255 | 256 | And use the CI docker file. 257 | 258 | ```bash 259 | $ docker build --target magma-mme --tag magma-mme:next-image-tag --file ci-scripts/docker/Dockerfile.mme.ci.ubuntu18 . 260 | ``` 261 | 262 | This will only take **5 to 10 minutes** to re-build a MAGMA-MME image. 263 | 264 | Normally you are ready to deploy and test. 265 | 266 | See [Deploy with MAGMA-MME](../docker-compose/magma-mme-demo/README.md). 267 | -------------------------------------------------------------------------------- /docker-compose/magma-mme-demo/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 12 | 13 |
4 | 5 | 6 | 7 | 8 | 10 | OpenAirInterface Core Network Docker Deployment : a Docker-Compose MAGMA-MME example 11 |
14 | 15 | **Table of Contents** 16 | 17 | 1. [Initialize the Cassandra Database](#1-initialize-the-cassandra-db) 18 | 2. [Deploy the rest of EPC](#2-deploy-the-rest-of-epc) 19 | 3. [Undeploy the EPC](#3-undeploy-the-epc) 20 | 4. [How to edit the docker-compose file](#4-how-to-edit-the-docker-compose-file) 21 | 1. [UE simcard and other UE configurations](#41-ue-simcard-and-other-ue-configurations) 22 | 2. [Your Public Land Mobile Network](#42-your-public-land-mobile-network) 23 | 3. [Your network configuration](#43-your-network-configuration) 24 | 4. [Miscellaneous](#44-miscellaneous) 25 | 5. [Connecting an eNB](#5-connecting-an-enb) 26 | 6. [Connecting a Smartphone in 5G using NSA support from OAI RAN](#6-connecting-a-smartphone-in-5g-using-nsa-support-from-oai-ran) 27 | 28 | # 1. Initialize the Cassandra DB # 29 | 30 | Starting and initializing a data-base takes a bit of time. 31 | 32 | In `docker-compose 3.x`, there are no more support for conditional healthy dependency when deploying. 33 | 34 | This step is now **manual**. 35 | 36 | ```bash 37 | $ cd docker-compose/magma-mme-demo 38 | $ docker-compose up -d db_init 39 | Creating network "demo-oai-private-net" with the default driver 40 | Creating network "demo-oai-public-net" with the default driver 41 | Creating demo-cassandra ... done 42 | Creating demo-db-init ... done 43 | 44 | $ docker logs demo-db-init --follow 45 | Connection error: ('Unable to connect to any servers', {'192.168.68.130': error(111, "Tried connecting to [('192.168.68.130', 9042)]. Last error: Connection refused")}) 46 | Connection error: ('Unable to connect to any servers', {'192.168.68.130': error(111, "Tried connecting to [('192.168.68.130', 9042)]. Last error: Connection refused")}) 47 | Connection error: ('Unable to connect to any servers', {'192.168.68.130': error(111, "Tried connecting to [('192.168.68.130', 9042)]. Last error: Connection refused")}) 48 | Connection error: ('Unable to connect to any servers', {'192.168.68.130': error(111, "Tried connecting to [('192.168.68.130', 9042)]. Last error: Connection refused")}) 49 | OK 50 | 51 | $ docker rm -f demo-db-init 52 | demo-db-init 53 | ``` 54 | 55 | Note: we are removing the `demo-db-init` container because it is not needed anymore. 56 | 57 | You can keep the container but it is dead. 58 | 59 | To go to the next step, you **SHALL** have the "OK" message in the `demo-db-init` container logs. 60 | 61 | Wait a bit to ensure that the following logs are present in launching the cassandra docker image. If its not the case, the HSS docker image will stop in the next step prematurely. 62 | 63 | ```bash 64 | $ docker logs demo-cassandra 65 | .... 66 | INFO 20:19:40 Initializing vhss.extid_imsi_xref 67 | ``` 68 | 69 | 70 | # 2. Deploy the rest of EPC # 71 | 72 | ```bash 73 | $ docker-compose up -d oai_spgwu 74 | demo-cassandra is up-to-date 75 | Creating demo-redis ... done 76 | Creating demo-oai-hss ... done 77 | Creating demo-magma-mme ... done 78 | Creating demo-oai-spgwc ... done 79 | Creating demo-oai-spgwu-tiny ... done 80 | 81 | # wait a bit 82 | 83 | $ docker ps -a 84 | CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 85 | cf93fa4c5fdf oai-spgwu-tiny:production "/openair-spgwu-tiny…" 46 seconds ago Up 44 seconds (healthy) 2152/udp, 8805/udp demo-oai-spgwu-tiny 86 | f59ceac1dba5 oai-spgwc:production "/openair-spgwc/bin/…" 49 seconds ago Up 46 seconds (healthy) 2123/udp, 8805/udp demo-oai-spgwc 87 | 80d71373ef4d magma-mme:nsa-support "/bin/bash -c 'cd /m…" 51 seconds ago Up 49 seconds 3870/tcp, 2123/udp, 5870/tcp demo-magma-mme 88 | 7b2f67eeeac0 oai-hss:production "/openair-hss/bin/en…" 56 seconds ago Up 51 seconds (healthy) 5868/tcp, 9042/tcp, 9080-9081/tcp demo-oai-hss 89 | b94d74330f92 redis:6.0.5 "/bin/bash -c 'redis…" 56 seconds ago Up 52 seconds 6379/tcp demo-redis 90 | e51afc6e107c cassandra:2.1 "docker-entrypoint.s…" 2 minutes ago Up 2 minutes (healthy) 7000-7001/tcp, 7199/tcp, 9042/tcp, 9160/tcp demo-cassandra 91 | 92 | ``` 93 | 94 | You are ready to connect the RAN and UE. 95 | 96 | # 3. Undeploy the EPC # 97 | 98 | ``` 99 | $ docker-compose down 100 | Stopping demo-oai-spgwu-tiny ... done 101 | Stopping demo-oai-spgwc ... done 102 | Stopping demo-magma-mme ... done 103 | Stopping demo-oai-hss ... done 104 | Stopping demo-redis ... done 105 | Stopping demo-cassandra ... done 106 | Removing demo-oai-spgwu-tiny ... done 107 | Removing demo-oai-spgwc ... done 108 | Removing demo-magma-mme ... done 109 | Removing demo-oai-hss ... done 110 | Removing demo-redis ... done 111 | Removing demo-cassandra ... done 112 | Removing network demo-oai-private-net 113 | Removing network demo-oai-public-net 114 | ``` 115 | 116 | # 4. How to edit the docker-compose file 117 | 118 | Obviously you want an EPC that runs for your environment. It means: 119 | 120 | * Dedicated UE simcard configuration 121 | * A different PLMN 122 | * Your network configuration is certainly different 123 | 124 | **Try to modify as little as possible the number of environment variables values in the docker-compose file.** 125 | 126 | The variables I describe in the next few sections should be the ones you shall focus on! 127 | 128 | * They are formatted in this markdown page as **ENV_VARIABLE** 129 | 130 | If you don't understand a value, it is better to **NOT** touch it! 131 | 132 | ## 4.1. UE simcard and other UE configurations ## 133 | 134 | The final purpose of deploying an EPC is to connect a 4G UE (smartphone or dongle) to internet through an eNB. 135 | 136 | When "burning" a simcard, you need to decide the following parameters: 137 | 138 | * **IMSI** : International Mobile Subscriber Identity 139 | * Formatting is explained [here](https://en.wikipedia.org/wiki/International_mobile_subscriber_identity) 140 | * **LTE_KEY** and **OPC_KEY** 141 | * There are more but I won't go into details. 142 | 143 | Once you've done this, put the simcard in your smartphone and power up it. You will need to add an new **APN** (Access Point Name). 144 | 145 | Here you can be creative. It's a string. Our only requirement --> It **SHALL** have at least one "." (dot). In our example "oai.ipv4". 146 | 147 | Now you need to provision the user(s) into the Cassandra Database, hence some of the **HSS** parameters: 148 | 149 | * **LTE_K** SHALL match **LTE_KEY** you used in burning the simcard 150 | * **OP_KEY** **is not** the **OPC_KEY** but it can be calculated from it and **LTE_KEY**. 151 | * A example of a generator can be found at [Ki/OPc Generator](https://github.com/PodgroupConnectivity/kiopcgenerator) 152 | * **APN1** SHALL match the one you created on your smartphone. 153 | * **FIRST_IMSI** should match the one you chose 154 | 155 | The **SPGW-C**, since the introduction of FDQN support, has 2 variables: 156 | 157 | * **APN_NI_1** 158 | * **DEFAULT_APN_NI_1** 159 | 160 | that shall match also the APN you created. 161 | 162 | ## 4.2. Your Public Land Mobile Network ## 163 | 164 | AKA PLMN. 165 | 166 | I strongly recommend to only modify the **MCC**-type and **MNC**-type parameters. 167 | 168 | You could touch the **TAC**-type ones but it's quite more difficult for a simple tutorial. 169 | 170 | In our example, we used **222** and **01** with TACs **1**, **2**, **3** (**1** being primary TAC). 171 | 172 | **CAUTION** : for **MCC**, **MNC** values, I am using a `'` -- 2 or 3 digits -- `'` notation: 173 | 174 | - I do this especially if your **MNC** is something like **'02'**, 2 digits with 1st being '0' 175 | - This 1st `zero` digit **SHALL** present in all of the cNF configuration files! 176 | 177 | Note that the **MNC3**-type parameters are encoded over 3 characters. This is mandatory. 178 | You have to fill with `zeroes` if needed. 179 | 180 | For the **MME**, at the time of writing, the configuration file is hard-coded in the same folder as the docker-compose file (`mme.conf`): 181 | 182 | ```bash 183 | # ------- MME served GUMMEIs 184 | GUMMEI_LIST = ( 185 | { MCC="222" ; MNC="01"; MME_GID="32768" ; MME_CODE="3"; } 186 | ); 187 | 188 | # ------- MME served TAIs 189 | TAI_LIST = ( 190 | {MCC="222" ; MNC="01"; TAC = "1"; }, 191 | {MCC="222" ; MNC="01"; TAC = "2"; }, 192 | {MCC="222" ; MNC="01"; TAC = "3"; } 193 | ); 194 | 195 | TAC_LIST = ( 196 | {MCC="222" ; MNC="01"; TAC = "1"; } 197 | ); 198 | 199 | CSFB : 200 | { 201 | NON_EPS_SERVICE_CONTROL = "OFF"; 202 | CSFB_MCC = "222"; 203 | CSFB_MNC = "01"; 204 | LAC = "1"; 205 | }; 206 | ``` 207 | 208 | For the **SPGWC-C** and **SPGW-U-TINY** section of the docker-compose file: 209 | 210 | * **MCC** 211 | * **MNC** 212 | * **MNC03** 213 | * **TAC** 214 | 215 | **Last important point:** Your MME PLMN **SHALL** match the one in your eNB configuration! 216 | 217 | For example, if you are using OAI eNB configuration file: 218 | 219 | ```bash 220 | tracking_area_code = 1; 221 | plmn_list = ( 222 | { mcc = 222; mnc = 01; mnc_length = 2; } 223 | ); 224 | ``` 225 | 226 | ## 4.3. Your network configuration ## 227 | 228 | ### DNS Settings ### 229 | 230 | Your EPC Docker host has its own gateway --> you need to provide it as "Local DNS server". 231 | 232 | **Otherwise** you won't have Internet access on your UE when it is connected to the Core Network! 233 | 234 | On your EPC docker host, type: 235 | 236 | ```bash 237 | $ route -n 238 | Kernel IP routing table 239 | Destination Gateway Genmask Flags Metric Ref Use Iface 240 | 0.0.0.0 192.168.18.129 0.0.0.0 UG 300 0 0 nm-bond 241 | .... 242 | ``` 243 | 244 | In the **SPGW-C** section of the docker-compose file. 245 | 246 | Use the 2nd field value as **DEFAULT_DNS_IPV4_ADDRESS** field. 247 | 248 | In our example, as **DEFAULT_DNS_SEC_IPV4_ADDRESS** we are using Google's 2nd one. You can pick anything else. 249 | 250 | You can also ask your IT team! 251 | 252 | You can tweak with the following 2 variables (but they are already at best values): 253 | 254 | * **PUSH_PROTOCOL_OPTION** 255 | * **NETWORK_UE_NAT_OPTION** 256 | 257 | ### the UE IP address allocation pool ### 258 | 259 | Last point: the UE IP address allocation pool is used to assign an IP address to the UE when it gets connected. 260 | 261 | In our example, I chose "12.1.1.2 - 12.1.1.254" range. 262 | 263 | Note that it is also defined in **CICDR** format for SPGW-U "12.1.1.0/24" 264 | 265 | If you have to change, please respect both formats. 266 | 267 | **SPGW-C** section of docker-compose file: 268 | 269 | * **UE_IP_ADDRESS_POOL_1** 270 | 271 | **SPGW-U-TINY** section of docker-compose file: 272 | 273 | * **NETWORK_UE_IP** 274 | 275 | ## 4.4. Miscellaneous ## 276 | 277 | At the time of writing (2021 / 02 / 01), the automation on the MAGMA-MME image is not completed. 278 | 279 | There are no entry-point scripts, no default MME configuration file. 280 | 281 | Hence there are 2 files in this folder: 282 | 283 | - `mme-cfg.sh` that behaves as `entrypoint` 284 | - `mme.conf` already completed MME configuration file 285 | 286 | Both files do have pre-filled parameters such realm, IP addresses... 287 | 288 | Be careful when modifying them. 289 | 290 | Note that in the `mme.conf`, the **S6A** section has changed: the MME supports now the connection with an HSS entity in a different realm. 291 | 292 | ```bash 293 | S6A : 294 | { 295 | S6A_CONF = "/magma-mme/etc/mme_fd.conf"; # YOUR MME freeDiameter config file path 296 | HSS_HOSTNAME = "hss.openairinterface.org"; 297 | HSS_REALM = "openairinterface.org"; 298 | }; 299 | ``` 300 | 301 | ### Time-Zone Settings ### 302 | 303 | You can specify the timezone at deployment time in each container. 304 | 305 | Just modify **TZ** in each container section! 306 | 307 | Note that by default at build I've set up `Europe/Paris`. 308 | 309 | Proper values can be found in your Linux system at `/usr/share/zoneinfo/`. 310 | 311 | # 5. Connecting an eNB # 312 | 313 | The network configuration on eNB server(s) still is valid. 314 | 315 | See [here](../../docs/CONFIGURE_NETWORKS_MAGMA.md#step-2-create-a-route-on-your-enbgnb-servers) for the commands to do 316 | 317 | And see [here](../../docs/CONFIGURE_NETWORKS_MAGMA.md#verify-your-network-configuration) for commands to verify. 318 | 319 | # 6. Connecting a Smartphone in 5G using NSA support from OAI RAN # 320 | 321 | This part explains the RAN-related section to the demo made during MAGMA-dev conference in February 3rd, 2021. 322 | See [here](../../docs/NSA_SUPPORT_OAI_RAN.md) 323 | -------------------------------------------------------------------------------- /ci-scripts/oai-ran-sanity-check/mme-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | function generateConfFile() 4 | { 5 | set +x 6 | rm -f mme.conf 7 | echo 'MME :' >> mme.conf 8 | echo '{' >> mme.conf 9 | echo ' REALM = "'$REALM'"' >> mme.conf 10 | echo ' PID_DIRECTORY = "/var/run";' >> mme.conf 11 | echo ' MAXENB = 8; # power of 2' >> mme.conf 12 | echo ' MAXUE = 16; # power of 2' >> mme.conf 13 | echo ' RELATIVE_CAPACITY = 10;' >> mme.conf 14 | echo '' >> mme.conf 15 | echo ' EMERGENCY_ATTACH_SUPPORTED = "no";' >> mme.conf 16 | echo ' UNAUTHENTICATED_IMSI_SUPPORTED = "no";' >> mme.conf 17 | echo '' >> mme.conf 18 | echo ' # EPS network feature support' >> mme.conf 19 | echo ' EPS_NETWORK_FEATURE_SUPPORT_IMS_VOICE_OVER_PS_SESSION_IN_S1 = "no"; # DO NOT CHANGE' >> mme.conf 20 | echo ' EPS_NETWORK_FEATURE_SUPPORT_EMERGENCY_BEARER_SERVICES_IN_S1_MODE = "no"; # DO NOT CHANGE' >> mme.conf 21 | echo ' EPS_NETWORK_FEATURE_SUPPORT_LOCATION_SERVICES_VIA_EPC = "no"; # DO NOT CHANGE' >> mme.conf 22 | echo ' EPS_NETWORK_FEATURE_SUPPORT_EXTENDED_SERVICE_REQUEST = "no"; # DO NOT CHANGE' >> mme.conf 23 | echo '' >> mme.conf 24 | echo ' # Display statistics about whole system (expressed in seconds)' >> mme.conf 25 | echo ' MME_STATISTIC_TIMER = 10;' >> mme.conf 26 | echo ' IP_CAPABILITY = "IPV4"; # UE PDN_TYPE' >> mme.conf 27 | echo ' USE_STATELESS = "";' >> mme.conf 28 | echo '' >> mme.conf 29 | echo ' INTERTASK_INTERFACE :' >> mme.conf 30 | echo ' {' >> mme.conf 31 | echo ' # max queue size per task' >> mme.conf 32 | echo ' ITTI_QUEUE_SIZE = 2000000;' >> mme.conf 33 | echo ' };' >> mme.conf 34 | echo '' >> mme.conf 35 | echo ' S6A :' >> mme.conf 36 | echo ' {' >> mme.conf 37 | echo ' S6A_CONF = "'$PREFIX'/mme_fd.conf"; # YOUR MME freeDiameter config file path' >> mme.conf 38 | echo ' HSS_HOSTNAME = "'$HSS_FQDN'";' >> mme.conf 39 | echo ' HSS_REALM = "'$HSS_REALM'";' >> mme.conf 40 | echo ' };' >> mme.conf 41 | echo '' >> mme.conf 42 | echo ' # ------- SCTP definitions' >> mme.conf 43 | echo ' SCTP :' >> mme.conf 44 | echo ' {' >> mme.conf 45 | echo ' # Number of streams to use in input/output' >> mme.conf 46 | echo ' SCTP_INSTREAMS = 8;' >> mme.conf 47 | echo ' SCTP_OUTSTREAMS = 8;' >> mme.conf 48 | echo ' };' >> mme.conf 49 | echo '' >> mme.conf 50 | echo ' # ------- S1AP definitions' >> mme.conf 51 | echo ' S1AP :' >> mme.conf 52 | echo ' {' >> mme.conf 53 | echo ' # outcome drop timer value (seconds)' >> mme.conf 54 | echo ' S1AP_OUTCOME_TIMER = 10;' >> mme.conf 55 | echo ' };' >> mme.conf 56 | echo ' # ------- MME served GUMMEIs' >> mme.conf 57 | echo ' GUMMEI_LIST = (' >> mme.conf 58 | echo ' { MCC="'$MCC'" ; MNC="'$MNC'"; MME_GID="455" ; MME_CODE="5"; }' >> mme.conf 59 | echo ' );' >> mme.conf 60 | echo '' >> mme.conf 61 | echo ' # ------- MME served TAIs' >> mme.conf 62 | echo ' TAI_LIST = (' >> mme.conf 63 | echo ' {MCC="'$MCC'" ; MNC="'$MNC'"; TAC = "'$TAC0'"; },' >> mme.conf 64 | echo ' {MCC="'$MCC'" ; MNC="'$MNC'"; TAC = "2"; },' >> mme.conf 65 | echo ' {MCC="'$MCC'" ; MNC="'$MNC'"; TAC = "3"; }' >> mme.conf 66 | echo ' );' >> mme.conf 67 | echo '' >> mme.conf 68 | echo ' TAC_LIST = (' >> mme.conf 69 | echo ' {MCC="'$MCC'" ; MNC="'$MNC'"; TAC = "'$TAC0'"; }' >> mme.conf 70 | echo ' );' >> mme.conf 71 | echo '' >> mme.conf 72 | echo ' CSFB :' >> mme.conf 73 | echo ' {' >> mme.conf 74 | echo ' NON_EPS_SERVICE_CONTROL = "OFF";' >> mme.conf 75 | echo ' CSFB_MCC = "'$MCC'";' >> mme.conf 76 | echo ' CSFB_MNC = "'$MNC'";' >> mme.conf 77 | echo ' LAC = "1";' >> mme.conf 78 | echo ' };' >> mme.conf 79 | echo ' NAS :' >> mme.conf 80 | echo ' {' >> mme.conf 81 | echo ' ORDERED_SUPPORTED_INTEGRITY_ALGORITHM_LIST = [ "EIA2" , "EIA1" , "EIA0" ];' >> mme.conf 82 | echo ' ORDERED_SUPPORTED_CIPHERING_ALGORITHM_LIST = [ "EEA0" , "EEA1" , "EEA2" ];' >> mme.conf 83 | echo ' T3402 = 1 # in minutes (default is 12 minutes)' >> mme.conf 84 | echo ' T3412 = 54 # in minutes (default is 54 minutes, network dependent)' >> mme.conf 85 | echo ' T3422 = 6 # in seconds (default is 6s)' >> mme.conf 86 | echo ' T3450 = 5000 # in seconds (default is 6s)' >> mme.conf 87 | echo ' T3460 = 6 # in seconds (default is 6s)' >> mme.conf 88 | echo ' T3470 = 6 # in seconds (default is 6s)' >> mme.conf 89 | echo ' T3485 = 8 # UNUSED in seconds (default is 8s)' >> mme.conf 90 | echo ' T3486 = 8 # UNUSED in seconds (default is 8s)' >> mme.conf 91 | echo ' T3489 = 4 # UNUSED in seconds (default is 4s)' >> mme.conf 92 | echo ' T3495 = 8 # UNUSED in seconds (default is 8s)' >> mme.conf 93 | echo ' };' >> mme.conf 94 | echo '' >> mme.conf 95 | echo ' SGS :' >> mme.conf 96 | echo ' {' >> mme.conf 97 | echo ' TS6_1 = 10 # in seconds (default is 10s)' >> mme.conf 98 | echo ' TS8 = 4 # in seconds (default is 4s)' >> mme.conf 99 | echo ' TS9 = 2 # in seconds (default is 4s)' >> mme.conf 100 | echo ' TS10 = 4 # in seconds (default is 4s)' >> mme.conf 101 | echo ' TS13 = 4 # in seconds (default is 4s)' >> mme.conf 102 | echo ' };' >> mme.conf 103 | echo '' >> mme.conf 104 | echo ' NETWORK_INTERFACES :' >> mme.conf 105 | echo ' {' >> mme.conf 106 | echo ' MME_INTERFACE_NAME_FOR_S1_MME = "eth0";' >> mme.conf 107 | echo ' MME_IPV4_ADDRESS_FOR_S1_MME = "'$MME_S1_IP_ADDR'/24";' >> mme.conf 108 | echo ' MME_INTERFACE_NAME_FOR_S11_MME = "eth0";' >> mme.conf 109 | echo ' MME_IPV4_ADDRESS_FOR_S11_MME = "'$MME_S1_IP_ADDR'/24";' >> mme.conf 110 | echo ' MME_PORT_FOR_S11_MME = 2123;' >> mme.conf 111 | echo ' };' >> mme.conf 112 | echo '' >> mme.conf 113 | echo ' LOGGING :' >> mme.conf 114 | echo ' {' >> mme.conf 115 | echo ' OUTPUT = "CONSOLE";' >> mme.conf 116 | echo ' THREAD_SAFE = "no";' >> mme.conf 117 | echo ' COLOR = "no";' >> mme.conf 118 | echo '' >> mme.conf 119 | echo ' SCTP_LOG_LEVEL = "ERROR";' >> mme.conf 120 | echo ' GTPV1U_LOG_LEVEL = "INFO";' >> mme.conf 121 | echo ' SPGW_APP_LOG_LEVEL = "INFO";' >> mme.conf 122 | echo ' UDP_LOG_LEVEL = "INFO";' >> mme.conf 123 | echo ' S1AP_LOG_LEVEL = "DEBUG";' >> mme.conf 124 | echo ' NAS_LOG_LEVEL = "DEBUG";' >> mme.conf 125 | echo ' MME_APP_LOG_LEVEL = "DEBUG";' >> mme.conf 126 | echo ' GTPV2C_LOG_LEVEL = "DEBUG";' >> mme.conf 127 | echo ' S11_LOG_LEVEL = "DEBUG";' >> mme.conf 128 | echo ' S6A_LOG_LEVEL = "DEBUG";' >> mme.conf 129 | echo ' UTIL_LOG_LEVEL = "INFO";' >> mme.conf 130 | echo ' MSC_LOG_LEVEL = "ERROR";' >> mme.conf 131 | echo ' ITTI_LOG_LEVEL = "ERROR";' >> mme.conf 132 | echo ' MME_SCENARIO_PLAYER_LOG_LEVEL = "ERROR";' >> mme.conf 133 | echo ' ASN1_VERBOSITY = "INFO";' >> mme.conf 134 | echo ' };' >> mme.conf 135 | echo '' >> mme.conf 136 | echo ' S-GW :' >> mme.conf 137 | echo ' {' >> mme.conf 138 | echo ' SGW_IPV4_ADDRESS_FOR_S11 = "'$SPGWC0_IP_ADDR'";' >> mme.conf 139 | echo ' };' >> mme.conf 140 | echo '};' >> mme.conf 141 | set -x 142 | } 143 | 144 | function generateFdConfFile() 145 | { 146 | set +x 147 | rm -f mme_fd.conf 148 | echo 'Identity = "'$MME_FQDN'";' >> mme_fd.conf 149 | echo 'Realm = "'$REALM'";' >> mme_fd.conf 150 | echo 'TLS_Cred = "'$PREFIX'/mme.cert.pem",' >> mme_fd.conf 151 | echo ' "'$PREFIX'/mme.key.pem";' >> mme_fd.conf 152 | echo 'TLS_CA = "'$PREFIX'/mme.cacert.pem";' >> mme_fd.conf 153 | echo 'No_SCTP;' >> mme_fd.conf 154 | echo 'Prefer_TCP;' >> mme_fd.conf 155 | echo 'No_IPv6;' >> mme_fd.conf 156 | echo 'SCTP_streams = 3;' >> mme_fd.conf 157 | echo 'NoRelay;' >> mme_fd.conf 158 | echo 'AppServThreads = 4;' >> mme_fd.conf 159 | echo 'ListenOn = "'$MME_S1_IP_ADDR'";' >> mme_fd.conf 160 | echo 'Port = 3870;' >> mme_fd.conf 161 | echo 'SecPort = 5870;' >> mme_fd.conf 162 | echo 'LoadExtension = "/usr/local/lib/freeDiameter/dict_3gpp2_avps.fdx";' >> mme_fd.conf 163 | echo 'LoadExtension = "/usr/local/lib/freeDiameter/dict_draftload_avps.fdx";' >> mme_fd.conf 164 | echo 'LoadExtension = "/usr/local/lib/freeDiameter/dict_etsi283034_avps.fdx";' >> mme_fd.conf 165 | echo 'LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc4004_avps.fdx";' >> mme_fd.conf 166 | echo 'LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc4006bis_avps.fdx";' >> mme_fd.conf 167 | echo 'LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc4072_avps.fdx";' >> mme_fd.conf 168 | echo 'LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc4590_avps.fdx";' >> mme_fd.conf 169 | echo 'LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc5447_avps.fdx";' >> mme_fd.conf 170 | echo 'LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc5580_avps.fdx";' >> mme_fd.conf 171 | echo 'LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc5777_avps.fdx";' >> mme_fd.conf 172 | echo 'LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc5778_avps.fdx";' >> mme_fd.conf 173 | echo 'LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc6734_avps.fdx";' >> mme_fd.conf 174 | echo 'LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc6942_avps.fdx";' >> mme_fd.conf 175 | echo 'LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc7155_avps.fdx";' >> mme_fd.conf 176 | echo 'LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc7683_avps.fdx";' >> mme_fd.conf 177 | echo 'LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc7944_avps.fdx";' >> mme_fd.conf 178 | echo 'LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29061_avps.fdx";' >> mme_fd.conf 179 | echo 'LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29128_avps.fdx";' >> mme_fd.conf 180 | echo 'LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29154_avps.fdx";' >> mme_fd.conf 181 | echo 'LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29173_avps.fdx";' >> mme_fd.conf 182 | echo 'LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29212_avps.fdx";' >> mme_fd.conf 183 | echo 'LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29214_avps.fdx";' >> mme_fd.conf 184 | echo 'LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29215_avps.fdx";' >> mme_fd.conf 185 | echo 'LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29217_avps.fdx";' >> mme_fd.conf 186 | echo 'LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29229_avps.fdx";' >> mme_fd.conf 187 | echo 'LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29272_avps.fdx";' >> mme_fd.conf 188 | echo 'LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29273_avps.fdx";' >> mme_fd.conf 189 | echo 'LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29329_avps.fdx";' >> mme_fd.conf 190 | echo 'LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29336_avps.fdx";' >> mme_fd.conf 191 | echo 'LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29337_avps.fdx";' >> mme_fd.conf 192 | echo 'LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29338_avps.fdx";' >> mme_fd.conf 193 | echo 'LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29343_avps.fdx";' >> mme_fd.conf 194 | echo 'LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29344_avps.fdx";' >> mme_fd.conf 195 | echo 'LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29345_avps.fdx";' >> mme_fd.conf 196 | echo 'LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29368_avps.fdx";' >> mme_fd.conf 197 | echo 'LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29468_avps.fdx";' >> mme_fd.conf 198 | echo 'LoadExtension = "/usr/local/lib/freeDiameter/dict_ts32299_avps.fdx";' >> mme_fd.conf 199 | echo 'LoadExtension = "/usr/local/lib/freeDiameter/dict_S6as6d.fdx";' >> mme_fd.conf 200 | echo 'LoadExtension = "/usr/local/lib/freeDiameter/dict_S6t.fdx";' >> mme_fd.conf 201 | echo 'LoadExtension = "/usr/local/lib/freeDiameter/dict_S6c.fdx";' >> mme_fd.conf 202 | echo '# -------- Peers ---------' >> mme_fd.conf 203 | echo 'ConnectPeer= "'$HSS_FQDN'" { ConnectTo = "'$HSS_IP_ADDR'"; No_SCTP ; No_IPv6; Prefer_TCP; No_TLS; port = 3868;};' >> mme_fd.conf 204 | set -x 205 | } 206 | 207 | set -x 208 | cd /magma-mme/scripts 209 | mkdir -p $PREFIX 210 | 211 | pushd $PREFIX 212 | 213 | generateConfFile 214 | generateFdConfFile 215 | 216 | # Configure REDIS container 217 | sed -i -e "s@bind: 127.0.0.1@bind: $REDIS_IP_ADDR@" /etc/magma/redis.yml 218 | 219 | # Generate freeDiameter certificate 220 | popd 221 | ./check_mme_s6a_certificate $PREFIX mme.$REALM 222 | set +x 223 | 224 | echo "Starting tcpdump capture" 225 | nohup tcpdump -i eth0 -f "not icmp6 and not arp and not port 22 and not port 53" -w /magma-mme/mme-`date -u +"%Y-%m-%dT%H-%M-%S"`.pcap > /dev/null 2>&1 & 226 | sleep 5 227 | 228 | echo "Starting sctpd" 229 | nohup /magma-mme/bin/sctpd > /magma-mme/sctpd.log 2>&1 & 230 | sleep 2 231 | echo "Starting mme executable" 232 | nohup /magma-mme/bin/oai_mme -c $PREFIX/mme.conf > /magma-mme/mme-stdout.log 2>&1 & 233 | sleep 2 234 | tail -f /var/log/mme.log 235 | 236 | -------------------------------------------------------------------------------- /ci-scripts/pcap_check.py: -------------------------------------------------------------------------------- 1 | #/* 2 | # * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more 3 | # * contributor license agreements. See the NOTICE file distributed with 4 | # * this work for additional information regarding copyright ownership. 5 | # * The OpenAirInterface Software Alliance licenses this file to You under 6 | # * the OAI Public License, Version 1.1 (the "License"); you may not use this file 7 | # * except in compliance with the License. 8 | # * You may obtain a copy of the License at 9 | # * 10 | # * http://www.openairinterface.org/?page_id=698 11 | # * 12 | # * Unless required by applicable law or agreed to in writing, software 13 | # * distributed under the License is distributed on an "AS IS" BASIS, 14 | # * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # * See the License for the specific language governing permissions and 16 | # * limitations under the License. 17 | # *------------------------------------------------------------------------------- 18 | # * For more information about the OpenAirInterface (OAI) Software Alliance: 19 | # * contact@openairinterface.org 20 | # */ 21 | #--------------------------------------------------------------------- 22 | 23 | import os 24 | import re 25 | import socket 26 | import struct 27 | import sys 28 | import subprocess 29 | import pyshark 30 | 31 | # IP addresses 32 | HSS_IP_ADDRESS = '192.168.61.67' 33 | MME_IP_ADDRESS = '192.168.61.68' 34 | SPGWC_IP_ADDRESS = '192.168.61.70' 35 | SPGWU_IP_ADDRESS = '192.168.61.71' 36 | ENB_IP_ADDRESS = '192.168.61.80' 37 | 38 | # Diameter constants 39 | FLAGS__REQUEST = '0x00000080' 40 | FLAGS__REQUEST_V2 = '0x80' 41 | FLAGS__ANSWER = '0x00000000' 42 | FLAGS__ANSWER_V2 = '0x00' 43 | 44 | CMD_CODE__ABORT_SESSION = '274' 45 | CMD_CODE__ACCOUNTING = '271' 46 | CMD_CODE__CAPABILITIES_EXCHANGE = '257' 47 | CMD_CODE__DEVICE_WATCHDOG = '280' 48 | CMD_CODE__DISCONNECT_PEER = '282' 49 | CMD_CODE__RE_AUTH = '258' 50 | CMD_CODE__SESSION_TERMINATE = '275' 51 | 52 | RES_CODE__DIAMETER_SUCCESS = '2001' 53 | RES_CODE__DIAMETER_LIMITED_SUCCESS = '2002' 54 | RES_CODE__COMMAND_UNSUPPORTED = '3001' 55 | RES_CODE__UNABLE_TO_DELIVER = '3002' 56 | RES_CODE__REALM_NOT_SERVED = '3003' 57 | RES_CODE__TOO_BUSY = '3003' 58 | 59 | # SCTP Constants 60 | CHUNK_TYPE__DATA = '0' 61 | CHUNK_TYPE__INIT = '1' 62 | CHUNK_TYPE__INIT_ACK = '2' 63 | CHUNK_TYPE__SACK = '3' 64 | CHUNK_TYPE__ABORT = '6' 65 | CHUNK_TYPE__SHUTDOWN = '7' 66 | CHUNK_TYPE__SHUTDOWN_ACK = '8' 67 | CHUNK_TYPE__ERROR = '9' 68 | CHUNK_TYPE__AUTH = '15' 69 | 70 | # S1AP Constants 71 | S1AP_PDU_INITIATINGMESSAGE = '0' 72 | S1AP_PDU_SUCCESSFULOUTCOME = '1' 73 | 74 | PROC_CODE__ID_S1SETUP = '17' 75 | PROC_CODE__ID_INITIALUEMESSAGE = '12' 76 | PROC_CODE__ID_DOWNLINKNASTRANSPORT = '11' 77 | PROC_CODE__ID_UPLINKNASTRANSPORT = '13' 78 | PROC_CODE__ID_INITIALCONTEXTSETUP = '9' 79 | 80 | NAS__AUTHENTICATION_REQ = '82' 81 | NAS__AUTHENTICATION_RES = '83' 82 | NAS__SECURITY_MODE_CMD = '93' 83 | NAS__SECURITY_MODE_COMPLETE = '94' 84 | NAS__ATTACH_ACCEPT = '66' 85 | 86 | # GTPV2 Constants 87 | GTPV2_MSG_TYPE__CREATE_SESSION_REQUEST = '32' 88 | GTPV2_MSG_TYPE__CREATE_SESSION_RESPONSE = '33' 89 | GTPV2_MSG_TYPE__MODIFY_BEARER_REQUEST = '34' 90 | GTPV2_MSG_TYPE__MODIFY_BEARER_RESPONSE = '35' 91 | GTPV2_MSG_TYPE__DELETE_SESSION_REQUEST = '36' 92 | GTPV2_MSG_TYPE__DELETE_SESSION_RESPONSE = '37' 93 | 94 | # PGCP Constants 95 | PFCP_MSG_TYPE__SX_HEARTBEAT_REQUEST = '1' 96 | PFCP_MSG_TYPE__SX_HEARTBEAT_RESPONSE = '2' 97 | PFCP_MSG_TYPE__SX_ASSOCIATION_SETUP_REQUEST = '5' 98 | PFCP_MSG_TYPE__SX_ASSOCIATION_SETUP_RESPONSE = '6' 99 | PFCP_NODE_ID_TYPE__FQDN = '2' 100 | 101 | def check_if_mme_connects_to_hss(pcap_file): 102 | """ Normally the 2 first DIAMETER packets are the MME <-> HSS peerage """ 103 | res = {} 104 | res['mme_request'] = False 105 | res['hss_answer'] = False 106 | res['origin_host'] = '' 107 | res['origin_realm'] = '' 108 | try: 109 | cap = {} 110 | cap = pyshark.FileCapture(pcap_file, keep_packets=True, display_filter="tcp.port == 3868") 111 | cnt = 0 112 | for pkt in cap: 113 | if pkt is not None: 114 | if 'DIAMETER' in pkt: 115 | if cnt == 0: 116 | if pkt.diameter.flags == FLAGS__REQUEST and pkt.diameter.cmd_code == CMD_CODE__CAPABILITIES_EXCHANGE: 117 | res['mme_request'] = True 118 | if pkt.diameter.flags == FLAGS__REQUEST_V2 and pkt.diameter.cmd_code == CMD_CODE__CAPABILITIES_EXCHANGE: 119 | res['mme_request'] = True 120 | if cnt == 1: 121 | if pkt.diameter.flags == FLAGS__ANSWER or pkt.diameter.flags == FLAGS__ANSWER_V2: 122 | if pkt.diameter.cmd_code == CMD_CODE__CAPABILITIES_EXCHANGE and pkt.diameter.result_code == RES_CODE__DIAMETER_SUCCESS: 123 | res['hss_answer'] = True 124 | res['origin_host']=pkt.diameter.origin_host 125 | res['origin_realm']=pkt.diameter.origin_realm 126 | cnt += 1 127 | cap.close() 128 | except Exception as e: 129 | print('Could not open MME PCAP file') 130 | return res 131 | 132 | def check_if_enb_connects_to_mme(pcap_file): 133 | """ 134 | Sequence is: 135 | - INIT 136 | - INIT_ACK 137 | - S1SetupRequest 138 | - S1SetupResponse 139 | """ 140 | res = {} 141 | res['enb_init_req'] = False 142 | res['mme_init_answer'] = False 143 | res['enb_s1_setup_req'] = False 144 | res['mme_s1_setup_res'] = False 145 | res['enb_mcc'] = '' 146 | res['enb_mnc'] = '' 147 | res['enb_name'] = '' 148 | try: 149 | cap = {} 150 | cap = pyshark.FileCapture(pcap_file, keep_packets=True, display_filter="sctp.port == 36412") 151 | cnt = 0 152 | for pkt in cap: 153 | if pkt is not None: 154 | if 'SCTP' in pkt: 155 | if pkt.sctp.chunk_type == CHUNK_TYPE__INIT: 156 | if pkt.ip.src == ENB_IP_ADDRESS and pkt.ip.dst == MME_IP_ADDRESS: 157 | res['enb_init_req'] = True 158 | if pkt.sctp.chunk_type == CHUNK_TYPE__INIT_ACK: 159 | if pkt.ip.src == MME_IP_ADDRESS and pkt.ip.dst == ENB_IP_ADDRESS: 160 | res['mme_init_answer'] = True 161 | if pkt.sctp.chunk_type == CHUNK_TYPE__DATA: 162 | if pkt.ip.src == ENB_IP_ADDRESS and pkt.ip.dst == MME_IP_ADDRESS and 'S1AP' in pkt: 163 | if pkt.s1ap.procedurecode == PROC_CODE__ID_S1SETUP and pkt.s1ap.s1ap_pdu == S1AP_PDU_INITIATINGMESSAGE: 164 | res['enb_s1_setup_req'] = True 165 | res['enb_mcc'] = pkt.s1ap.e212_mcc 166 | res['enb_mnc'] = pkt.s1ap.e212_mnc 167 | res['enb_name'] = pkt.s1ap.enbname 168 | if pkt.ip.src == MME_IP_ADDRESS and pkt.ip.dst == ENB_IP_ADDRESS and 'S1AP' in pkt: 169 | if pkt.s1ap.procedurecode == PROC_CODE__ID_S1SETUP and pkt.s1ap.s1ap_pdu == S1AP_PDU_SUCCESSFULOUTCOME: 170 | res['mme_s1_setup_res'] = True 171 | elif pkt.s1ap.procedurecode == PROC_CODE__ID_S1SETUP: 172 | res['mme_s1_setup_res'] = False 173 | cnt += 1 174 | cap.close() 175 | except Exception as e: 176 | print('Could not open MME PCAP file') 177 | return res 178 | 179 | def check_if_ue_attachs(pcap_file): 180 | res = {} 181 | res['ue_init_msg'] = False 182 | res['nas_auth_req'] = False 183 | res['nas_auth_res'] = False 184 | res['nas_security_cmd'] = False 185 | res['nas_security_cmplt'] = False 186 | res['initial_ue_context_req'] = False 187 | res['initial_ue_context_res'] = False 188 | res['s11_create_session_req'] = False 189 | res['s11_create_session_res'] = False 190 | res['s11_modify_bearer_req'] = False 191 | res['s11_modify_bearer_res'] = False 192 | res['ue_imsi'] = '' 193 | res['apn'] = '' 194 | res['transportlayeraddress'] = '' 195 | res['enb_transportlayeraddress'] = '' 196 | res['s11_cr_sess_imsi'] = '' 197 | res['s11_cr_sess_mcc'] = '' 198 | res['s11_cr_sess_mnc'] = '' 199 | res['s11_cr_sess_apn'] = '' 200 | res['s11_cr_sess_pdn_addr'] = '' 201 | res['s11_mod_bear_fteid'] = '' 202 | res['s11_mod_bear_ufteid'] = '' 203 | try: 204 | cap = {} 205 | cap = pyshark.FileCapture(pcap_file, keep_packets=True, display_filter="sctp.port == 36412 || udp.port == 2123") 206 | cnt = 0 207 | for pkt in cap: 208 | if pkt is not None: 209 | if 'SCTP' in pkt: 210 | if pkt.sctp.chunk_type == CHUNK_TYPE__DATA: 211 | if pkt.ip.src == ENB_IP_ADDRESS and pkt.ip.dst == MME_IP_ADDRESS and 'S1AP' in pkt: 212 | if pkt.s1ap.procedurecode == PROC_CODE__ID_INITIALUEMESSAGE and pkt.s1ap.s1ap_pdu == S1AP_PDU_INITIATINGMESSAGE: 213 | res['ue_init_msg'] = True 214 | res['ue_imsi'] = pkt.s1ap.e212_imsi 215 | print('UE --> send NAS INITIAL UE MESSAGE (pkt #' + str(cnt) + ')') 216 | # The UE Initial Context Response has 2 S1AP layers! 217 | myLayers = pkt.get_multiple_layers('S1AP') 218 | if len(myLayers) == 2: 219 | if myLayers[0].procedurecode == PROC_CODE__ID_INITIALCONTEXTSETUP and myLayers[0].s1ap_pdu == S1AP_PDU_SUCCESSFULOUTCOME and \ 220 | myLayers[1].procedurecode == PROC_CODE__ID_UPLINKNASTRANSPORT and myLayers[1].s1ap_pdu == S1AP_PDU_INITIATINGMESSAGE: 221 | res['initial_ue_context_res'] = True 222 | res['enb_transportlayeraddress'] = myLayers[0].transportlayeraddressipv4 223 | #print (myLayers[1].nas_eps_nas_msg_emm_type) 224 | print('UE --> send UE INITIAL UE CONTEXT RESPONSE (pkt #' + str(cnt) + ')') 225 | 226 | if pkt.sctp.chunk_type == CHUNK_TYPE__SACK: 227 | if pkt.ip.src == MME_IP_ADDRESS and pkt.ip.dst == ENB_IP_ADDRESS and 'S1AP' in pkt: 228 | if pkt.s1ap.procedurecode == PROC_CODE__ID_DOWNLINKNASTRANSPORT and pkt.s1ap.s1ap_pdu == S1AP_PDU_INITIATINGMESSAGE: 229 | emmType = convertStringHexaToStringInteger(pkt.s1ap.nas_eps_nas_msg_emm_type) 230 | if emmType == NAS__AUTHENTICATION_REQ: 231 | res['nas_auth_req'] = True 232 | print('MME --> send NAS AUTHENTICATION_REQ (pkt #' + str(cnt) + ')') 233 | if emmType == NAS__SECURITY_MODE_CMD: 234 | res['nas_security_cmd'] = True 235 | print('MME --> send NAS SECURITY_MODE_CMD (pkt #' + str(cnt) + ')') 236 | if pkt.s1ap.procedurecode == PROC_CODE__ID_INITIALCONTEXTSETUP and pkt.s1ap.s1ap_pdu == S1AP_PDU_INITIATINGMESSAGE: 237 | emmType = convertStringHexaToStringInteger(pkt.s1ap.nas_eps_nas_msg_emm_type) 238 | if emmType == NAS__ATTACH_ACCEPT: 239 | res['initial_ue_context_req'] = True 240 | res['apn'] = pkt.s1ap.gsm_a_gm_sm_apn 241 | res['transportlayeraddress'] = pkt.s1ap.transportlayeraddressipv4 242 | print('MME --> send NAS INITIAL UE CONTEXT (pkt #' + str(cnt) + ')') 243 | 244 | if pkt.ip.src == ENB_IP_ADDRESS and pkt.ip.dst == MME_IP_ADDRESS and 'S1AP' in pkt: 245 | if pkt.s1ap.procedurecode == PROC_CODE__ID_UPLINKNASTRANSPORT and pkt.s1ap.s1ap_pdu == S1AP_PDU_INITIATINGMESSAGE: 246 | emmType = convertStringHexaToStringInteger(pkt.s1ap.nas_eps_nas_msg_emm_type) 247 | if emmType == NAS__AUTHENTICATION_RES: 248 | res['nas_auth_res'] = True 249 | print('eNB --> send NAS AUTHENTICATION_RES (pkt #' + str(cnt) + ')') 250 | if emmType == NAS__SECURITY_MODE_COMPLETE: 251 | res['nas_security_cmplt'] = True 252 | print('eNB --> send NAS SECURITY_MODE_COMPLETE (pkt #' + str(cnt) + ')') 253 | cnt += 1 254 | if 'GTPV2' in pkt: 255 | if pkt.ip.src == MME_IP_ADDRESS and pkt.ip.dst == SPGWC_IP_ADDRESS: 256 | if pkt.gtpv2.message_type == GTPV2_MSG_TYPE__CREATE_SESSION_REQUEST: 257 | res['s11_create_session_req'] = True 258 | res['s11_cr_sess_imsi'] = pkt.gtpv2.e212_imsi 259 | res['s11_cr_sess_mcc'] = pkt.gtpv2.e212_tai_mcc 260 | res['s11_cr_sess_mnc'] = pkt.gtpv2.e212_tai_mnc 261 | res['s11_cr_sess_apn'] = pkt.gtpv2.apn 262 | print('S11 CREATE SESSION REQ (pkt #' + str(cnt) + ')') 263 | if pkt.gtpv2.message_type == GTPV2_MSG_TYPE__MODIFY_BEARER_REQUEST: 264 | res['s11_modify_bearer_req'] = True 265 | res['s11_mod_bear_fteid'] = pkt.gtpv2.f_teid_ipv4 266 | print('S11 MODIFY BEARER REQ (pkt #' + str(cnt) + ')') 267 | if pkt.ip.src == SPGWC_IP_ADDRESS and pkt.ip.dst == MME_IP_ADDRESS: 268 | if pkt.gtpv2.message_type == GTPV2_MSG_TYPE__CREATE_SESSION_RESPONSE: 269 | res['s11_create_session_res'] = True 270 | res['s11_cr_sess_pdn_addr'] = pkt.gtpv2.pdn_addr_and_prefix_ipv4 271 | print('S11 CREATE SESSION RES (pkt #' + str(cnt) + ')') 272 | if pkt.gtpv2.message_type == GTPV2_MSG_TYPE__MODIFY_BEARER_RESPONSE: 273 | res['s11_modify_bearer_res'] = True 274 | res['s11_mod_bear_ufteid'] = pkt.gtpv2.f_teid_ipv4 275 | print('S11 MODIFY BEARER RES (pkt #' + str(cnt) + ')') 276 | cnt += 1 277 | cap.close() 278 | except Exception as e: 279 | print('Could not open MME PCAP file') 280 | return res 281 | 282 | def check_if_spgwu_connects_to_spgwc(pcap_file): 283 | """ Normally the 2 first PFCP packets are the SPGWC <-> SPGWU association """ 284 | res = {} 285 | res['spgwu_request'] = False 286 | res['spgwc_answer'] = False 287 | res['spgwu_fdqn'] = '' 288 | res['spgwc_ipv4'] = '' 289 | try: 290 | cap = {} 291 | cap = pyshark.FileCapture(pcap_file, keep_packets=True, display_filter="udp.port == 8805") 292 | cnt = 0 293 | for pkt in cap: 294 | if pkt is not None: 295 | if 'PFCP' in pkt: 296 | if cnt == 0: 297 | if pkt.pfcp.msg_type == PFCP_MSG_TYPE__SX_ASSOCIATION_SETUP_REQUEST and pkt.pfcp.node_id_type == PFCP_NODE_ID_TYPE__FQDN: 298 | res['spgwu_request'] = True 299 | res['spgwu_fdqn'] = pkt.pfcp.node_id_fqdn 300 | if cnt == 1: 301 | if pkt.pfcp.msg_type == PFCP_MSG_TYPE__SX_ASSOCIATION_SETUP_RESPONSE: 302 | if pkt.pfcp.cause == '1': 303 | res['spgwc_answer'] = True 304 | res['spgwc_ipv4']=pkt.pfcp.node_id_ipv4 305 | cnt += 1 306 | cap.close() 307 | except Exception as e: 308 | print('Could not open SPGWC PCAP file') 309 | return res 310 | 311 | def check_cups_heartbeat(pcap_file): 312 | """ Normally the heartbeat request/response pace is one every second """ 313 | res = {} 314 | res['spgwc_hrt_request'] = False 315 | res['spgwu_hrt_answer'] = False 316 | res['spgwc_hrt_nb_req'] = '0' 317 | res['spgwu_hrt_nb_res'] = '0' 318 | nb_requests = 0 319 | nb_responses = 0 320 | try: 321 | cap = {} 322 | cap = pyshark.FileCapture(pcap_file, keep_packets=True, display_filter="udp.port == 8805") 323 | cnt = 0 324 | for pkt in cap: 325 | if pkt is not None: 326 | if 'PFCP' in pkt: 327 | if pkt.pfcp.msg_type == PFCP_MSG_TYPE__SX_HEARTBEAT_REQUEST: 328 | nb_requests += 1 329 | if pkt.pfcp.msg_type == PFCP_MSG_TYPE__SX_HEARTBEAT_RESPONSE: 330 | nb_responses += 1 331 | cnt += 1 332 | cap.close() 333 | except Exception as e: 334 | print('Could not open SPGWC PCAP file') 335 | if nb_requests > 0: 336 | res['spgwc_hrt_request'] = True 337 | res['spgwc_hrt_nb_req'] = str(nb_requests) 338 | if nb_responses > 0: 339 | res['spgwu_hrt_answer'] = True 340 | res['spgwu_hrt_nb_res'] = str(nb_responses) 341 | return res 342 | 343 | def convertStringHexaToStringInteger(originalField): 344 | intStringField = originalField 345 | if intStringField.count('0x') > 0: 346 | intStringField = str(int(intStringField, 16)) 347 | return intStringField 348 | -------------------------------------------------------------------------------- /ci-scripts/Jenkinsfile-Magma-OAI-DsTester: -------------------------------------------------------------------------------- 1 | #!/bin/groovy 2 | /* 3 | * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more 4 | * contributor license agreements. See the NOTICE file distributed with 5 | * this work for additional information regarding copyright ownership. 6 | * The OpenAirInterface Software Alliance licenses this file to You under 7 | * the OAI Public License, Version 1.1 (the "License"); you may not use this file 8 | * except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.openairinterface.org/?page_id=698 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | *------------------------------------------------------------------------------- 19 | * For more information about the OpenAirInterface (OAI) Software Alliance: 20 | * contact@openairinterface.org 21 | */ 22 | 23 | // Location of the CN executor node 24 | def cn_ci_host = params.Host_CN_CI_Server 25 | 26 | // for lock 27 | def cn_ci_resource = params.DockerContainers 28 | def ds_tester_ci_resource = params.DsTester 29 | def ds_tester_flag = params.PerformDsTesterTestSuite 30 | 31 | // Location of the DsTester workspace 32 | def dsTestFrameworkLocation = params.dsTestFrameworkLocation 33 | 34 | // Default tags / branches --> could be passed on by upstream job or by PR content 35 | def hssTag = 'develop' 36 | def hssBranch = 'develop' 37 | def magmaMmeTag = 'master' 38 | // No branch for MAGMA 39 | def spgwcTag = 'develop' 40 | def spgwcBranch = 'develop' 41 | def spgwuTag = 'develop' 42 | def spgwuBranch = 'develop' 43 | 44 | // Flags 45 | def scmEvent = false 46 | def upstreamEvent = false 47 | 48 | //------------------------------------------------------------------------------- 49 | // Pipeline start 50 | pipeline { 51 | agent { 52 | label cn_ci_host 53 | } 54 | options { 55 | disableConcurrentBuilds() 56 | timestamps() 57 | ansiColor('xterm') 58 | lock(cn_ci_resource) 59 | } 60 | stages { 61 | stage ('Verify Parameters') { 62 | steps { 63 | script { 64 | echo '\u2705 \u001B[32mVerify Parameters\u001B[0m' 65 | 66 | JOB_TIMESTAMP = sh returnStdout: true, script: 'date --utc --rfc-3339=seconds | sed -e "s#+00:00##"' 67 | JOB_TIMESTAMP = JOB_TIMESTAMP.trim() 68 | 69 | // Clean workspace and prepare artifacts location 70 | sh "git clean -x -d -f > /dev/null 2>&1" 71 | sh "mkdir -p archives DS-TEST-RESULTS" 72 | 73 | // Find out the cause of the trigger 74 | for (cause in currentBuild.getBuildCauses()) { 75 | if (cause.toString() ==~ /.*GitHubPushCause.*/) { 76 | scmEvent = true 77 | } else if (cause.toString() ==~ /.*GhprbCause.*/) { 78 | scmEvent = true 79 | } else if (cause.toString() ==~ /.*UpstreamCause.*/) { 80 | upstreamEvent = true 81 | } 82 | } 83 | 84 | if (upstreamEvent) { 85 | if (params.HSS_TAG != null) { 86 | hssTag = params.HSS_TAG 87 | echo "Upstream Job passed HSS_TAG to use: ${hssTag}" 88 | } 89 | if (params.HSS_BRANCH != null) { 90 | hssBranch = params.HSS_BRANCH 91 | echo "Upstream Job passed HSS_BRANCH to use: ${hssBranch}" 92 | } 93 | if (params.MAGMA_MME_TAG != null) { 94 | magmaMmeTag = params.MAGMA_MME_TAG 95 | echo "Upstream Job passed MAGMA_MME_TAG to use: ${magmaMmeTag}" 96 | } 97 | if (params.SPGWC_TAG != null) { 98 | spgwcTag = params.SPGWC_TAG 99 | echo "Upstream Job passed SPGWC_TAG to use: ${spgwcTag}" 100 | } 101 | if (params.SPGWC_BRANCH != null) { 102 | spgwcBranch = params.SPGWC_BRANCH 103 | echo "Upstream Job passed SPGWC_BRANCH to use: ${spgwcBranch}" 104 | } 105 | if (params.SPGWU_TAG != null) { 106 | spgwuTag = params.SPGWU_TAG 107 | echo "Upstream Job passed SPGWU_TAG to use: ${spgwuTag}" 108 | } 109 | if (params.SPGWU_BRANCH != null) { 110 | spgwuBranch = params.SPGWU_BRANCH 111 | echo "Upstream Job passed SPGWU_BRANCH to use: ${spgwuBranch}" 112 | } 113 | } 114 | // Here we verify if all images tags are available. 115 | try { 116 | sh 'echo "MAGMA_MME_TAG: magma-mme:' + magmaMmeTag +'" > archives/magma_mme_image_info.log' 117 | sh 'docker image inspect --format=\'Size = {{.Size}} bytes\' magma-mme:' + magmaMmeTag + ' >> archives/magma_mme_image_info.log' 118 | sh 'docker image inspect --format=\'Date = {{.Created}}\' magma-mme:' + magmaMmeTag + ' >> archives/magma_mme_image_info.log' 119 | } catch (Exception e) { 120 | error "Magma MME Image tag to test does not exist!" 121 | } 122 | try { 123 | sh 'echo "OAI_HSS_TAG: oai-hss:' + hssTag +'" > archives/oai_hss_image_info.log' 124 | sh 'docker image inspect --format=\'Size = {{.Size}} bytes\' oai-hss:' + hssTag + ' >> archives/oai_hss_image_info.log' 125 | sh 'docker image inspect --format=\'Date = {{.Created}}\' oai-hss:' + hssTag + ' >> archives/oai_hss_image_info.log' 126 | } catch (Exception e) { 127 | error "OAI HSS Image tag to test does not exist!" 128 | } 129 | try { 130 | sh 'echo "OAI_SPGWC_TAG: oai-spgwc:' + spgwcTag +'" > archives/oai_spgwc_image_info.log' 131 | sh 'docker image inspect --format=\'Size = {{.Size}} bytes\' oai-spgwc:' + spgwcTag + ' >> archives/oai_spgwc_image_info.log' 132 | sh 'docker image inspect --format=\'Date = {{.Created}}\' oai-spgwc:' + spgwcTag + ' >> archives/oai_spgwc_image_info.log' 133 | } catch (Exception e) { 134 | error "OAI SPGW-C Image tag to test does not exist!" 135 | } 136 | try { 137 | sh 'echo "OAI_SPGWU_TAG: oai-spgwu-tiny:' + spgwuTag +'" > archives/oai_spgwu_image_info.log' 138 | sh 'docker image inspect --format=\'Size = {{.Size}} bytes\' oai-spgwu-tiny:' + spgwuTag + ' >> archives/oai_spgwu_image_info.log' 139 | sh 'docker image inspect --format=\'Date = {{.Created}}\' oai-spgwu-tiny:' + spgwuTag + ' >> archives/oai_spgwu_image_info.log' 140 | } catch (Exception e) { 141 | error "OAI SPGW-U-Tiny Image tag to test does not exist!" 142 | } 143 | 144 | // Prepare workspace 145 | sh './scripts/syncComponents.sh --hss-branch ' + hssBranch + ' --spgwc-branch ' + spgwcBranch + ' --spgwu-tiny-branch ' + spgwuBranch 146 | } 147 | } 148 | } 149 | stage ('Deploy Whole EPC') { 150 | steps { 151 | script { 152 | // EPC is in idle mode because our DsTester framework starts and stops all cNFs for each scenario 153 | echo '\u2705 \u001B[32mDeploy EPC in idle mode\u001B[0m' 154 | // Prepare all needed files for docker-compose 155 | // First put all correct tags to test 156 | sh 'sed -e "s#HSS_IMAGE_TAG#' + hssTag + '#" -e "s#MAGMA_MME_IMAGE_TAG#' + magmaMmeTag + '#" -e "s#SPGWC_IMAGE_TAG#' + spgwcTag + '#" -e "s#SPGWU_IMAGE_TAG#' + spgwuTag + '#" ci-scripts/dsTesterDockerCompose/docker-compose.tplt > ci-scripts/dsTesterDockerCompose/docker-compose.yml' 157 | sh 'cp ci-scripts/dsTesterDockerCompose/mme.conf.tplt ci-scripts/dsTesterDockerCompose/mme.conf' 158 | sh 'cp component/oai-hss/src/hss_rel14/db/oai_db.cql ci-scripts/dsTesterDockerCompose' 159 | // Entrypoints are modified to be inactive for dsTester framework 160 | sh 'sed -e "s@exec.*@sleep infinity@" component/oai-hss/scripts/entrypoint.sh > ci-scripts/dsTesterDockerCompose/hss-entrypoint-sleep.sh' 161 | sh 'sed -e "s@exec.*@sleep infinity@" component/oai-spgwc/scripts/entrypoint.sh > ci-scripts/dsTesterDockerCompose/spgwc-entrypoint-sleep.sh' 162 | sh 'sed -e "s@exec.*@sleep infinity@" component/oai-spgwu-tiny/scripts/entrypoint.sh > ci-scripts/dsTesterDockerCompose/spgwu-entrypoint-sleep.sh' 163 | sh 'chmod 755 ci-scripts/dsTesterDockerCompose/*entrypoint-sleep.sh' 164 | 165 | // Deploy 166 | dir('ci-scripts/dsTesterDockerCompose') { 167 | // Making sure not leftover. 168 | sh 'docker-compose down > /dev/null 2>&1 || true' 169 | sh 'docker-compose up -d cicd_db_init > ../../archives/compose_cassandra_up.log 2>&1' 170 | int count = 0 171 | while (count<6) { 172 | sh 'sleep 10' 173 | ret = sh returnStdout: true, script: 'docker logs cicd-db-init 2> /dev/null | grep -c OK || true' 174 | ret = ret.trim() 175 | if (ret == '1') { 176 | count = 10 177 | } 178 | count++ 179 | } 180 | if (count<10) { 181 | error('Could not init Cassandra tables in time') 182 | } 183 | sh 'docker rm cicd-db-init' 184 | 185 | sh 'docker-compose up -d cicd_oai_spgwu > ../../archives/compose_epc_up.log 2>&1' 186 | // All healthy checks should be done after 50 seconds 187 | sh 'sleep 50' 188 | // Do a check on number of healthy containers 189 | // 6 == cassandra + hss + redis + mme + spgwc + spgwu 190 | ret = sh returnStdout: true, script: 'docker-compose ps -a | grep -v unhealthy | grep -c healthy || true' 191 | ret = ret.trim() 192 | if (ret != '6') { 193 | error "Deployment went wrong!" 194 | } 195 | } 196 | } 197 | } 198 | post { 199 | always { 200 | script { 201 | // Check status on cassandra. 202 | try { 203 | sh 'docker exec -i cicd-cassandra /bin/bash -c "nodetool status" > archives/cassandra_status.log 2>&1' 204 | sh 'docker inspect --format=\'STATUS: {{.State.Health.Status}}\' cicd-cassandra >> archives/cassandra_status.log' 205 | } catch (Exception e) { 206 | sh 'echo "STATUS: KO" >> archives/cassandra_status.log' 207 | } 208 | // Check status on redis. 209 | try { 210 | sh 'docker top cicd-redis | grep -c redis-server > archives/redis_status.log' 211 | sh 'docker inspect --format=\'STATUS: {{.State.Health.Status}}\' cicd-redis >> archives/redis_status.log' 212 | sh 'echo "STATUS: OK" >> archives/redis_status.log' 213 | } catch (Exception e) { 214 | sh 'echo "STATUS: KO" >> archives/redis_status.log' 215 | } 216 | // Do docker logs to recover the configuration results 217 | try { 218 | sh 'docker logs cicd-oai-hss > archives/hss_config.log 2>&1' 219 | sh 'docker inspect --format=\'STATUS: {{.State.Health.Status}}\' cicd-oai-hss >> archives/hss_config.log' 220 | } catch (Exception e) { 221 | sh 'echo "STATUS: KO" >> archives/hss_config.log' 222 | } 223 | try { 224 | sh 'docker logs cicd-oai-mme > archives/mme_config.log 2>&1' 225 | sh 'docker inspect --format=\'STATUS: {{.State.Health.Status}}\' cicd-oai-mme >> archives/mme_config.log' 226 | } catch (Exception e) { 227 | sh 'echo "STATUS: KO" >> archives/mme_config.log' 228 | } 229 | try { 230 | sh 'docker logs cicd-oai-spgwc > archives/spgwc_config.log 2>&1' 231 | sh 'docker inspect --format=\'STATUS: {{.State.Health.Status}}\' cicd-oai-spgwc >> archives/spgwc_config.log' 232 | } catch (Exception e) { 233 | sh 'echo "STATUS: OK" >> archives/spgwc_config.log' 234 | } 235 | try { 236 | sh 'docker logs cicd-oai-spgwu-tiny > archives/spgwu_config.log 2>&1' 237 | sh 'docker inspect --format=\'STATUS: {{.State.Health.Status}}\' cicd-oai-spgwu-tiny >> archives/spgwu_config.log' 238 | } catch (Exception e) { 239 | sh 'echo "STATUS: KO" >> archives/spgwu_config.log' 240 | } 241 | } 242 | } 243 | success { 244 | script { 245 | sh 'echo "DEPLOYMENT: OK" > archives/deployment_status.log' 246 | } 247 | } 248 | unsuccessful { 249 | script { 250 | sh 'echo "DEPLOYMENT: KO" > archives/deployment_status.log' 251 | } 252 | } 253 | } 254 | } 255 | stage ('Test EPC') { 256 | when { expression {ds_tester_flag} } 257 | steps { 258 | lock (ds_tester_ci_resource) { 259 | script { 260 | echo '\u2705 \u001B[32mTesting with DsTester framework\u001B[0m' 261 | sh 'cd ' + dsTestFrameworkLocation + ' && git clean -x -d -f > /dev/null' 262 | sh 'cd ' + dsTestFrameworkLocation + '/scripts && export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:.:/usr/local/devsol/bin && CI_ENV=True CI_MAGMA=True SRC_BASE_DIR=' + WORKSPACE + ' ./run-4gc.bash -pt --shark --detach --get-results --4g > ' + WORKSPACE + '/archives/run-4g-dstester.log 2>&1' 263 | sh 'cd ' + dsTestFrameworkLocation + ' && git stash > /dev/null' 264 | sh 'cd ' + dsTestFrameworkLocation + ' && git stash clear > /dev/null' 265 | } 266 | } 267 | } 268 | } 269 | stage ('Undeploy Whole EPC') { 270 | steps { 271 | script { 272 | echo '\u2705 \u001B[32mUn-Deploy EPC\u001B[0m' 273 | dir('ci-scripts/dsTesterDockerCompose') { 274 | sh 'docker-compose down > ../../archives/compose_normal_down.log 2>&1' 275 | } 276 | } 277 | } 278 | } 279 | } 280 | post { 281 | always { 282 | script { 283 | dir('ci-scripts/dsTesterDockerCompose') { 284 | sh 'docker-compose down > ../../archives/compose_preventive_down.log 2>&1 || true' 285 | sh 'docker volume prune --force > /dev/null 2>&1 || true' 286 | } 287 | // Zipping all archived log files 288 | sh "zip -r -qq fed_docker_logs.zip archives DS-TEST-RESULTS/*.tar DS-TEST-RESULTS/status.txt" 289 | if (fileExists('fed_docker_logs.zip')) { 290 | archiveArtifacts artifacts: 'fed_docker_logs.zip' 291 | } 292 | if (ds_tester_flag) { 293 | sh 'python3 ./ci-scripts/dsTestGenerateHTMLReport.py --job_name=' + JOB_NAME + ' --job_id=' + BUILD_ID + ' --job_url=' + BUILD_URL + ' --ds_tester=True' 294 | } else { 295 | sh 'python3 ./ci-scripts/dsTestGenerateHTMLReport.py --job_name=' + JOB_NAME + ' --job_id=' + BUILD_ID + ' --job_url=' + BUILD_URL + ' --ds_tester=False' 296 | } 297 | if (fileExists('test_results_oai_epc.html')) { 298 | sh 'mv test_results_oai_epc.html test_results_magma_oai_epc.html' 299 | archiveArtifacts artifacts: 'test_results_magma_oai_epc.html' 300 | } 301 | } 302 | } 303 | } 304 | } 305 | -------------------------------------------------------------------------------- /ci-scripts/Jenkinsfile-Magma-Sanity-Check: -------------------------------------------------------------------------------- 1 | #!/bin/groovy 2 | /* 3 | * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more 4 | * contributor license agreements. See the NOTICE file distributed with 5 | * this work for additional information regarding copyright ownership. 6 | * The OpenAirInterface Software Alliance licenses this file to You under 7 | * the OAI Public License, Version 1.1 (the "License"); you may not use this file 8 | * except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.openairinterface.org/?page_id=698 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | *------------------------------------------------------------------------------- 19 | * For more information about the OpenAirInterface (OAI) Software Alliance: 20 | * contact@openairinterface.org 21 | */ 22 | 23 | // Location of the CN executor node 24 | def cn_ci_host = params.Host_CN_CI_Server 25 | 26 | // for lock 27 | def cn_ci_resource = params.DockerContainers 28 | 29 | // Default tags / branches --> could be passed on by upstream job or by PR content 30 | def hssTag = 'develop' 31 | def hssBranch = 'develop' 32 | def magmaMmeTag = 'master' 33 | // No branch for MAGMA 34 | def spgwcTag = 'develop' 35 | def spgwcBranch = 'develop' 36 | def spgwuTag = 'develop' 37 | def spgwuBranch = 'develop' 38 | 39 | // RAN Tags to use 40 | def oaiEnbTag = '' 41 | def oaiLteUeTag = '' 42 | 43 | // Flags 44 | def scmEvent = false 45 | def upstreamEvent = false 46 | def retrievedLogs = false 47 | 48 | // Syntax 49 | def containerCli = '' 50 | def containerHealth = '' 51 | def reportName = '' 52 | def zipName = '' 53 | 54 | //------------------------------------------------------------------------------- 55 | // Pipeline start 56 | pipeline { 57 | agent { 58 | label cn_ci_host 59 | } 60 | options { 61 | disableConcurrentBuilds() 62 | timestamps() 63 | ansiColor('xterm') 64 | lock(cn_ci_resource) 65 | } 66 | stages { 67 | stage ('Verify Parameters') { 68 | steps { 69 | script { 70 | if (cn_ci_host == 'cetautomatix') { 71 | containerCli = 'sudo podman' 72 | containerHealth = 'Healthcheck' 73 | oaiEnbTag = 'develop-2022-w10' 74 | oaiLteUeTag = 'develop-2022-w10' 75 | reportName = 'test_results_magma_epc_rhel8.html' 76 | zipName = 'fed_podman_logs.zip' 77 | } else if (cn_ci_host == 'orion') { 78 | containerCli = 'docker' 79 | containerHealth = 'Health' 80 | oaiEnbTag = 'develop' 81 | oaiLteUeTag = 'develop' 82 | reportName = 'test_results_magma_epc_u18.html' 83 | zipName = 'fed_docker_logs.zip' 84 | } else if (cn_ci_host == 'selfix') { 85 | containerCli = 'docker' 86 | containerHealth = 'Health' 87 | oaiEnbTag = 'develop' 88 | oaiLteUeTag = 'develop' 89 | reportName = 'test_results_magma_epc_u18.html' 90 | zipName = 'fed_docker_logs.zip' 91 | } else { 92 | error 'Not supported CI host' 93 | } 94 | echo '\u2705 \u001B[32mVerify Parameters\u001B[0m' 95 | 96 | JOB_TIMESTAMP = sh returnStdout: true, script: 'date --utc --rfc-3339=seconds | sed -e "s#+00:00##"' 97 | JOB_TIMESTAMP = JOB_TIMESTAMP.trim() 98 | 99 | // Clean workspace and prepare artifacts location 100 | sh "git clean -x -d -f > /dev/null 2>&1" 101 | sh "mkdir -p archives" 102 | 103 | // Find out the cause of the trigger 104 | for (cause in currentBuild.getBuildCauses()) { 105 | if (cause.toString() ==~ /.*GitHubPushCause.*/) { 106 | scmEvent = true 107 | } else if (cause.toString() ==~ /.*GhprbCause.*/) { 108 | scmEvent = true 109 | } else if (cause.toString() ==~ /.*UpstreamCause.*/) { 110 | upstreamEvent = true 111 | } 112 | } 113 | 114 | if (upstreamEvent) { 115 | if (params.HSS_TAG != null) { 116 | hssTag = params.HSS_TAG 117 | echo "Upstream Job passed HSS_TAG to use: ${hssTag}" 118 | } 119 | if (params.HSS_BRANCH != null) { 120 | hssBranch = params.HSS_BRANCH 121 | echo "Upstream Job passed HSS_BRANCH to use: ${hssBranch}" 122 | } 123 | if (params.MAGMA_MME_TAG != null) { 124 | magmaMmeTag = params.MAGMA_MME_TAG 125 | echo "Upstream Job passed MAGMA_MME_TAG to use: ${magmaMmeTag}" 126 | } 127 | if (params.SPGWC_TAG != null) { 128 | spgwcTag = params.SPGWC_TAG 129 | echo "Upstream Job passed SPGWC_TAG to use: ${spgwcTag}" 130 | } 131 | if (params.SPGWC_BRANCH != null) { 132 | spgwcBranch = params.SPGWC_BRANCH 133 | echo "Upstream Job passed SPGWC_BRANCH to use: ${spgwcBranch}" 134 | } 135 | if (params.SPGWU_TAG != null) { 136 | spgwuTag = params.SPGWU_TAG 137 | echo "Upstream Job passed SPGWU_TAG to use: ${spgwuTag}" 138 | } 139 | if (params.SPGWU_BRANCH != null) { 140 | spgwuBranch = params.SPGWU_BRANCH 141 | echo "Upstream Job passed SPGWU_BRANCH to use: ${spgwuBranch}" 142 | } 143 | } else { 144 | if (params.MAGMA_MME_TAG != null) { 145 | magmaMmeTag = params.MAGMA_MME_TAG 146 | if (magmaMmeTag != 'master') { 147 | echo "Testing MAGMA_MME_TAG to use: ${magmaMmeTag}" 148 | } 149 | } 150 | } 151 | 152 | // Prepare workspace 153 | sh './scripts/syncComponents.sh --hss-branch ' + hssBranch + ' --spgwc-branch ' + spgwcBranch + ' --spgwu-tiny-branch ' + spgwuBranch 154 | 155 | // On Ubuntu servers, we shall pull from private local registry 156 | if ((cn_ci_host == 'selfix') || (cn_ci_host == 'orion')) { 157 | // Login 158 | sh containerCli + ' login -u oaicicd -p oaicicd selfix.sboai.cs.eurecom.fr > /dev/null 2>&1' 159 | // HSS 160 | if ((hssTag == 'develop') && (hssBranch == 'develop')) { 161 | dir ('component/oai-hss') { 162 | shortenShaOne = sh returnStdout: true, script: 'git log -1 --pretty=format:"%h"' 163 | shortenShaOne.trim() 164 | hssTag = 'develop-' + shortenShaOne 165 | echo "HSS_TAG will be ${hssTag}" 166 | } 167 | } 168 | sh containerCli + ' pull selfix.sboai.cs.eurecom.fr/oai-hss:' + hssTag 169 | sh containerCli + ' image tag selfix.sboai.cs.eurecom.fr/oai-hss:' + hssTag + ' oai-hss:' + hssTag 170 | sh containerCli + ' rmi selfix.sboai.cs.eurecom.fr/oai-hss:' + hssTag 171 | // SPGWC 172 | if ((spgwcTag == 'develop') && (spgwcBranch == 'develop')) { 173 | dir ('component/oai-spgwc') { 174 | shortenShaOne = sh returnStdout: true, script: 'git log -1 --pretty=format:"%h"' 175 | shortenShaOne.trim() 176 | spgwcTag = 'develop-' + shortenShaOne 177 | echo "SPGWC_TAG will be ${spgwcTag}" 178 | } 179 | } 180 | sh containerCli + ' pull selfix.sboai.cs.eurecom.fr/oai-spgwc:' + spgwcTag 181 | sh containerCli + ' image tag selfix.sboai.cs.eurecom.fr/oai-spgwc:' + spgwcTag + ' oai-spgwc:' + spgwcTag 182 | sh containerCli + ' rmi selfix.sboai.cs.eurecom.fr/oai-spgwc:' + spgwcTag 183 | // SPGWU 184 | if ((spgwuTag == 'develop') && (spgwuBranch == 'develop')) { 185 | dir ('component/oai-spgwu-tiny') { 186 | shortenShaOne = sh returnStdout: true, script: 'git log -1 --pretty=format:"%h" --abbrev=8' 187 | shortenShaOne.trim() 188 | spgwuTag = 'develop-' + shortenShaOne 189 | echo "SPGWU_TAG will be ${spgwuTag}" 190 | } 191 | } 192 | sh containerCli + ' pull selfix.sboai.cs.eurecom.fr/oai-spgwu-tiny:' + spgwuTag 193 | sh containerCli + ' image tag selfix.sboai.cs.eurecom.fr/oai-spgwu-tiny:' + spgwuTag + ' oai-spgwu-tiny:' + spgwuTag 194 | sh containerCli + ' rmi selfix.sboai.cs.eurecom.fr/oai-spgwu-tiny:' + spgwuTag 195 | // Logout 196 | sh containerCli + ' logout selfix.sboai.cs.eurecom.fr > /dev/null 2>&1' 197 | } 198 | 199 | // Here we verify if all images tags are available. 200 | try { 201 | sh 'echo "MAGMA_MME_TAG: magma-mme:' + magmaMmeTag +'" > archives/magma_mme_image_info.log' 202 | sh containerCli + ' image inspect --format=\'Size = {{.Size}} bytes\' magma-mme:' + magmaMmeTag + ' >> archives/magma_mme_image_info.log' 203 | sh containerCli + ' image inspect --format=\'Date = {{.Created}}\' magma-mme:' + magmaMmeTag + ' >> archives/magma_mme_image_info.log' 204 | } catch (Exception e) { 205 | error "Magma MME Image tag to test does not exist!" 206 | } 207 | try { 208 | sh 'echo "OAI_HSS_TAG: oai-hss:' + hssTag +'" > archives/oai_hss_image_info.log' 209 | sh containerCli + ' image inspect --format=\'Size = {{.Size}} bytes\' oai-hss:' + hssTag + ' >> archives/oai_hss_image_info.log' 210 | sh containerCli + ' image inspect --format=\'Date = {{.Created}}\' oai-hss:' + hssTag + ' >> archives/oai_hss_image_info.log' 211 | } catch (Exception e) { 212 | error "OAI HSS Image tag to test does not exist!" 213 | } 214 | try { 215 | sh 'echo "OAI_SPGWC_TAG: oai-spgwc:' + spgwcTag +'" > archives/oai_spgwc_image_info.log' 216 | sh containerCli + ' image inspect --format=\'Size = {{.Size}} bytes\' oai-spgwc:' + spgwcTag + ' >> archives/oai_spgwc_image_info.log' 217 | sh containerCli + ' image inspect --format=\'Date = {{.Created}}\' oai-spgwc:' + spgwcTag + ' >> archives/oai_spgwc_image_info.log' 218 | } catch (Exception e) { 219 | error "OAI SPGW-C Image tag to test does not exist!" 220 | } 221 | try { 222 | sh 'echo "OAI_SPGWU_TAG: oai-spgwu-tiny:' + spgwuTag +'" > archives/oai_spgwu_image_info.log' 223 | sh containerCli + ' image inspect --format=\'Size = {{.Size}} bytes\' oai-spgwu-tiny:' + spgwuTag + ' >> archives/oai_spgwu_image_info.log' 224 | sh containerCli + ' image inspect --format=\'Date = {{.Created}}\' oai-spgwu-tiny:' + spgwuTag + ' >> archives/oai_spgwu_image_info.log' 225 | } catch (Exception e) { 226 | error "OAI SPGW-U-Tiny Image tag to test does not exist!" 227 | } 228 | } 229 | } 230 | } 231 | stage ('Deploy EPC') { 232 | steps { 233 | script { 234 | // Currently docker-compose does not work with podman3 the way we want 235 | // Re-using a python based approach 236 | // First making sure remanent from previous run 237 | sh 'python3 ./ci-scripts/OAI-RAN-Sanity-Check-Deploy.py --action=RemoveAllContainers > /dev/null 2>&1' 238 | sh 'python3 ./ci-scripts/OAI-RAN-Sanity-Check-Deploy.py --action=RemoveNetworks > /dev/null 2>&1' 239 | // Create networks 240 | sh 'python3 ./ci-scripts/OAI-RAN-Sanity-Check-Deploy.py --action=CreateNetworks 2>&1' 241 | // Deploy all CN containers 242 | sh 'python3 ./ci-scripts/OAI-RAN-Sanity-Check-Deploy.py --action=DeployCassandra 2>&1' 243 | sh 'python3 ./ci-scripts/OAI-RAN-Sanity-Check-Deploy.py --action=DeployHSS --tag=' + hssTag + ' 2>&1' 244 | sh 'python3 ./ci-scripts/OAI-RAN-Sanity-Check-Deploy.py --action=DeployRedis 2>&1' 245 | sh 'python3 ./ci-scripts/OAI-RAN-Sanity-Check-Deploy.py --action=DeployMME --tag=' + magmaMmeTag + ' 2>&1' 246 | sh 'python3 ./ci-scripts/OAI-RAN-Sanity-Check-Deploy.py --action=DeploySPGWC --tag=' + spgwcTag + ' 2>&1' 247 | sh 'python3 ./ci-scripts/OAI-RAN-Sanity-Check-Deploy.py --action=DeploySPGWU --tag=' + spgwuTag + ' 2>&1' 248 | sh 'python3 ./ci-scripts/OAI-RAN-Sanity-Check-Deploy.py --action=DeployTrfGen --tag=production 2>&1' 249 | if (cn_ci_host == 'orion') { 250 | // SPGWU seems a bit long to be healthy on orion 251 | sh 'sleep 30' 252 | } 253 | } 254 | } 255 | post { 256 | always { 257 | script { 258 | // Check status on cassandra. 259 | try { 260 | sh containerCli + ' exec -i cicd-cassandra /bin/bash -c "nodetool status" > archives/cassandra_status.log 2>&1' 261 | sh containerCli + ' inspect --format=\'STATUS: {{.State.' + containerHealth + '.Status}}\' cicd-cassandra >> archives/cassandra_status.log' 262 | } catch (Exception e) { 263 | sh 'echo "STATUS: KO" >> archives/cassandra_status.log' 264 | } 265 | // Check status on redis. 266 | try { 267 | sh containerCli + ' inspect --format=\'STATUS: {{.State.' + containerHealth + '.Status}}\' cicd-redis > archives/redis_status.log' 268 | } catch (Exception e) { 269 | sh 'echo "STATUS: KO" >> archives/redis_status.log' 270 | } 271 | try { 272 | sh containerCli + ' inspect --format=\'STATUS: {{.State.' + containerHealth + '.Status}}\' cicd-oai-hss > archives/hss_config.log' 273 | } catch (Exception e) { 274 | sh 'echo "STATUS: KO" >> archives/hss_config.log' 275 | } 276 | try { 277 | sh containerCli + ' inspect --format=\'STATUS: {{.State.' + containerHealth + '.Status}}\' cicd-oai-mme > archives/mme_config.log' 278 | } catch (Exception e) { 279 | sh 'echo "STATUS: KO" >> archives/mme_config.log' 280 | } 281 | try { 282 | sh containerCli + ' inspect --format=\'STATUS: {{.State.' + containerHealth + '.Status}}\' cicd-oai-spgwc > archives/spgwc_config.log' 283 | } catch (Exception e) { 284 | sh 'echo "STATUS: KO" >> archives/spgwc_config.log' 285 | } 286 | try { 287 | sh containerCli + ' inspect --format=\'STATUS: {{.State.' + containerHealth + '.Status}}\' cicd-oai-spgwu-tiny > archives/spgwu_config.log' 288 | } catch (Exception e) { 289 | sh 'echo "STATUS: KO" >> archives/spgwu_config.log' 290 | } 291 | } 292 | } 293 | success { 294 | script { 295 | sh 'echo "DEPLOYMENT: OK" > archives/deployment_status.log' 296 | } 297 | } 298 | unsuccessful { 299 | script { 300 | sh 'echo "DEPLOYMENT: KO" > archives/deployment_status.log' 301 | sh 'python3 ./ci-scripts/OAI-RAN-Sanity-Check-Deploy.py --action=RetrieveLogs' 302 | retrievedLogs = true 303 | } 304 | } 305 | } 306 | } 307 | stage ('Deploy OAI eNB/UE RF Sim') { 308 | steps { 309 | script { 310 | // Deploy all RAN/UE containers 311 | sh 'python3 ./ci-scripts/OAI-RAN-Sanity-Check-Deploy.py --action=DeployRfSimENB --tag=' + oaiEnbTag + ' 2>&1' 312 | sh 'python3 ./ci-scripts/OAI-RAN-Sanity-Check-Deploy.py --action=DeployRfSimUE --tag=' + oaiLteUeTag + ' 2>&1' 313 | sh 'sleep 120' 314 | sh 'python3 ./ci-scripts/OAI-RAN-Sanity-Check-Deploy.py --action=TestTrafficPing 2>&1' 315 | // Retrieve all logs 316 | sh 'python3 ./ci-scripts/OAI-RAN-Sanity-Check-Deploy.py --action=RetrieveLogs' 317 | retrievedLogs = true 318 | // Generate HTML report by parsing PCAP-captured packets is the final say on pass/fail criteria 319 | // Something wrong occurs before this line, then it will be generate in the final post section 320 | sh 'python3 ./ci-scripts/rhel8SanityCheckReport.py --job_name=' + JOB_NAME + ' --job_id=' + BUILD_ID + ' --job_url=' + BUILD_URL 321 | } 322 | } 323 | post { 324 | always { 325 | script { 326 | if (!retrievedLogs) { 327 | sh 'python3 ./ci-scripts/OAI-RAN-Sanity-Check-Deploy.py --action=RetrieveLogs' 328 | } 329 | } 330 | } 331 | success { 332 | script { 333 | sh 'echo "OAI RAN STACK TEST: OK" > archives/oai_ran_stack_test.log' 334 | } 335 | } 336 | unsuccessful { 337 | script { 338 | sh 'echo "OAI RAN STACK TEST: KO" > archives/oai_ran_stack_test.log' 339 | } 340 | } 341 | } 342 | } 343 | stage ('Undeploy EPC') { 344 | steps { 345 | script { 346 | sh 'python3 ./ci-scripts/OAI-RAN-Sanity-Check-Deploy.py --action=RemoveAllContainers 2>&1' 347 | sh 'python3 ./ci-scripts/OAI-RAN-Sanity-Check-Deploy.py --action=RemoveNetworks 2>&1' 348 | if ((cn_ci_host == 'selfix') || (cn_ci_host == 'orion')) { 349 | sh containerCli + ' rmi oai-hss:' + hssTag + ' || true' 350 | sh containerCli + ' rmi oai-spgwc:' + spgwcTag + ' || true' 351 | sh containerCli + ' rmi oai-spgwu-tiny:' + spgwuTag + ' || true' 352 | } 353 | } 354 | } 355 | } 356 | } 357 | post { 358 | always { 359 | script { 360 | sh 'python3 ./ci-scripts/OAI-RAN-Sanity-Check-Deploy.py --action=RemoveAllContainers > /dev/null 2>&1 || true' 361 | sh 'python3 ./ci-scripts/OAI-RAN-Sanity-Check-Deploy.py --action=RemoveNetworks > /dev/null 2>&1 || true' 362 | sh containerCli + ' volume prune --force > /dev/null 2>&1 || true' 363 | if ((cn_ci_host == 'selfix') || (cn_ci_host == 'orion')) { 364 | sh containerCli + ' rmi oai-hss:' + hssTag + ' || true' 365 | sh containerCli + ' rmi oai-spgwc:' + spgwcTag + ' || true' 366 | sh containerCli + ' rmi oai-spgwu-tiny:' + spgwuTag + ' || true' 367 | } 368 | // Zipping all archived log files 369 | sh 'zip -r -qq ' + zipName + ' archives' 370 | if (fileExists(zipName)) { 371 | archiveArtifacts artifacts: zipName 372 | } 373 | // If report not present, certainly something wrong occured. 374 | // Generate it anyway without caring out about result 375 | if (!fileExists('test_results_oai_epc_rhel8.html')) { 376 | sh 'python3 ./ci-scripts/rhel8SanityCheckReport.py --job_name=' + JOB_NAME + ' --job_id=' + BUILD_ID + ' --job_url=' + BUILD_URL + ' || true' 377 | } 378 | if (fileExists('test_results_oai_epc_rhel8.html')) { 379 | sh 'mv test_results_oai_epc_rhel8.html ' + reportName 380 | archiveArtifacts artifacts: reportName 381 | } 382 | } 383 | } 384 | } 385 | } 386 | --------------------------------------------------------------------------------