Commit 6764287a authored by Raphael Defosseux's avatar Raphael Defosseux
Browse files

Merge branch 'prepare-public-release' into 'develop'

Adding NRF client

See merge request !6
parents 68b73303 3d1ad18d
# RELEASE NOTES: #
## vX.X.X -- YYY 2021 ##
## v1.2.0 -- September 2021 ##
* Initial release
* Initial Public Release
* Full support for Ubuntu18 and RHEL7
* CI Build support
## v1.0.0 -- January 2021 ##
* Initial Private Release
This diff is collapsed.
`oai-cn5g-upf-vpp` repository is distributed under **Apache V2.0 License**.
For more details of the license, refer to [LICENSE](LICENSE) file in the same directory.
However, it also includes OAI code or third party-software indicated below.
* **`src/nrf_client.py`** is dstributed under `OAI Public License V1.1`.
......@@ -18,14 +18,26 @@ At the moment, it contains the following network elements:
Each has its own repository: this repository (`oai-cn5g-upf-vpp`) is meant for UPF.
This `UPF` repository contains mainly patches / hacks over 2 open-source projects:
- [Vector Packet Processing](https://github.com/fdio/vpp.git)
- [User Plane Gateway (UPG) based on VPP](https://github.com/travelping/upg-vpp)
# Licence info
It is distributed under `OAI Public License V1.1`.
See [OAI Website for more details](https://www.openairinterface.org/?page_id=698).
As this repository contains mainly patches over 2 open-source projects that are
distributed under Apache V2, it is distributed under `Apache V2.0 License`.
See [Apache Website for more details](http://www.apache.org/licenses/LICENSE-2.0).
The text for `OAI Public License V1.1` is also available under [LICENSE](LICENSE)
The text for `Apache V2.0 License` is also available under [LICENSE](LICENSE)
file at the root of this repository.
Some part(s) of the repository that are decorrelated from the 2 original open-source
projects may be under another LICENSE type.
Check the [NOTICE](NOTICE.md) file for more details.
# Where to start
The Openair-CN-5G UPF code is written, executed, and tested on UBUNTU server bionic version.
......@@ -63,10 +75,11 @@ openair-cn5g-upf-vpp
│   └── scripts
├── ci-scripts
├── docker
├── docker-compose
├── docs
│   └── images
── scripts
├── patches
├── tests
└── upf_conf
── scripts
│   ├── patches
│   └── upf_conf
└── src
</pre>
#!/bin/bash
set -eo pipefail
STATUS=0
AMF_PORT_FOR_NGAP=38412
AMF_PORT_FOR_N11_HTTP=80
AMF_IP_NGAP_INTERFACE=$(ifconfig $AMF_INTERFACE_NAME_FOR_NGAP | grep inet | awk {'print $2'})
AMF_IP_N11_INTERFACE=$(ifconfig $AMF_INTERFACE_NAME_FOR_N11 | grep inet | awk {'print $2'})
N2_PORT_STATUS=$(netstat -Snpl | grep -o "$AMF_IP_NGAP_INTERFACE:$AMF_PORT_FOR_NGAP")
N11_PORT_STATUS=$(netstat -tnpl | grep -o "$AMF_IP_N11_INTERFACE:$AMF_PORT_FOR_N11_HTTP")
#Check if entrypoint properly configured the conf file and no parameter is unset (optional)
NB_UNREPLACED_AT=`cat /openair-amf/etc/*.conf | grep -v contact@openairinterface.org | grep -c @ || true`
if [ $NB_UNREPLACED_AT -ne 0 ]; then
STATUS=1
echo "Healthcheck error: configuration file is not configured properly"
fi
if [[ -z $N2_PORT_STATUS ]]; then
STATUS=1
echo "Healthcheck error: N2 SCTP port $AMF_PORT_FOR_NGAP is not listening"
fi
if [[ -z $N11_PORT_STATUS ]]; then
STATUS=1
echo "Healthcheck error: N11/SBI TCP/HTTP port $AMF_PORT_FOR_N11_HTTP is not listening"
fi
#host="${MYSQL_SERVER}"
#user="${MYSQL_USER:-root}"
#export MYSQL_PWD="${MYSQL_PASS}"
#args=(
# -h"$host"
# -u"$user"
# --silent
#)
#if ! command -v mysql &> /dev/null; then
# echo "Installing mysql command"
# apt update
# apt-get -y install mysql-client
#else
# if select="$(echo 'SELECT 1' | mysql "${args[@]}")" && [ "$select" = '1' ]; then
# database_check=$(mysql -h$host -u$user -D oai_db --silent -e "SELECT * FROM users;")
# if [[ -z $database_check ]]; then
# echo "Healthcheck error: oai_db not populated"
# STATUS=1
# fi
# STATUS=0
# else
# echo "Healthcheck error: Mysql port inactive"
# STATUS=1
# fi
#fi
exit $STATUS
version: '3.8'
services:
mysql:
container_name: "mysql"
image: mysql:5.7
volumes:
- ./oai_db.sql:/docker-entrypoint-initdb.d/oai_db.sql
- ./mysql-healthcheck.sh:/tmp/mysql-healthcheck.sh
environment:
- TZ=Europe/Paris
- MYSQL_DATABASE=oai_db
- MYSQL_USER=test
- MYSQL_PASSWORD=test
- MYSQL_ROOT_PASSWORD=linux
healthcheck:
test: /bin/bash -c "/tmp/mysql-healthcheck.sh"
interval: 10s
timeout: 5s
retries: 5
networks:
public_net_cp:
ipv4_address: 192.168.71.131
oai-nrf:
container_name: "oai-nrf"
image: oai-nrf:latest
environment:
- NRF_INTERFACE_NAME_FOR_SBI=eth0
- NRF_INTERFACE_PORT_FOR_SBI=80
- NRF_INTERFACE_HTTP2_PORT_FOR_SBI=8080
- NRF_API_VERSION=v1
- INSTANCE=0
- PID_DIRECTORY=/var/run
networks:
public_net_cp:
ipv4_address: 192.168.71.130
volumes:
- ./nrf-healthcheck.sh:/openair-nrf/bin/nrf-healthcheck.sh
healthcheck:
test: /bin/bash -c "/openair-nrf/bin/nrf-healthcheck.sh"
interval: 10s
timeout: 5s
retries: 5
oai-amf:
container_name: "oai-amf"
image: oai-amf:latest
environment:
- TZ=Europe/paris
- INSTANCE=0
- PID_DIRECTORY=/var/run
- MCC=208
- MNC=95
- REGION_ID=128
- AMF_SET_ID=1
- SERVED_GUAMI_MCC_0=208
- SERVED_GUAMI_MNC_0=95
- SERVED_GUAMI_REGION_ID_0=128
- SERVED_GUAMI_AMF_SET_ID_0=1
- SERVED_GUAMI_MCC_1=460
- SERVED_GUAMI_MNC_1=11
- SERVED_GUAMI_REGION_ID_1=10
- SERVED_GUAMI_AMF_SET_ID_1=1
- PLMN_SUPPORT_MCC=208
- PLMN_SUPPORT_MNC=95
- PLMN_SUPPORT_TAC=0xa000
- SST_0=222
- SD_0=123
- SST_1=1
- SD_1=12
- AMF_INTERFACE_NAME_FOR_NGAP=eth0
- AMF_INTERFACE_NAME_FOR_N11=eth0
- SMF_INSTANCE_ID_0=1
- SMF_FQDN_0=oai-smf
- SMF_IPV4_ADDR_0=192.168.71.133
- SMF_HTTP_VERSION_0=v1
- SMF_INSTANCE_ID_1=2
- SMF_FQDN_1=oai-smf
- SMF_IPV4_ADDR_1=0.0.0.0
- SMF_HTTP_VERSION_1=v1
- MYSQL_SERVER=192.168.71.131
- MYSQL_USER=root
- MYSQL_PASS=linux
- MYSQL_DB=oai_db
- OPERATOR_KEY=63bfa50ee6523365ff14c1f45f88737d
- NRF_IPV4_ADDRESS=0.0.0.0
- NRF_PORT=80
- NF_REGISTRATION=no
- SMF_SELECTION=no
- USE_FQDN_DNS=no
- NRF_FQDN=oai-nrf
- NRF_API_VERSION=v1
- EXTERNAL_AUSF=no
- AUSF_IPV4_ADDRESS=127.0.0.1
- AUSF_PORT=80
- AUSF_API_VERSION=v1
- AUSF_FQDN=localhost
depends_on:
- mysql
- vpp-upf
- oai-ext-dn
volumes:
- ./amf-healthcheck.sh:/openair-amf/bin/amf-healthcheck.sh
healthcheck:
test: /bin/bash -c "/openair-amf/bin/amf-healthcheck.sh"
interval: 10s
timeout: 15s
retries: 5
networks:
public_net_cp:
ipv4_address: 192.168.71.132
oai-smf:
container_name: "oai-smf"
image: oai-smf:latest
environment:
- TZ=Europe/Paris
- INSTANCE=0
- PID_DIRECTORY=/var/run
- SMF_INTERFACE_NAME_FOR_N4=eth0
- SMF_INTERFACE_NAME_FOR_SBI=eth0
- SMF_INTERFACE_PORT_FOR_SBI=80
- SMF_INTERFACE_HTTP2_PORT_FOR_SBI=9090
- SMF_API_VERSION=v1
- DEFAULT_DNS_IPV4_ADDRESS=192.168.18.129
- DEFAULT_DNS_SEC_IPV4_ADDRESS=8.8.8.8
- AMF_FQDN=oai-amf
- AMF_IPV4_ADDRESS=192.168.71.132
- AMF_PORT=80
- AMF_API_VERSION=v1
- UDM_IPV4_ADDRESS=127.0.0.1
- UDM_FQDN=localhost
- UDM_PORT=80
- UDM_API_VERSION=v1
- UPF_FQDN_0=gw1.vppupf.node.5gcn.mnc95.mcc208.3gppnetwork.org
- UPF_IPV4_ADDRESS=192.168.71.202
- NRF_FQDN=oai-nrf
- NRF_IPV4_ADDRESS=0.0.0.0
- NRF_PORT=80
- NRF_API_VERSION=v1
- REGISTER_NRF=no
- DISCOVER_UPF=no
- USE_NETWORK_INSTANCE=yes
- USE_FQDN_DNS=no
extra_hosts:
- "gw1.vppupf.node.5gcn.mnc95.mcc208.3gppnetwork.org:192.168.71.202"
depends_on:
- oai-amf
volumes:
- ./smf-healthcheck.sh:/openair-smf/bin/smf-healthcheck.sh
healthcheck:
test: /bin/bash -c "/openair-smf/bin/smf-healthcheck.sh"
interval: 10s
timeout: 5s
retries: 5
networks:
public_net_cp:
ipv4_address: 192.168.71.133
vpp-upf:
image: oai-upf-vpp:latest
privileged: true
container_name: vpp-upf
environment:
- NWI_N3=access.oai.org
- NWI_N6=core.oai.org
- GW_ID=1
- MNC03=95
- MCC=208
- REALM=3gppnetwork.org
- NETWORK_UE_IP=12.1.1.0/24
- N3_IPV4_ADDRESS_REMOTE=192.168.72.141 # GNB IP Address
- N4_IPV4_ADDRESS_REMOTE=192.168.71.133 # SMF IP Address
- N6_IPV4_ADDRESS_REMOTE=192.168.73.135 # EXT-DN IP Address
- VPP_MAIN_CORE=0
- VPP_CORE_WORKER=1
# - VPP_PLUGIN_PATH=/usr/lib64/vpp_plugins/ # RHEL7
- VPP_PLUGIN_PATH=/usr/lib/x86_64-linux-gnu/vpp_plugins/ # Ubntu18.04
- INTERFACE_ACCESS=eth0
- INTERFACE_CORE=eth1
- INTERFACE_CP=eth2
- NSSAI_SD_0=222
- SST=123
- DNN=default
- REGISTER_NRF=yes
- NRF_IP_ADDR=192.168.71.130
- NRF_PORT=8080
- HTTP_VERSION=2
healthcheck:
test: /bin/bash -c "pgrep vpp"
interval: 10s
timeout: 5s
retries: 5
networks:
public_net_cp:
ipv4_address: 192.168.71.134
public_net_access:
ipv4_address: 192.168.72.134
public_net_core:
ipv4_address: 192.168.73.134
oai-ext-dn:
image: ubuntu:bionic
privileged: true
container_name: oai-ext-dn
entrypoint: /bin/bash -c \
"apt update; apt install -y iptables iproute2 iputils-ping;"\
"iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE;"\
"ip route add 12.1.1.0/24 via 192.168.73.202 dev eth0; sleep infinity"
command: ["/bin/bash", "-c", "trap : TERM INT; sleep infinity & wait"]
depends_on:
- vpp-upf
networks:
public_net_core:
ipv4_address: 192.168.73.135
networks:
public_net_cp:
name: oai-public-cp
ipam:
config:
- subnet: 192.168.71.0/24
driver_opts:
com.docker.network.bridge.name: "cn5g-public"
public_net_access:
name: oai-public-access
ipam:
config:
- subnet: 192.168.72.0/24
driver_opts:
com.docker.network.bridge.name: "cn5g-access"
public_net_core:
name: oai-public-core
ipam:
config:
- subnet: 192.168.73.0/24
driver_opts:
com.docker.network.bridge.name: "cn5g-core"
#!/bin/bash
set -eo pipefail
STATUS=0
NRF_IP_SBI_INTERFACE=$(ifconfig $NRF_INTERFACE_NAME_FOR_SBI | grep inet | awk {'print $2'})
NRF_SBI_PORT_STATUS=$(netstat -tnpl | grep -o "$NRF_IP_SBI_INTERFACE:$NRF_INTERFACE_PORT_FOR_SBI")
#Check if entrypoint properly configured the conf file and no parameter is unset(optional)
NB_UNREPLACED_AT=`cat /openair-nrf/etc/*.conf | grep -v contact@openairinterface.org | grep -c @ || true`
if [ $NB_UNREPLACED_AT -ne 0 ]; then
STATUS=1
echo "Healthcheck error: UNHEALTHY configuration file is not configured properly"
fi
if [[ -z $NRF_SBI_PORT_STATUS ]]; then
STATUS=1
echo "Healthcheck error: UNHEALTHY SBI TCP/HTTP port $NRF_INTERFACE_PORT_FOR_SBI is not listening."
fi
exit $STATUS
\ No newline at end of file
#!/bin/bash
set -eo pipefail
STATUS=0
SMF_IP_SBI_INTERFACE=$(ifconfig $SMF_INTERFACE_NAME_FOR_SBI | grep inet | awk {'print $2'})
#Check if entrypoint properly configured the conf file and no parameter is unset(optional)
SMF_SBI_PORT_STATUS=$(netstat -tnpl | grep -o "$SMF_IP_SBI_INTERFACE:$SMF_INTERFACE_PORT_FOR_SBI")
NB_UNREPLACED_AT=`cat /openair-smf/etc/*.conf | grep -v contact@openairinterface.org | grep -c @ || true`
if [ $NB_UNREPLACED_AT -ne 0 ]; then
STATUS=-1
echo "Healthcheck error: UNHEALTHY configuration file is not configured properly"
fi
if [[ -z $SMF_SBI_PORT_STATUS ]]; then
STATUS=-1
echo "Healthcheck error: UNHEALTHY SBI TCP/HTTP port $SMF_INTERFACE_PORT_FOR_SBI is not listening."
fi
exit $STATUS
......@@ -60,7 +60,7 @@ RUN wget http://repo.openfusion.net/centos7-x86_64/hyperscan-devel-5.3.0-1.of.el
&& rpm -i *.rpm
WORKDIR /vpp-upf
COPY scripts/ /vpp-upf/scripts
COPY . .
# Applying vpp patches
RUN git clone -b stable/2101 https://github.com/fdio/vpp.git && \
......@@ -91,7 +91,8 @@ RUN yum repolist --disablerepo=* && \
tshark \
tzdata\
iproute \
wget && \
wget \
https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm && \
wget http://repo.openfusion.net/centos7-x86_64/hyperscan-devel-5.3.0-1.of.el7.x86_64.rpm \
http://repo.openfusion.net/centos7-x86_64/hyperscan-5.3.0-1.of.el7.x86_64.rpm && \
rpm -i *.rpm && \
......@@ -99,14 +100,18 @@ RUN yum repolist --disablerepo=* && \
yum remove -y wget && \
rm -rf /var/lib/apt/lists/*
RUN yum install -y python-pip && pip install termcolor
WORKDIR /openair-upf/bin
COPY --from=vpp-upf-builder /vpp-upf/scripts/entrypoint.sh .
COPY --from=vpp-upf-builder /vpp-upf/vpp/build-root/install-vpp-native/vpp/bin/vpp .
COPY --from=vpp-upf-builder /vpp-upf/vpp/build-root/install-vpp-native/vpp/bin/vppctl .
COPY --from=vpp-upf-builder /vpp-upf/src/nrf_client.py .
WORKDIR /openair-upf/etc
COPY --from=vpp-upf-builder /vpp-upf/scripts/upf_conf/init.conf .
COPY --from=vpp-upf-builder /vpp-upf/scripts/upf_conf/startup_debug.conf .
COPY --from=vpp-upf-builder /vpp-upf/scripts/upf_conf/upf_profile.json .
WORKDIR /usr/lib64
COPY --from=vpp-upf-builder /vpp-upf/vpp/build-root/install-vpp-native/vpp/lib/ .
......
......@@ -53,7 +53,7 @@ RUN git config --global https.postBuffer 123289600 && \
git config --global http.sslverify false
WORKDIR /vpp-upf
COPY scripts/ /vpp-upf/scripts
COPY . .
# Applying vpp patches
RUN git clone -b stable/2101 https://github.com/fdio/vpp.git && \
......@@ -93,16 +93,23 @@ RUN apt-get update && \
iproute2 \
iputils-ping \
vim \
python \
python-pip \
libcurl4-openssl-dev \
libssl-dev \
&& rm -rf /var/lib/apt/lists/*
RUN pip install pycurl termcolor
WORKDIR /openair-upf/bin
COPY --from=vpp-upf-builder /vpp-upf/scripts/entrypoint.sh .
COPY --from=vpp-upf-builder /vpp-upf/vpp/build-root/install-vpp-native/vpp/bin/vpp .
COPY --from=vpp-upf-builder /vpp-upf/vpp/build-root/install-vpp-native/vpp/bin/vppctl .
COPY --from=vpp-upf-builder /vpp-upf/src/nrf_client.py .
WORKDIR /openair-upf/etc
COPY --from=vpp-upf-builder /vpp-upf/scripts/upf_conf/init.conf .
COPY --from=vpp-upf-builder /vpp-upf/scripts/upf_conf/startup_debug.conf .
COPY --from=vpp-upf-builder /vpp-upf/scripts/upf_conf/upf_profile.json .
WORKDIR /usr/lib/x86_64-linux-gnu/
COPY --from=vpp-upf-builder /vpp-upf/vpp/build-root/install-vpp-native/vpp/lib/ .
......
......@@ -19,7 +19,7 @@ Here in our network configuration, we need to pass the "GIT PROXY" configuration
## 3.1 On a Ubuntu 18.04 Host ##
```bash
$ docker build --target oai-upf-vpp --tag vpp-upg:develop \
$ docker build --target oai-upf-vpp --tag oai-upf-vpp:latest \
--file docker/Dockerfile.upf-vpp.ubuntu18 \
--build-arg NEEDED_GIT_PROXY="http://proxy.eurecom.fr:8080" .
```
......@@ -27,7 +27,7 @@ $ docker build --target oai-upf-vpp --tag vpp-upg:develop \
## 3.2 On a RHEL 7 Host ##
```bash
$ docker build --target oai-upf-vpp --tag vpp-upg:develop \
$ docker build --target oai-upf-vpp --tag oai-upf-vpp:latest \
--file docker/Dockerfile.upf-vpp.rhel7 \
--build-arg NEEDED_GIT_PROXY="http://proxy.eurecom.fr:8080" .
```
#!/usr/bin/env bash
#"""
#/*
# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
# * contributor license agreements. See the NOTICE file distributed with
# * this work for additional information regarding copyright ownership.
# * The OpenAirInterface Software Alliance licenses this file to You under
# * the OAI Public License, Version 1.1 (the "License"); you may not use this
# * file except in compliance with the License. You may obtain a copy of the
# * License at
# *
# * http://www.openairinterface.org/?page_id=698
# *
# * Unless required by applicable law or agreed to in writing, software
# * distributed under the License is distributed on an "AS IS" BASIS,
# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# * See the License for the specific language governing permissions and
# * limitations under the License.
# *-------------------------------------------------------------------------------
# * For more information about the OpenAirInterface (OAI) Software Alliance:
# * contact@openairinterface.org
# */
#
#/*! \file nrf_client.py
# \author Rohan KHARADE
# \date 2021
# \email: rohan.kharade@openairinterface.org
#*/
#"""
# files are common to docker and native installation
#____________
# init.conf => upf config
......@@ -10,12 +39,19 @@
set -euo pipefail
CONFIG_DIR="/openair-upf/etc"
SGI_IPV4=$(ifconfig $INTERFACE_CORE | grep "inet " | awk '{print $2}')
ACCESS_IPV4=$(ifconfig $INTERFACE_ACCESS | grep "inet " | awk '{print $2}')
CORE_IPV4=$(ifconfig $INTERFACE_CP | grep "inet " | awk '{print $2}')
N3_IPV4_ADDRESS_LOCAL=$(ifconfig $INTERFACE_ACCESS | grep "inet " | awk '{print $2}' | cut -d"." -f1-3)".202"
N4_IPV4_ADDRESS_LOCAL=$(ifconfig $INTERFACE_CP | grep "inet " | awk '{print $2}' | cut -d"." -f1-3)".202"
N6_IPV4_ADDRESS_LOCAL=$(ifconfig $INTERFACE_CORE | grep "inet " | awk '{print $2}' | cut -d"." -f1-3)".202"
###############################
# UPF Config
###############################
for c in ${CONFIG_DIR}/*.conf; do
array=(${CONFIG_DIR}/*.conf ${CONFIG_DIR}/*.json)
for c in "${array[@]}"; do
# grep variable names (format: ${VAR}) from template to be rendered
VARS=$(grep -oP '@[a-zA-Z0-9_]+@' ${c} | sort | uniq | xargs)
# create sed expressions for substituting each occurrence of ${VAR}
......@@ -44,21 +80,20 @@ done
# Near future we will have multiple interfaces (e.g. two n6 interface for edge computing case)
# We define in this order in docker-compose -> it is alphabetical order
#
SGI_IPV4=$(ifconfig $INTERFACE_SGI | grep "inet " | awk '{print $2}')
ip link set $INTERFACE_ACCESS down
ip link set $INTERFACE_ACCESS name access
ip link set access up
ip link set $INTERFACE_ACCESS name n3
ip link set n3 up
ip link set $INTERFACE_CORE down
ip link set $INTERFACE_CORE name core
ip link set core up
ip link set $INTERFACE_CP down
ip link set $INTERFACE_CP name n4
ip link set n4 up
ip link set $INTERFACE_SGI down
ip link set $INTERFACE_SGI name sgi
ip link set sgi up
ip link set $INTERFACE_CORE down
ip link set $INTERFACE_CORE name n6
ip link set n6 up
ip route add $NETWORK_UE_IP via $SGI_IPV4 dev sgi
ip route add $NETWORK_UE_IP via $SGI_IPV4 dev n6
echo "Done setting the configuration"
......
#!/bin/sh -x
#!/bin/bash
#"""
#/*
# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
# * contributor license agreements. See the NOTICE file distributed with
# * this work for additional information regarding copyright ownership.
# * The OpenAirInterface Software Alliance licenses this file to You under
# * the OAI Public License, Version 1.1 (the "License"); you may not use this
# * file except in compliance with the License. You may obtain a copy of the
# * License at
# *
# * http://www.openairinterface.org/?page_id=698
# *
# * Unless required by applicable law or agreed to in writing, software
# * distributed under the License is distributed on an "AS IS" BASIS,
# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# * See the License for the specific language governing permissions and
# * limitations under the License.
# *-------------------------------------------------------------------------------
# * For more information about the OpenAirInterface (OAI) Software Alliance:
# * contact@openairinterface.org
# */
#
#/*! \file nrf_client.py
# \author Rohan KHARADE
# \date 2021
# \email: rohan.kharade@openairinterface.org
#*/
#"""
if [ $(id -u) -ne 0 ]; then
exec sudo -E "$0" "$@"
......@@ -25,10 +54,11 @@ while getopts ":r" opt; do
;;
esac
done
shift $((OPTIND-1))
if test -z "$1"; then
$APP $ARGS
$APP $ARGS &
elif test "$1" = "debug"; then