From d1b1b59381fcc552d6386c0fe0812ca2effcd902 Mon Sep 17 00:00:00 2001 From: Louis Royer Date: Mon, 22 Jan 2024 17:26:30 +0100 Subject: [PATCH] Add SMF --- .github/workflows/docker-image-smf.yml | 59 +++++++++++++++++ README.md | 91 ++++++++++++++++++++++++-- smf/Dockerfile | 46 +++++++++++++ smf/entrypoint.sh | 37 +++++++++++ smf/template-script.sh | 86 ++++++++++++++++++++++++ smf/template-smf.yaml | 52 +++++++++++++++ 6 files changed, 365 insertions(+), 6 deletions(-) create mode 100644 .github/workflows/docker-image-smf.yml create mode 100644 smf/Dockerfile create mode 100755 smf/entrypoint.sh create mode 100755 smf/template-script.sh create mode 100644 smf/template-smf.yaml diff --git a/.github/workflows/docker-image-smf.yml b/.github/workflows/docker-image-smf.yml new file mode 100644 index 0000000..ab6761a --- /dev/null +++ b/.github/workflows/docker-image-smf.yml @@ -0,0 +1,59 @@ +name: Docker Image CI - SMF + +on: + schedule: + - cron: '00 04 * * Sun' + push: + paths: + - 'smf/**' + branches: [ master ] + workflow_dispatch: + +jobs: + docker: + runs-on: ubuntu-latest + steps: + - + name: Checkout + uses: actions/checkout@v3 + - + name: Get current date + id: date + run: echo "date=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT + - + name: Docker meta + id: meta + uses: docker/metadata-action@v4 + with: + images: | + ${{ vars.DOCKERHUB_USERNAME }}/${{ vars.DOCKERHUB_REPO_SMF }} + tags: | + type=raw,enable=true,priority=100,prefix=bookworm-,suffix=-slim,value={{date 'YYYY-MM-DD'}}-{{sha}} + flavor: | + latest=true + prefix= + suffix= + - + name: Set up QEMU + uses: docker/setup-qemu-action@v2 + - + name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + - + name: Login to DockerHub + uses: docker/login-action@v2 + with: + username: ${{ vars.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - + name: Build and push + uses: docker/build-push-action@v3 + with: + context: "{{defaultContext}}:smf" + push: true + tags: ${{ steps.meta.outputs.tags }} + build-args: BUILD_DATE=${{ steps.date.outputs.date }} + labels: ${{ steps.meta.outputs.labels }} + platforms: linux/amd64 + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/README.md b/README.md index da8af8c..7660d8c 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ Environment variables for templating: environment: N2: "192.0.2.1" SBI_REGISTER_IP: "amf.sbi" # you can use a domain or an IP address - SBI_BINDING_IP: "192.51.100.1" # use only an IP address in this field + SBI_BINDING_IP: "198.51.100.1" # use only an IP address in this field SBI_BINDING_PORT: "8000" # default: "8000" MCC: "001" MNC: "01" @@ -72,7 +72,7 @@ Environment variables for templating: ```yaml environment: SBI_REGISTER_IP: "ausf.sbi" # you can use a domain or an IP address - SBI_BINDING_IP: "192.51.100.2" # use only an IP address in this field + SBI_BINDING_IP: "198.51.100.2" # use only an IP address in this field SBI_BINDING_PORT: "8000" # default: "8000" MCC: "001" MNC: "01" @@ -103,7 +103,7 @@ environment: MONGO_PORT: "27017" MONGO_NAME: "free5gc" SBI_REGISTER_IP: "nrf.sbi" # you can use a domain or an IP address - SBI_BINDING_IP: "192.51.100.3" # use only an IP address in this field + SBI_BINDING_IP: "198.51.100.3" # use only an IP address in this field SBI_BINDING_PORT: "8000" # default: "8000" MCC: "001" MNC: "01" @@ -134,7 +134,7 @@ environment: MONGO_PORT: "27017" MONGO_NAME: "free5gc" SBI_REGISTER_IP: "pcf.sbi" # you can use a domain or an IP address - SBI_BINDING_IP: "192.51.100.5" # use only an IP address in this field + SBI_BINDING_IP: "198.51.100.5" # use only an IP address in this field SBI_BINDING_PORT: "8000" # default: "8000" NRF: "nrf.sbi:8000" PCF_NAME: "PCF" @@ -142,6 +142,85 @@ environment: ``` ### SMF +- On Dockerhub: [`louisroyer/dev-free5gc-smf`](https://hub.docker.com/r/louisroyer/dev-free5gc-smf). + +Please note that even if this software is not yet properly packaged using `.deb`, the generated binary file `/usr/local/bin/smf` is provided to you under Apache Version 2.0 License. A copy of this license can be found in `/usr/share/common-licenses/Apache-2.0`. +A copy of the source code is available at in the repository [`free5gc/smf`](https://github.com/free5gc/smf). + +Environment variable used to select templating system: +```yaml +environment: + ROUTING_SCRIPT: "docker-setup" + TEMPLATE_SCRIPT: "template-script.sh" + TEMPLATE_SCRIPT_ARGS: "" + CONFIG_FILE: "/etc/free5gc/smf.yaml" + CONFIG_TEMPLATE: "/etc/free5gc/template-smf.yaml" +``` + +Environment variables for templating: +```yaml +environment: + N4: "203.0.113.1" + SBI_REGISTER_IP: "smf.sbi" # you can use a domain or an IP address + SBI_BINDING_IP: "198.51.100.6" # use only an IP address in this field + SBI_BINDING_PORT: "8000" # default: "8000" + NRF: "nrf.sbi:8000" + LOCALITY: "area1" + MCC: "001" + MNC: "01" + SNSSAI_INFOS: |- + - sNssai: + sst: 1 + sd: 000001 + dnnInfos: + - dnn: internet + dns: + ipv4: 9.9.9.9 + ipv6: 2620:fe::fe + - sNssai: + sst: 1 + sd: 000002 + dnnInfos: + - dnn: edge + dns: + ipv4: 9.9.9.9 + ipv6: 2620:fe::fe + UP_NODES: |- + gNB1: + type: AN + UPF: + type: UPF + nodeID: "203.0.113.2" + addr: "203.0.113.2" + sNssaiUpfInfos: + - sNssai: + sst: 1 + sd: 000001 + dnnUpfInfoList: + - dnn: internet + pool: + - cidr: 10.0.0.0/24 + staticPools: + - cidr: 10.0.1.0/24 + - sNssai: + sst: 1 + sd: 000002 + dnnUpfInfoList: + - dnn: edge + pool: + - cidr: 10.0.2.0/24 + staticPools: + - cidr: 10.0.3.0/24 + interfaces: + - interfaceType: N3 + endpoints: + - 233.252.0.1 + networkInstances: + - internet + LINKS: |- + - A: gNB1 + B: UPF +``` ### UDM - On Dockerhub: [`louisroyer/dev-free5gc-udm`](https://hub.docker.com/r/louisroyer/dev-free5gc-udm). @@ -163,7 +242,7 @@ Environment variables for templating: ```yaml environment: SBI_REGISTER_IP: "udm.sbi" # you can use a domain or an IP address - SBI_BINDING_IP: "192.51.100.7" # use only an IP address in this field + SBI_BINDING_IP: "198.51.100.7" # use only an IP address in this field SBI_BINDING_PORT: "8000" # default: "8000" NRF: "nrf.sbi:8000" ``` @@ -191,7 +270,7 @@ environment: MONGO_PORT: "27017" MONGO_NAME: "free5gc" SBI_REGISTER_IP: "udr.sbi" # you can use a domain or an IP address - SBI_BINDING_IP: "192.51.100.8" # use only an IP address in this field + SBI_BINDING_IP: "198.51.100.8" # use only an IP address in this field SBI_BINDING_PORT: "8000" # default: "8000" NRF: "nrf.sbi:8000" ``` diff --git a/smf/Dockerfile b/smf/Dockerfile new file mode 100644 index 0000000..26e9acc --- /dev/null +++ b/smf/Dockerfile @@ -0,0 +1,46 @@ +# Copyright 2024 Louis Royer. All rights reserved. +# Use of this source code is governed by a MIT-style license that can be +# found in the LICENSE file. +# SPDX-License-Identifier: MIT + +FROM golang:1.21 AS builder +ARG COMMIT=05c55bbb9c052e670a27fda03335da660bc5636f +RUN : ${COMMIT:? Missing build-arg COMMIT.} && go install github.com/free5gc/smf/cmd@${COMMIT} + + +FROM louisroyer/base-irit:latest + +LABEL maintainer="Louis Royer " \ + org.opencontainers.image.authors="Louis Royer " \ + org.opencontainers.image.source="https://github.com/louisroyer-docker/free5gc" + +# Used to disable caching of next steps, if not build since 1 day, +# allowing to search and apply security upgrades +ARG BUILD_DATE="" + +RUN apt-get update -q && DEBIAN_FRONTEND=non-interactive apt-get install -qy --no-install-recommends --no-install-suggests \ + docker-setup \ + && apt-get upgrade -qy \ + && rm -rf /var/lib/apt/lists/* + +COPY --from=builder /go/bin/cmd /usr/local/bin/smf + +COPY ./entrypoint.sh /usr/local/bin/entrypoint.sh +ENV ROUTING_SCRIPT="docker-setup" + +COPY ./template-script.sh /usr/local/bin/template-script.sh +ENV TEMPLATE_SCRIPT="template-script.sh" +ENV TEMPLATE_SCRIPT_ARGS="" + +COPY ./template-smf.yaml /etc/free5gc/template-smf.yaml +ENV CONFIG_FILE="/etc/free5gc/smf.yaml" +ENV CONFIG_TEMPLATE="/etc/free5gc/template-smf.yaml" + +# uerouting: ulcl disabled +# COPY ./template-smf-uerouting.yaml /etc/free5gc/template-smf-uerouting.yaml +# ENV CONFIG_FILE_UEROUTING="/etc/free5gc/smf.yaml" +# ENV CONFIG_TEMPLATE_UEROUTING="/etc/free5gc/template-smf.yaml" + + +ENTRYPOINT ["entrypoint.sh"] +CMD ["--help"] diff --git a/smf/entrypoint.sh b/smf/entrypoint.sh new file mode 100755 index 0000000..58be253 --- /dev/null +++ b/smf/entrypoint.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env bash +# Copyright 2024 Louis Royer. All rights reserved. +# Use of this source code is governed by a MIT-style license that can be +# found in the LICENSE file. +# SPDX-License-Identifier: MIT + +# TODO: add option --uerouting with the right file, currently ulcl is disabled + +set -e +savedargs=( "$@" ) +config_opt=1 +while [ $# -gt 0 ]; do + if [[ $1 == "--config" || $1 == "-c" ]]; then + config_opt=0 + fi + shift +done +set -- "${savedargs[@]}" + +if [[ -n "${CONFIG_TEMPLATE}" && -n "${CONFIG_FILE}" ]]; then + if [ -n "${TEMPLATE_SCRIPT}" ]; then + echo "[$(date --iso-8601=s)] Running ${TEMPLATE_SCRIPT}${TEMPLATE_SCRIPT_ARGS:+ }${TEMPLATE_SCRIPT_ARGS} for building ${CONFIG_FILE} from ${CONFIG_TEMPLATE}." > /dev/stderr + "$TEMPLATE_SCRIPT" "$TEMPLATE_SCRIPT_ARGS" + fi +else + config_opt=0 +fi + +if [ -n "${ROUTING_SCRIPT}" ]; then + "${ROUTING_SCRIPT}" & +fi + +if [[ $config_opt -eq 1 ]]; then + exec smf --config "$CONFIG_FILE" "$@" +else + exec smf "$@" +fi diff --git a/smf/template-script.sh b/smf/template-script.sh new file mode 100755 index 0000000..7b544d6 --- /dev/null +++ b/smf/template-script.sh @@ -0,0 +1,86 @@ +#!/usr/bin/env bash +# Copyright 2024 Louis Royer. All rights reserved. +# Use of this source code is governed by a MIT-style license that can be +# found in the LICENSE file. +# SPDX-License-Identifier: MIT + +set -e +if [ -z "$N4" ]; then + echo "Missing mandatory environment variable (N4)." > /dev/stderr + exit 1 +fi +if [ -z "$SBI_REGISTER_IP" ]; then + echo "Missing mandatory environment variable (SBI_REGISTER_IP)." > /dev/stderr + exit 1 +fi +if [ -z "$SBI_BINDING_IP" ]; then + echo "Missing mandatory environment variable (SBI_BINDING_IP)." > /dev/stderr + exit 1 +fi +if [ -z "$NRF" ]; then + echo "Missing mandatory environment variable (NRF)." > /dev/stderr + exit 1 +fi +if [ -z "$SNSSAI_INFOS" ]; then + echo "Missing mandatory environment variable (SNSSAI_INFOS)." > /dev/stderr + exit 1 +fi +if [ -z "$UP_NODES" ]; then + echo "Missing mandatory environment variable (UP_NODES)." > /dev/stderr + exit 1 +fi +if [ -z "$LINKS" ]; then + echo "Missing mandatory environment variable (LINKS)." > /dev/stderr + exit 1 +fi + + +IFS=$'\n' +SNSSAI_INFOS_SUB="" +for SNSSAI_INFO in ${SNSSAI_INFOS}; do + if [ -n "${SNSSAI_INFO}" ]; then + SNSSAI_INFOS_SUB="${SNSSAI_INFOS_SUB}\n ${SNSSAI_INFO}" + fi +done + +UP_NODES_SUB="" +for UP_NODE in ${UP_NODES}; do + if [ -n "${UP_NODE}" ]; then + UP_NODES_SUB="${UP_NODES_SUB}\n ${UP_NODE}" + fi +done + +LINKS_SUB="" +for LINK in ${LINKS}; do + if [ -n "${LINK}" ]; then + LINKS_SUB="${LINKS_SUB}\n ${LINK}" + fi +done + +awk \ + -v N4="${N4}" \ + -v SBI_REGISTER_IP="${SBI_REGISTER_IP}" \ + -v SBI_BINDING_IP="${SBI_BINDING_IP}" \ + -v SBI_BINDING_PORT="${SBI_BINDING_PORT:-8000}" \ + -v MCC="${MCC:-001}" \ + -v MNC="${MNC:-01}" \ + -v NRF="${NRF}" \ + -v LOCALITY="${LOCALITY:-area1}" \ + -v SNSSAI_INFOS="${SNSSAI_INFOS_SUB}" \ + -v UP_NODES="${UP_NODES_SUB}" \ + -v LINKS="${LINKS_SUB}" \ + '{ + sub(/%N4/, N4); + sub(/%SBI_REGISTER_IP/, SBI_REGISTER_IP); + sub(/%SBI_BINDING_IP/, SBI_BINDING_IP); + sub(/%SBI_BINDING_PORT/, SBI_BINDING_PORT); + sub(/%MCC/, MCC); + sub(/%MNC/, MNC); + sub(/%NRF/, NRF); + sub(/%LOCALITY/, LOCALITY); + sub(/%SNSSAI_INFOS/, SNSSAI_INFOS); + sub(/%UP_NODES/, UP_NODES); + sub(/%LINKS/, LINKS); + print; + }' \ + "${CONFIG_TEMPLATE}" > "${CONFIG_FILE}" diff --git a/smf/template-smf.yaml b/smf/template-smf.yaml new file mode 100644 index 0000000..2b26e22 --- /dev/null +++ b/smf/template-smf.yaml @@ -0,0 +1,52 @@ +info: + version: 1.0.7 + description: SMF initial local configuration + +configuration: + smfName: SMF # the name of this SMF + sbi: # Service-based interface information + scheme: http # the protocol for sbi (http or https) + registerIPv4: %SBI_REGISTER_IP # IP used to register to NRF + bindingIPv4: %SBI_BINDING_IP # IP used to bind the service + port: %SBI_BINDING_PORT # Port used to bind the service + tls: # the local path of TLS key + key: cert/smf.key # SMF TLS Certificate + pem: cert/smf.pem # SMF TLS Private key + serviceNameList: # the SBI services provided by this SMF, refer to TS 29.502 + - nsmf-pdusession # Nsmf_PDUSession service + - nsmf-event-exposure # Nsmf_EventExposure service + - nsmf-oam # OAM service + snssaiInfos: %SNSSAI_INFOS # the S-NSSAI (Single Network Slice Selection Assistance Information) list supported by this AMF + plmnList: # the list of PLMN IDs that this SMF belongs to (optional, remove this key when unnecessary) + - mcc: %MCC # Mobile Country Code (3 digits string, digit: 0~9) + mnc: %MNC # Mobile Network Code (2 or 3 digits string, digit: 0~9) + locality: %LOCALITY # Name of the location where a set of AMF, SMF, PCF and UPFs are located + pfcp: # the IP address of N4 interface on this SMF (PFCP) + # addr config is deprecated in smf config v1.0.3, please use the following config + nodeID: %N4 # the Node ID of this SMF + listenAddr: %N4 # the IP/FQDN of N4 interface on this SMF (PFCP) + externalAddr: %N4 # the IP/FQDN of N4 interface on this SMF (PFCP) + userplaneInformation: # list of userplane information + upNodes: %UP_NODES # information of userplane node (AN or UPF) + links: %LINKS # the topology graph of userplane, A and B represent the two nodes of each link + # retransmission timer for pdu session modification command + t3591: + enable: true # true or false + expireTime: 16s # default is 6 seconds + maxRetryTimes: 3 # the max number of retransmission + # retransmission timer for pdu session release command + t3592: + enable: true # true or false + expireTime: 16s # default is 6 seconds + maxRetryTimes: 3 # the max number of retransmission + nrfUri: http://%NRF # a valid URI of NRF + nrfCertPem: cert/nrf.pem # NRF Certificate + #urrPeriod: 10 # default usage report period in seconds + #urrThreshold: 1000 # default usage report threshold in bytes + + ulcl: false # ulcl is disabled + +logger: # log output setting + enable: true # true or false + level: info # how detailed to output, value: trace, debug, info, warn, error, fatal, panic + reportCaller: false # enable the caller report or not, value: true or false