From 94d59d515397bd3eb85bad20a7ad106234e9c353 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Fri, 12 Jul 2024 17:20:50 +0200 Subject: [PATCH 1/6] Fix link in documentation --- common/utils/LOG/DOC/rtusage.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/utils/LOG/DOC/rtusage.md b/common/utils/LOG/DOC/rtusage.md index 04ff9647a8..b3de6cd71e 100644 --- a/common/utils/LOG/DOC/rtusage.md +++ b/common/utils/LOG/DOC/rtusage.md @@ -1,5 +1,5 @@ ## configuring the logging facility -The logging facility is fully configurable and it uses the [config module](../../../config/config.md) to get its parameters at init time. The [telnet server](../../telnetsrv/DOC/telnetsrv.md) includes a set of commands which can be used to dynamically modify the logging facility behavior +The logging facility is fully configurable and it uses the [config module](../../../../common/config/DOC/config.md) to get its parameters at init time. The [telnet server](../../telnetsrv/DOC/telnetsrv.md) includes a set of commands which can be used to dynamically modify the logging facility behavior All logging facility parameters are defined in the log_config section. Some parameters are global to the logging facility, they modify the way messages are printed to stdout. Conversely, some parameters are specific to a component and only modify the behavior for messages issued by a given component. A third type of parameters can be used to activate conditional debug code or dump messages or buffers. From 21de8666d3762b275f2e419d79578ec4212a6033 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Mon, 19 Aug 2024 17:06:03 +0200 Subject: [PATCH 2/6] Updated Wireshark documentation --- common/utils/T/DOC/T/wireshark.md | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/common/utils/T/DOC/T/wireshark.md b/common/utils/T/DOC/T/wireshark.md index 67587d139f..af11535bdc 100644 --- a/common/utils/T/DOC/T/wireshark.md +++ b/common/utils/T/DOC/T/wireshark.md @@ -103,7 +103,7 @@ of wireshark. Adapt as necessary. 2) Then, in the menu, choose `Edit->Preferences`. 3) In the preference window, unroll `Protocols` and configure the following: -**MAC** +**MAC-NR** Go to `MAC-NR`. Select: @@ -117,7 +117,7 @@ For `Source of LCID -> drb channel settings`: Type `AM, SN Len=18`, same thing for DL RLC Bearer Type. * Click OK. -**RLC** +**RLC-NR** Now, go to `RLC-NR`. Select: @@ -129,7 +129,7 @@ Now, go to `RLC-NR`. Select: You don't need to select `May see RLC headers only` and `Try to reassemble UM frames`. -**PDCP** +**PDCP-NR** Now, go to `PDCP-NR`. Select what you need in there. @@ -146,6 +146,12 @@ You are done with the preferences. You can click OK. 4) Then, in the menu `Analyze`, choose `Enabled Protocols...`. 5) In the new window search for `nr` and select `mac_nr_udp` to have `MAC-NR over UDP`. +**NAS-5GS** + +Under `NAS-5GS`, select: + +* `Try to detect and decode 5G-EA0 ciphered messages` + And that's it. Maybe other settings can be changed, but those steps should be enough for a start. From 031622b1a3f9606592e08872a228b7db46953430 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Thu, 25 Jul 2024 11:59:44 +0200 Subject: [PATCH 3/6] Review of CL options section in RUNMODEM * place all NR UE CL optional options in the same section, in a table * add a section for common CL options * add subsection for UE capabilities * removed redundant text --- doc/RUNMODEM.md | 68 +++++++++++++++++++++++++++++++------------------ 1 file changed, 43 insertions(+), 25 deletions(-) diff --git a/doc/RUNMODEM.md b/doc/RUNMODEM.md index 928935f898..d0722ff8dd 100644 --- a/doc/RUNMODEM.md +++ b/doc/RUNMODEM.md @@ -102,47 +102,65 @@ Command line parameters for UE in `--sa` mode: - `--band` : NR band number (default value 78) - `--ssb` : SSB start subcarrier (default value 516) -**Optional parameters**: -- `-E`: use three-quarter sampling for split 8 sample rate. Required for - certain radios (e.g., 40MHz with B210). If used on the gNB, it is a good idea - to use for the UE as well (and vice versa). -- `--ue-scan-carrier` : scan for cells in current bandwidth. This option can be used if the SSB position of the gNB is unknown. If multiple cells are detected, the UE will try to connect to the first cell. By default, this option is disabled and the UE attempts to only decode SSB given by `--ssb`. +To simplify the configuration for the user testing OAI UE with OAI gNB, the latter prints the following LOG that guides the user to correctly set some of the UE command line parameters: -To simplify the configuration for the user testing OAI UE with OAI gNB, the latter prints the following LOG that guides the user to correctly set some of the UE command line parameters. - -``` +```shell [PHY] Command line parameters for OAI UE: -C 3319680000 -r 106 --numerology 1 --ssb 516 ``` You can run this, using USRPs, on two separate machines: -``` +```shell sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf --gNBs.[0].min_rxtxtime 6 --sa sudo ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --ssb 516 --sa ``` -With the RFsimulator (on the same machine): +With the **RFsimulator** (on the same machine), just add the option `--rfsim` to both gNB and NR UE command lines. -```bash -sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf --gNBs.[0].min_rxtxtime 6 --rfsim --sa -sudo ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --ssb 516 --rfsim --sa -``` +UE capabilities can be passed according to the [UE Capabilities](#UE-Capabilities) section. -Additionally, at UE side `--uecap_file` option can be used to pass the UE Capabilities input file (path location + filename), e.g. `--uecap_file ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/uecap_ports1.xml` +A detailed tutorial is provided at this page [NR_SA_Tutorial_OAI_nrUE.md](./NR_SA_Tutorial_OAI_nrUE.md). -## Some useful NR-UE parameters +## Optional NR-UE command line options -Some other useful paramters of the UE are +Here are some useful command line options for the NR UE: -- `--ue-fo-compensation`: enables the frequency offset compenstation at the UE. This is useful when running over the air and/or without an external clock/time source -- `--usrp-args`: this is the equivalend paramter of `sdr_addrs` field in the gNB config file and can be used to identify the USRP and set some basic paramters (like the clock source) -- `--clock-source`: sets the clock-source (internal or external). -- `--time-source`: sets the time-source (internal or external). +| Parameter | Description | +|--------------------------|---------------------------------------------------------------------------------------------------------------| +| `--ue-scan-carrier` | Scan for cells in current bandwidth. This option can be used if the SSB position of the gNB is unknown. If multiple cells are detected, the UE will try to connect to the first cell. By default, this option is disabled and the UE attempts to only decode SSB given by `--ssb`. | +| `--ue-fo-compensation` | Enables the frequency offset compensation at the UE. Useful when running over the air and/or without an external clock/time source. | +| `--usrp-args` | Equivalent to the `sdr_addrs` field in the gNB config file. Used to identify the USRP and set some basic parameters (like the clock source). | +| `--clock-source` | Sets the clock source (internal or external). | +| `--time-source` | Sets the time source (internal or external). | -You can see all options by typing -``` +You can view all available options by typing: + +```shell ./nr-uesoftmodem --help ``` +## Common gNB and NR UE command line options + +### Three-quarter sampling + +The command line option `-E` can be used to enable three-quarter sampling for split 8 sample rate. Required for certain radios (e.g., 40MHz with B210). If used on the gNB, it is a good idea to use for the UE as well (and vice versa). + +### UE Capabilities + +The `--uecap_file` option can be used to pass the UE Capabilities input file (path location + filename), e.g.`--uecap_file ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/uecap_ports1.xml` for 1 layer or e.g. `--uecap_file ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/uecap_ports2.xml` for 2 layers. + +This option is available for the following combinations of operation modes and gNB/nrUE softmodems: + +| Mode | Executable | Description | +|------------|----------------|-----------------------------------------------------| +| SA | nr-uesoftmodem | Send UE capabilities from the UE to the gNB via RRC | +| phy-test | nr-softmodem | Mimic the reception of UE capabilities by the gNB | +| do-ra | nr-softmodem | Mimic the reception of UE capabilities by the gNB | + +e.g. + +```shell +sudo ./nr-uesoftmodem --sa -r 106 --numerology 1 --band 78 -C 3319680000 --ue-nb-ant-tx 2 --ue-nb-ant-rx 2 --uecap_file /opt/oai-nr-ue/etc/uecap.xml +``` ## How to run a NTN configuration @@ -252,7 +270,7 @@ In summary: * `scp usera@machineA:/the/path/where/you/launched/nr-softmodem/r*config.raw userb@machineB:/the/path/where/you/will/launch/nr-uesoftmodem/` * Obviously this operation should be done before launching the `nr-uesoftmodem` executable. -In phy-test mode it is possible to mimic the reception of UE Capabilities at gNB by passing through the command line parameter `--uecap_file` the location and file name of the input UE Capability file, e.g. `--uecap_file ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/uecap_ports1.xml` (1 layer) or `--uecap_file ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/uecap_ports2.xml` (2 layers). +In phy-test mode it is possible to mimic the reception of UE Capabilities at gNB through the command line parameter `--uecap_file`. Refer to the [UE Capabilities](#UE-Capabilities) section for more details. ## noS1 setup with OAI UE @@ -288,7 +306,7 @@ The do-ra flag is used to ran the NR Random Access procedures in contention-free In order to run the RA, the `--do-ra` flag is needed for both the gNB and the UE. -In do-ra mode it is possible to mimic the reception of UE Capabilities at gNB by passing through the command line parameter `--uecap_file` the location and file name of the input UE Capability file, e.g. `--uecap_file ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/uecap_ports1.xml` +In do-ra mode it is possible to mimic the reception of UE Capabilities at gNB through the command line parameter `--uecap_file`. Refer to the [UE Capabilities](#UE-Capabilities) section for more details. To run using the RFsimulator: From 9102e10747ba224de7c9cb739ddd75abe0163a81 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Thu, 1 Aug 2024 14:13:17 +0200 Subject: [PATCH 4/6] Updated F1-design.md * restructured the documentation * add details from specs * add tables and Mermaid diagrams whenever possible --- doc/F1-design.md | 174 ++++++++++++++++++++++++++++++++------------- doc/FEATURE_SET.md | 18 +++-- 2 files changed, 136 insertions(+), 56 deletions(-) diff --git a/doc/F1-design.md b/doc/F1-design.md index 22781650f1..4690639d5b 100644 --- a/doc/F1-design.md +++ b/doc/F1-design.md @@ -18,38 +18,58 @@ The F1 interface is the functional split of 3GPP between the CU (centralized unit: PDCP, RRC, SDAP) and the DU (distributed unit: RLC, MAC, PHY). It is -standardized in TS 38.470 - 38.473 for 5G NR. No equivalent for 4G exists. +standardized in TS 38.470 - 38.473 for 5G NR. -We assume that each DU handles only one cell. Multiple DUs connected to one CU -are supported. Mobility over F1 is not yet supported. +F1 specs: +* 3GPP TS 38.470 F1 general aspects and principles +* 3GPP TS 38.471 F1 layer 1 -# Control plane status (F1-C) +F1-C: +* 3GPP TS 38.472 F1 signalling transport +* 3GPP TS 38.473 F1 Application Protocol (F1AP) -## Implementation Status +F1-U: +* 3GPP TS 38.474 F1 Data Transport -Note that OAI uses F1 "internally". That means, that even **if you run a -monolithic gNB, the internal information exchange uses F1**. You can therefore -expect that everything working in a monolithic deployment should also work in -F1. The current implementation is based on R16.3. +No equivalent for 4G exists. -Note that NSA does NOT follow this logic yet, and does not work with F1. +## Control plane (F1-C) -The following messages are currently implemented: +The interface F1-C is designed for the exchange of signalling messages between the +Radio Network Layer (RNL) and the Transport Network Layer (TNL). It +consists of F1 Application Protocol messages (F1-AP) exchanged over SCTP. -- F1 Setup Request and F1 Setup Response/Failure -- Initial UL RRC, UL/DL RRC Message Transfer -- F1 UE Context management messages for the "good case" - * Setup Request/Response - * Modification Request/Response - * Release Request/Command/Complete +## Data plane (F1-U) -All other messages are not implemented or not working reliably: +F1-U uses GTP-U for information exchange. -- F1 CU/DU configuration updade -- Paging messages -- Warning Message transmissions +# OAI Implementation Status -## High-level F1-C code structure +The implementation of F1AP messages is seamlessly integrated into OAI, supporting both Monolithic SA +and CU/DU functional split modes. The F1 code is therefore always compiled with nr-softmodem. +This architecture ensures that even *when operating a monolithic gNB, internal information exchange +always utilizes F1AP messages*. +The major difference lies in the CU/DU split scenario, where ASN.1-encoded F1AP messages (F1-C) are +exchanges over SCTP, via a socket interface. + +This is the current status: + +- gNB-CU/gNB-DU split +- Supported deployments: + * SA + * Single cell per DU + * Multiple DUs connected to one CU (both CP and UP) +- Not supported: + * Mobility + * NSA + +## F1-C + +### F1AP messages + +Refer to [FEATURE_SET.md](FEATURE_SET.md#gNB-F1AP) to learn about the current F1AP implementation status. + +### High-level F1-C code structure The F1 interface is used internally between CU (mostly RRC) and DU (mostly MAC) to exchange information. In DL, the CU sends messages as defined by the @@ -69,38 +89,94 @@ dedicated handler). In F1, the DU task receives the ITTI message, encodes using ASN.1, and sends it over a network socket. The CU task decodes, and sends the same ITTI message to the RRC task as done directly in the monolithic case. +Summary of callbacks and handlers: + +| Entity | Callback definition | Callback F1 Implementation | Callback Monolithic SA Implementation | Handler | +|--------|---------------------|----------------------------|---------------------------------------|----------------------| +| CU/RRC | `mac_rrc_dl.h` | `mac_rrc_dl_f1ap.c` | `mac_rrc_dl_direct.c` |No handler (use ITTI) | +| DU/MAC | `mac_rrc_ul.h` | `mac_rrc_ul_f1ap.c` | `mac_rrc_ul_direct.c` |`mac_rrc_dl_handler.c`| + +A sequence diagram for downlink F1AP messages over the OAI CU/DU functional split: + +```mermaid +sequenceDiagram + box rgba(17,158,189,255) CU/RRC + participant TASK_RRC_GNB + participant TASK_CU_F1 + end + Note over TASK_RRC_GNB: MAC/RRC callback + TASK_RRC_GNB->>+TASK_CU_F1: F1AP message (ITTI) + Note over TASK_CU_F1: F1 message encoding + Note over TASK_CU_F1: ASN.1 encoding + box Grey DU/MAC + participant TASK_DU_F1 + participant MAC + end + Note over TASK_DU_F1: F1AP DL message handler + TASK_CU_F1->>+TASK_DU_F1: SCTP (ITTI) + Note over TASK_DU_F1: F1 message decoding + Note over TASK_DU_F1: ASN.1 decoding + TASK_DU_F1->>+MAC: F1AP message (function call) + Note over MAC: MAC DL message handler ``` - +-------------+ - | | - | CU/RRC | - | | - +-------------+ - | ^ - Callback def: mac_rrc_dl.h | | No handler needed: - F1 impl: mac_rrc_dl_f1ap.c | | RRC has ITTI -Monolithic: mac_rrc_dl_direct.c | | - | | - DL | | UL - | | - | | Callback def: mac_rrc_ul.h - Message handler: | | F1 impl: mac_rrc_ul_f1ap.c - mac_rrc_dl_handler.c | | Monolithic: mac_rrc_ul_direct.c - v | - +-------------+ - | | - | DU/MAC | - | | - +-------------+ +and for the uplink F1AP messages: + +```mermaid +sequenceDiagram + box rgba(17,158,189,255) CU/RRC + participant TASK_RRC_GNB + participant TASK_CU_F1 + end + box Grey DU/MAC + participant TASK_DU_F1 + participant TASK_MAC_GNB + end + Note over TASK_MAC_GNB: MAC/RRC callback + TASK_MAC_GNB->>+TASK_DU_F1: F1AP message (ITTI) + Note over TASK_DU_F1: F1 message encoding + Note over TASK_DU_F1: ASN.1 encoding + Note over TASK_CU_F1: F1AP UL message handler + TASK_DU_F1->>+TASK_CU_F1: SCTP (ITTI) + Note over TASK_CU_F1: F1 message decoding + Note over TASK_CU_F1: ASN.1 decoding + TASK_CU_F1->>+TASK_RRC_GNB: F1AP message (ITTI) ``` -# Data plane status (F1-U) +Alternative sequence handling (e.g. Monolithic), for downlink: -F1-U uses GTP-U for information exchange. The GTP protocol uses some extensions -for NR-U protocol to report buffer status, but this is not properly tested and -might malfunction. One limitation is that the current implementation -acknowledges each packet individually. +```mermaid +sequenceDiagram + box rgba(17,158,189,255) RRC + participant TASK_RRC_GNB + end + Note over TASK_RRC_GNB: mac_rrc_dl_direct.c callback + box Grey MAC + participant TASK_MAC_GNB + end + TASK_RRC_GNB->>+TASK_MAC_GNB: raw F1AP message + Note over TASK_MAC_GNB: mac_rrc_dl_handler.c +``` +and for the uplink: -Multiple DUs at one CU are supported in the data plane (as in the control plane). +```mermaid +sequenceDiagram + box rgba(17,158,189,255) RRC + participant TASK_RRC_GNB + end + box Grey MAC + participant TASK_MAC_GNB + end + Note over TASK_MAC_GNB: mac_rrc_ul_direct.c callback + TASK_MAC_GNB->>+TASK_RRC_GNB: raw F1AP message (ITTI) +``` + +## F1-U + +Current status: + +* Buffer status report over GTP-U +* Each packet is acknowledged individually +* Support of multiple DUs per CU # How to run diff --git a/doc/FEATURE_SET.md b/doc/FEATURE_SET.md index 17d3f3b801..5469687ade 100644 --- a/doc/FEATURE_SET.md +++ b/doc/FEATURE_SET.md @@ -197,13 +197,17 @@ These modes of operation are supported: ## gNB F1AP - Integration of F1AP messages and procedures for the control plane exchanges between the CU and DU entities according to 38.473 Rel. 16 - - F1 Setup request/response/failure - - F1 DL/UL RRC message transfer - - F1 Initial UL RRC message transfer - - F1 UE Context setup request/response - - F1 UE Context modification request/response - - F1 UE Context modification required - - F1 UE Context release req/cmd/complete + - F1 Interface Management: + * F1 Setup request/response/failure + - F1 RRC Message Transfer: + * F1 Initial UL RRC Message Transfer + * F1 DL RRC Message Transfer + * F1 UL RRC Message Transfer + - F1 UE Context Management: + * F1 UE Context setup request/response + * F1 UE Context modification request/response + * F1 UE Context modification required + * F1 UE Context release req/cmd/complete - F1 gNB CU configuration update - F1 Reset (handled at DU only, full reset only) - Interface with RRC From 5764422342c42b94485032d03b30ff88e6367d98 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Fri, 16 Aug 2024 16:44:59 +0200 Subject: [PATCH 5/6] Section about connecting to an NG-Core in NR_SA_Tutorial_OAI_nrUE.md --- doc/NR_SA_Tutorial_OAI_nrUE.md | 35 ++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/doc/NR_SA_Tutorial_OAI_nrUE.md b/doc/NR_SA_Tutorial_OAI_nrUE.md index 8c1b0afaf1..043820d11b 100644 --- a/doc/NR_SA_Tutorial_OAI_nrUE.md +++ b/doc/NR_SA_Tutorial_OAI_nrUE.md @@ -159,6 +159,41 @@ cd ~/openairinterface5g/cmake_targets/ran_build/build sudo ./nr-uesoftmodem -r 32 --numerology 3 --band 257 -C 27533280000 --sa --uicc0.imsi 001010000000001 --ssb 72 --rfsim ``` +### Connection to an NG-Core + +A configuration file can be fed to the nrUE command line in order to connect to the local NGC. + +The nrUE configuration file (e.g. [ue.conf](../targets/PROJECTS/GENERIC-NR-5GC/CONF/ue.conf)) is structured in a key-value format and contains the relevant UICC parameters that are necessary to authenticate the UE to the local 5GC. E.g.: + +```shell +uicc0 = { + imsi = "001010000000001"; + key = "fec86ba6eb707ed08905757b1bb44b8f"; + opc = "C42449363BBAD02B66D16BC975D77CC1"; + dnn = "oai"; + nssai_sst = 1; +} +``` + +| **Parameter** | **Description** | **Default Value** | +|---------------|-----------------|-------------------| +| **IMSI** | Unique identifier for the UE within the mobile network. Used by the network to identify the UE during authentication. It ensures that the UE is correctly identified by the network. | 001010000000001 | +| **key** | Cryptographic key shared between the UE and the network, used for encryption during the authentication process. | `fec86ba6eb707ed08905757b1bb44b8f` | +| **OPC** | Operator key for the Milenage Authentication and Key Agreement algorithm used for encryption during the authentication process. | Ensures secure communication between the UE and the network by matching the encryption keys. | `C42449363BBAD02B66D16BC975D77CC1` | +| **DNN** | Specifies the name of the data network the UE wishes to connect to, similar to an APN in 4G networks. | `oai` | +| **NSSAI** | Allows the UE to select the appropriate network slice, which provides different QoS. | `1` | + +The UE configuration must match the one of the network's AMF. The nrUE can connect by default to OAI CN5G with no need to provide the configuration file. + +When running the `nr-uesoftmodem`, one can specify the nrUE configuration file using the `-O` option. E.g.: + +```bash +sudo ./nr-uesoftmodem --rfsim --rfsimulator.serveraddr 127.0.0.1 --sa -r 106 --numerology 1 --band 78 -C 3619200000 -O ~/nrue.uicc.conf +``` +The CL option `--uicc0.imsi` can override the IMSI value in the configuration file if necessary (e.g. when running multiple UEs): `--uicc0.imsi 001010000000001`. + +More details available at [ci-scripts/yaml_files/5g_rfsimulator/README.md](../ci-scripts/yaml_files/5g_rfsimulator/README.md). + ## 5.2 End-to-end connectivity test - Ping test from the UE host to the CN5G ```bash From dbe5c5ee61047a56a10496e2f74a4dc501a779ef Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Fri, 16 Aug 2024 17:01:52 +0200 Subject: [PATCH 6/6] Minor additions to UnitTests.md --- doc/UnitTests.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/doc/UnitTests.md b/doc/UnitTests.md index d1bbbed0ae..b9dc1194ff 100644 --- a/doc/UnitTests.md +++ b/doc/UnitTests.md @@ -25,7 +25,8 @@ ninja tests ``` Then, you can run `ctest` to run all tests: -``` + +```bash $ ctest Test project /home/richie/w/ctest/build Start 1: nr_rlc_tests @@ -36,6 +37,8 @@ Test project /home/richie/w/ctest/build Total Test time (real) = 0.06 sec ``` +The user can see all available tests by typing `ctest -N` and then run a specific with `ctest -R `, e.g. `ctest -R nr_rlc_tests`. + A couple of interesting variables are `--verbose`, `--output-on-failure`. # How to add a new test @@ -59,7 +62,8 @@ process is In the simplest case, in an existing `CMakeLists.txt`, you might add the following: -``` + +```bash if(ENABLE_TESTS) add_executable(my_test mytest.c) add_dependencies(tests my_test)