From 8189a0843bcafa8e7c872298a1c7a62523600265 Mon Sep 17 00:00:00 2001 From: "Jordi J. Gimenez" <87380947+jordijoangimenez@users.noreply.github.com> Date: Mon, 24 Jun 2024 09:23:32 +0200 Subject: [PATCH] Updates to projects (#77) * Update testing-AS.md * Delete pages/5g-media-streaming/usage/application-server/development-AS.md * Update usage-application-server.md * Update testing-AS.md * Create index.md * Update index.md * Update index.md * Update index.md * Update index.md * Update index.md * Update index.md * Update index.md * Update index.md * Create projects.md * Update index.md * Create repositories.md * Update projects.md * Update repositories.md * Create docker-implementation.md * Update tutorials.md * Update tutorials.md * Update index.md * Update projects.md * Update repositories.md * Update features.md * Create usage.md * Update usage.md * Create managing-tmgi.md * Create creating-mbs-sessions.md * Rename pages/5g-multicast-broadcast-services/docker-implementation.md to pages/5g-multicast-broadcast-services/usage/docker-implementation.md * Create testing.md * Create 5G-MBS_5G_Core.png * Create MBS_Broadcast_Session_Create_call_flow.png * Add files via upload * Update docker-implementation.md * Update testing.md * Update repositories.md * Update index.md --- .../application-server/development-AS.md | 275 ---------------- .../usage/application-server/testing-AS.md | 304 ++++++++++++++++-- .../usage-application-server.md | 2 +- .../features.md | 120 +++++++ .../images/5G-MBS_5G_Core.png | Bin 0 -> 44330 bytes ...MBS_Broadcast_Session_Create_call_flow.png | Bin 0 -> 49353 bytes .../5g-multicast-broadcast-services/index.md | 2 +- .../repositories.md | 3 + .../tutorials.md | 1 - .../5g-multicast-broadcast-services/usage.md | 8 + .../usage/creating-mbs-sessions.md | 55 ++++ .../usage/docker-implementation.md | 74 +++++ .../usage/managing-tmgi.md | 133 ++++++++ .../usage/testing.md | 109 +++++++ pages/dvbi-over-5g/index.md | 2 +- pages/emergency-alerts/index.md | 2 +- pages/lte-based-5g-broadcast/index.md | 2 +- pages/lte-based-5g-broadcast/tutorials.md | 1 - pages/multimedia-content-delivery/index.md | 2 +- .../index.md | 9 + .../projects.md | 11 + .../repositories.md | 9 + pages/xr-media-integration-in-5g/index.md | 4 +- 23 files changed, 821 insertions(+), 307 deletions(-) delete mode 100644 pages/5g-media-streaming/usage/application-server/development-AS.md create mode 100644 pages/5g-multicast-broadcast-services/images/5G-MBS_5G_Core.png create mode 100644 pages/5g-multicast-broadcast-services/images/MBS_Broadcast_Session_Create_call_flow.png create mode 100644 pages/5g-multicast-broadcast-services/usage.md create mode 100644 pages/5g-multicast-broadcast-services/usage/creating-mbs-sessions.md create mode 100644 pages/5g-multicast-broadcast-services/usage/docker-implementation.md create mode 100644 pages/5g-multicast-broadcast-services/usage/managing-tmgi.md create mode 100644 pages/5g-multicast-broadcast-services/usage/testing.md create mode 100644 pages/ue-data-collection-reporting-exposure/index.md create mode 100644 pages/ue-data-collection-reporting-exposure/projects.md create mode 100644 pages/ue-data-collection-reporting-exposure/repositories.md diff --git a/pages/5g-media-streaming/usage/application-server/development-AS.md b/pages/5g-media-streaming/usage/application-server/development-AS.md deleted file mode 100644 index 01f6e927..00000000 --- a/pages/5g-media-streaming/usage/application-server/development-AS.md +++ /dev/null @@ -1,275 +0,0 @@ ---- -layout: default -title: Developing the 5GMS AS -parent: Application Server -grand_parent: Usage -has_children: false -nav_order: 4 ---- - -CONTENT TO BE CHECKED - -In this directory you will find files to assist with development and testing of -the 5G-MAG Reference Tools 5GMS Application Server (AS). - -Files in this repository: -- ATTRIBUTION_NOTICE - List of 3rd party software used when running the 5GMS application server. -- LICENSE - The software license for this project. -- README.md - Project README file. -- pyproject.toml - The Python project description for building and installing the application. -- build_scripts/ - Scripts used when building the python project. - - api.mustache - openapi-generator template file to pass operations onto methods in the class defined in src/rt_5gms_as/server.py. - - backend.py - build backend wrapper to trigger extra build actions. - - generate_5gms_as_openapi - Will generate the OpenAPI python modules if not already present. - - M3_merged.yaml - OpenAPI YAML wrapper file to merge the M3 interface files into one for API bindings generation. - - openapi-generator-config.yaml.in - openapi-generator configuration file template. -- docs/ - Development documentation and examples. - - README.md - This document. - - example-application-server.conf - An application configuration which documents the defaults and meaning for each application configuration option. -- external/ - Directory containing submodule mount points. - - rt-common-shared/ - The common shared examples and scripts. -- src/ - The application source modules. - - rt_5gms_as/ - The main Python module for this application - - app.py - Application entry point. - - exceptions.py - Application specific Exception class definitions. - - context.py - Module for the application Context class. - - openapi_5g/ - Python bindings generated by openapi-generator-cli from the 5G APIs. Note: This directory is not present in the tree until `build_scripts/generate_openapi` is run. - - proxies/ - Contains the web server/proxy detection and configuration classes and any data files they need. - - proxy_factory.py - Factory module to pick a suitable web server/proxy. - - server.py - M3 Server implementation. - - utils.py - Common utility functions for the web server/proxy classes. -- tests/ - Regression and build acceptance tests and other testing tools. - - examples/ - Example configurations to go along with the tests. - -Running the example without building ------------------------------------- -Make sure that git, java, wget and nginx are installed on the local system and -can be found on the current command path (`$PATH`). -``` -sudo apt install git wget nginx default-jdk python3-regex -``` - -Generate the OpenAPI python modules (these are not part of the source -distribution). Read documentation below on "Regenerating the 5G API bindings": -``` -cd ~/rt-5gms-application-server -build_scripts/generate_5gms_as_openapi -``` - -Create a configuration to run the application server as a local, unprivileged, -user. -``` -mkdir ~/.rt_5gms -cat > ~/.rt_5gms/application-server.conf < - m3_client_cli.py -c | --certificate (add|update) - m3_client_cli.py -c | --certificate delete - m3_client_cli.py -H | --content-hosting-configuration - m3_client_cli.py -H | --content-hosting-configuration (add|update) - m3_client_cli.py -H | --content-hosting-configuration delete - m3_client_cli.py -H | --content-hosting-configuration purge [] - -Parameters: - connect Hostname:Port of the server providing M3. - provisioning-session-id Provisioning Session Identifier. - certificate-id Certificate Identifier. - pem-file Server PEM format X.509 public certificate, private key and intermediate CA certificates. - content-hosting-configuration-json-file - Filename of a ContentHostingConfiguration in JSON format. - pattern Regular expression to match the cache entry URL paths to delete. - -Options: - -h --help Display the command help - -v --version Display command version - -c --certificate List known certificates or perform a certificate operation. - -H --content-hosting-configuration - List known ContentHostingConfigurations or perform an operation on ContentHostingConfigurations. -``` - -This can be used instead of the AF to configure a running AS. - -### Prerequisite packages - -These testing scripts require a few more Python 3 modules to be installed, beyond what is brought in as requirements when the when the application server is installed. - -The extra modules are: `docopt`, `aiofiles` and `httpx[http2]`. - -These can be installed on ubuntu using: -```bash -apt install python3-docopt python3-aiofiles python3-httpx python3-h2 -``` -...or on most distributions by using the python `pip` module: -``` -python3 -m pip install docopt aiofiles 'httpx[http2]' -``` - -### Running the Application Server for testing with `m3_client_cli.py` - -When running any of the following tests the Application Server must be running first. The exact command will depend on how you installed the Application Server or whether you are [running directly without building](#running-the-example-without-building). - -#### Running from a virtual Python environment installation - -If the AS you are testing has been installed in a virtual Python environment, as described in the [Development and Testing](https://github.com/5G-MAG/rt-5gms-application-server/wiki/Development-and-Testing) wiki page, then you would simply run the AS from the virtual environment using your local configuration file. For example: - -```bash -cd ~/rt-5gms-application-server -venv/bin/5gms-application-server -c local-dev.conf -``` - -#### Running a system wide AS installation - -If the Application Server under test has been installed as a system process, using a command like `sudo python3 -m pip install .` or `sudo python3 -m pip install rt-5gms-application-server-1.X.X.tar.gz`, then you can run the AS as root. For example: - -```bash -sudo 5gms-application-server -``` - -### To configure a simple HTTP Application Server - -Make sure the AS is running first (see ["Running the Application Server for testing with `m3_client_cli.py`"](#running-the-application-server-for-testing-with-m3_client_clipy) above). - -```bash -cd ~/rt-5gms-application-server -tests/m3_client_cli.py -H localhost:7777 add ps1 tests/examples/ContentHostingConfiguration_Big-Buck-Bunny_pull-ingest.json -``` -This should respond with a "Success!" message, and NGINX should now be running on port 8080 using the example Big Buck Bunny configuration. You can check the NGINX configuration in `/tmp/rt_5gms_as.conf`. - -### To configure an HTTPS Application Server - -Make sure the AS is running first (see ["Running the Application Server for testing with `m3_client_cli.py`"](#running-the-application-server-for-testing-with-m3_client_clipy) above). - -This requires that the server certificate is pushed to the Application Server before the content hosting configuration is. - -To generate server certificates, ensure that `openssl` is installed (e.g. `apt -y install openssl`), and then: -```bash -cd ~/rt-5gms-application-server -external/rt-common-shared/5gms/scripts/make_self_signed_certs.py tests/examples/ContentHostingConfiguration_Big-Buck-Bunny_pull-ingest_https.json tests/examples/Certificates.json -``` - -The 5GMS Application Server stores the certificates it has been configured with in a certificates cache. This cache is reloaded when the Application Server starts up, so it will remember certificates from previous runs. - -The 5GMS Application Server can be checked for what certificates it already has by using the command: -```bash -cd ~/rt-5gms-application-server -tests/m3_client_cli.py -c localhost:7777 -``` - -To push a new certificate (with id "testcert1" using the generated certificate file): -```bash -cd ~/rt-5gms-application-server -tests/m3_client_cli.py -c localhost:7777 add testcert1 tests/examples/certificate-1.pem -``` - -...or to update an existing certificate: -```bash -cd ~/rt-5gms-application-server -tests/m3_client_cli.py -c localhost:7777 update testcert1 tests/examples/certificate-1.pem -``` - -Now the Content Hosting Configuration can be pushed: -```bash -cd ~/rt-5gms-application-server -tests/m3_client_cli.py -H localhost:7777 add ps1 tests/examples/ContentHostingConfiguration_Big-Buck-Bunny_pull-ingest_https.json -``` -This should result in "Success!" and NGINX will now be listening on "https://localhost:8443/...". - -To start both HTTPS and HTTP reverse proxies for the Big Buck Bunny content, substitute the ContentHostingConfiguration above for the `tests/examples/ContentHostingConfiguration_Big-Buck-Bunny_pull-ingest_http_and_https.json` file, or update the configuration using: -```bash -cd ~/rt-5gms-application-server -tests/m3_client_cli.py -H localhost:7777 update ps1 tests/examples/ContentHostingConfiguration_Big-Buck-Bunny_pull-ingest_http_and_https.json -``` - -Note: Following these instructions will create a self-signed certificate for localhost in `~/rt-5gms-application-server/tests/examples/certificate-1.pem`, this certificate will not pass normal CA verification so to access the URL you need to turn off SSL validation or accept the self-signed certificate in your browser or media player application. - -Regenerating the 5G API bindings --------------------------------- -The `build_scripts/generate_5gms_as_openapi` script will use wget, git and java to download the openapi-generator tool, the 5G OpenAPI YAML and generate the `rt_5gms_as.openapi_5g` Python module package. The script will only do this if the `src/rt_5gms_as/openapi_5g` directory does not already exist. - -Therefore to regenerate the API bindings you first need to remove the old bindings: -``` -cd ~/rt-5gms-application-server -rm -rf src/rt_5gms_as/openapi_5g -``` - -Then run the generator script: -``` -~/rt-5gms-application-server/build_scripts/generate_5gms_as_openapi -``` - -For reference (or if it is desirable to recreate the steps manually) the `generate_5gms_as_openapi` script performs the following actions: -- Uses `wget` to fetch version 6.0.1 of the [openapi-generator-cli](https://github.com/OpenAPITools/openapi-generator-cli). - - e.g. `wget https://repo1.maven.org/maven2/org/openapitools/openapi-generator-cli/6.0.1/openapi-generator-cli-6.0.1.jar -O openapi-generator-cli.jar` -- Uses `git` to clone the [5G OpenAPI repository](https://forge.3gpp.org/rep/all/5G_APIs.git). - - e.g. `git clone -b REL-17 https://forge.3gpp.org/rep/all/5G_APIs.git` -- Copies in the API override files - - e.g. `cp -f ~/rt-5gms-application-server/external/rt-common-shared/5gms/5G_APIs-overrides/*.yaml ~/rt-5gms-application-server/build_scripts/M3_merged.yaml 5G_APIs/` -- Uses the openapi-generator-cli, downloaded in the first step, to generate the API bindings. - - e.g. `mkdir 5g-api-python; java -jar openapi-generator-cli.jar generate -i 5G_APIs/TS26512_M1_ContentHostingProvisioning.yaml -g python --additional-properties packageName=rt_5gms_as.openapi_5g,projectName=openapi-5g -o 5g-api-python; java -jar openapi-generator-cli.jar generate -t ~/rt-5gms-application-server/build_scripts -i 5G_APIs/M3_merged.yaml -g python --additional-properties packageName=rt_5gms_as.openapi_5g,projectName=openapi-5g -o 5g-api-python` -- Copies the API Python package to the `src/rt_5gms_as/openapi_5g` directory. - - e.g. `cp -r 5g-api-python/rt_5gms_as/openapi_5g ~/rt-5gms-application-server/src/rt_5gms_as/` - diff --git a/pages/5g-media-streaming/usage/application-server/testing-AS.md b/pages/5g-media-streaming/usage/application-server/testing-AS.md index 6b39b827..b0ab6607 100644 --- a/pages/5g-media-streaming/usage/application-server/testing-AS.md +++ b/pages/5g-media-streaming/usage/application-server/testing-AS.md @@ -4,14 +4,44 @@ title: Testing the 5GMS AS parent: Application Server grand_parent: Usage has_children: false -nav_order: 3 +nav_order: 1 --- # Developing and Testing the 5GMSd Application Server +Here you will find information to assist with development and testing of the 5G-MAG Reference Tools 5GMS Application Server (AS). + +Files in the 5GMS AS repository include: +- ATTRIBUTION_NOTICE - List of 3rd party software used when running the 5GMS application server. +- LICENSE - The software license for this project. +- README.md - Project README file. +- pyproject.toml - The Python project description for building and installing the application. +- build_scripts/ - Scripts used when building the python project. + - api.mustache - openapi-generator template file to pass operations onto methods in the class defined in src/rt_5gms_as/server.py. + - backend.py - build backend wrapper to trigger extra build actions. + - generate_5gms_as_openapi - Will generate the OpenAPI python modules if not already present. + - M3_merged.yaml - OpenAPI YAML wrapper file to merge the M3 interface files into one for API bindings generation. + - openapi-generator-config.yaml.in - openapi-generator configuration file template. +- docs/ - Development documentation and examples. + - example-application-server.conf - An application configuration which documents the defaults and meaning for each application configuration option. +- external/ - Directory containing submodule mount points. + - rt-common-shared/ - The common shared examples and scripts. +- src/ - The application source modules. + - rt_5gms_as/ - The main Python module for this application + - app.py - Application entry point. + - exceptions.py - Application specific Exception class definitions. + - context.py - Module for the application Context class. + - openapi_5g/ - Python bindings generated by openapi-generator-cli from the 5G APIs. Note: This directory is not present in the tree until `build_scripts/generate_openapi` is run. + - proxies/ - Contains the web server/proxy detection and configuration classes and any data files they need. + - proxy_factory.py - Factory module to pick a suitable web server/proxy. + - server.py - M3 Server implementation. + - utils.py - Common utility functions for the web server/proxy classes. +- tests/ - Regression and build acceptance tests and other testing tools. + - examples/ - Example configurations to go along with the tests. + While the instructions in the main project [README](https://github.com/5G-MAG/rt-5gms-application-server#readme) tell you how to install the 5GMSd Application Server as a system-wide application, during development it is usually more appropriate to have one or more local clones of the repository that are being used for development and testing. This page provides details of one suggested way to arrange your development environment to ensure separation from the main system during development and testing. -# Prerequisites +## Prerequisites There are some packages that will need to be installed system wide that the build and install system relies on. These prerequisite packages are: - **Commands** @@ -34,11 +64,11 @@ sudo apt -y install git default-jdk python3 wget python3-pip python3-venv sudo dnf -y install git java-latest-openjdk python3 wget python3-pip python3-venv ``` -# Checking out the project code +## Checking out the project code Since this will be used for development and testing, the instructions here will show you how to check out the latest development branch. -## Checkout for development +### Checkout for development 1. **Create a fork** 1. Login to GitHub ([create a GitHub account](https://github.com/join) and [set an SSH key](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/adding-a-new-ssh-key-to-your-github-account) if you haven't already done so). @@ -51,7 +81,7 @@ Since this will be used for development and testing, the instructions here will ``` Where `` is the username of your GitHub login. -## Checkout for testing only +### Checkout for testing only 1. **Clone the 5G-MAG repository** ```bash @@ -59,7 +89,7 @@ Since this will be used for development and testing, the instructions here will git clone -b development --recurse-submodules https://github.com/5G-MAG/rt-5gms-application-server.git ``` -# Creating the virtual Python environment +## Creating the virtual Python environment By using a Python virtual environment you can use upgraded versions of existing system Python modules and automatically install project module dependencies without having to install or upgrade modules system wide. @@ -77,14 +107,14 @@ By using a Python virtual environment you can use upgraded versions of existing venv/bin/python3 -m pip install --upgrade pip build setuptools docopt PyYAML ``` -# Build and install the 5GMSd Application Server +## Build and install the 5GMSd Application Server ```bash cd ~/rt-5gms-application-server venv/bin/python3 -m pip install . ``` -# Create a local-user friendly configuration +## Create a local-user friendly configuration Save these configuration file contents as `~/rt-5gms-application-server/local-dev.conf`: ```ini @@ -123,7 +153,7 @@ Using this configuration will: - Turn on `debug` level output from the 5GMSd Application Server in order to better see what it happening. - Some settings above are commented out but may be useful while testing and so have been left in with their default values and prefixed with `#` to comment them out. If you wish to change one then remove the `#` and change the value to your desired setting. -# Running the installed 5GMSd Application server +## Running the installed 5GMSd Application server To run the version of the 5GMSd Application Server installed in the virtual environment with the `local-dev.conf` configuration (above), use: @@ -132,11 +162,216 @@ cd ~/rt-5gms-application-server PATH="/usr/local/openresty/nginx/sbin:$PATH" venv/bin/5gms-application-server -c local-dev.conf ``` -# Runtime configuration +# Testing + +## Running the example without building +Make sure that git, java, wget and nginx are installed on the local system and +can be found on the current command path (`$PATH`). +``` +sudo apt install git wget nginx default-jdk python3-regex +``` + +Generate the OpenAPI python modules (these are not part of the source +distribution). Read documentation below on "Regenerating the 5G API bindings": +``` +cd ~/rt-5gms-application-server +build_scripts/generate_5gms_as_openapi +``` + +Create a configuration to run the application server as a local, unprivileged, +user. +``` +mkdir ~/.rt_5gms +cat > ~/.rt_5gms/application-server.conf < + m3_client_cli.py -c | --certificate (add|update) + m3_client_cli.py -c | --certificate delete + m3_client_cli.py -H | --content-hosting-configuration + m3_client_cli.py -H | --content-hosting-configuration (add|update) + m3_client_cli.py -H | --content-hosting-configuration delete + m3_client_cli.py -H | --content-hosting-configuration purge [] + +Parameters: + connect Hostname:Port of the server providing M3. + provisioning-session-id Provisioning Session Identifier. + certificate-id Certificate Identifier. + pem-file Server PEM format X.509 public certificate, private key and intermediate CA certificates. + content-hosting-configuration-json-file + Filename of a ContentHostingConfiguration in JSON format. + pattern Regular expression to match the cache entry URL paths to delete. + +Options: + -h --help Display the command help + -v --version Display command version + -c --certificate List known certificates or perform a certificate operation. + -H --content-hosting-configuration + List known ContentHostingConfigurations or perform an operation on ContentHostingConfigurations. +``` + +This can be used instead of the AF to configure a running AS. + +### Prerequisite packages + +These testing scripts require a few more Python 3 modules to be installed, beyond what is brought in as requirements when the when the application server is installed. + +The extra modules are: `docopt`, `aiofiles` and `httpx[http2]`. + +These can be installed on ubuntu using: +```bash +apt install python3-docopt python3-aiofiles python3-httpx python3-h2 +``` +...or on most distributions by using the python `pip` module: +``` +python3 -m pip install docopt aiofiles 'httpx[http2]' +``` + +### Running the Application Server for testing with `m3_client_cli.py` + +When running any of the following tests the Application Server must be running first. The exact command will depend on how you installed the Application Server or whether you are [running directly without building](#running-the-example-without-building). + +#### Running from a virtual Python environment installation + +If the AS you are testing has been installed in a virtual Python environment, as described in the [Development and Testing](https://github.com/5G-MAG/rt-5gms-application-server/wiki/Development-and-Testing) wiki page, then you would simply run the AS from the virtual environment using your local configuration file. For example: + +```bash +cd ~/rt-5gms-application-server +venv/bin/5gms-application-server -c local-dev.conf +``` +#### Running a system wide AS installation + +If the Application Server under test has been installed as a system process, using a command like `sudo python3 -m pip install .` or `sudo python3 -m pip install rt-5gms-application-server-1.X.X.tar.gz`, then you can run the AS as root. For example: + +```bash +sudo 5gms-application-server +``` + +### To configure a simple HTTP Application Server + +Make sure the AS is running first (see ["Running the Application Server for testing with `m3_client_cli.py`"](#running-the-application-server-for-testing-with-m3_client_clipy) above). + +```bash +cd ~/rt-5gms-application-server +tests/m3_client_cli.py -H localhost:7777 add ps1 tests/examples/ContentHostingConfiguration_Big-Buck-Bunny_pull-ingest.json +``` +This should respond with a "Success!" message, and NGINX should now be running on port 8080 using the example Big Buck Bunny configuration. You can check the NGINX configuration in `/tmp/rt_5gms_as.conf`. + +### To configure an HTTPS Application Server + +Make sure the AS is running first (see ["Running the Application Server for testing with `m3_client_cli.py`"](#running-the-application-server-for-testing-with-m3_client_clipy) above). + +This requires that the server certificate is pushed to the Application Server before the content hosting configuration is. + +To generate server certificates, ensure that `openssl` is installed (e.g. `apt -y install openssl`), and then: +```bash +cd ~/rt-5gms-application-server +external/rt-common-shared/5gms/scripts/make_self_signed_certs.py tests/examples/ContentHostingConfiguration_Big-Buck-Bunny_pull-ingest_https.json tests/examples/Certificates.json +``` + +The 5GMS Application Server stores the certificates it has been configured with in a certificates cache. This cache is reloaded when the Application Server starts up, so it will remember certificates from previous runs. + +The 5GMS Application Server can be checked for what certificates it already has by using the command: +```bash +cd ~/rt-5gms-application-server +tests/m3_client_cli.py -c localhost:7777 +``` + +To push a new certificate (with id "testcert1" using the generated certificate file): +```bash +cd ~/rt-5gms-application-server +tests/m3_client_cli.py -c localhost:7777 add testcert1 tests/examples/certificate-1.pem +``` + +...or to update an existing certificate: +```bash +cd ~/rt-5gms-application-server +tests/m3_client_cli.py -c localhost:7777 update testcert1 tests/examples/certificate-1.pem +``` + +Now the Content Hosting Configuration can be pushed: +```bash +cd ~/rt-5gms-application-server +tests/m3_client_cli.py -H localhost:7777 add ps1 tests/examples/ContentHostingConfiguration_Big-Buck-Bunny_pull-ingest_https.json +``` +This should result in "Success!" and NGINX will now be listening on "https://localhost:8443/...". + +To start both HTTPS and HTTP reverse proxies for the Big Buck Bunny content, substitute the ContentHostingConfiguration above for the `tests/examples/ContentHostingConfiguration_Big-Buck-Bunny_pull-ingest_http_and_https.json` file, or update the configuration using: +```bash +cd ~/rt-5gms-application-server +tests/m3_client_cli.py -H localhost:7777 update ps1 tests/examples/ContentHostingConfiguration_Big-Buck-Bunny_pull-ingest_http_and_https.json +``` + +Note: Following these instructions will create a self-signed certificate for localhost in `~/rt-5gms-application-server/tests/examples/certificate-1.pem`, this certificate will not pass normal CA verification so to access the URL you need to turn off SSL validation or accept the self-signed certificate in your browser or media player application. + +## Runtime configuration The 5GMSd Application Server is configured at run-time for distribution of media via the interface at reference point M3. This is usually done by the [5GMSd Application Function](https://github.com/5G-MAG/rt-5gms-application-function), but this project also contains a simple M3 client that can be used to push run-time configuration for testing. -## M3 test client +### M3 test client This client script provides a simple command line interface to issue M3 API calls and see the result from the response. @@ -154,67 +389,67 @@ cd ~/rt-5gms-application-server tests/m3_client_cli.py -h ``` -## M3 Certificates API +### M3 Certificates API -### List known certificates +#### List known certificates ```bash cd ~/rt-5gms-application-server tests/m3_client_cli.py -c localhost:7777 ``` -### Add a new certificate +#### Add a new certificate ```bash cd ~/rt-5gms-application-server tests/m3_client_cli.py -c localhost:7777 add testcert1 tests/examples/certificate-1.pem ``` -### Update an existing certificate +#### Update an existing certificate ```bash cd ~/rt-5gms-application-server tests/m3_client_cli.py -c localhost:7777 update testcert1 tests/examples/certificate-1.pem ``` -### Delete a certificate +#### Delete a certificate ```bash cd ~/rt-5gms-application-server tests/m3_client_cli.py -c localhost:7777 delete testcert1 ``` -## M3 ContentHostingConfiguration API +### M3 ContentHostingConfiguration API -### List known ContentHostingConfigurations +#### List known ContentHostingConfigurations ```bash cd ~/rt-5gms-application-server tests/m3_client_cli.py -H localhost:7777 ``` -### Add a new ContentHostingConfiguration +#### Add a new ContentHostingConfiguration ```bash cd ~/rt-5gms-application-server tests/m3_client_cli.py -H localhost:7777 add prov-sess-1 tests/examples/ContentHostingConfiguration_Big-Buck-Bunny_pull-ingest_http_and_https.json ``` -### Update an existing ContentHostingConfiguration +#### Update an existing ContentHostingConfiguration ```bash cd ~/rt-5gms-application-server tests/m3_client_cli.py -H localhost:7777 update prov-sess-1 tests/examples/ContentHostingConfiguration_Big-Buck-Bunny_pull-ingest_https.json ``` -### Delete a ContentHostingConfiguration +#### Delete a ContentHostingConfiguration ```bash cd ~/rt-5gms-application-server tests/m3_client_cli.py -H localhost:7777 delete prov-sess-1 ``` -### Purge all cached objects for a ContentHostingConfiguration +#### Purge all cached objects for a ContentHostingConfiguration ```bash cd ~/rt-5gms-application-server @@ -229,3 +464,28 @@ cd ~/rt-5gms-application-server tests/m3_client_cli.py -H localhost:7777 purge prov-sess-1 '\.mpd$' ``` +Regenerating the 5G API bindings +-------------------------------- +The `build_scripts/generate_5gms_as_openapi` script will use wget, git and java to download the openapi-generator tool, the 5G OpenAPI YAML and generate the `rt_5gms_as.openapi_5g` Python module package. The script will only do this if the `src/rt_5gms_as/openapi_5g` directory does not already exist. + +Therefore to regenerate the API bindings you first need to remove the old bindings: +``` +cd ~/rt-5gms-application-server +rm -rf src/rt_5gms_as/openapi_5g +``` + +Then run the generator script: +``` +~/rt-5gms-application-server/build_scripts/generate_5gms_as_openapi +``` + +For reference (or if it is desirable to recreate the steps manually) the `generate_5gms_as_openapi` script performs the following actions: +- Uses `wget` to fetch version 6.0.1 of the [openapi-generator-cli](https://github.com/OpenAPITools/openapi-generator-cli). + - e.g. `wget https://repo1.maven.org/maven2/org/openapitools/openapi-generator-cli/6.0.1/openapi-generator-cli-6.0.1.jar -O openapi-generator-cli.jar` +- Uses `git` to clone the [5G OpenAPI repository](https://forge.3gpp.org/rep/all/5G_APIs.git). + - e.g. `git clone -b REL-17 https://forge.3gpp.org/rep/all/5G_APIs.git` +- Copies in the API override files + - e.g. `cp -f ~/rt-5gms-application-server/external/rt-common-shared/5gms/5G_APIs-overrides/*.yaml ~/rt-5gms-application-server/build_scripts/M3_merged.yaml 5G_APIs/` +- Uses the openapi-generator-cli, downloaded in the first step, to generate the API bindings. + - e.g. `mkdir 5g-api-python; java -jar openapi-generator-cli.jar generate -i 5G_APIs/TS26512_M1_ContentHostingProvisioning.yaml -g python --additional-properties packageName=rt_5gms_as.openapi_5g,projectName=openapi-5g -o 5g-api-python; java -jar openapi-generator-cli.jar generate -t ~/rt-5gms-application-server/build_scripts -i 5G_APIs/M3_merged.yaml -g python --additional-properties packageName=rt_5gms_as.openapi_5g,projectName=openapi-5g -o 5g-api-python` +- Copies the API Python package to the `src/rt_5gms_as/openapi_5g` directory. diff --git a/pages/5g-media-streaming/usage/application-server/usage-application-server.md b/pages/5g-media-streaming/usage/application-server/usage-application-server.md index dba80440..6e31973b 100644 --- a/pages/5g-media-streaming/usage/application-server/usage-application-server.md +++ b/pages/5g-media-streaming/usage/application-server/usage-application-server.md @@ -4,7 +4,7 @@ title: Application Server parent: Usage grand_parent: 5G Downlink Media Streaming has_children: true -nav_order: 3 +nav_order: 0 --- # Application Server diff --git a/pages/5g-multicast-broadcast-services/features.md b/pages/5g-multicast-broadcast-services/features.md index 7e6f48db..7dcc1928 100644 --- a/pages/5g-multicast-broadcast-services/features.md +++ b/pages/5g-multicast-broadcast-services/features.md @@ -7,3 +7,123 @@ nav_order: 1 --- # List of features under implementation +## 5G-MAG 5G-MBS development over Open5GS + +The development of 5G-MBS in 5G-MAG targets the 3GPP Release 17 MBS Broadcast features: +- Multicast transport over N6mb [^1]. +- Shared delivery on the 5G Core [^2]. +- Point to Multipoint (PTM) delivery on RAN [^3]. + +[^1]: From AF to MB-UPF. +[^2]: From MB-UPF to gNBs. +[^3]: From gNBs to UEs. + +
+Current status of the MVP + +## Current status of the MVP + +The Minimum Viable Product (MVP) **currently supports**: +- `MB-SMF TMGI Service API` (Following 3GPP TS 29.532 - Release 17.4.0) + - TMGI Allocate Service operation + - TMGI Deallocate Service operation +- `MB-SMF MBS Session Service API` (Following 3GPP TS 29.532 - Release 17.4.0) + - MBS Session Create Service operation + - MBS Session Release Service operation +- `MB-SMF PFCP Session Establishment extensions` (Following 3GPP TS 29.244 - Release 17.9.0) + - PFCP Session Establishment Request extensions +- `MB-UPF PFCP Session Establishment extensions` (Following 3GPP TS 29.244 - Release 17.9.0) + - PFCP Session Establishment Response extensions + +The MVP **currently lacks support** for: +- `AMF MBS Broadcast Service API` (Following 3GPP TS 29.518 - Release 17.11.0) + - MBS Broadcast ContextCreate Service operation + - MBS Broadcast ContextRelease Service operation +- `AMF NGAP extensions` (Following 3GPP TS 38.413 - Release 17.6.0) + - BROADCAST SESSION SETUP REQUEST +- `gNB NGAP extensions` (Following 3GPP TS 38.413 - Release 17.6.0) + - BROADCAST SESSION SETUP RESPONSE +- `NRF NFDiscovery Service API extensions` (Following 3GPP TS 29.510 - Release 17.11.0) + - MB-SMF TMGI Service API extensions + - MB-SMF MBS Session Service API extensions + - AMF MBS Broadcast Service API extensions + +
+ +
5G-MBS architecture using Open5GS + +## 5G-MBS architecture using Open5GS + +![5G-MBS architecture using Open5GS](images/5G-MBS_5G_Core.png) + +
+ +
MBS Session Establishment for Broadcast call flow + +## MBS Session Establishment for Broadcast call flow + +![MBS Broadcast Session Create call flow](images/MBS_Broadcast_Session_Create_call_flow.png) + +
+ +
+Overview of the current implementation + +## Overview of the current implementation + +> Note: Read this section to understand the current implementation and its limitations + +MBS Sessions can be of two different types, Broadcast MBS Sessions and Multicast MBS Sessions. Broadcast MBS Sessions can be seen as a subset of the Multicast MBS Sessions functionality. In the MBS Sessions context, two kinds of identifiers exist, TMGI (Temporary Mobile Group Identifier) and SSM (Source Specific Multicast). Broadcast MBS Sessions are identified by a TMGI, while Multicast MBS Sessions can be identified by using TMGI or SSM. Even if SSM is selected as identifier, a TMGI is **always** allocated. + +The current implementation lets you create a TMGI by sending an HTTP/2 request to the MB-SMF. + +The TMGI can be created in two ways: + +1. Sending an HTTP/2 request to the MB-SMF to the `MB-SMF TMGI Service API` using the _TMGI Allocate Service operation_ (this way only the TMGI is created) +2. Sending an HTTP/2 request to the MB-SMF to the `MB-SMF MBS Session Service API` using the _MBS Session Create Service operation_ with `tmgiAllocReq` property set to _true_ (this way a TMGI and MBS Session are created) + +In this implementation, the TMGI stores the expiration time for the MBS Session. Currently the Network Functions local time is set in UTC and everytime a TMGI is created the _expiration time_ is set to two hours. The `MB-SMF TMGI Service API` using the _TMGI Allocate Service operation_ can be used to refresh the _expiration time_ of an existing TMGI. This process adds two extra hours to the _expiration time_ of the TMGIs specified in the request. + +The MBS Session can be created in various ways, depending on the service type of the session, the existing service types are _BROADCAST_ or _MULTICAST_. + +A Broadcast MBS Session can be created in two ways: + +1. If the TMGI has been previously allocated using the `MB-SMF TMGI Service API`, an MBS Session must be created sending an HTTP/2 request to the MB-SMF to the `MB-SMF MBS Session Service API` using the _MBS Session Create Service operation_ with `tmgiAllocReq` property set to _false_ (this way only a MBS Session is created). The request must contain the previously allocated TMGI in the `tmgi` object +2. If the TMGI has not been previously allocated, TMGI allocation and MBS Session creation can be done at the same time, as explained before. Sending an HTTP/2 request to the MB-SMF to the `MB-SMF MBS Session Service API` using the _MBS Session Create Service operation_ with `tmgiAllocReq` property set to _true_ (this way a TMGI and MBS Session are created) + +A Multicast MBS Session can be created in three ways: + +> Note: To be documented + +After sending the request for the MBS Session creation, some side effects occur: +- MB-SMF and MB-UPF start the PFCP Session Establishment with the `MB-SMF PFCP Session Establishment extensions` using _PFCP Session Establishment Request extensions_ and the `MB-UPF PFCP Session Establishment extensions` using _PFCP Session Establishment Response extensions_ +- MB-SMF sends the AMF MBS Broadcast ContextCreate with the `AMF MBS Broadcast Service API` using _MBS Broadcast ContextCreate Service operation_ +- AMF sends the NGAP BROADCAST SESSION SETUP to the gNBs with the `AMF NGAP extensions` using _BROADCAST SESSION SETUP REQUEST_ and the gNBs respond with the `gNB NGAP extensions` using _BROADCAST SESSION SETUP RESPONSE_ + +### Detailed explanations of the side effects + +#### [MB-SMF <-> MB-UPF]: PFCP Session Establishment side effects + +Due to the use of multicast transport on the N6mb interface, the SSM identifier must be present on the `MB-SMF MBS Session Service API` request using the _MBS Session Create Service operation_. It does not matter if the requested service type is of type _BROADCAST_ or _MULTICAST_. + +The placement of the SSM in the request selects which kind of identifier is being used. In the JSON data of the request, if the SSM is present inside the `mbsSession` object, right at the `ssm` object, the TMGI is being used as identifier. If the SSM is present inside the `mbsSession` object and inside the `mbsSessionId` object, at the `ssm` object, then SSM is being used as identifier. The addresses defined in the `ssm` object are the ones being used by the MB-UPF as Packet Detection Rules (PDR) to identify the N6mb multicast traffic. + +The MB-UPF detects the traffic coming from the SSM and forwards it to the gNBs that have joined the multicast group defined by the LLSSM (Lower Layer Source Specific Multicast). Because of the use of GTPU, a TEID must be selected to forward the traffic, in the case of multicast transport, a C-TEID (Common TEID) is selected and is shared between all the gNBs receiving the multicast traffic. + + +> Warning: Currently, only one LLSSM and C-TEID are being allocated. After sending the request to create the MBS Session, a PDR is configured to detect the traffic coming from the SSM specified on the request and the traffic is forwarded to the LLSSM that is using the multicast destination address `239.0.0.4` and C-TEID `33`. + +#### [MB-SMF <-> AMF]: AMF MBS Broadcast ContextCreate side effect + +> Note: To be implemented and to be documented + +#### [AMF <-> gNBs]: NGAP BROADCAST SESSION SETUP side effect + +> Note: To be implemented and to be documented + +
+ +
Usage of the current implementation + + +
diff --git a/pages/5g-multicast-broadcast-services/images/5G-MBS_5G_Core.png b/pages/5g-multicast-broadcast-services/images/5G-MBS_5G_Core.png new file mode 100644 index 0000000000000000000000000000000000000000..a79b89f5c8762fd5d7362544f72edf611f6505b4 GIT binary patch literal 44330 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

okn}SN_pI~ZlmQ(xH*96nh1Cx=Fp%nY^3uFTp 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 tKK%12FbJGzMu+K$9(;aUIy literal 0 HcmV?d00001 diff --git a/pages/5g-multicast-broadcast-services/images/MBS_Broadcast_Session_Create_call_flow.png b/pages/5g-multicast-broadcast-services/images/MBS_Broadcast_Session_Create_call_flow.png new file mode 100644 index 0000000000000000000000000000000000000000..6bbd14c60bfe21d0aa82fa33b6198f6669060173 GIT binary patch literal 49353 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 Jl|y*ye*g|C=W_r6 literal 0 HcmV?d00001 diff --git a/pages/5g-multicast-broadcast-services/index.md b/pages/5g-multicast-broadcast-services/index.md index 6ad7fed7..f916bce8 100644 --- a/pages/5g-multicast-broadcast-services/index.md +++ b/pages/5g-multicast-broadcast-services/index.md @@ -2,7 +2,7 @@ layout: default title: 5G Multicast Broadcast Services has_children: true -nav_order: 6 +nav_order: 7 --- # 5G Multicast and Broadcast Services (5MBS) diff --git a/pages/5g-multicast-broadcast-services/repositories.md b/pages/5g-multicast-broadcast-services/repositories.md index 59a59cb2..c4239021 100644 --- a/pages/5g-multicast-broadcast-services/repositories.md +++ b/pages/5g-multicast-broadcast-services/repositories.md @@ -7,3 +7,6 @@ nav_order: 3 --- # ⭐ Related repositories +Please note that 5G Multicast Broadcast Services is implemented as an extension of [Open5GS](https://github.com/5G-MAG/open5gs) + +## 5G Core (with MBS components): [open5gs/tree/upv-mbs](https://github.com/5G-MAG/open5gs/tree/upv-mbs) diff --git a/pages/5g-multicast-broadcast-services/tutorials.md b/pages/5g-multicast-broadcast-services/tutorials.md index 3ed1d6ce..fa7dd451 100644 --- a/pages/5g-multicast-broadcast-services/tutorials.md +++ b/pages/5g-multicast-broadcast-services/tutorials.md @@ -8,4 +8,3 @@ nav_order: 4 # ▶️ Using the tools Check the [TUTORIALS & DEVELOPER XCHANGES](https://www.5g-mag.com/tutorials) in the 5G-MAG website and the information below. -* We are working on it... diff --git a/pages/5g-multicast-broadcast-services/usage.md b/pages/5g-multicast-broadcast-services/usage.md new file mode 100644 index 00000000..3e735b1c --- /dev/null +++ b/pages/5g-multicast-broadcast-services/usage.md @@ -0,0 +1,8 @@ +--- +layout: default +title: Usage +parent: 5G Multicast Broadcast Services +has_children: true +nav_order: 4 +--- +# 🚧 Usage diff --git a/pages/5g-multicast-broadcast-services/usage/creating-mbs-sessions.md b/pages/5g-multicast-broadcast-services/usage/creating-mbs-sessions.md new file mode 100644 index 00000000..93afdb6d --- /dev/null +++ b/pages/5g-multicast-broadcast-services/usage/creating-mbs-sessions.md @@ -0,0 +1,55 @@ +--- +layout: default +title: Creating MBS Sessions +parent: Usage +grand_parent: 5G Multicast Broadcast Services +has_children: false +nav_order: 2 +--- +# Creating MBS Sessions + +## Creating a Broadcast MBS Session + +### Method 1: Creating a Broadcast MBS Session and a TMGI in the same request + +With this method, the AF will ask the MB-SMF to allocate one TMGI and an MBS Session will be created and associated with this TMGI in the same request. The SSM is used for the detection of the multicast transport over N6mb. + +```bash +# MBS Session Create request with TMGI allocate: /nmbsmf-mbssession/v1/mbs-sessions with multicast source +curl --http2-prior-knowledge \ + --request POST \ + --header "Content-Type: application/json" \ + --data '{ "mbsSession": { "ssm": { "sourceIpAddr": { "ipv4Addr": "10.33.33.3" }, "destIpAddr": { "ipv4Addr": "239.0.0.20" } },"tmgiAllocReq": true, "serviceType":"BROADCAST" } }' \ + mb-smf.open5gs.org:80/nmbsmf-mbssession/v1/mbs-sessions +``` + +The response of the MB-SMF contains the allocated TMGI as MBS Session identifier and also de SSM specified in the request: + +```json +{"mbsSession":{"mbsSessionId":{"tmgi":{"mbsServiceId":"F9ECB4","plmnId":{"mcc":"001","mnc":"01"}}},"tmgi":{"mbsServiceId":"F9ECB4","plmnId":{"mcc":"001","mnc":"01"}},"serviceType":"BROADCAST"}} +``` + +### Method 2: Creating a Broadcast MBS Session using an existing TMGI + +With this method, the AF will ask the MB-SMF to create an MBS Session and the existing TMGI will be associated with it. The SSM is used for the detection of the multicast transport over N6mb. + +```bash +# MBS Session Create request with existing TMGI: /nmbsmf-mbssession/v1/mbs-sessions +curl --http2-prior-knowledge \ + --request POST \ + --header "Content-Type: application/json" \ + --data '{ "mbsSession": { "mbsSessionId": { "tmgi": { "mbsServiceId": "9236F7", "plmnId": { "mcc":"001", "mnc":"01" } } }, "ssm": { "sourceIpAddr": { "ipv4Addr": "10.33.33.3" }, "destIpAddr": { "ipv4Addr": "239.0.0.20" } }, "serviceType":"BROADCAST" } }' \ + mb-smf.open5gs.org:80/nmbsmf-mbssession/v1/mbs-sessions +``` + +The response of the MB-SMF contains the specified TMGI and SSM, using the TMGI as MBS Session identifier as specified in the request: + +```json +{"mbsSession":{"mbsSessionId":{"tmgi":{"mbsServiceId":"9236F7","plmnId":{"mcc":"001","mnc":"01"}}},"tmgi":{"mbsServiceId":"9236F7","plmnId":{"mcc":"001","mnc":"01"}},"serviceType":"BROADCAST"}} +``` + +### Method 3: Creating a Broadcast MBS Session using SSM as identifier + +> Note: To be documented + + diff --git a/pages/5g-multicast-broadcast-services/usage/docker-implementation.md b/pages/5g-multicast-broadcast-services/usage/docker-implementation.md new file mode 100644 index 00000000..ba70ddc3 --- /dev/null +++ b/pages/5g-multicast-broadcast-services/usage/docker-implementation.md @@ -0,0 +1,74 @@ +--- +layout: default +title: Docker implementation +parent: Tutorials +grand_parent: 5G Multicast Broadcast Services +has_children: false +nav_order: 3 +--- + +# Docker Implementation +Here you will find an easy way to try the current 5G-MBS MVP being developed by the [iTEAM Mobile Communications Group](https://github.com/iTEAM-MCG) as part of the [5G-MAG](https://github.com/5G-MAG), following the 3GPP Release 17 specifications. + +This implementation is being developed on top of the [Open5GS](https://github.com/open5gs/open5gs) 5G Core. The repository containing the source code can be found [here](https://github.com/5G-MAG/open5gs/tree/upv-mbs). + +This playground uses Docker Compose to deploy a 5G-MBS capable 5G Core using Docker images present in a container repository. + +## 5G-MBS architecture using Open5GS + +![5G-MBS architecture using Open5GS](../images/5G-MBS_5G_Core.png) + +> [!NOTE] +> Ports `TCP 27017`, `SCTP 38412` and `UDP 2152` are being exposed to the host running this Docker Compose deployment + +These ports are being used for the following: +- `TCP 27017` to add subscribers to the MongoDB database +- `SCTP 38412` from the AMF for the NGAP `N2 interface`, used for the control plane connection with the external gNB +- `UDP 2152` from the MB-UPF for the GTPU `N3mb interface`, used for the data plane connection with the external gNB + +> [!NOTE] +> Modify the `.env` file present on this repository to change the values being deployed on `docker-compose.yaml` + +Add your host's IP address to the `DOCKER_HOST_IP` variable in the `.env` file for the MB-UPF to be reachable by external gNBs. + +## Basic usage + +

+Build it + +> Note: This method uses the `docker-bake.hcl` file and requires `docker-buildx-plugin` + +From the top level directory of the repository run: +```bash +docker buildx bake +``` + +This builds the AF, MB-SMF and MB-UPF images locally. + +
+ +
+Deploy it +To download the rest of the Docker images from the repository and start everything: + +```bash +docker compose up -d +``` + +To stop everything: + +```bash +docker compose down +``` + +
+ +## Find more information + +- `docs` has extra documentation regarding the project + - [docs/Overview](docs/Overview.md) to see the current status and features of the project + - [docs/Detailed Instructions](docs/Detailed-Instructions.md) to see how to manage the containers + - [docs/Tests](docs/Tests.md) to see how to use the tests present in the `test` directory +- `configs` to check/modify the Network Function configuration files of the deployment +- `images` where the Network Function Dockerfiles are present +- `test` testing suite being developed in Python to test the features present diff --git a/pages/5g-multicast-broadcast-services/usage/managing-tmgi.md b/pages/5g-multicast-broadcast-services/usage/managing-tmgi.md new file mode 100644 index 00000000..5a366611 --- /dev/null +++ b/pages/5g-multicast-broadcast-services/usage/managing-tmgi.md @@ -0,0 +1,133 @@ +--- +layout: default +title: TMGI Management +parent: Usage +grand_parent: 5G Multicast Broadcast Services +has_children: false +nav_order: 1 +--- + +# TMGI Management + +The TMGI can be created by using the `TMGI Service API` or by using the `MBS Session Service API` with the `tmgiAllocReq` set to _true_. + +## Creating/Allocating a TMGI +### Method 1: TMGI Service API + +With this method, the AF will ask the MB-SMF to allocate the number of TMGIs present on the `tmgiNumber` field in the JSON data of the request. + +```bash +# TMGI Allocate (allocate) request: /nmbsmf-tmgi/v1/tmgi +curl --http2-prior-knowledge \ + --request POST \ + --header "Content-Type: application/json" \ + --data '{ "tmgiNumber": 1 }' \ + mb-smf.open5gs.org:80/nmbsmf-tmgi/v1/tmgi +``` + +The response of the MB-SMF, should send the list of allocated TMGIs: + +```json +{"tmgiList":[{"mbsServiceId":"9236F7","plmnId":{"mcc":"001","mnc":"01"}}],"expirationTime":"2024-06-04T16:59:10.628193+00:00"} +``` + +### Method 2: MBS Session Service API + +With this method, the AF will ask the MB-SMF to allocate one TMGI and an MBS Session will be created and associated with this TMGI in the same request. The SSM is used for the detection of the multicast transport over N6mb. + +```bash +# MBS Session Create request with TMGI allocate: /nmbsmf-mbssession/v1/mbs-sessions with multicast source +curl --http2-prior-knowledge \ + --request POST \ + --header "Content-Type: application/json" \ + --data '{ "mbsSession": { "ssm": { "sourceIpAddr": { "ipv4Addr": "10.33.33.3" }, "destIpAddr": { "ipv4Addr": "239.0.0.20" } },"tmgiAllocReq": true, "serviceType":"BROADCAST" } }' \ + mb-smf.open5gs.org:80/nmbsmf-mbssession/v1/mbs-sessions +``` + +The response of the MB-SMF, should send the MBS Session with the allocated TMGI: + +```json +{"mbsSession":{"mbsSessionId":{"tmgi":{"mbsServiceId":"0D3BE6","plmnId":{"mcc":"001","mnc":"01"}}},"tmgi":{"mbsServiceId":"0D3BE6","plmnId":{"mcc":"001","mnc":"01"}},"serviceType":"BROADCAST"}} +``` + +## Updating an existing TMGI + +### TMGI Service API + +With this method, the AF will ask the MB-SMF to refresh an existing TMGI. This method is only accesible through the `TMGI Service API` but can be combined with the allocation too: + +```bash +# TMGI Allocate (refresh) request: /nmbsmf-tmgi/v1/tmgi +curl --http2-prior-knowledge \ + --request POST \ + --header "Content-Type: application/json" \ + --data '{ "tmgiList": [ { "mbsServiceId": "9236F7", "plmnId": { "mcc": "001", "mnc": "01" } } ] }' \ + mb-smf.open5gs.org:80/nmbsmf-tmgi/v1/tmgi +``` + +The response of the MB-SMF, should send the new expiration time for the refreshed TMGIs: + +```json +{"tmgiList":[],"expirationTime":"2024-06-04T17:02:07.119039+00:00"} +``` + +Combination of TMGI allocate request and TMGI refresh: + +```bash +# TMGI Allocate (allocate + refresh) request: /nmbsmf-tmgi/v1/tmgi +curl --http2-prior-knowledge \ + --request POST \ + --header "Content-Type: application/json" \ + --data '{ "tmgiNumber": 1, "tmgiList": [ { "mbsServiceId": "9236F7", "plmnId": { "mcc": "001", "mnc": "01" } } ] }' \ + mb-smf.open5gs.org:80/nmbsmf-tmgi/v1/tmgi +``` + +The response of the MB-SMF, should send the allocated TMGIs and the new expiration time for the refreshed TMGIs: + +```json +{"tmgiList":[{"mbsServiceId":"E79DA9","plmnId":{"mcc":"001","mnc":"01"}}],"expirationTime":"2024-06-04T17:03:01.036961+00:00"} +``` + +## Creating a Broadcast MBS Session + +### Method 1: Creating a Broadcast MBS Session and a TMGI in the same request + +With this method, the AF will ask the MB-SMF to allocate one TMGI and an MBS Session will be created and associated with this TMGI in the same request. The SSM is used for the detection of the multicast transport over N6mb. + +```bash +# MBS Session Create request with TMGI allocate: /nmbsmf-mbssession/v1/mbs-sessions with multicast source +curl --http2-prior-knowledge \ + --request POST \ + --header "Content-Type: application/json" \ + --data '{ "mbsSession": { "ssm": { "sourceIpAddr": { "ipv4Addr": "10.33.33.3" }, "destIpAddr": { "ipv4Addr": "239.0.0.20" } },"tmgiAllocReq": true, "serviceType":"BROADCAST" } }' \ + mb-smf.open5gs.org:80/nmbsmf-mbssession/v1/mbs-sessions +``` + +The response of the MB-SMF contains the allocated TMGI as MBS Session identifier and also de SSM specified in the request: + +```json +{"mbsSession":{"mbsSessionId":{"tmgi":{"mbsServiceId":"F9ECB4","plmnId":{"mcc":"001","mnc":"01"}}},"tmgi":{"mbsServiceId":"F9ECB4","plmnId":{"mcc":"001","mnc":"01"}},"serviceType":"BROADCAST"}} +``` + +### Method 2: Creating a Broadcast MBS Session using an existing TMGI + +With this method, the AF will ask the MB-SMF to create an MBS Session and the existing TMGI will be associated with it. The SSM is used for the detection of the multicast transport over N6mb. + +```bash +# MBS Session Create request with existing TMGI: /nmbsmf-mbssession/v1/mbs-sessions +curl --http2-prior-knowledge \ + --request POST \ + --header "Content-Type: application/json" \ + --data '{ "mbsSession": { "mbsSessionId": { "tmgi": { "mbsServiceId": "9236F7", "plmnId": { "mcc":"001", "mnc":"01" } } }, "ssm": { "sourceIpAddr": { "ipv4Addr": "10.33.33.3" }, "destIpAddr": { "ipv4Addr": "239.0.0.20" } }, "serviceType":"BROADCAST" } }' \ + mb-smf.open5gs.org:80/nmbsmf-mbssession/v1/mbs-sessions +``` + +The response of the MB-SMF contains the specified TMGI and SSM, using the TMGI as MBS Session identifier as specified in the request: + +```json +{"mbsSession":{"mbsSessionId":{"tmgi":{"mbsServiceId":"9236F7","plmnId":{"mcc":"001","mnc":"01"}}},"tmgi":{"mbsServiceId":"9236F7","plmnId":{"mcc":"001","mnc":"01"}},"serviceType":"BROADCAST"}} +``` + +### Method 3: Creating a Broadcast MBS Session using SSM as identifier + +> Note: To be documented diff --git a/pages/5g-multicast-broadcast-services/usage/testing.md b/pages/5g-multicast-broadcast-services/usage/testing.md new file mode 100644 index 00000000..bcfd51ae --- /dev/null +++ b/pages/5g-multicast-broadcast-services/usage/testing.md @@ -0,0 +1,109 @@ +# Testing + +This section explains how to use the Python tests present on the `test` directory. + +The Python modules requirements are preinstalled on the AF container image. This container mounts the `test` directory as readonly to be able to run the tests. + +To run the tests, execute an interactive session with the AF container and navigate to the test directory: +```bash +docker exec -it af bash + +# inside the AF container +cd test + +# to run the tests +python3 tests.py +``` + +The `test` directory contains the following subdirectories: +- `MB_SMF` the developed tests regarding the MB-SMF Network Function +- `utils` a Python package containing some common utils for the tests +- `support` some support files for the tests like JSON files for the requests and JSON schemas to validate them + +Using the `config.toml` file some parameters can be configured: +- the log_level for the tests can be adjusted. The values supported are: DEBUG, INFO, WARNING, ERROR, CRITICAL +- some endpoint parameters like the MB-SMF address, the protocol (HTTP or HTTPS) and the port being used + +The file `tests.py` contains the main logic for the tests. In this file the test suites are defined and run by the unittest testing framework. + +# Detailed Instructions + +## Inspect all the traffic being sent in the network + +You can use tcpdump/Wireshark to sniff all the messages being sent between the Network Functions by inspecting the `br-ogs` network bridge. This bridge is created by the Docker Compose network and is used to connect all the Network Functions. + +```bash +$ tcpdump -i br-ogs +``` + +## Connect to the AF container to start sending requests to the Network Functions + +The AF container is not Open5GS related, in fact, it is not even an AF, it is just a container called AF being used to send curl requests to the Open5GS APIs. + +```bash +# Connect to the AF container +docker exec -it af bash +``` + +Use curl inside the container to send requests to the other Network Functions: + +```bash +# Inside the AF container, example of the AF sending the MB-SMF the TMGI allocate request +curl --http2-prior-knowledge \ + --request POST \ + --header "Content-Type: application/json" \ + --data '{ "tmgiNumber": 1 }' \ + mb-smf.open5gs.org:80/nmbsmf-tmgi/v1/tmgi +``` + +## Configure the MB-UPF multicast + +Apart from editing the `.env` for the MB-UPF to be reachable by external gNBs, the MB-UPF needs extra configuration. To be able to forward the multicast traffic to the lower layer source specific multicast (LLSSM) address, the MB-UPF needs to udpate the multicast forwarding cache (MFC) in the linux kernel. + +For this purpose, the `smcroute` tool is installed on the MB-UPF container. Through the `smcroutectl` command, the MFC can be updated to the desired values. Currently this is done manually but other ways to update the MFC are being studied. + +```bash +# Execute this command inside the MB-UPF container +smcroutectl add eth0 ogstun +``` + +After this, and after creating the MBS Session, the MVP can be tested by using the AF to send multicast traffic to the MB-UPF and inspecting the MB-UPF output: +```bash +# Execute this command inside the AF container +sendip -p ipv4 -is -id +``` + +### Full example + +Create a Broadcast MBS Session using TMGI as identifier but specifying also the SSM address, this SSM will be the address that the AF will use to send the multicast traffic to the MB-UPF through the N6mb interface. + +```bash +# MBS Session Create request with TMGI allocate: /nmbsmf-mbssession/v1/mbs-sessions with multicast source +curl --http2-prior-knowledge \ + --request POST \ + --header "Content-Type: application/json" \ + --data '{ "mbsSession": { "ssm": { "sourceIpAddr": { "ipv4Addr": "10.33.33.3" }, "destIpAddr": { "ipv4Addr": "239.0.0.20" } },"tmgiAllocReq": true, "serviceType":"BROADCAST" } }' \ + mb-smf.open5gs.org:80/nmbsmf-mbssession/v1/mbs-sessions +``` + +The AF with IP address 10.33.33.3 will send an IP packet to the multicast destination 239.0.0.20. The MB-UPF will receive the traffic being sent to this multicast group and then forward it to the LLSSM. + +For this, we will configure the MB-UPF like this: +```bash +# Execute this command inside the MB-UPF container +smcroutectl add eth0 239.0.0.20 ogstun +``` + +This command will update the MFC of the MB-UPF to receive the traffic for the multicast group 239.0.0.20 and forward it internally using the `ogstun` interface. + +After all of this is configured, the MB-UPF has been configured through PFCP to forward the traffic received to the LLSSM. The LLSSM is uses the multicast destination address `239.0.0.4` and C-TEID `33`. + +Now, sending traffic with the AF to the MB-UPF with the addresses configured causes the MB-UPF to forward the traffic using GTPU to the LLSSM: + +> [!TIP] +> Check AF container IP executing `ip address` from the AF container and use the `eth0` interface address as + +```bash +# To send traffic from the AF to the MB-UPF +sendip -p ipv4 -is -id 239.0.0.20 mb-upf.open5gs.org +``` diff --git a/pages/dvbi-over-5g/index.md b/pages/dvbi-over-5g/index.md index 1b98bf35..8842a518 100644 --- a/pages/dvbi-over-5g/index.md +++ b/pages/dvbi-over-5g/index.md @@ -2,7 +2,7 @@ layout: default title: DVB-I Services over 5G has_children: true -nav_order: 9 +nav_order: 10 --- # DVB-I Services over 5G diff --git a/pages/emergency-alerts/index.md b/pages/emergency-alerts/index.md index 5d52b463..e1154147 100644 --- a/pages/emergency-alerts/index.md +++ b/pages/emergency-alerts/index.md @@ -2,7 +2,7 @@ layout: default title: Emergency Alerts over 5G Broadcast has_children: true -nav_order: 5 +nav_order: 6 --- # Emergency Alerts over 5G Broadcast diff --git a/pages/lte-based-5g-broadcast/index.md b/pages/lte-based-5g-broadcast/index.md index 151af9fe..7d7666bd 100644 --- a/pages/lte-based-5g-broadcast/index.md +++ b/pages/lte-based-5g-broadcast/index.md @@ -2,7 +2,7 @@ layout: default title: MBMS and LTE-based 5G Broadcast has_children: true -nav_order: 4 +nav_order: 5 --- # MBMS & LTE-based 5G Broadcast diff --git a/pages/lte-based-5g-broadcast/tutorials.md b/pages/lte-based-5g-broadcast/tutorials.md index 9e8aa70a..9a8e6d0e 100644 --- a/pages/lte-based-5g-broadcast/tutorials.md +++ b/pages/lte-based-5g-broadcast/tutorials.md @@ -8,4 +8,3 @@ nav_order: 4 # ▶️ Using the tools Check the [TUTORIALS & DEVELOPER XCHANGES](https://www.5g-mag.com/tutorials) in the 5G-MAG website and the information below. -* We are working on it... diff --git a/pages/multimedia-content-delivery/index.md b/pages/multimedia-content-delivery/index.md index 053dcda4..5fa38672 100644 --- a/pages/multimedia-content-delivery/index.md +++ b/pages/multimedia-content-delivery/index.md @@ -2,7 +2,7 @@ layout: default title: Multimedia Content Delivery has_children: true -nav_order: 3 +nav_order: 4 --- # Multimedia content delivery protocols diff --git a/pages/ue-data-collection-reporting-exposure/index.md b/pages/ue-data-collection-reporting-exposure/index.md new file mode 100644 index 00000000..b5ec8756 --- /dev/null +++ b/pages/ue-data-collection-reporting-exposure/index.md @@ -0,0 +1,9 @@ +--- +layout: default +title: UE data collection, reporting & event exposure +has_children: true +nav_order: 3 +--- + +# UE data collection, reporting and event exposure + diff --git a/pages/ue-data-collection-reporting-exposure/projects.md b/pages/ue-data-collection-reporting-exposure/projects.md new file mode 100644 index 00000000..a50fe4e0 --- /dev/null +++ b/pages/ue-data-collection-reporting-exposure/projects.md @@ -0,0 +1,11 @@ +--- +layout: default +title: Projects +parent: UE data collection, reporting & event exposure +has_children: false +nav_order: 2 +--- +# 🚧 Related projects +## UE data collection, reporting and event exposure +Reference implementation of the generic Data Collection AF and its instantiation in the 5GMS Application Function. +* [Kanban board](https://github.com/orgs/5G-MAG/projects/30) diff --git a/pages/ue-data-collection-reporting-exposure/repositories.md b/pages/ue-data-collection-reporting-exposure/repositories.md new file mode 100644 index 00000000..b9c472ea --- /dev/null +++ b/pages/ue-data-collection-reporting-exposure/repositories.md @@ -0,0 +1,9 @@ +--- +layout: default +title: Repositories +parent: UE data collection, reporting & event exposure +has_children: false +nav_order: 3 +--- +# ⭐ Related repositories +## Data Collection Application Function: [rt-data-collection-application-function](https://github.com/5G-MAG/rt-data-collection-application-function) diff --git a/pages/xr-media-integration-in-5g/index.md b/pages/xr-media-integration-in-5g/index.md index fc70d6c1..0f14e65b 100644 --- a/pages/xr-media-integration-in-5g/index.md +++ b/pages/xr-media-integration-in-5g/index.md @@ -2,8 +2,8 @@ layout: default title: XR Media Integration in 5G has_children: true -nav_order: 7 +nav_order: 9 --- # XR Media integration in 5G - \ No newline at end of file +