diff options
author | Matias Elo <matias.elo@nokia.com> | 2021-07-08 09:07:13 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-07-08 09:07:13 +0300 |
commit | 6c7ac017886e2f1f63a27871254326d7cd1b48d1 (patch) | |
tree | a89fd543bacd9483642ebc27517ff59577ba55ad | |
parent | 3a7a24023021f5959dd2f00fe83cf2635bf25c2d (diff) | |
parent | 75b2e7ed219c2f087b7068c4e8b708d475c9026a (diff) |
Merge ODP v1.30.0.0v1.30.0.0_DPDK_19.11
Merge ODP linux-generic v1.30.0.0 into ODP-DPDK.
131 files changed, 3897 insertions, 1116 deletions
diff --git a/.github/workflows/ci-pipeline-arm64.yml b/.github/workflows/ci-pipeline-arm64.yml new file mode 100644 index 000000000..ceedec3e3 --- /dev/null +++ b/.github/workflows/ci-pipeline-arm64.yml @@ -0,0 +1,204 @@ +name: CI arm64 + +# github.repository has been used to ensure CI is only run on the repo where +# self-hosted runners are installed. This will prevent [self-hosted, ARM64] CI failing on forks + +on: [push, pull_request] +env: + ARCH: arm64 + CC: gcc + CONTAINER_NAMESPACE: ghcr.io/opendataplane/odp-docker-images + OS: ubuntu_20.04 + +jobs: + + Build: + if: ${{ github.repository == 'OpenDataPlane/odp' }} + runs-on: [self-hosted, ARM64] + strategy: + fail-fast: false + matrix: + cc: [gcc, clang] + conf: ['', 'CFLAGS=-O3', 'CFLAGS=-O1', 'CFLAGS=-O0 --enable-debug=full', '--enable-lto', + '--enable-lto --enable-abi-compat', '--enable-pcapng-support'] + exclude: + - cc: clang + conf: '--enable-lto' + - cc: clang + conf: '--enable-lto --enable-abi-compat' + steps: + - uses: AutoModality/action-clean@v1.1.0 + - uses: actions/checkout@v2 + - run: sudo docker run -i -v `pwd`:/odp --privileged --shm-size 8g -e CC="${{matrix.cc}}" + -e CONF="${{matrix.conf}}" $CONTAINER_NAMESPACE/odp-ci-${OS}-${ARCH}-native /odp/scripts/ci/build_${ARCH}.sh + + Build_OS: + if: ${{ github.repository == 'OpenDataPlane/odp' }} + runs-on: [self-hosted, ARM64] + strategy: + fail-fast: false + matrix: + cc: [gcc, clang] + os: ['ubuntu_16.04', 'ubuntu_18.04'] + steps: + - uses: AutoModality/action-clean@v1.1.0 + - uses: actions/checkout@v2 + - run: sudo docker run -i -v `pwd`:/odp --privileged --shm-size 8g -e CC="${{matrix.cc}}" + -e CONF="${CONF}" $CONTAINER_NAMESPACE/odp-ci-${{matrix.os}}-${ARCH}-native /odp/scripts/ci/build_${ARCH}.sh + + Build_gcc-10: + if: ${{ github.repository == 'OpenDataPlane/odp' }} + runs-on: [self-hosted, ARM64] + env: + CC: gcc-10 + strategy: + fail-fast: false + matrix: + conf: ['', '--enable-lto'] + steps: + - uses: AutoModality/action-clean@v1.1.0 + - uses: actions/checkout@v2 + - run: sudo docker run -i -v `pwd`:/odp --privileged --shm-size 8g -e CC="${CC}" + -e CONF="${{matrix.conf}}" $CONTAINER_NAMESPACE/odp-ci-${OS}-${ARCH}-native /odp/scripts/ci/build_${ARCH}.sh + + Build_out-of-tree: + if: ${{ github.repository == 'OpenDataPlane/odp' }} + runs-on: [self-hosted, ARM64] + steps: + - uses: AutoModality/action-clean@v1.1.0 + - uses: actions/checkout@v2 + - run: sudo docker run -i -v `pwd`:/odp --privileged --shm-size 8g -e CC="${CC}" + -e CONF="${CONF}" $CONTAINER_NAMESPACE/odp-ci-${OS}-${ARCH}-native /odp/scripts/ci/out_of_tree.sh + + + Build_sched_config: + if: ${{ github.repository == 'OpenDataPlane/odp' }} + runs-on: [self-hosted, ARM64] + steps: + - uses: AutoModality/action-clean@v1.1.0 + - uses: actions/checkout@v2 + - run: sudo docker run -i -v `pwd`:/odp --privileged --shm-size 8g -e CC="${CC}" + -e CONF="--enable-debug=full" -e ODP_CONFIG_FILE=/odp/platform/linux-generic/test/sched-basic.conf + $CONTAINER_NAMESPACE/odp-ci-${OS}-${ARCH}-native /odp/scripts/ci/build_${ARCH}.sh + + Run_distcheck: + if: ${{ github.repository == 'OpenDataPlane/odp' }} + runs-on: [self-hosted, ARM64] + strategy: + fail-fast: false + matrix: + conf: ['--enable-user-guides', '--enable-user-guides --enable-abi-compat'] + steps: + - uses: AutoModality/action-clean@v1.1.0 + - uses: actions/checkout@v2 + - run: sudo docker run -i -v `pwd`:/odp --privileged --shm-size 8g -e CC="${{matrix.cc}}" + -e CONF="${{matrix.conf}}" $CONTAINER_NAMESPACE/odp-ci-${OS}-${ARCH}-native /odp/scripts/ci/distcheck.sh + - name: Failure log + if: ${{ failure() }} + run: find . -name "*.trs" | xargs grep -l '^.test-result. FAIL' | while read trs ; do echo FAILURE detected at $trs; cat ${trs%%.trs}.log ; done + + + Run: + if: ${{ github.repository == 'OpenDataPlane/odp' }} + runs-on: [self-hosted, ARM64] + strategy: + fail-fast: false + matrix: + cc: [gcc, clang] + conf: ['', '--enable-abi-compat', '--enable-deprecated --enable-debug=full', + '--enable-dpdk-zero-copy --disable-static-applications', + '--disable-host-optimization', '--disable-host-optimization --enable-abi-compat', + '--without-openssl --without-pcap'] + steps: + - uses: AutoModality/action-clean@v1.1.0 + - uses: actions/checkout@v2 + - run: sudo docker run -i -v `pwd`:/odp --privileged --shm-size 8g -e CC="${{matrix.cc}}" -e ARCH="${ARCH}" + -e CXX=g++-10 -e CONF="${{matrix.conf}}" $CONTAINER_NAMESPACE/odp-ci-${OS}-${ARCH}-native /odp/scripts/ci/check.sh + - name: Failure log + if: ${{ failure() }} + run: find . -name "*.trs" | xargs grep -l '^.test-result. FAIL' | while read trs ; do echo FAILURE detected at $trs; cat ${trs%%.trs}.log ; done + + + Run_OS: + if: ${{ github.repository == 'OpenDataPlane/odp' }} + runs-on: [self-hosted, ARM64] + strategy: + fail-fast: false + matrix: + os: ['ubuntu_18.04'] + steps: + - uses: AutoModality/action-clean@v1.1.0 + - uses: actions/checkout@v2 + - run: sudo docker run -i -v `pwd`:/odp --privileged --shm-size 8g -e CC="${{matrix.cc}}" -e ARCH="${ARCH}" + -e CONF="${CONF}" $CONTAINER_NAMESPACE/odp-ci-${{matrix.os}}-${ARCH}-native /odp/scripts/ci/check.sh + - name: Failure log + if: ${{ failure() }} + run: find . -name "*.trs" | xargs grep -l '^.test-result. FAIL' | while read trs ; do echo FAILURE detected at $trs; cat ${trs%%.trs}.log ; done + + Run_scheduler_sp: + if: ${{ github.repository == 'OpenDataPlane/odp' }} + runs-on: [self-hosted, ARM64] + steps: + - uses: AutoModality/action-clean@v1.1.0 + - uses: actions/checkout@v2 + - run: sudo docker run -i -v `pwd`:/odp --privileged --shm-size 8g -e CC="${CC}" -e ARCH="${ARCH}" + -e CONF="${CONF}" -e ODP_SCHEDULER=sp $CONTAINER_NAMESPACE/odp-ci-${OS}-${ARCH}-native /odp/scripts/ci/check.sh + - name: Failure log + if: ${{ failure() }} + run: find . -name "*.trs" | xargs grep -l '^.test-result. FAIL' | while read trs ; do echo FAILURE detected at $trs; cat ${trs%%.trs}.log ; done + + Run_scheduler_scalable: + if: ${{ github.repository == 'OpenDataPlane/odp' }} + runs-on: [self-hosted, ARM64] + steps: + - uses: AutoModality/action-clean@v1.1.0 + - uses: actions/checkout@v2 + - run: sudo docker run -i -v `pwd`:/odp --privileged --shm-size 8g -e CC="${CC}" -e ARCH="${ARCH}" + -e CONF="${CONF}" -e ODP_SCHEDULER=scalable -e CI_SKIP=pktio_test_pktin_event_sched $CONTAINER_NAMESPACE/odp-ci-${OS}-${ARCH}-native /odp/scripts/ci/check.sh + - name: Failure log + if: ${{ failure() }} + run: find . -name "*.trs" | xargs grep -l '^.test-result. FAIL' | while read trs ; do echo FAILURE detected at $trs; cat ${trs%%.trs}.log ; done + + Run_inline_timer: + if: ${{ github.repository == 'OpenDataPlane/odp' }} + runs-on: [self-hosted, ARM64] + steps: + - uses: AutoModality/action-clean@v1.1.0 + - uses: actions/checkout@v2 + - run: sudo docker run -i -v `pwd`:/odp --privileged --shm-size 8g -e CC="${CC}" -e ARCH="${ARCH}" + -e CONF="${CONF}" -e ODP_CONFIG_FILE=/odp/platform/linux-generic/test/inline-timer.conf + $CONTAINER_NAMESPACE/odp-ci-${OS}-${ARCH}-native /odp/scripts/ci/check_inline_timer.sh + - name: Failure log + if: ${{ failure() }} + run: find . -name "*.trs" | xargs grep -l '^.test-result. FAIL' | while read trs ; do echo FAILURE detected at $trs; cat ${trs%%.trs}.log ; done + + + Run_packet_align: + if: ${{ github.repository == 'OpenDataPlane/odp' }} + runs-on: [self-hosted, ARM64] + steps: + - uses: AutoModality/action-clean@v1.1.0 + - uses: actions/checkout@v2 + - run: sudo docker run -i -v `pwd`:/odp --privileged --shm-size 8g -e CC="${CC}" -e ARCH="${ARCH}" + -e CONF="${CONF}" -e ODP_CONFIG_FILE=/odp/platform/linux-generic/test/packet_align.conf + $CONTAINER_NAMESPACE/odp-ci-${OS}-${ARCH}-native /odp/scripts/ci/check_pktio.sh + - name: Failure log + if: ${{ failure() }} + run: find . -name "*.trs" | xargs grep -l '^.test-result. FAIL' | while read trs ; do echo FAILURE detected at $trs; cat ${trs%%.trs}.log ; done + + + Run_dpdk-18_11: + if: ${{ github.repository == 'OpenDataPlane/odp' }} + runs-on: [self-hosted, ARM64] + strategy: + fail-fast: false + matrix: + os: ['ubuntu_18.04'] + steps: + - uses: AutoModality/action-clean@v1.1.0 + - uses: actions/checkout@v2 + - run: sudo docker run -i -v `pwd`:/odp --privileged --shm-size 8g -e CC="${CC}" -e ARCH="${ARCH}" + -e CONF="${CONF}" $CONTAINER_NAMESPACE/odp-ci-${{matrix.os}}-${ARCH}-native-dpdk_18.11 /odp/scripts/ci/check.sh + - name: Failure log + if: ${{ failure() }} + run: find . -name "*.trs" | xargs grep -l '^.test-result. FAIL' | while read trs ; do echo FAILURE detected at $trs; cat ${trs%%.trs}.log ; done diff --git a/.github/workflows/ci-pipeline.yml b/.github/workflows/ci-pipeline.yml index c3109ff2c..089d96c2c 100644 --- a/.github/workflows/ci-pipeline.yml +++ b/.github/workflows/ci-pipeline.yml @@ -1,4 +1,4 @@ -name: CI +name: CI x86_64 on: [push, pull_request] env: @@ -58,15 +58,14 @@ jobs: make doxygen-doc 2>&1 | tee ./doxygen.log ! fgrep -rq warning ./doxygen.log - Build_x86_64: + Build: runs-on: ubuntu-18.04 - env: - ARCH: x86_64 strategy: fail-fast: false matrix: cc: [gcc, clang] - conf: ['', 'CFLAGS=-O3', 'CFLAGS=-O1', 'CFLAGS=-O0 --enable-debug=full', '--enable-lto', '--enable-lto --enable-abi-compat', '--enable-pcapng-support'] + conf: ['', 'CFLAGS=-O3', 'CFLAGS=-O1', 'CFLAGS=-O0 --enable-debug=full', '--enable-lto', + '--enable-lto --enable-abi-compat', '--enable-pcapng-support'] exclude: - cc: clang conf: '--enable-lto' @@ -135,8 +134,6 @@ jobs: Build_OS: runs-on: ubuntu-18.04 - env: - ARCH: x86_64 strategy: fail-fast: false matrix: @@ -151,7 +148,6 @@ jobs: Build_gcc-10: runs-on: ubuntu-18.04 env: - ARCH: x86_64 CC: gcc-10 OS: ubuntu_20.04 strategy: @@ -214,18 +210,19 @@ jobs: if: ${{ failure() }} run: find . -name "*.trs" | xargs grep -l '^.test-result. FAIL' | while read trs ; do echo FAILURE detected at $trs; cat ${trs%%.trs}.log ; done - Run_x86_64: + Run: runs-on: ubuntu-18.04 - env: - ARCH: x86_64 strategy: fail-fast: false matrix: cc: [gcc, clang] - conf: ['', '--enable-abi-compat', '--enable-deprecated', '--disable-static-applications', '--disable-host-optimization', '--disable-host-optimization --enable-abi-compat', '--without-openssl --without-pcap'] + conf: ['', '--enable-abi-compat', '--enable-deprecated --enable-debug=full', + '--disable-static-applications', + '--disable-host-optimization', '--disable-host-optimization --enable-abi-compat', + '--without-openssl --without-pcap'] steps: - uses: actions/checkout@v2 - - run: sudo docker run -i -v `pwd`:/odp --privileged --shm-size 8g -e CC="${{matrix.cc}}" + - run: sudo docker run -i -v `pwd`:/odp --privileged --shm-size 8g -e CC="${{matrix.cc}}" -e ARCH="${ARCH}" -e CXX=g++-10 -e CONF="${{matrix.conf}}" $CONTAINER_NAMESPACE/odp-ci-${OS}-${ARCH} /odp/scripts/ci/check.sh - name: Failure log if: ${{ failure() }} @@ -240,22 +237,18 @@ jobs: os: ['ubuntu_20.04'] steps: - uses: actions/checkout@v2 - - run: sudo docker run -i -v `pwd`:/odp --privileged --shm-size 8g -e CC="${{matrix.cc}}" + - run: sudo docker run -i -v `pwd`:/odp --privileged --shm-size 8g -e CC="${{matrix.cc}}" -e ARCH="${ARCH}" -e CONF="${CONF}" $CONTAINER_NAMESPACE/odp-ci-${{matrix.os}}-${ARCH} /odp/scripts/ci/check.sh - name: Failure log if: ${{ failure() }} run: find . -name "*.trs" | xargs grep -l '^.test-result. FAIL' | while read trs ; do echo FAILURE detected at $trs; cat ${trs%%.trs}.log ; done - Run_scheduler: + Run_scheduler_sp: runs-on: ubuntu-18.04 - strategy: - fail-fast: false - matrix: - scheduler: ['sp'] steps: - uses: actions/checkout@v2 - - run: sudo docker run -i -v `pwd`:/odp --privileged --shm-size 8g -e CC="${CC}" - -e CONF="${CONF}" -e ODP_SCHEDULER=${{matrix.scheduler}} $CONTAINER_NAMESPACE/odp-ci-${OS}-${ARCH} /odp/scripts/ci/check.sh + - run: sudo docker run -i -v `pwd`:/odp --privileged --shm-size 8g -e CC="${CC}" -e ARCH="${ARCH}" + -e CONF="${CONF}" -e ODP_SCHEDULER=sp $CONTAINER_NAMESPACE/odp-ci-${OS}-${ARCH} /odp/scripts/ci/check.sh - name: Failure log if: ${{ failure() }} run: find . -name "*.trs" | xargs grep -l '^.test-result. FAIL' | while read trs ; do echo FAILURE detected at $trs; cat ${trs%%.trs}.log ; done @@ -264,7 +257,7 @@ jobs: runs-on: ubuntu-18.04 steps: - uses: actions/checkout@v2 - - run: sudo docker run -i -v `pwd`:/odp --privileged --shm-size 8g -e CC="${CC}" + - run: sudo docker run -i -v `pwd`:/odp --privileged --shm-size 8g -e CC="${CC}" -e ARCH="${ARCH}" -e CONF="${CONF}" -e ODPH_PROC_MODE=1 $CONTAINER_NAMESPACE/odp-ci-${OS}-${ARCH} /odp/scripts/ci/check.sh - name: Failure log if: ${{ failure() }} @@ -274,7 +267,7 @@ jobs: runs-on: ubuntu-18.04 steps: - uses: actions/checkout@v2 - - run: sudo docker run -i -v `pwd`:/odp --privileged --shm-size 8g -e CC="${CC}" + - run: sudo docker run -i -v `pwd`:/odp --privileged --shm-size 8g -e CC="${CC}" -e ARCH="${ARCH}" -e CONF="${CONF}" $CONTAINER_NAMESPACE/odp-ci-${OS}-${ARCH}-dpdk_18.11 /odp/scripts/ci/check.sh - name: Failure log if: ${{ failure() }} @@ -287,7 +280,7 @@ jobs: OS: ubuntu_20.04 steps: - uses: actions/checkout@v2 - - run: sudo docker run -i -v `pwd`:/odp --privileged --shm-size 8g -e CC="${CC}" + - run: sudo docker run -i -v `pwd`:/odp --privileged --shm-size 8g -e CC="${CC}" -e ARCH="${ARCH}" -e CONF="${CONF}" $CONTAINER_NAMESPACE/odp-ci-${OS}-${ARCH}-dpdk_20.11 /odp/scripts/ci/check.sh - name: Failure log if: ${{ failure() }} diff --git a/.github/workflows/gh-pages.yml b/.github/workflows/gh-pages.yml index 0c5e187c4..e347efa6f 100644 --- a/.github/workflows/gh-pages.yml +++ b/.github/workflows/gh-pages.yml @@ -29,8 +29,6 @@ jobs: run: | pushd doc mkdir gh-pages - # Prevent Shippable run on gh-pages branch - printf "branches:\n except:\n - gh-pages\n" >> gh-pages/.shippable.yml cp -r application-api-guide/output/html/* gh-pages/ cp -r platform-api-guide/output/html/ gh-pages/platform-api-guide cp -r helper-guide/output/html/ gh-pages/helper-guide @@ -1,3 +1,47 @@ +== OpenDataPlane (1.30.0.0) +=== API +==== IPsec +* New success bytes field in stats (`odp_ipsec_stats_t.success_bytes`) + +==== Packet IO +* Specify explicitly that an application may enqueue to packet input side event +queues, and cannot dequeue from output side event queues + +==== Time +* Added time stamp read functions which read time stamp value more strictly +in the program order: `odp_time_local_strict()`, `odp_time_local_strict_ns()`, +`odp_time_global_strict()`, `odp_time_global_strict_ns()` + +==== Timer +* Added new default clock source enumeration `ODP_CLOCK_DEFAULT` +(=`ODP_CLOCK_SRC_0`) and support for multiple clock sources (`ODP_CLOCK_SRC_1`, +`ODP_CLOCK_SRC_2`...). The old `ODP_CLOCK_CPU` and `ODP_CLOCK_EXT` enumerations +will be deprecated in the future. +* Renamed set operation return codes (`odp_timer_set_t`) to better document +expiration time position to current time: +`ODP_TIMER_TOOEARLY` -> `ODP_TIMER_TOO_NEAR`, `ODP_TIMER_TOOLATE` -> +`ODP_TIMER_TOO_FAR` +* Renamed set operation failure code (`odp_timer_set_t`) to cover all error +cases: `ODP_TIMER_NOEVENT` -> `ODP_TIMER_FAIL` + +==== Traffic Manager +* Added option to enable packet mode shaper (packets per second as opposed to +bits per second) +* Added new mandatory `odp_tm_start()` and `odp_tm_stop()` calls for starting and +stopping traffic manager system +* Added capabilities (`odp_tm_capabilities_t`) for supported dynamic +configuration updates +* Deprecated shaper commit information rate bps +(`odp_tm_shaper_params_t.commit_bps`) and peak information rate bps +(`odp_tm_shaper_params_t.peak_bps`) fields. `odp_tm_shaper_params_t.commit_rate` +and `odp_tm_shaper_params_t.peak_rate` fields should be used instead. + +=== Helper (1.1.0) +* Added new mandatory `odph_cli_init()` and `odph_cli_term()` functions for +initializing and terminating the CLI helper +* Added `odph_cli_register_command()` function for registering user defined CLI +commands + == OpenDataPlane (1.29.0.0) === API ==== Packet IO diff --git a/config/odp-linux-dpdk.conf b/config/odp-linux-dpdk.conf index 0c541fdd5..cc63c1576 100644 --- a/config/odp-linux-dpdk.conf +++ b/config/odp-linux-dpdk.conf @@ -16,7 +16,7 @@ # Mandatory fields odp_implementation = "linux-dpdk" -config_file_version = "0.1.11" +config_file_version = "0.1.12" # System options system: { @@ -171,3 +171,52 @@ timer: { # accordingly. inline_poll_interval_nsec = 500000 } + +ipsec: { + # Packet ordering method for asynchronous IPsec processing + # + # Asynchronous IPsec processing maintains original packet order when + # started within ordered or atomic scheduling context. In addition + # to that, ODP API specifies that the order of IPsec processing + # (i.e. anti-replay window update and sequence number generation) + # is the same as the original packet order. + # + # The following settings control how the order is maintained in + # asynchronous IPsec operations. They have no effect on synchronous + # operations where the ODP application is responsible of the ordering. + # + # Values: + # + # 0: Ordering is not attempted. + # + # This has the lowest overhead and the greatest parallelism but + # is not fully compliant with the API specification. + # + # Lack of ordering means that outbound IPsec packets, although + # remaining in the correct order, may have their sequence numbers + # assigned out of order. This can cause unexpected packet loss if + # the anti-replay window of the receiving end is not large enough + # to cover the possible misordering. + # + # Similarly, since anti-replay check is not done in the reception + # order, the anti-replay check sees additional packet misordering + # on top of the true misordering of the received packets. This + # means that a larger anti-replay window may be required to avoid + # packet loss. + # + # 1: Ordering by waiting + # + # Correct processing order is maintained by a simple mechanism + # that makes a thread wait until its scheduling context has + # reached the head of its input queue. + # + # This limits parallelism when single input queue is used, even + # when packets get distributed to multiple SAs. + ordering: { + # Odering method for asynchronous inbound operations. + async_inbound = 0 + + # Odering method for asynchronous outbound operations. + async_outbound = 0 + } +} diff --git a/config/odp-linux-generic.conf b/config/odp-linux-generic.conf index 8469b72d7..3ac3e3e58 100644 --- a/config/odp-linux-generic.conf +++ b/config/odp-linux-generic.conf @@ -16,7 +16,7 @@ # Mandatory fields odp_implementation = "linux-generic" -config_file_version = "0.1.15" +config_file_version = "0.1.16" # System options system: { @@ -234,3 +234,52 @@ timer: { # 2: Only control threads process non-private timer pools inline_thread_type = 0 } + +ipsec: { + # Packet ordering method for asynchronous IPsec processing + # + # Asynchronous IPsec processing maintains original packet order when + # started within ordered or atomic scheduling context. In addition + # to that, ODP API specifies that the order of IPsec processing + # (i.e. anti-replay window update and sequence number generation) + # is the same as the original packet order. + # + # The following settings control how the order is maintained in + # asynchronous IPsec operations. They have no effect on synchronous + # operations where the ODP application is responsible of the ordering. + # + # Values: + # + # 0: Ordering is not attempted. + # + # This has the lowest overhead and the greatest parallelism but + # is not fully compliant with the API specification. + # + # Lack of ordering means that outbound IPsec packets, although + # remaining in the correct order, may have their sequence numbers + # assigned out of order. This can cause unexpected packet loss if + # the anti-replay window of the receiving end is not large enough + # to cover the possible misordering. + # + # Similarly, since anti-replay check is not done in the reception + # order, the anti-replay check sees additional packet misordering + # on top of the true misordering of the received packets. This + # means that a larger anti-replay window may be required to avoid + # packet loss. + # + # 1: Ordering by waiting + # + # Correct processing order is maintained by a simple mechanism + # that makes a thread wait until its scheduling context has + # reached the head of its input queue. + # + # This limits parallelism when single input queue is used, even + # when packets get distributed to multiple SAs. + ordering: { + # Odering method for asynchronous inbound operations. + async_inbound = 0 + + # Odering method for asynchronous outbound operations. + async_outbound = 0 + } +} diff --git a/configure.ac b/configure.ac index e84cb3297..1bc682712 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ AC_PREREQ([2.5]) # ODP API version ########################################################################## m4_define([odpapi_generation_version], [1]) -m4_define([odpapi_major_version], [29]) +m4_define([odpapi_major_version], [30]) m4_define([odpapi_minor_version], [0]) m4_define([odpapi_point_version], [0]) m4_define([odpapi_version], @@ -21,8 +21,8 @@ AC_SUBST(ODP_VERSION_API_MINOR) # Helper library version ########################################################################## m4_define([odph_version_generation], [1]) -m4_define([odph_version_major], [0]) -m4_define([odph_version_minor], [6]) +m4_define([odph_version_major], [1]) +m4_define([odph_version_minor], [0]) m4_define([odph_version], [odph_version_generation.odph_version_major.odph_version_minor]) diff --git a/example/cli/odp_cli.c b/example/cli/odp_cli.c index e3998129c..597d01812 100644 --- a/example/cli/odp_cli.c +++ b/example/cli/odp_cli.c @@ -88,6 +88,14 @@ static void sig_handler(int signo) shutdown_sig = 1; } +static void my_cmd(int argc, char *argv[]) +{ + odph_cli_log("%s(%d): %s\n", __FILE__, __LINE__, __func__); + + for (int i = 0; i < argc; i++) + odph_cli_log("argv[%d]: %s\n", i, argv[i]); +} + int main(int argc, char *argv[]) { signal(SIGINT, sig_handler); @@ -140,13 +148,27 @@ int main(int argc, char *argv[]) if (opt.port) cli_param.port = opt.port; + /* Initialize CLI helper. */ + if (odph_cli_init(inst, &cli_param)) { + ODPH_ERR("CLI helper initialization failed.\n"); + exit(EXIT_FAILURE); + } + + /* Register user command. */ + if (odph_cli_register_command("my_command", my_cmd, + "Example user command.")) { + ODPH_ERR("Registering user command failed.\n"); + exit(EXIT_FAILURE); + } + /* Start CLI server. */ - if (odph_cli_start(inst, &cli_param)) { + if (odph_cli_start()) { ODPH_ERR("CLI start failed.\n"); exit(EXIT_FAILURE); } - printf("CLI server started on %s:%d\n", cli_param.address, cli_param.port); + printf("CLI server started on %s:%d\n", cli_param.address, + cli_param.port); /* Wait for the given number of seconds. */ for (int i = 0; (opt.time < 0 || i < opt.time) && !shutdown_sig; i++) @@ -160,6 +182,12 @@ int main(int argc, char *argv[]) exit(EXIT_FAILURE); } + /* Terminate CLI helper. */ + if (odph_cli_term()) { + ODPH_ERR("CLI helper termination failed.\n"); + exit(EXIT_FAILURE); + } + /* Terminate ODP. */ if (odp_term_local()) { diff --git a/example/debug/odp_debug.c b/example/debug/odp_debug.c index 48591134a..24364a688 100644 --- a/example/debug/odp_debug.c +++ b/example/debug/odp_debug.c @@ -346,6 +346,7 @@ static int timer_debug(void) odp_pool_t pool; odp_pool_param_t pool_param; odp_timeout_t timeout; + odp_timer_res_capability_t timer_res_capa; odp_timer_capability_t timer_capa; odp_timer_pool_t timer_pool; odp_timer_pool_param_t timer_param; @@ -374,7 +375,7 @@ static int timer_debug(void) return -1; } - if (odp_timer_capability(ODP_CLOCK_CPU, &timer_capa)) { + if (odp_timer_capability(ODP_CLOCK_DEFAULT, &timer_capa)) { ODPH_ERR("Timer capa failed\n"); return -1; } @@ -382,15 +383,22 @@ static int timer_debug(void) if (timer_capa.max_tmo.max_tmo < max_tmo) max_tmo = timer_capa.max_tmo.max_tmo; - if (timer_capa.max_tmo.res_ns > res) - res = timer_capa.max_tmo.res_ns; + memset(&timer_res_capa, 0, sizeof(odp_timer_res_capability_t)); + timer_res_capa.max_tmo = max_tmo; + if (odp_timer_res_capability(ODP_CLOCK_DEFAULT, &timer_res_capa)) { + ODPH_ERR("Timer resolution capability failed\n"); + return -1; + } + + if (timer_res_capa.res_ns > res) + res = timer_res_capa.res_ns; memset(&timer_param, 0, sizeof(timer_param)); timer_param.res_ns = res; timer_param.min_tmo = max_tmo / 10; timer_param.max_tmo = max_tmo; timer_param.num_timers = 10; - timer_param.clk_src = ODP_CLOCK_CPU; + timer_param.clk_src = ODP_CLOCK_DEFAULT; timer_pool = odp_timer_pool_create("debug_timer", &timer_param); diff --git a/example/ipfragreass/odp_ipfragreass_reassemble.c b/example/ipfragreass/odp_ipfragreass_reassemble.c index 35742d3a5..fba900f7a 100644 --- a/example/ipfragreass/odp_ipfragreass_reassemble.c +++ b/example/ipfragreass/odp_ipfragreass_reassemble.c @@ -303,11 +303,17 @@ static int send_packet(struct packet *tail, odp_queue_t out) */ while (current && equal_flow(current, &result)) { struct packet new_result = *current; - int concat_success; + int concat_success, trunc_success; current = prev_packet(new_result); header = odp_packet_data(result.handle); - odp_packet_pull_head(result.handle, ipv4hdr_ihl(*header)); + trunc_success = odp_packet_trunc_head(&result.handle, ipv4hdr_ihl(*header), + NULL, NULL); + if (trunc_success < 0) { + fprintf(stderr, "ERROR: odp_packet_trunc_head\n"); + return -1; + } + concat_success = odp_packet_concat(&new_result.handle, result.handle); if (concat_success < 0) { diff --git a/example/ipsec_api/.gitignore b/example/ipsec_api/.gitignore index 78ef1173c..77f399c54 100644 --- a/example/ipsec_api/.gitignore +++ b/example/ipsec_api/.gitignore @@ -1 +1,2 @@ odp_ipsec_api +pktio_env diff --git a/example/ipsec_api/Makefile.am b/example/ipsec_api/Makefile.am index b3621fcd2..05471008d 100644 --- a/example/ipsec_api/Makefile.am +++ b/example/ipsec_api/Makefile.am @@ -2,18 +2,31 @@ include $(top_srcdir)/example/Makefile.inc bin_PROGRAMS = odp_ipsec_api -dist_check_SCRIPTS = \ - odp_ipsec_api_run_ah_in.sh \ - odp_ipsec_api_run_ah_out.sh \ - odp_ipsec_api_run_ah_tun_in.sh \ - odp_ipsec_api_run_ah_tun_out.sh \ - odp_ipsec_api_run_esp_in.sh \ - odp_ipsec_api_run_esp_out.sh \ - odp_ipsec_api_run_esp_tun_in.sh \ - odp_ipsec_api_run_esp_tun_out.sh \ - odp_ipsec_api_run_live.sh \ - odp_ipsec_api_run_router.sh \ - odp_ipsec_api_run_simple.sh +if test_example +TESTS = \ + odp_ipsec_api_run_ah_in.sh \ + odp_ipsec_api_run_ah_out.sh \ + odp_ipsec_api_run_ah_tun_in.sh \ + odp_ipsec_api_run_ah_tun_out.sh \ + odp_ipsec_api_run_esp_in.sh \ + odp_ipsec_api_run_esp_out.sh \ + odp_ipsec_api_run_esp_tun_in.sh \ + odp_ipsec_api_run_esp_tun_out.sh \ + odp_ipsec_api_run_simple.sh +endif + +EXTRA_DIST = \ + odp_ipsec_api_run_ah_in.sh \ + odp_ipsec_api_run_ah_out.sh \ + odp_ipsec_api_run_ah_tun_in.sh \ + odp_ipsec_api_run_ah_tun_out.sh \ + odp_ipsec_api_run_esp_in.sh \ + odp_ipsec_api_run_esp_out.sh \ + odp_ipsec_api_run_esp_tun_in.sh \ + odp_ipsec_api_run_esp_tun_out.sh \ + odp_ipsec_api_run_live.sh \ + odp_ipsec_api_run_router.sh \ + odp_ipsec_api_run_simple.sh odp_ipsec_api_SOURCES = \ odp_ipsec.c \ @@ -45,16 +58,17 @@ endif # So copy all script and data files explicitly here. all-local: if [ "x$(srcdir)" != "x$(builddir)" ]; then \ - for f in $(dist_check_SCRIPTS); do \ + for f in $(EXTRA_DIST); do \ if [ -e $(srcdir)/$$f ]; then \ mkdir -p $(builddir)/$$(dirname $$f); \ cp -f $(srcdir)/$$f $(builddir)/$$f; \ fi \ done \ fi + ln -f -s ../../platform/$(with_platform)/test/example/ipsec_api/pktio_env pktio_env clean-local: if [ "x$(srcdir)" != "x$(builddir)" ]; then \ - for f in $(dist_check_SCRIPTS); do \ + for f in $(EXTRA_DIST); do \ rm -f $(builddir)/$$f; \ done \ fi diff --git a/example/ipsec_api/odp_ipsec.c b/example/ipsec_api/odp_ipsec.c index 98e31d6ce..d23eeb2c6 100644 --- a/example/ipsec_api/odp_ipsec.c +++ b/example/ipsec_api/odp_ipsec.c @@ -640,11 +640,20 @@ pkt_disposition_e do_ipsec_in_classify(odp_packet_t *ppkt) return PKT_POSTED; } else { int out = 1; + odp_ipsec_packet_result_t result; rc = odp_ipsec_in(ppkt, 1, ppkt, &out, &in_param); if (rc <= 0) return PKT_DROP; + if (odp_ipsec_result(&result, *ppkt) < 0) { + ODPH_DBG("odp_ipsec_result() failed\n"); + return PKT_DROP; + } + if (result.status.error.all != 0) { + ODPH_DBG("Error in inbound IPsec processing\n"); + return PKT_DROP; + } return PKT_CONTINUE; } } @@ -704,11 +713,20 @@ pkt_disposition_e do_ipsec_out_classify(odp_packet_t *ppkt, pkt_ctx_t *ctx) return PKT_POSTED; } else { int out = 1; + odp_ipsec_packet_result_t result; rc = odp_ipsec_out(ppkt, 1, ppkt, &out, &out_param); if (rc <= 0) return PKT_DROP; + if (odp_ipsec_result(&result, *ppkt) < 0) { + ODPH_DBG("odp_ipsec_result() failed\n"); + return PKT_DROP; + } + if (result.status.error.all != 0) { + ODPH_DBG("Error in outbound IPsec processing\n"); + return PKT_DROP; + } return PKT_CONTINUE; } } diff --git a/example/ipsec_api/odp_ipsec_api_run_ah_in.sh b/example/ipsec_api/odp_ipsec_api_run_ah_in.sh index 22a56f380..3aa8ea577 100755 --- a/example/ipsec_api/odp_ipsec_api_run_ah_in.sh +++ b/example/ipsec_api/odp_ipsec_api_run_ah_in.sh @@ -4,9 +4,36 @@ # - 2 loop interfaces # - 10 packets # - Specify API mode on command line -./odp_ipsec_api -i loop1,loop2 \ --r 192.168.111.2/32,loop1,08:00:27:76:B5:E0 \ --p 192.168.222.0/24,192.168.111.0/24,in,ah \ --a 192.168.222.2,192.168.111.2,md5,300,27f6d123d7077b361662fc6e451f65d8 \ --s 192.168.222.2,192.168.111.2,loop2,loop1,10,100 \ --c 2 "$@" + +# IPSEC_APP_MODE: 0 - STANDALONE, 1 - LIVE, 2 - ROUTER +IPSEC_APP_MODE=0 + +if [ -f ./pktio_env ]; then + . ./pktio_env +else + echo "BUG: unable to find pktio_env!" + echo "pktio_env has to be in current directory" + exit 1 +fi + +setup_interfaces + +./odp_ipsec_api -i $IF_LIST \ + -r 192.168.111.2/32,$ROUTE_IF_INB,08:00:27:76:B5:E0 \ + -p 192.168.222.0/24,192.168.111.0/24,in,ah \ + -a 192.168.222.2,192.168.111.2,md5,300,27f6d123d7077b361662fc6e451f65d8 \ + -s 192.168.222.2,192.168.111.2,$OUT_IF,$IN_IF,10,100 \ + -c 2 "$@" + +STATUS=$? + +if [ ${STATUS} -ne 0 ]; then + echo "Error: status ${STATUS}" + exit 1 +fi + +validate_result + +cleanup_interfaces + +exit 0 diff --git a/example/ipsec_api/odp_ipsec_api_run_ah_out.sh b/example/ipsec_api/odp_ipsec_api_run_ah_out.sh index 8194485a4..2712da52a 100755 --- a/example/ipsec_api/odp_ipsec_api_run_ah_out.sh +++ b/example/ipsec_api/odp_ipsec_api_run_ah_out.sh @@ -4,9 +4,36 @@ # - 2 loop interfaces # - 10 packets # - Specify API mode on command line -./odp_ipsec_api -i loop1,loop2 \ --r 192.168.222.2/32,loop2,08:00:27:F5:8B:DB \ --p 192.168.111.0/24,192.168.222.0/24,out,ah \ --a 192.168.111.2,192.168.222.2,md5,200,a731649644c5dee92cbd9c2e7e188ee6 \ --s 192.168.111.2,192.168.222.2,loop1,loop2,10,100 \ --c 2 "$@" + +# IPSEC_APP_MODE: 0 - STANDALONE, 1 - LIVE, 2 - ROUTER +IPSEC_APP_MODE=0 + +if [ -f ./pktio_env ]; then + . ./pktio_env +else + echo "BUG: unable to find pktio_env!" + echo "pktio_env has to be in current directory" + exit 1 +fi + +setup_interfaces + +./odp_ipsec_api -i $IF_LIST \ + -r 192.168.222.2/32,$ROUTE_IF_OUTB,08:00:27:F5:8B:DB \ + -p 192.168.111.0/24,192.168.222.0/24,out,ah \ + -a 192.168.111.2,192.168.222.2,md5,200,a731649644c5dee92cbd9c2e7e188ee6 \ + -s 192.168.111.2,192.168.222.2,$IN_IF,$OUT_IF,10,100 \ + -c 2 "$@" + +STATUS=$? + +if [ ${STATUS} -ne 0 ]; then + echo "Error: status ${STATUS}" + exit 1 +fi + +validate_result + +cleanup_interfaces + +exit 0 diff --git a/example/ipsec_api/odp_ipsec_api_run_ah_tun_in.sh b/example/ipsec_api/odp_ipsec_api_run_ah_tun_in.sh index 89331bbea..f6efc3869 100755 --- a/example/ipsec_api/odp_ipsec_api_run_ah_tun_in.sh +++ b/example/ipsec_api/odp_ipsec_api_run_ah_tun_in.sh @@ -4,10 +4,37 @@ # - 2 loop interfaces # - 10 packets # - Specify API mode on command line -./odp_ipsec_api -i loop1,loop2 \ --r 192.168.111.2/32,loop1,08:00:27:76:B5:E0 \ --p 192.168.222.0/24,192.168.111.0/24,in,ah \ --a 192.168.222.2,192.168.111.2,md5,300,27f6d123d7077b361662fc6e451f65d8 \ --t 192.168.222.2,192.168.111.2,10.0.222.2,10.0.111.2 \ --s 192.168.222.2,192.168.111.2,loop2,loop1,10,100 \ --c 2 "$@" + +# IPSEC_APP_MODE: 0 - STANDALONE, 1 - LIVE, 2 - ROUTER +IPSEC_APP_MODE=0 + +if [ -f ./pktio_env ]; then + . ./pktio_env +else + echo "BUG: unable to find pktio_env!" + echo "pktio_env has to be in current directory" + exit 1 +fi + +setup_interfaces + +./odp_ipsec_api -i $IF_LIST \ + -r 192.168.111.2/32,$ROUTE_IF_INB,08:00:27:76:B5:E0 \ + -p 192.168.222.0/24,192.168.111.0/24,in,ah \ + -a 192.168.222.2,192.168.111.2,md5,300,27f6d123d7077b361662fc6e451f65d8 \ + -t 192.168.222.2,192.168.111.2,10.0.222.2,10.0.111.2 \ + -s 192.168.222.2,192.168.111.2,$OUT_IF,$IN_IF,10,100 \ + -c 2 "$@" + +STATUS=$? + +if [ ${STATUS} -ne 0 ]; then + echo "Error: status ${STATUS}" + exit 1 +fi + +validate_result + +cleanup_interfaces + +exit 0 diff --git a/example/ipsec_api/odp_ipsec_api_run_ah_tun_out.sh b/example/ipsec_api/odp_ipsec_api_run_ah_tun_out.sh index bd15f5956..ec888d314 100755 --- a/example/ipsec_api/odp_ipsec_api_run_ah_tun_out.sh +++ b/example/ipsec_api/odp_ipsec_api_run_ah_tun_out.sh @@ -4,10 +4,37 @@ # - 2 loop interfaces # - 10 packets # - Specify API mode on command line -./odp_ipsec_api -i loop1,loop2 \ --r 192.168.222.2/32,loop2,08:00:27:F5:8B:DB \ --p 192.168.111.0/24,192.168.222.0/24,out,ah \ --a 192.168.111.2,192.168.222.2,md5,200,a731649644c5dee92cbd9c2e7e188ee6 \ --t 192.168.111.2,192.168.222.2,10.0.111.2,10.0.222.2 \ --s 192.168.111.2,192.168.222.2,loop1,loop2,10,100 \ --c 2 "$@" + +# IPSEC_APP_MODE: 0 - STANDALONE, 1 - LIVE, 2 - ROUTER +IPSEC_APP_MODE=0 + +if [ -f ./pktio_env ]; then + . ./pktio_env +else + echo "BUG: unable to find pktio_env!" + echo "pktio_env has to be in current directory" + exit 1 +fi + +setup_interfaces + +./odp_ipsec_api -i $IF_LIST \ + -r 192.168.222.2/32,$ROUTE_IF_OUTB,08:00:27:F5:8B:DB \ + -p 192.168.111.0/24,192.168.222.0/24,out,ah \ + -a 192.168.111.2,192.168.222.2,md5,200,a731649644c5dee92cbd9c2e7e188ee6 \ + -t 192.168.111.2,192.168.222.2,10.0.111.2,10.0.222.2 \ + -s 192.168.111.2,192.168.222.2,$IN_IF,$OUT_IF,10,100 \ + -c 2 "$@" + +STATUS=$? + +if [ ${STATUS} -ne 0 ]; then + echo "Error: status ${STATUS}" + exit 1 +fi + +validate_result + +cleanup_interfaces + +exit 0 diff --git a/example/ipsec_api/odp_ipsec_api_run_esp_in.sh b/example/ipsec_api/odp_ipsec_api_run_esp_in.sh index 61873bf76..1c3414498 100755 --- a/example/ipsec_api/odp_ipsec_api_run_esp_in.sh +++ b/example/ipsec_api/odp_ipsec_api_run_esp_in.sh @@ -4,10 +4,36 @@ # - 2 loop interfaces # - 10 packets # - Specify API mode on command line -./odp_ipsec_api -i loop1,loop2 \ --r 192.168.111.2/32,loop1,08:00:27:76:B5:E0 \ --p 192.168.222.0/24,192.168.111.0/24,in,esp \ --e 192.168.222.2,192.168.111.2,\ -3des,301,c966199f24d095f3990a320d749056401e82b26570320292 \ --s 192.168.222.2,192.168.111.2,loop2,loop1,10,100 \ --c 2 "$@" + +# IPSEC_APP_MODE: 0 - STANDALONE, 1 - LIVE, 2 - ROUTER +IPSEC_APP_MODE=0 + +if [ -f ./pktio_env ]; then + . ./pktio_env +else + echo "BUG: unable to find pktio_env!" + echo "pktio_env has to be in current directory" + exit 1 +fi + +setup_interfaces + +./odp_ipsec_api -i $IF_LIST \ + -r 192.168.111.2/32,$ROUTE_IF_INB,08:00:27:76:B5:E0 \ + -p 192.168.222.0/24,192.168.111.0/24,in,esp \ + -e 192.168.222.2,192.168.111.2,3des,301,c966199f24d095f3990a320d749056401e82b26570320292 \ + -s 192.168.222.2,192.168.111.2,$OUT_IF,$IN_IF,10,100 \ + -c 2 "$@" + +STATUS=$? + +if [ ${STATUS} -ne 0 ]; then + echo "Error: status ${STATUS}" + exit 1 +fi + +validate_result + +cleanup_interfaces + +exit 0 diff --git a/example/ipsec_api/odp_ipsec_api_run_esp_out.sh b/example/ipsec_api/odp_ipsec_api_run_esp_out.sh index 834daa4cc..c9809e8ac 100755 --- a/example/ipsec_api/odp_ipsec_api_run_esp_out.sh +++ b/example/ipsec_api/odp_ipsec_api_run_esp_out.sh @@ -5,14 +5,39 @@ # - 10 packets # - Specify API mode on command line +# IPSEC_APP_MODE: 0 - STANDALONE, 1 - LIVE, 2 - ROUTER +IPSEC_APP_MODE=0 + +if [ -f ./pktio_env ]; then + . ./pktio_env +else + echo "BUG: unable to find pktio_env!" + echo "pktio_env has to be in current directory" + exit 1 +fi + +setup_interfaces + if [ -z "$IPSEC_EXAMPLE_PATH" ]; then IPSEC_EXAMPLE_PATH=. fi -${IPSEC_EXAMPLE_PATH}/odp_ipsec_api -i loop1,loop2 \ --r 192.168.222.2/32,loop2,08:00:27:F5:8B:DB \ --p 192.168.111.0/24,192.168.222.0/24,out,esp \ --e 192.168.111.2,192.168.222.2,\ -3des,201,656c8523255ccc23a66c1917aa0cf30991fce83532a4b224 \ --s 192.168.111.2,192.168.222.2,loop1,loop2,10,100 \ --c 2 "$@" +${IPSEC_EXAMPLE_PATH}/odp_ipsec_api -i $IF_LIST \ + -r 192.168.222.2/32,$ROUTE_IF_OUTB,08:00:27:F5:8B:DB \ + -p 192.168.111.0/24,192.168.222.0/24,out,esp \ + -e 192.168.111.2,192.168.222.2,3des,201,656c8523255ccc23a66c1917aa0cf30991fce83532a4b224 \ + -s 192.168.111.2,192.168.222.2,$IN_IF,$OUT_IF,10,100 \ + -c 2 "$@" + +STATUS=$? + +if [ ${STATUS} -ne 0 ]; then + echo "Error: status ${STATUS}" + exit 1 +fi + +validate_result + +cleanup_interfaces + +exit 0 diff --git a/example/ipsec_api/odp_ipsec_api_run_esp_tun_in.sh b/example/ipsec_api/odp_ipsec_api_run_esp_tun_in.sh index 42be4559f..3b4f91e41 100755 --- a/example/ipsec_api/odp_ipsec_api_run_esp_tun_in.sh +++ b/example/ipsec_api/odp_ipsec_api_run_esp_tun_in.sh @@ -4,11 +4,37 @@ # - 2 loop interfaces # - 10 packets # - Specify API mode on command line -./odp_ipsec_api -i loop1,loop2 \ --r 192.168.111.2/32,loop1,08:00:27:76:B5:E0 \ --p 192.168.222.0/24,192.168.111.0/24,in,esp \ --e 192.168.222.2,192.168.111.2,\ -3des,301,c966199f24d095f3990a320d749056401e82b26570320292 \ --t 192.168.222.2,192.168.111.2,10.0.222.2,10.0.111.2 \ --s 192.168.222.2,192.168.111.2,loop2,loop1,10,100 \ --c 2 "$@" + +# IPSEC_APP_MODE: 0 - STANDALONE, 1 - LIVE, 2 - ROUTER +IPSEC_APP_MODE=0 + +if [ -f ./pktio_env ]; then + . ./pktio_env +else + echo "BUG: unable to find pktio_env!" + echo "pktio_env has to be in current directory" + exit 1 +fi + +setup_interfaces + +./odp_ipsec_api -i $IF_LIST \ + -r 192.168.111.2/32,$ROUTE_IF_INB,08:00:27:76:B5:E0 \ + -p 192.168.222.0/24,192.168.111.0/24,in,esp \ + -e 192.168.222.2,192.168.111.2,3des,301,c966199f24d095f3990a320d749056401e82b26570320292 \ + -t 192.168.222.2,192.168.111.2,10.0.222.2,10.0.111.2 \ + -s 192.168.222.2,192.168.111.2,$OUT_IF,$IN_IF,10,100 \ + -c 2 "$@" + +STATUS=$? + +if [ ${STATUS} -ne 0 ]; then + echo "Error: status ${STATUS}" + exit 1 +fi + +validate_result + +cleanup_interfaces + +exit 0 diff --git a/example/ipsec_api/odp_ipsec_api_run_esp_tun_out.sh b/example/ipsec_api/odp_ipsec_api_run_esp_tun_out.sh index 7b0c42bcb..a4c62e226 100755 --- a/example/ipsec_api/odp_ipsec_api_run_esp_tun_out.sh +++ b/example/ipsec_api/odp_ipsec_api_run_esp_tun_out.sh @@ -4,10 +4,36 @@ # - 2 loop interfaces # - 10 packets # - Specify API mode on command line -./odp_ipsec_api -i loop1,loop2 \ --r 192.168.222.2/32,loop2,08:00:27:F5:8B:DB \ --p 192.168.111.0/24,192.168.222.0/24,out,esp \ --e 192.168.111.2,192.168.222.2,\ -3des,201,656c8523255ccc23a66c1917aa0cf30991fce83532a4b224 \ --s 192.168.111.2,192.168.222.2,loop1,loop2,10,100 \ --c 2 "$@" + +# IPSEC_APP_MODE: 0 - STANDALONE, 1 - LIVE, 2 - ROUTER +IPSEC_APP_MODE=0 + +if [ -f ./pktio_env ]; then + . ./pktio_env +else + echo "BUG: unable to find pktio_env!" + echo "pktio_env has to be in current directory" + exit 1 +fi + +setup_interfaces + +./odp_ipsec_api -i $IF_LIST \ + -r 192.168.222.2/32,$ROUTE_IF_OUTB,08:00:27:F5:8B:DB \ + -p 192.168.111.0/24,192.168.222.0/24,out,esp \ + -e 192.168.111.2,192.168.222.2,3des,201,656c8523255ccc23a66c1917aa0cf30991fce83532a4b224 \ + -s 192.168.111.2,192.168.222.2,$IN_IF,$OUT_IF,10,100 \ + -c 2 "$@" + +STATUS=$? + +if [ ${STATUS} -ne 0 ]; then + echo "Error: status ${STATUS}" + exit 1 +fi + +validate_result + +cleanup_interfaces + +exit 0 diff --git a/example/ipsec_api/odp_ipsec_api_run_live.sh b/example/ipsec_api/odp_ipsec_api_run_live.sh index 318e640fe..da8523485 100755 --- a/example/ipsec_api/odp_ipsec_api_run_live.sh +++ b/example/ipsec_api/odp_ipsec_api_run_live.sh @@ -3,13 +3,59 @@ # Live router test # - 2 interfaces interfaces # - Specify API mode on command line -sudo ./odp_ipsec_api -i p7p1,p8p1 \ --r 192.168.111.2/32,p7p1,08:00:27:76:B5:E0 \ --r 192.168.222.2/32,p8p1,08:00:27:F5:8B:DB \ --p 192.168.111.0/24,192.168.222.0/24,out,esp \ --e 192.168.111.2,192.168.222.2,\ -3des,201,656c8523255ccc23a66c1917aa0cf30991fce83532a4b224 \ --p 192.168.222.0/24,192.168.111.0/24,in,esp \ --e 192.168.222.2,192.168.111.2,\ -3des,301,c966199f24d095f3990a320d749056401e82b26570320292 \ --c 2 "$@" + +# IPSEC_APP_MODE: 0 - STANDALONE, 1 - LIVE, 2 - ROUTER +IPSEC_APP_MODE=1 + +if [ -f ./pktio_env ]; then + . ./pktio_env +else + echo "BUG: unable to find pktio_env!" + echo "pktio_env has to be in current directory" + exit 1 +fi + +setup_interfaces + +# this just turns off output buffering so that you still get periodic +# output while piping to tee, as long as stdbuf is available. +STDBUF="`which stdbuf 2>/dev/null` -o 0" || STDBUF= +LOG=odp_ipsec_api_tmp.log +PID=app_pid + +($STDBUF \ + ./odp_ipsec_api -i $IF0,$IF1 \ + -r 192.168.111.2/32,$IF0,$NEXT_HOP_MAC0 \ + -r 192.168.222.2/32,$IF1,$NEXT_HOP_MAC1 \ + -p 192.168.111.0/24,192.168.222.0/24,out,esp \ + -e 192.168.111.2,192.168.222.2,3des,201,656c8523255ccc23a66c1917aa0cf30991fce83532a4b224 \ + -p 192.168.222.0/24,192.168.111.0/24,in,esp \ + -e 192.168.222.2,192.168.111.2,3des,301,c966199f24d095f3990a320d749056401e82b26570320292 \ + -c 2 "$@" & echo $! > $PID) | tee $LOG & + +APP_PID=`cat $PID` + +# Wait till application thread starts. +APP_READY="Pktio thread \[..\] starts" + +until [ -f $LOG ] +do + sleep 1 +done + +tail -f $LOG | grep -qm 1 "$APP_READY" + +validate_result +ret=$? + +kill -2 ${APP_PID} + +# Wait till the application exits +tail --pid=$APP_PID -f /dev/null + +rm -f $PID +rm -f $LOG + +cleanup_interfaces + +exit $ret diff --git a/example/ipsec_api/odp_ipsec_api_run_router.sh b/example/ipsec_api/odp_ipsec_api_run_router.sh index 2cdbd2272..79a0ef5c6 100755 --- a/example/ipsec_api/odp_ipsec_api_run_router.sh +++ b/example/ipsec_api/odp_ipsec_api_run_router.sh @@ -3,7 +3,55 @@ # Live router test # - 2 interfaces interfaces # - Specify API mode on command line -sudo ./odp_ipsec_api -i p7p1,p8p1 \ --r 192.168.111.2/32,p7p1,08:00:27:76:B5:E0 \ --r 192.168.222.2/32,p8p1,08:00:27:F5:8B:DB \ --c 1 "$@" + +# IPSEC_APP_MODE: 0 - STANDALONE, 1 - LIVE, 2 - ROUTER +IPSEC_APP_MODE=2 + +if [ -f ./pktio_env ]; then + . ./pktio_env +else + echo "BUG: unable to find pktio_env!" + echo "pktio_env has to be in current directory" + exit 1 +fi + +setup_interfaces + +# this just turns off output buffering so that you still get periodic +# output while piping to tee, as long as stdbuf is available. +STDBUF="`which stdbuf 2>/dev/null` -o 0" || STDBUF= +LOG=odp_ipsec_api_tmp.log +PID=app_pid + +($STDBUF \ + ./odp_ipsec_api -i $IF0,$IF1 \ + -r 192.168.111.2/32,$IF0,$NEXT_HOP_MAC0 \ + -r 192.168.222.2/32,$IF1,$NEXT_HOP_MAC1 \ + -c 1 "$@" & echo $! > $PID) | tee -a $LOG & + +APP_PID=`cat $PID` + +# Wait till application thread starts. +APP_READY="Pktio thread \[..\] starts" + +until [ -f $LOG ] +do + sleep 1 +done + +tail -f $LOG | grep -qm 1 "$APP_READY" + +validate_result +ret=$? + +kill -2 ${APP_PID} + +# Wait till the application stops +tail --pid=$APP_PID -f /dev/null + +rm -f $PID +rm -f $LOG + +cleanup_interfaces + +exit $ret diff --git a/example/ipsec_api/odp_ipsec_api_run_simple.sh b/example/ipsec_api/odp_ipsec_api_run_simple.sh index 56c022291..2921f978b 100755 --- a/example/ipsec_api/odp_ipsec_api_run_simple.sh +++ b/example/ipsec_api/odp_ipsec_api_run_simple.sh @@ -5,11 +5,37 @@ # - 10 packets # - Specify API mode on command line +# IPSEC_APP_MODE: 0 - STANDALONE, 1 - LIVE, 2 - ROUTER +IPSEC_APP_MODE=0 + +if [ -f ./pktio_env ]; then + . ./pktio_env +else + echo "BUG: unable to find pktio_env!" + echo "pktio_env has to be in current directory" + exit 1 +fi + +setup_interfaces + if [ -z "$IPSEC_EXAMPLE_PATH" ]; then IPSEC_EXAMPLE_PATH=. fi -${IPSEC_EXAMPLE_PATH}/odp_ipsec_api -i loop1,loop2 \ --r 192.168.222.2/32,loop2,08:00:27:F5:8B:DB \ --s 192.168.111.2,192.168.222.2,loop1,loop2,10,100 \ --c 2 "$@" +${IPSEC_EXAMPLE_PATH}/odp_ipsec_api -i $IF_LIST \ + -r 192.168.222.2/32,$ROUTE_IF_OUTB,08:00:27:F5:8B:DB \ + -s 192.168.111.2,192.168.222.2,$IN_IF,$OUT_IF,10,100 \ + -c 2 "$@" + +STATUS=$? + +if [ ${STATUS} -ne 0 ]; then + echo "Error: status ${STATUS}" + exit 1 +fi + +validate_result + +cleanup_interfaces + +exit 0 diff --git a/example/ipsec_crypto/.gitignore b/example/ipsec_crypto/.gitignore index 2467edfd4..e8b9e69a1 100644 --- a/example/ipsec_crypto/.gitignore +++ b/example/ipsec_crypto/.gitignore @@ -1 +1,2 @@ odp_ipsec_crypto +pktio_env diff --git a/example/ipsec_crypto/Makefile.am b/example/ipsec_crypto/Makefile.am index 2e3652252..1db0d72d0 100644 --- a/example/ipsec_crypto/Makefile.am +++ b/example/ipsec_crypto/Makefile.am @@ -2,16 +2,28 @@ include $(top_srcdir)/example/Makefile.inc bin_PROGRAMS = odp_ipsec_crypto -dist_check_SCRIPTS = \ - odp_ipsec_crypto_run_ah_in.sh \ - odp_ipsec_crypto_run_ah_out.sh \ - odp_ipsec_crypto_run_both_in.sh \ - odp_ipsec_crypto_run_both_out.sh \ - odp_ipsec_crypto_run_esp_in.sh \ - odp_ipsec_crypto_run_esp_out.sh \ - odp_ipsec_crypto_run_live.sh \ - odp_ipsec_crypto_run_router.sh \ - odp_ipsec_crypto_run_simple.sh +if test_example +TESTS = \ + odp_ipsec_crypto_run_ah_in.sh \ + odp_ipsec_crypto_run_ah_out.sh \ + odp_ipsec_crypto_run_both_in.sh \ + odp_ipsec_crypto_run_both_out.sh \ + odp_ipsec_crypto_run_esp_in.sh \ + odp_ipsec_crypto_run_esp_out.sh \ + odp_ipsec_crypto_run_live.sh \ + odp_ipsec_crypto_run_router.sh \ + odp_ipsec_crypto_run_simple.sh +endif +EXTRA_DIST = \ + odp_ipsec_crypto_run_ah_in.sh \ + odp_ipsec_crypto_run_ah_out.sh \ + odp_ipsec_crypto_run_both_in.sh \ + odp_ipsec_crypto_run_both_out.sh \ + odp_ipsec_crypto_run_esp_in.sh \ + odp_ipsec_crypto_run_esp_out.sh \ + odp_ipsec_crypto_run_live.sh \ + odp_ipsec_crypto_run_router.sh \ + odp_ipsec_crypto_run_simple.sh odp_ipsec_crypto_SOURCES = \ odp_ipsec.c \ @@ -43,16 +55,18 @@ endif # So copy all script and data files explicitly here. all-local: if [ "x$(srcdir)" != "x$(builddir)" ]; then \ - for f in $(dist_check_SCRIPTS); do \ + for f in $(EXTRA_DIST); do \ if [ -e $(srcdir)/$$f ]; then \ mkdir -p $(builddir)/$$(dirname $$f); \ cp -f $(srcdir)/$$f $(builddir)/$$f; \ fi \ done \ fi + ln -f -s ../../platform/$(with_platform)/test/example/ipsec_crypto/pktio_env pktio_env clean-local: if [ "x$(srcdir)" != "x$(builddir)" ]; then \ - for f in $(dist_check_SCRIPTS); do \ + for f in $(EXTRA_DIST); do \ rm -f $(builddir)/$$f; \ done \ fi + rm -f pktio_env diff --git a/example/ipsec_crypto/odp_ipsec_crypto_run_ah_in.sh b/example/ipsec_crypto/odp_ipsec_crypto_run_ah_in.sh index b64fd7d2d..0c8112306 100755 --- a/example/ipsec_crypto/odp_ipsec_crypto_run_ah_in.sh +++ b/example/ipsec_crypto/odp_ipsec_crypto_run_ah_in.sh @@ -4,9 +4,40 @@ # - 2 loop interfaces # - 10 packets # - Specify API mode on command line -./odp_ipsec_crypto -i loop1,loop2 \ --r 192.168.111.2/32,loop1,08:00:27:76:B5:E0 \ --p 192.168.222.0/24,192.168.111.0/24,in,ah \ --a 192.168.222.2,192.168.111.2,md5,300,27f6d123d7077b361662fc6e451f65d8 \ --s 192.168.222.2,192.168.111.2,loop2,loop1,10,100 \ --c 2 -m $1 + +# IPSEC_APP_MODE: 0 - STANDALONE, 1 - LIVE, 2 - ROUTER +IPSEC_APP_MODE=0 + +if [ -f ./pktio_env ]; then + . ./pktio_env +else + echo "BUG: unable to find pktio_env!" + echo "pktio_env has to be in current directory" + exit 1 +fi + +setup_interfaces + +if [ -z "$IPSEC_EXAMPLE_PATH" ]; then +IPSEC_EXAMPLE_PATH=. +fi + +${IPSEC_EXAMPLE_PATH}/odp_ipsec_crypto -i $IF_LIST \ + -r 192.168.111.2/32,$ROUTE_IF_INB,08:00:27:76:B5:E0 \ + -p 192.168.222.0/24,192.168.111.0/24,in,ah \ + -a 192.168.222.2,192.168.111.2,md5,300,27f6d123d7077b361662fc6e451f65d8 \ + -s 192.168.222.2,192.168.111.2,$OUT_IF,$IN_IF,10,100 \ + -c 2 "$@" + +STATUS=$? + +if [ ${STATUS} -ne 0 ]; then + echo "Error: status ${STATUS}" + exit 1 +fi + +validate_result + +cleanup_interfaces + +exit 0 diff --git a/example/ipsec_crypto/odp_ipsec_crypto_run_ah_out.sh b/example/ipsec_crypto/odp_ipsec_crypto_run_ah_out.sh index 0ff42289c..b0bb210f5 100755 --- a/example/ipsec_crypto/odp_ipsec_crypto_run_ah_out.sh +++ b/example/ipsec_crypto/odp_ipsec_crypto_run_ah_out.sh @@ -4,9 +4,40 @@ # - 2 loop interfaces # - 10 packets # - Specify API mode on command line -./odp_ipsec_crypto -i loop1,loop2 \ --r 192.168.222.2/32,loop2,08:00:27:F5:8B:DB \ --p 192.168.111.0/24,192.168.222.0/24,out,ah \ --a 192.168.111.2,192.168.222.2,md5,200,a731649644c5dee92cbd9c2e7e188ee6 \ --s 192.168.111.2,192.168.222.2,loop1,loop2,10,100 \ --c 2 -m $1 + +# IPSEC_APP_MODE: 0 - STANDALONE, 1 - LIVE, 2 - ROUTER +IPSEC_APP_MODE=0 + +if [ -f ./pktio_env ]; then + . ./pktio_env +else + echo "BUG: unable to find pktio_env!" + echo "pktio_env has to be in current directory" + exit 1 +fi + +setup_interfaces + +if [ -z "$IPSEC_EXAMPLE_PATH" ]; then +IPSEC_EXAMPLE_PATH=. +fi + +${IPSEC_EXAMPLE_PATH}/odp_ipsec_crypto -i $IF_LIST \ + -r 192.168.222.2/32,$ROUTE_IF_OUTB,08:00:27:F5:8B:DB \ + -p 192.168.111.0/24,192.168.222.0/24,out,ah \ + -a 192.168.111.2,192.168.222.2,md5,200,a731649644c5dee92cbd9c2e7e188ee6 \ + -s 192.168.111.2,192.168.222.2,$IN_IF,$OUT_IF,10,100 \ + -c 2 "$@" + +STATUS=$? + +if [ ${STATUS} -ne 0 ]; then + echo "Error: status ${STATUS}" + exit 1 +fi + +validate_result + +cleanup_interfaces + +exit 0 diff --git a/example/ipsec_crypto/odp_ipsec_crypto_run_both_in.sh b/example/ipsec_crypto/odp_ipsec_crypto_run_both_in.sh index a986b713e..4b8c6ab63 100755 --- a/example/ipsec_crypto/odp_ipsec_crypto_run_both_in.sh +++ b/example/ipsec_crypto/odp_ipsec_crypto_run_both_in.sh @@ -4,11 +4,41 @@ # - 2 loop interfaces # - 10 packets # - Specify API mode on command line -./odp_ipsec_crypto -i loop1,loop2 \ --r 192.168.111.2/32,loop1,08:00:27:76:B5:E0 \ --p 192.168.222.0/24,192.168.111.0/24,in,both \ --a 192.168.222.2,192.168.111.2,md5,300,27f6d123d7077b361662fc6e451f65d8 \ --e 192.168.222.2,192.168.111.2,\ -3des,301,c966199f24d095f3990a320d749056401e82b26570320292 \ --s 192.168.222.2,192.168.111.2,loop2,loop1,10,100 \ --c 2 -m $1 + +# IPSEC_APP_MODE: 0 - STANDALONE, 1 - LIVE, 2 - ROUTER +IPSEC_APP_MODE=0 + +if [ -f ./pktio_env ]; then + . ./pktio_env +else + echo "BUG: unable to find pktio_env!" + echo "pktio_env has to be in current directory" + exit 1 +fi + +setup_interfaces + +if [ -z "$IPSEC_EXAMPLE_PATH" ]; then +IPSEC_EXAMPLE_PATH=. +fi + +${IPSEC_EXAMPLE_PATH}/odp_ipsec_crypto -i $IF_LIST \ + -r 192.168.111.2/32,$ROUTE_IF_INB,08:00:27:76:B5:E0 \ + -p 192.168.222.0/24,192.168.111.0/24,in,both \ + -a 192.168.222.2,192.168.111.2,md5,300,27f6d123d7077b361662fc6e451f65d8 \ + -e 192.168.222.2,192.168.111.2,3des,301,c966199f24d095f3990a320d749056401e82b26570320292 \ + -s 192.168.222.2,192.168.111.2,$OUT_IF,$IN_IF,10,100 \ + -c 2 "$@" + +STATUS=$? + +if [ ${STATUS} -ne 0 ]; then + echo "Error: status ${STATUS}" + exit 1 +fi + +validate_result + +cleanup_interfaces + +exit 0 diff --git a/example/ipsec_crypto/odp_ipsec_crypto_run_both_out.sh b/example/ipsec_crypto/odp_ipsec_crypto_run_both_out.sh index ebbcde071..665534d98 100755 --- a/example/ipsec_crypto/odp_ipsec_crypto_run_both_out.sh +++ b/example/ipsec_crypto/odp_ipsec_crypto_run_both_out.sh @@ -4,11 +4,41 @@ # - 2 loop interfaces # - 10 packets # - Specify API mode on command line -./odp_ipsec_crypto -i loop1,loop2 \ --r 192.168.222.2/32,loop2,08:00:27:F5:8B:DB \ --p 192.168.111.0/24,192.168.222.0/24,out,both \ --e 192.168.111.2,192.168.222.2,\ -3des,201,656c8523255ccc23a66c1917aa0cf30991fce83532a4b224 \ --a 192.168.111.2,192.168.222.2,md5,200,a731649644c5dee92cbd9c2e7e188ee6 \ --s 192.168.111.2,192.168.222.2,loop1,loop2,10,100 \ --c 2 -m $1 + +# IPSEC_APP_MODE: 0 - STANDALONE, 1 - LIVE, 2 - ROUTER +IPSEC_APP_MODE=0 + +if [ -f ./pktio_env ]; then + . ./pktio_env +else + echo "BUG: unable to find pktio_env!" + echo "pktio_env has to be in current directory" + exit 1 +fi + +setup_interfaces + +if [ -z "$IPSEC_EXAMPLE_PATH" ]; then +IPSEC_EXAMPLE_PATH=. +fi + +${IPSEC_EXAMPLE_PATH}/odp_ipsec_crypto -i $IF_LIST \ + -r 192.168.222.2/32,$ROUTE_IF_OUTB,08:00:27:F5:8B:DB \ + -p 192.168.111.0/24,192.168.222.0/24,out,both \ + -e 192.168.111.2,192.168.222.2,3des,201,656c8523255ccc23a66c1917aa0cf30991fce83532a4b224 \ + -a 192.168.111.2,192.168.222.2,md5,200,a731649644c5dee92cbd9c2e7e188ee6 \ + -s 192.168.111.2,192.168.222.2,$IN_IF,$OUT_IF,10,100 \ + -c 2 "$@" + +STATUS=$? + +if [ ${STATUS} -ne 0 ]; then + echo "Error: status ${STATUS}" + exit 1 +fi + +validate_result + +cleanup_interfaces + +exit 0 diff --git a/example/ipsec_crypto/odp_ipsec_crypto_run_esp_in.sh b/example/ipsec_crypto/odp_ipsec_crypto_run_esp_in.sh index cdf84c517..6e6ff5769 100755 --- a/example/ipsec_crypto/odp_ipsec_crypto_run_esp_in.sh +++ b/example/ipsec_crypto/odp_ipsec_crypto_run_esp_in.sh @@ -4,10 +4,40 @@ # - 2 loop interfaces # - 10 packets # - Specify API mode on command line -./odp_ipsec_crypto -i loop1,loop2 \ --r 192.168.111.2/32,loop1,08:00:27:76:B5:E0 \ --p 192.168.222.0/24,192.168.111.0/24,in,esp \ --e 192.168.222.2,192.168.111.2,\ -3des,301,c966199f24d095f3990a320d749056401e82b26570320292 \ --s 192.168.222.2,192.168.111.2,loop2,loop1,10,100 \ --c 2 -m $1 + +# IPSEC_APP_MODE: 0 - STANDALONE, 1 - LIVE, 2 - ROUTER +IPSEC_APP_MODE=0 + +if [ -f ./pktio_env ]; then + . ./pktio_env +else + echo "BUG: unable to find pktio_env!" + echo "pktio_env has to be in current directory" + exit 1 +fi + +setup_interfaces + +if [ -z "$IPSEC_EXAMPLE_PATH" ]; then +IPSEC_EXAMPLE_PATH=. +fi + +${IPSEC_EXAMPLE_PATH}/odp_ipsec_crypto -i $IF_LIST \ + -r 192.168.111.2/32,$ROUTE_IF_INB,08:00:27:76:B5:E0 \ + -p 192.168.222.0/24,192.168.111.0/24,in,esp \ + -e 192.168.222.2,192.168.111.2,3des,301,c966199f24d095f3990a320d749056401e82b26570320292 \ + -s 192.168.222.2,192.168.111.2,$OUT_IF,$IN_IF,10,100 \ + -c 2 "$@" + +STATUS=$? + +if [ ${STATUS} -ne 0 ]; then + echo "Error: status ${STATUS}" + exit 1 +fi + +validate_result + +cleanup_interfaces + +exit 0 diff --git a/example/ipsec_crypto/odp_ipsec_crypto_run_esp_out.sh b/example/ipsec_crypto/odp_ipsec_crypto_run_esp_out.sh index ae257be4f..2b7107f80 100755 --- a/example/ipsec_crypto/odp_ipsec_crypto_run_esp_out.sh +++ b/example/ipsec_crypto/odp_ipsec_crypto_run_esp_out.sh @@ -5,14 +5,39 @@ # - 10 packets # - Specify API mode on command line +# IPSEC_APP_MODE: 0 - STANDALONE, 1 - LIVE, 2 - ROUTER +IPSEC_APP_MODE=0 + +if [ -f ./pktio_env ]; then + . ./pktio_env +else + echo "BUG: unable to find pktio_env!" + echo "pktio_env has to be in current directory" + exit 1 +fi + +setup_interfaces + if [ -z "$IPSEC_EXAMPLE_PATH" ]; then IPSEC_EXAMPLE_PATH=. fi -${IPSEC_EXAMPLE_PATH}/odp_ipsec_crypto -i loop1,loop2 \ --r 192.168.222.2/32,loop2,08:00:27:F5:8B:DB \ --p 192.168.111.0/24,192.168.222.0/24,out,esp \ --e 192.168.111.2,192.168.222.2,\ -3des,201,656c8523255ccc23a66c1917aa0cf30991fce83532a4b224 \ --s 192.168.111.2,192.168.222.2,loop1,loop2,10,100 \ --c 2 "$@" +${IPSEC_EXAMPLE_PATH}/odp_ipsec_crypto -i $IF_LIST \ + -r 192.168.222.2/32,$ROUTE_IF_OUTB,08:00:27:F5:8B:DB \ + -p 192.168.111.0/24,192.168.222.0/24,out,esp \ + -e 192.168.111.2,192.168.222.2,3des,201,656c8523255ccc23a66c1917aa0cf30991fce83532a4b224 \ + -s 192.168.111.2,192.168.222.2,$IN_IF,$OUT_IF,10,100 \ + -c 2 "$@" + +STATUS=$? + +if [ ${STATUS} -ne 0 ]; then + echo "Error: status ${STATUS}" + exit 1 +fi + +validate_result + +cleanup_interfaces + +exit 0 diff --git a/example/ipsec_crypto/odp_ipsec_crypto_run_live.sh b/example/ipsec_crypto/odp_ipsec_crypto_run_live.sh index c212097e0..90dda11ec 100755 --- a/example/ipsec_crypto/odp_ipsec_crypto_run_live.sh +++ b/example/ipsec_crypto/odp_ipsec_crypto_run_live.sh @@ -3,15 +3,63 @@ # Live router test # - 2 interfaces interfaces # - Specify API mode on command line -sudo ./odp_ipsec_crypto -i p7p1,p8p1 \ --r 192.168.111.2/32,p7p1,08:00:27:76:B5:E0 \ --r 192.168.222.2/32,p8p1,08:00:27:F5:8B:DB \ --p 192.168.111.0/24,192.168.222.0/24,out,both \ --e 192.168.111.2,192.168.222.2,\ -3des,201,656c8523255ccc23a66c1917aa0cf30991fce83532a4b224 \ --a 192.168.111.2,192.168.222.2,md5,200,a731649644c5dee92cbd9c2e7e188ee6 \ --p 192.168.222.0/24,192.168.111.0/24,in,both \ --e 192.168.222.2,192.168.111.2,\ -3des,301,c966199f24d095f3990a320d749056401e82b26570320292 \ --a 192.168.222.2,192.168.111.2,md5,300,27f6d123d7077b361662fc6e451f65d8 \ --c 2 -m $1 + +# IPSEC_APP_MODE: 0 - STANDALONE, 1 - LIVE, 2 - ROUTER +IPSEC_APP_MODE=1 + +if [ -f ./pktio_env ]; then + . ./pktio_env +else + echo "BUG: unable to find pktio_env!" + echo "pktio_env has to be in current directory" + exit 1 +fi + +setup_interfaces + +# this just turns off output buffering so that you still get periodic +# output while piping to tee, as long as stdbuf is available. +STDBUF="`which stdbuf 2>/dev/null` -o 0" || STDBUF= +LOG=odp_ipsec_crypto_tmp.log +PID=app_pid + +($STDBUF \ + ./odp_ipsec_crypto -i $IF0,$IF1 \ + -r 192.168.111.2/32,$IF0,$NEXT_HOP_MAC0 \ + -r 192.168.222.2/32,$IF1,$NEXT_HOP_MAC1 \ + -p 192.168.111.0/24,192.168.222.0/24,out,both \ + -e 192.168.111.2,192.168.222.2,\ + 3des,201,656c8523255ccc23a66c1917aa0cf30991fce83532a4b224 \ + -a 192.168.111.2,192.168.222.2,md5,200,a731649644c5dee92cbd9c2e7e188ee6 \ + -p 192.168.222.0/24,192.168.111.0/24,in,both \ + -e 192.168.222.2,192.168.111.2,\ + 3des,301,c966199f24d095f3990a320d749056401e82b26570320292 \ + -a 192.168.222.2,192.168.111.2,md5,300,27f6d123d7077b361662fc6e451f65d8 \ + -c 2 "$@" & echo $! > $PID) | tee -a $LOG & + +APP_PID=`cat $PID` + +# Wait till application thread starts. +APP_READY="Pktio thread \[..\] starts" + +until [ -f $LOG ] +do + sleep 1 +done + +tail -f $LOG | grep -qm 1 "$APP_READY" + +validate_result +ret=$? + +kill -2 ${APP_PID} + +# Wait till the application exits +tail --pid=$APP_PID -f /dev/null + +rm -f $PID +rm -f $LOG + +cleanup_interfaces + +exit $ret diff --git a/example/ipsec_crypto/odp_ipsec_crypto_run_router.sh b/example/ipsec_crypto/odp_ipsec_crypto_run_router.sh index d08490946..675027b59 100755 --- a/example/ipsec_crypto/odp_ipsec_crypto_run_router.sh +++ b/example/ipsec_crypto/odp_ipsec_crypto_run_router.sh @@ -3,7 +3,55 @@ # Live router test # - 2 interfaces interfaces # - Specify API mode on command line -sudo ./odp_ipsec_crypto -i p7p1,p8p1 \ --r 192.168.111.2/32,p7p1,08:00:27:76:B5:E0 \ --r 192.168.222.2/32,p8p1,08:00:27:F5:8B:DB \ --c 1 -m $1 + +# IPSEC_APP_MODE: 0 - STANDALONE, 1 - LIVE, 2 - ROUTER +IPSEC_APP_MODE=2 + +if [ -f ./pktio_env ]; then + . ./pktio_env +else + echo "BUG: unable to find pktio_env!" + echo "pktio_env has to be in current directory" + exit 1 +fi + +setup_interfaces + +# this just turns off output buffering so that you still get periodic +# output while piping to tee, as long as stdbuf is available. +STDBUF="`which stdbuf 2>/dev/null` -o 0" || STDBUF= +LOG=odp_ipsec_crypto_tmp.log +PID=app_pid + +($STDBUF \ + ./odp_ipsec_crypto -i $IF0,$IF1 \ + -r 192.168.111.2/32,$IF0,$NEXT_HOP_MAC0 \ + -r 192.168.222.2/32,$IF1,$NEXT_HOP_MAC1 \ + -c 1 "$@" & echo $! > $PID) | tee -a $LOG & + +APP_PID=`cat $PID` + +# Wait till application thread starts. +APP_READY="Pktio thread \[..\] starts" + +until [ -f $LOG ] +do + sleep 1 +done + +tail -f $LOG | grep -qm 1 "$APP_READY" + +validate_result +ret=$? + +kill -2 ${APP_PID} + +# Wait till the application exits +tail --pid=$APP_PID -f /dev/null + +rm -f $PID +rm -f $LOG + +cleanup_interfaces + +exit $ret diff --git a/example/ipsec_crypto/odp_ipsec_crypto_run_simple.sh b/example/ipsec_crypto/odp_ipsec_crypto_run_simple.sh index 5d3abcd51..00b176b36 100755 --- a/example/ipsec_crypto/odp_ipsec_crypto_run_simple.sh +++ b/example/ipsec_crypto/odp_ipsec_crypto_run_simple.sh @@ -5,11 +5,37 @@ # - 10 packets # - Specify API mode on command line +# IPSEC_APP_MODE: 0 - STANDALONE, 1 - LIVE, 2 - ROUTER +IPSEC_APP_MODE=0 + +if [ -f ./pktio_env ]; then + . ./pktio_env +else + echo "BUG: unable to find pktio_env!" + echo "pktio_env has to be in current directory" + exit 1 +fi + +setup_interfaces + if [ -z "$IPSEC_EXAMPLE_PATH" ]; then IPSEC_EXAMPLE_PATH=. fi -${IPSEC_EXAMPLE_PATH}/odp_ipsec_crypto -i loop1,loop2 \ --r 192.168.222.2/32,loop2,08:00:27:F5:8B:DB \ --s 192.168.111.2,192.168.222.2,loop1,loop2,10,100 \ --c 2 "$@" +${IPSEC_EXAMPLE_PATH}/odp_ipsec_crypto -i $IF_LIST \ + -r 192.168.222.2/32,$ROUTE_IF_OUTB,08:00:27:F5:8B:DB \ + -s 192.168.111.2,192.168.222.2,$IN_IF,$OUT_IF,10,100 \ + -c 2 "$@" + +STATUS=$? + +if [ ${STATUS} -ne 0 ]; then + echo "Error: status ${STATUS}" + exit 1 +fi + +validate_result + +cleanup_interfaces + +exit 0 diff --git a/example/ipsec_crypto/odp_ipsec_stream.c b/example/ipsec_crypto/odp_ipsec_stream.c index e53dbce0d..0ca5138bc 100644 --- a/example/ipsec_crypto/odp_ipsec_stream.c +++ b/example/ipsec_crypto/odp_ipsec_stream.c @@ -272,6 +272,10 @@ odp_packet_t create_ipv4_packet(stream_db_entry_t *stream, inner_ip = (odph_ipv4hdr_t *)data; memset((char *)inner_ip, 0, sizeof(*inner_ip)); inner_ip->ver_ihl = 0x45; + inner_ip->tot_len = odp_cpu_to_be_16(sizeof(odph_ipv4hdr_t) + + sizeof(odph_icmphdr_t) + + sizeof(stream_pkt_hdr_t) + + stream->length); inner_ip->proto = ODPH_IPPROTO_ICMPV4; inner_ip->id = odp_cpu_to_be_16(stream->id); inner_ip->ttl = 64; @@ -322,8 +326,8 @@ odp_packet_t create_ipv4_packet(stream_db_entry_t *stream, encrypt_len = ESP_ENCODE_LEN(payload_len + sizeof(*esp_t), entry->esp.block_len); - memset(data, 0, encrypt_len - payload_len); - data += encrypt_len - payload_len; + for (int n = 0; n < encrypt_len - payload_len; n++) + *data++ = n + 1; esp_t = (odph_esptrl_t *)(data) - 1; esp_t->pad_len = encrypt_len - payload_len - sizeof(*esp_t); diff --git a/example/sysinfo/odp_sysinfo.c b/example/sysinfo/odp_sysinfo.c index cad87b121..9e4ed4147 100644 --- a/example/sysinfo/odp_sysinfo.c +++ b/example/sysinfo/odp_sysinfo.c @@ -408,7 +408,7 @@ int main(void) return -1; } - if (odp_timer_capability(ODP_CLOCK_CPU, &timer_capa)) { + if (odp_timer_capability(ODP_CLOCK_DEFAULT, &timer_capa)) { printf("timer capability failed\n"); return -1; } diff --git a/example/timer/odp_timer_accuracy.c b/example/timer/odp_timer_accuracy.c index cafe362a7..df1fd5919 100644 --- a/example/timer/odp_timer_accuracy.c +++ b/example/timer/odp_timer_accuracy.c @@ -37,7 +37,7 @@ typedef struct { uint64_t num_exact; uint64_t num_after; - uint64_t num_tooearly; + uint64_t num_too_near; } test_stat_t; @@ -103,11 +103,11 @@ static void print_usage(void) " 1: Set first burst of timers at init. Restart timers during test with absolute time.\n" " 2: Set first burst of timers at init. Restart timers during test with relative time.\n" " -o, --output <file> Output file for measurement logs\n" - " -e, --early_retry <num> When timer restart fails due to ODP_TIMER_TOOEARLY, retry this many times\n" + " -e, --early_retry <num> When timer restart fails due to ODP_TIMER_TOO_NEAR, retry this many times\n" " with expiration time incremented by the period. Default: 0\n" " -s, --clk_src Clock source select (default 0):\n" - " 0: ODP_CLOCK_CPU\n" - " 1: ODP_CLOCK_EXT\n" + " 0: ODP_CLOCK_DEFAULT\n" + " 1: ODP_CLOCK_SRC_1, ...\n" " -i, --init Set global init parameters. Default: init params not set.\n" " -h, --help Display help and exit.\n\n"); } @@ -144,7 +144,7 @@ static int parse_options(int argc, char *argv[], test_global_t *test_global) test_global->opt.burst = 1; test_global->opt.burst_gap = 0; test_global->opt.mode = 0; - test_global->opt.clk_src = 0; + test_global->opt.clk_src = ODP_CLOCK_DEFAULT; test_global->opt.init = 0; test_global->opt.output = 0; test_global->opt.early_retry = 0; @@ -289,11 +289,7 @@ static int start_timers(test_global_t *test_global) } test_global->timeout_pool = pool; - - if (test_global->opt.clk_src == 0) - clk_src = ODP_CLOCK_CPU; - else - clk_src = ODP_CLOCK_EXT; + clk_src = test_global->opt.clk_src; if (odp_timer_capability(clk_src, &timer_capa)) { printf("Timer capa failed\n"); @@ -565,7 +561,7 @@ static void print_stat(test_global_t *test_global) printf(" num exact: %12" PRIu64 " / %.2f%%\n", stat->num_exact, 100.0 * stat->num_exact / tot_timers); printf(" num retry: %12" PRIu64 " / %.2f%%\n", - stat->num_tooearly, 100.0 * stat->num_tooearly / tot_timers); + stat->num_too_near, 100.0 * stat->num_too_near / tot_timers); printf(" error after (nsec):\n"); printf(" min: %12" PRIu64 " / %.3fx resolution\n", stat->nsec_after_min, (double)stat->nsec_after_min / res_ns); @@ -674,8 +670,8 @@ static void run_test(test_global_t *test_global) ret = odp_timer_set_rel(tim, tick, &ev); } - if (ret == ODP_TIMER_TOOEARLY) - stat->num_tooearly++; + if (ret == ODP_TIMER_TOO_NEAR) + stat->num_too_near++; else break; } diff --git a/example/timer/odp_timer_simple.c b/example/timer/odp_timer_simple.c index 683d6ff8d..4e28807c6 100644 --- a/example/timer/odp_timer_simple.c +++ b/example/timer/odp_timer_simple.c @@ -65,7 +65,7 @@ int main(int argc ODP_UNUSED, char *argv[] ODP_UNUSED) /* * Create pool of timeouts */ - if (odp_timer_capability(ODP_CLOCK_CPU, &timer_capa)) { + if (odp_timer_capability(ODP_CLOCK_DEFAULT, &timer_capa)) { ret += 1; goto err_tp; } @@ -76,7 +76,7 @@ int main(int argc ODP_UNUSED, char *argv[] ODP_UNUSED) tparams.max_tmo = 1 * ODP_TIME_SEC_IN_NS; tparams.num_timers = 1; /* One timer per worker */ tparams.priv = 0; /* Shared */ - tparams.clk_src = ODP_CLOCK_CPU; + tparams.clk_src = ODP_CLOCK_DEFAULT; timer_pool = odp_timer_pool_create("timer_pool", &tparams); if (timer_pool == ODP_TIMER_POOL_INVALID) { ret += 1; diff --git a/example/timer/odp_timer_test.c b/example/timer/odp_timer_test.c index ddb2ccfd5..8bfb99d8f 100644 --- a/example/timer/odp_timer_test.c +++ b/example/timer/odp_timer_test.c @@ -56,12 +56,12 @@ static const char *timerset2str(odp_timer_set_t val) switch (val) { case ODP_TIMER_SUCCESS: return "success"; - case ODP_TIMER_TOOEARLY: - return "too early"; - case ODP_TIMER_TOOLATE: - return "too late"; - case ODP_TIMER_NOEVENT: - return "no event"; + case ODP_TIMER_TOO_NEAR: + return "too near"; + case ODP_TIMER_TOO_FAR: + return "too far"; + case ODP_TIMER_FAIL: + return "failure"; default: return "?"; } @@ -273,7 +273,7 @@ static int parse_args(int argc, char *argv[], test_args_t *args) static const char *shortopts = "+c:r:m:x:p:t:h"; /* defaults */ - if (odp_timer_capability(ODP_CLOCK_CPU, &timer_capa)) + if (odp_timer_capability(ODP_CLOCK_DEFAULT, &timer_capa)) return -1; args->cpu_count = 1; @@ -444,7 +444,7 @@ int main(int argc, char *argv[]) tparams.max_tmo = gbls->args.max_us * ODP_TIME_USEC_IN_NS; tparams.num_timers = num_workers; /* One timer per worker */ tparams.priv = 0; /* Shared */ - tparams.clk_src = ODP_CLOCK_CPU; + tparams.clk_src = ODP_CLOCK_DEFAULT; gbls->tp = odp_timer_pool_create("timer_pool", &tparams); if (gbls->tp == ODP_TIMER_POOL_INVALID) { err = 1; diff --git a/example/traffic_mgmt/odp_traffic_mgmt.c b/example/traffic_mgmt/odp_traffic_mgmt.c index fba494853..521338785 100644 --- a/example/traffic_mgmt/odp_traffic_mgmt.c +++ b/example/traffic_mgmt/odp_traffic_mgmt.c @@ -62,8 +62,8 @@ static const odp_init_t ODP_INIT_PARAMS = { static profile_params_set_t COMPANY_PROFILE_PARAMS = { .shaper_params = { - .commit_bps = 50 * MBPS, .commit_burst = 1000000, - .peak_bps = 0, .peak_burst = 0, + .commit_rate = 50 * MBPS, .commit_burst = 1000000, + .peak_rate = 0, .peak_burst = 0, .dual_rate = FALSE, .shaper_len_adjust = 20 }, @@ -95,8 +95,8 @@ static profile_params_set_t COMPANY_PROFILE_PARAMS = { static profile_params_set_t COS0_PROFILE_PARAMS = { .shaper_params = { - .commit_bps = 1 * MBPS, .commit_burst = 100000, - .peak_bps = 4 * MBPS, .peak_burst = 200000, + .commit_rate = 1 * MBPS, .commit_burst = 100000, + .peak_rate = 4 * MBPS, .peak_burst = 200000, .dual_rate = FALSE, .shaper_len_adjust = 20 }, @@ -128,8 +128,8 @@ static profile_params_set_t COS0_PROFILE_PARAMS = { static profile_params_set_t COS1_PROFILE_PARAMS = { .shaper_params = { - .commit_bps = 500 * KBPS, .commit_burst = 50000, - .peak_bps = 1500 * KBPS, .peak_burst = 150000, + .commit_rate = 500 * KBPS, .commit_burst = 50000, + .peak_rate = 1500 * KBPS, .peak_burst = 150000, .dual_rate = FALSE, .shaper_len_adjust = 20 }, @@ -161,8 +161,8 @@ static profile_params_set_t COS1_PROFILE_PARAMS = { static profile_params_set_t COS2_PROFILE_PARAMS = { .shaper_params = { - .commit_bps = 200 * KBPS, .commit_burst = 20000, - .peak_bps = 400 * KBPS, .peak_burst = 40000, + .commit_rate = 200 * KBPS, .commit_burst = 20000, + .peak_rate = 400 * KBPS, .peak_burst = 40000, .dual_rate = FALSE, .shaper_len_adjust = 20 }, @@ -194,8 +194,8 @@ static profile_params_set_t COS2_PROFILE_PARAMS = { static profile_params_set_t COS3_PROFILE_PARAMS = { .shaper_params = { - .commit_bps = 100 * KBPS, .commit_burst = 5000, - .peak_bps = 0, .peak_burst = 0, + .commit_rate = 100 * KBPS, .commit_burst = 5000, + .peak_rate = 0, .peak_burst = 0, .dual_rate = FALSE, .shaper_len_adjust = 20 }, @@ -272,8 +272,8 @@ static uint32_t create_profile_set(profile_params_set_t *profile_params_set, odp_tm_shaper_params_init(&shaper_params); shaper = &profile_params_set->shaper_params; - shaper_params.commit_bps = shaper->commit_bps * shaper_scale; - shaper_params.peak_bps = shaper->peak_bps * shaper_scale; + shaper_params.commit_rate = shaper->commit_rate * shaper_scale; + shaper_params.peak_rate = shaper->peak_rate * shaper_scale; shaper_params.commit_burst = shaper->commit_burst * shaper_scale; shaper_params.peak_burst = shaper->peak_burst * shaper_scale; shaper_params.dual_rate = shaper->dual_rate; @@ -826,6 +826,13 @@ int main(int argc, char *argv[]) create_and_config_tm(); + /* Start TM */ + rc = odp_tm_start(odp_tm_test); + if (rc != 0) { + printf("Error: odp_tm_start() failed, rc=%d\n", rc); + return -1; + } + odp_random_data(random_buf, RANDOM_BUF_LEN, 1); next_rand_byte = 0; @@ -841,6 +848,13 @@ int main(int argc, char *argv[]) odp_tm_stats_print(odp_tm_test); + /* Stop TM */ + rc = odp_tm_stop(odp_tm_test); + if (rc != 0) { + printf("Error: odp_tm_stop() failed, rc = %d\n", rc); + return -1; + } + rc = destroy_tm_queues(); if (rc != 0) { printf("Error: destroy_tm_queues() failed, rc = %d\n", rc); diff --git a/helper/cli.c b/helper/cli.c index dd4b5fe4f..ebc5b01e1 100644 --- a/helper/cli.c +++ b/helper/cli.c @@ -16,6 +16,7 @@ #include <errno.h> #include <poll.h> #include <stdio.h> +#include <strings.h> /* Socketpair socket roles. */ enum { @@ -23,6 +24,15 @@ enum { SP_WRITE = 1, }; +#define MAX_NAME_LEN 20 +#define MAX_HELP_LEN 100 + +typedef struct { + odph_cli_user_cmd_func_t fn; + char name[MAX_NAME_LEN]; + char help[MAX_HELP_LEN]; +} user_cmd_t; + typedef struct { volatile int cli_fd; /* Server thread will exit if this is false. */ @@ -30,9 +40,15 @@ typedef struct { /* Socketpair descriptors. */ int sp[2]; int listen_fd; - /* This lock guards cli_fd and run, which must be accessed atomically. */ + /* Guards cli_fd and run, which must be accessed atomically. */ odp_spinlock_t lock; + odp_spinlock_t api_lock; odph_thread_t thr_server; + odp_instance_t instance; + struct sockaddr_in addr; + uint32_t max_user_commands; + uint32_t num_user_commands; + user_cmd_t user_cmd[0]; } cli_shm_t; static const char *shm_name = "_odp_cli"; @@ -40,6 +56,7 @@ static const char *shm_name = "_odp_cli"; static const odph_cli_param_t param_default = { .address = "127.0.0.1", .port = 55555, + .max_user_commands = 50, }; void odph_cli_param_init(odph_cli_param_t *param) @@ -47,28 +64,114 @@ void odph_cli_param_init(odph_cli_param_t *param) *param = param_default; } -static int cmd_show_cpu(struct cli_def *cli, const char *command ODP_UNUSED, - char *argv[] ODP_UNUSED, int argc ODP_UNUSED) +static cli_shm_t *shm_lookup(void) +{ + cli_shm_t *shm = NULL; + odp_shm_t shm_hdl = odp_shm_lookup(shm_name); + + if (shm_hdl != ODP_SHM_INVALID) + shm = (cli_shm_t *)odp_shm_addr(shm_hdl); + + return shm; +} + +int odph_cli_init(odp_instance_t instance, const odph_cli_param_t *param) { - for (int c = 0; c < odp_cpu_count(); c++) { - cli_print(cli, "% 4d: %s %.03f / %.03f GHz", c, - odp_cpu_model_str_id(c), - (float)odp_cpu_hz_id(c) / 1000000000.0, - (float)odp_cpu_hz_max_id(c) / 1000000000.0); + if (odp_shm_lookup(shm_name) != ODP_SHM_INVALID) { + ODPH_ERR("Error: shm %s already exists\n", shm_name); + return -1; } - return CLI_OK; + cli_shm_t *shm = NULL; + int shm_size = sizeof(cli_shm_t) + + param->max_user_commands * sizeof(user_cmd_t); + odp_shm_t shm_hdl = + odp_shm_reserve(shm_name, shm_size, 64, ODP_SHM_SW_ONLY); + + if (shm_hdl != ODP_SHM_INVALID) + shm = (cli_shm_t *)odp_shm_addr(shm_hdl); + + if (!shm) { + ODPH_ERR("Error: failed to reserve shm %s\n", shm_name); + return -1; + } + + memset(shm, 0, shm_size); + odp_spinlock_init(&shm->lock); + odp_spinlock_init(&shm->api_lock); + shm->sp[SP_READ] = -1; + shm->sp[SP_WRITE] = -1; + shm->listen_fd = -1; + shm->cli_fd = -1; + shm->instance = instance; + + shm->addr.sin_family = AF_INET; + shm->addr.sin_port = htons(param->port); + + switch (inet_pton(AF_INET, param->address, &shm->addr.sin_addr)) { + case -1: + ODPH_ERR("Error: inet_pton(): %s\n", strerror(errno)); + return -1; + case 0: + ODPH_ERR("Error: inet_pton(): illegal address format\n"); + return -1; + default: + break; + } + + shm->max_user_commands = param->max_user_commands; + + return 0; } -static int cmd_show_version(struct cli_def *cli, const char *command ODP_UNUSED, - char *argv[] ODP_UNUSED, int argc ODP_UNUSED) +int odph_cli_register_command(const char *name, odph_cli_user_cmd_func_t func, + const char *help) { - cli_print(cli, "ODP API version: %s", odp_version_api_str()); - cli_print(cli, "ODP implementation name: %s", odp_version_impl_name()); - cli_print(cli, "ODP implementation version: %s", - odp_version_impl_str()); + cli_shm_t *shm = shm_lookup(); - return CLI_OK; + if (!shm) { + ODPH_ERR("Error: shm %s not found\n", shm_name); + return -1; + } + + odp_spinlock_lock(&shm->api_lock); + + odp_spinlock_lock(&shm->lock); + if (shm->run) { + odp_spinlock_unlock(&shm->lock); + ODPH_ERR("Error: cannot register commands while cli server is running\n"); + goto error; + } + odp_spinlock_unlock(&shm->lock); + + if (shm->num_user_commands >= shm->max_user_commands) { + ODPH_ERR("Error: maximum number of user commands already registered\n"); + goto error; + } + + user_cmd_t *cmd = &shm->user_cmd[shm->num_user_commands]; + + cmd->fn = func; + + if (strlen(name) >= MAX_NAME_LEN - 1) { + ODPH_ERR("Error: command name too long\n"); + goto error; + } + strcpy(cmd->name, name); + + if (strlen(help) >= MAX_HELP_LEN - 1) { + ODPH_ERR("Error: command help too long\n"); + goto error; + } + strcpy(cmd->help, help); + + shm->num_user_commands++; + odp_spinlock_unlock(&shm->api_lock); + return 0; + +error: + odp_spinlock_unlock(&shm->api_lock); + return -1; } /* @@ -91,6 +194,18 @@ static int check_num_args(struct cli_def *cli, int argc, int req_argc) return 0; } +static int cmd_call_odp_cls_print_all(struct cli_def *cli, + const char *command ODP_UNUSED, + char *argv[] ODP_UNUSED, int argc) +{ + if (check_num_args(cli, argc, 0)) + return CLI_ERROR; + + odp_cls_print_all(); + + return CLI_OK; +} + static int cmd_call_odp_ipsec_print(struct cli_def *cli, const char *command ODP_UNUSED, char *argv[] ODP_UNUSED, int argc) @@ -196,6 +311,18 @@ static int cmd_call_odp_queue_print(struct cli_def *cli, return CLI_OK; } +static int cmd_call_odp_queue_print_all(struct cli_def *cli, + const char *command ODP_UNUSED, + char *argv[] ODP_UNUSED, int argc) +{ + if (check_num_args(cli, argc, 0)) + return CLI_ERROR; + + odp_queue_print_all(); + + return CLI_OK; +} + static int cmd_call_odp_shm_print(struct cli_def *cli, const char *command ODP_UNUSED, char *argv[], int argc) @@ -215,7 +342,27 @@ static int cmd_call_odp_shm_print(struct cli_def *cli, return CLI_OK; } -static struct cli_def *create_cli(void) +static int cmd_user_cmd(struct cli_def *cli ODP_UNUSED, const char *command, + char *argv[], int argc) +{ + cli_shm_t *shm = shm_lookup(); + + if (!shm) { + ODPH_ERR("Error: shm %s not found\n", shm_name); + return CLI_ERROR; + } + + for (uint32_t i = 0; i < shm->num_user_commands; i++) { + if (!strcasecmp(command, shm->user_cmd[i].name)) { + shm->user_cmd[i].fn(argc, argv); + break; + } + } + + return CLI_OK; +} + +static struct cli_def *create_cli(cli_shm_t *shm) { struct cli_command *c; struct cli_def *cli; @@ -224,19 +371,12 @@ static struct cli_def *create_cli(void) cli_set_banner(cli, NULL); cli_set_hostname(cli, "ODP"); - c = cli_register_command(cli, NULL, "show", NULL, - PRIVILEGE_UNPRIVILEGED, MODE_EXEC, - "Show information."); - cli_register_command(cli, c, "cpu", cmd_show_cpu, - PRIVILEGE_UNPRIVILEGED, MODE_EXEC, - "Show CPU information."); - cli_register_command(cli, c, "version", cmd_show_version, - PRIVILEGE_UNPRIVILEGED, MODE_EXEC, - "Show version information."); - c = cli_register_command(cli, NULL, "call", NULL, PRIVILEGE_UNPRIVILEGED, MODE_EXEC, "Call ODP API function."); + cli_register_command(cli, c, "odp_cls_print_all", + cmd_call_odp_cls_print_all, + PRIVILEGE_UNPRIVILEGED, MODE_EXEC, NULL); cli_register_command(cli, c, "odp_ipsec_print", cmd_call_odp_ipsec_print, PRIVILEGE_UNPRIVILEGED, MODE_EXEC, NULL); @@ -249,6 +389,9 @@ static struct cli_def *create_cli(void) cli_register_command(cli, c, "odp_queue_print", cmd_call_odp_queue_print, PRIVILEGE_UNPRIVILEGED, MODE_EXEC, "<name>"); + cli_register_command(cli, c, "odp_queue_print_all", + cmd_call_odp_queue_print_all, + PRIVILEGE_UNPRIVILEGED, MODE_EXEC, NULL); cli_register_command(cli, c, "odp_shm_print_all", cmd_call_odp_shm_print_all, PRIVILEGE_UNPRIVILEGED, MODE_EXEC, NULL); @@ -262,6 +405,12 @@ static struct cli_def *create_cli(void) cmd_call_odp_sys_info_print, PRIVILEGE_UNPRIVILEGED, MODE_EXEC, NULL); + for (uint32_t i = 0; i < shm->num_user_commands; i++) { + cli_register_command(cli, NULL, shm->user_cmd[i].name, + cmd_user_cmd, PRIVILEGE_UNPRIVILEGED, + MODE_EXEC, shm->user_cmd[i].help); + } + return cli; } @@ -269,8 +418,8 @@ static struct cli_def *create_cli(void) static struct cli_def *cli; static char *cli_log_fn_buf; -ODP_PRINTF_FORMAT(2, 3) -static int cli_log_fn(odp_log_level_t level, const char *fmt, ...) +ODP_PRINTF_FORMAT(2, 0) +static int cli_log_va(odp_log_level_t level, const char *fmt, va_list in_args) { (void)level; @@ -289,17 +438,17 @@ static int cli_log_fn(odp_log_level_t level, const char *fmt, ...) * If the string does not end in a newline, we keep the part of the * string after the last newline and use it the next time we're called. */ - va_start(args, fmt); + va_copy(args, in_args); len = vsnprintf(NULL, 0, fmt, args) + 1; va_end(args); str = malloc(len); if (!str) { - ODPH_ERR("malloc failed"); - return 0; + ODPH_ERR("malloc failed\n"); + return -1; } - va_start(args, fmt); + va_copy(args, in_args); vsnprintf(str, len, fmt, args); va_end(args); p = str; @@ -323,7 +472,7 @@ static int cli_log_fn(odp_log_level_t level, const char *fmt, ...) malloc(strlen(cli_log_fn_buf) + strlen(p) + 1); if (!buffer_new) { - ODPH_ERR("malloc failed"); + ODPH_ERR("malloc failed\n"); goto out; } @@ -335,7 +484,7 @@ static int cli_log_fn(odp_log_level_t level, const char *fmt, ...) cli_log_fn_buf = malloc(strlen(p) + 1); if (!cli_log_fn_buf) { - ODPH_ERR("malloc failed"); + ODPH_ERR("malloc failed\n"); goto out; } @@ -346,23 +495,47 @@ static int cli_log_fn(odp_log_level_t level, const char *fmt, ...) out: free(str); - return 0; + return len; } -static int cli_server(void *arg ODP_UNUSED) +ODP_PRINTF_FORMAT(2, 3) +static int cli_log(odp_log_level_t level, const char *fmt, ...) { - cli_shm_t *shm = NULL; - odp_shm_t shm_hdl = odp_shm_lookup(shm_name); + (void)level; - if (shm_hdl != ODP_SHM_INVALID) - shm = (cli_shm_t *)odp_shm_addr(shm_hdl); + int r; + va_list args; + + va_start(args, fmt); + r = cli_log_va(level, fmt, args); + va_end(args); + + return r; +} + +ODP_PRINTF_FORMAT(1, 2) +int odph_cli_log(const char *fmt, ...) +{ + int r; + va_list args; + + va_start(args, fmt); + r = cli_log_va(ODP_LOG_PRINT, fmt, args); + va_end(args); + + return r; +} + +static int cli_server(void *arg ODP_UNUSED) +{ + cli_shm_t *shm = shm_lookup(); if (!shm) { - ODPH_ERR("Error: can't start cli server (shm %s not found)\n", shm_name); + ODPH_ERR("Error: shm %s not found\n", shm_name); return -1; } - cli = create_cli(); + cli = create_cli(shm); while (1) { struct pollfd pfd[2] = { @@ -399,26 +572,55 @@ static int cli_server(void *arg ODP_UNUSED) break; } + /* + * The only way to stop cli_loop() is to close the socket, after + * which cli_loop() gets an error on the next select() and then + * calls close() before returning. This is a problem because the + * fd may be reused before the select() or the final close(). + * + * To avoid this problem, switch to a higher fd number + * (select() maximum). We will still run into problems if the + * descriptor numbers in the process reach FD_SETSIZE - 1 = + * 1023. + */ + int newfd = dup2(fd, FD_SETSIZE - 1); + + if (newfd < 0) { + ODPH_ERR("Error: dup2(): %s\n", strerror(errno)); + close(fd); + continue; + } + + close(fd); + fd = newfd; + odp_spinlock_lock(&shm->lock); if (!shm->run) { + odp_spinlock_unlock(&shm->lock); /* * odph_cli_stop() has been called. Close the * socket we just accepted and exit. */ close(fd); - odp_spinlock_unlock(&shm->lock); break; } shm->cli_fd = fd; odp_spinlock_unlock(&shm->lock); - odp_log_thread_fn_set(cli_log_fn); + + odp_log_thread_fn_set(cli_log); /* * cli_loop() returns only when client is disconnected. One * possible reason for disconnect is odph_cli_stop(). */ cli_loop(cli, shm->cli_fd); odp_log_thread_fn_set(NULL); - close(shm->cli_fd); + + odp_spinlock_lock(&shm->lock); + /* + * cli_loop() closes the socket before returning (undocumented). + */ + shm->cli_fd = -1; + odp_spinlock_unlock(&shm->lock); /* * Throw away anything left in the buffer (in case the last @@ -433,32 +635,30 @@ static int cli_server(void *arg ODP_UNUSED) return 0; } -int odph_cli_start(const odp_instance_t instance, - const odph_cli_param_t *param_in) +int odph_cli_start(void) { - if (odp_shm_lookup(shm_name) != ODP_SHM_INVALID) { - ODPH_ERR("Error: cli server already running (shm %s exists)\n", shm_name); + cli_shm_t *shm = shm_lookup(); + + if (!shm) { + ODPH_ERR("Error: shm %s not found\n", shm_name); return -1; } - cli_shm_t *shm = NULL; - odp_shm_t shm_hdl = odp_shm_reserve(shm_name, sizeof(cli_shm_t), 64, - ODP_SHM_SW_ONLY); - - if (shm_hdl != ODP_SHM_INVALID) - shm = (cli_shm_t *)odp_shm_addr(shm_hdl); - - if (!shm) { - ODPH_ERR("Error: failed to reserve shm %s\n", shm_name); + odp_spinlock_lock(&shm->api_lock); + odp_spinlock_lock(&shm->lock); + if (shm->run) { + odp_spinlock_unlock(&shm->lock); + odp_spinlock_unlock(&shm->api_lock); + ODPH_ERR("Error: cli server has already been started\n"); return -1; } + shm->run = 1; + shm->cli_fd = -1; + odp_spinlock_unlock(&shm->lock); - memset(shm, 0, sizeof(cli_shm_t)); - odp_spinlock_init(&shm->lock); - shm->sp[SP_READ] = shm->sp[SP_WRITE] = -1; + shm->sp[SP_READ] = -1; + shm->sp[SP_WRITE] = -1; shm->listen_fd = -1; - shm->cli_fd = -1; - shm->run = 1; if (socketpair(PF_LOCAL, SOCK_STREAM, 0, shm->sp)) { ODPH_ERR("Error: socketpair(): %s\n", strerror(errno)); @@ -480,21 +680,8 @@ int odph_cli_start(const odp_instance_t instance, goto error; } - struct sockaddr_in addr; - - addr.sin_family = AF_INET; - addr.sin_port = htons(param_in->port); - - switch (inet_pton(AF_INET, param_in->address, &addr.sin_addr)) { - case -1: - ODPH_ERR("Error: inet_pton(): %s\n", strerror(errno)); - goto error; - case 0: - ODPH_ERR("Error: inet_pton(): illegal address format\n"); - goto error; - } - - if (bind(shm->listen_fd, (struct sockaddr *)&addr, sizeof(addr))) { + if (bind(shm->listen_fd, (struct sockaddr *)&shm->addr, + sizeof(shm->addr))) { ODPH_ERR("Error: bind(): %s\n", strerror(errno)); goto error; } @@ -516,7 +703,7 @@ int odph_cli_start(const odp_instance_t instance, } memset(&thr_common, 0, sizeof(thr_common)); - thr_common.instance = instance; + thr_common.instance = shm->instance; thr_common.cpumask = &cpumask; memset(&thr_param, 0, sizeof(thr_param)); @@ -530,36 +717,50 @@ int odph_cli_start(const odp_instance_t instance, goto error; } + odp_spinlock_unlock(&shm->api_lock); return 0; error: - close(shm->sp[SP_READ]); - close(shm->sp[SP_WRITE]); - close(shm->listen_fd); - close(shm->cli_fd); shm->run = 0; + if (shm->sp[SP_READ] >= 0) + close(shm->sp[SP_READ]); + if (shm->sp[SP_WRITE] >= 0) + close(shm->sp[SP_WRITE]); + if (shm->listen_fd >= 0) + close(shm->listen_fd); + if (shm->cli_fd >= 0) + close(shm->cli_fd); + odp_spinlock_unlock(&shm->api_lock); return -1; } int odph_cli_stop(void) { - cli_shm_t *shm = NULL; - odp_shm_t shm_hdl = odp_shm_lookup(shm_name); - - if (shm_hdl != ODP_SHM_INVALID) - shm = (cli_shm_t *)odp_shm_addr(shm_hdl); + cli_shm_t *shm = shm_lookup(); if (!shm) { - ODPH_ERR("Error: cli server not running (shm %s not found)\n", shm_name); + ODPH_ERR("Error: shm %s not found\n", shm_name); return -1; } + odp_spinlock_lock(&shm->api_lock); odp_spinlock_lock(&shm->lock); + if (!shm->run) { + odp_spinlock_unlock(&shm->lock); + odp_spinlock_unlock(&shm->api_lock); + ODPH_ERR("Error: cli server has not been started\n"); + return -1; + } shm->run = 0; /* - * Close the current cli connection. This stops cli_loop(). + * Close the current cli connection. This stops cli_loop(). If cli + * client is disconnecting at the same time, cli_fd may already have + * been closed. */ - close(shm->cli_fd); + if (shm->cli_fd >= 0) { + close(shm->cli_fd); + shm->cli_fd = -1; + } odp_spinlock_unlock(&shm->lock); /* @@ -572,17 +773,37 @@ int odph_cli_stop(void) if (sent != sizeof(stop)) { ODPH_ERR("Error: send() = %d: %s\n", sent, strerror(errno)); - return -1; + goto error; } if (odph_thread_join(&shm->thr_server, 1) != 1) { ODPH_ERR("Error: odph_thread_join() failed\n"); - return -1; + goto error; } close(shm->sp[SP_READ]); close(shm->sp[SP_WRITE]); close(shm->listen_fd); + odp_spinlock_unlock(&shm->api_lock); + return 0; + +error: + odp_spinlock_unlock(&shm->api_lock); + return -1; +} + +int odph_cli_term(void) +{ + cli_shm_t *shm = NULL; + odp_shm_t shm_hdl = odp_shm_lookup(shm_name); + + if (shm_hdl != ODP_SHM_INVALID) + shm = (cli_shm_t *)odp_shm_addr(shm_hdl); + + if (!shm) { + ODPH_ERR("Error: shm %s not found\n", shm_name); + return -1; + } if (odp_shm_free(shm_hdl)) { ODPH_ERR("Error: odp_shm_free() failed\n"); diff --git a/helper/include/odp/helper/cli.h b/helper/include/odp/helper/cli.h index 41e438857..ef1c24d05 100644 --- a/helper/include/odp/helper/cli.h +++ b/helper/include/odp/helper/cli.h @@ -12,9 +12,6 @@ * This API allows control of ODP CLI server, which may be connected to * using a telnet client. CLI commands may be used to get information * from an ODP instance, for debugging purposes. - * - * Many CLI commands output the information to the console, or wherever - * ODP logs have been directed to in global init. */ #ifndef ODPH_CLI_H_ @@ -33,6 +30,17 @@ extern "C" { * @{ */ +/** + * User defined command function type. See odph_cli_register_command(). + * + * The arguments (argv) are the arguments to the command given in the CLI + * client. For example, having registered a command with the name "my_command", + * and given the command "my_command one two" in the CLI client, the user + * command function would be called with argc = 2, argv[0] = "one" and argv[1] = + * "two". + */ +typedef void (*odph_cli_user_cmd_func_t)(int argc, char *argv[]); + /** ODP CLI server parameters */ typedef struct { /** @@ -42,6 +50,8 @@ typedef struct { const char *address; /** TCP port. Default is 55555. */ uint16_t port; + /** Maximum number of user defined commands. Default is 50. */ + uint32_t max_user_commands; } odph_cli_param_t; /** @@ -55,19 +65,56 @@ typedef struct { void odph_cli_param_init(odph_cli_param_t *param); /** + * Initialize CLI helper + * + * This function initializes the CLI helper. It must be called before + * odph_cli_register_command() and odph_cli_start(). + * + * @param instance ODP instance + * @param param CLI server parameters to use + * @retval 0 Success + * @retval <0 Failure + */ +int odph_cli_init(odp_instance_t instance, const odph_cli_param_t *param); + +/** + * Register a user defined command + * + * Register a command with a name, function, and an optional help text. The + * registered command is displayed in the output of the "help" command. When the + * command is invoked by the CLI client, the registered function is called with + * the parameters entered by the CLI client user. + * + * Command names are case-insensitive. In the CLI client, they are displayed in + * the case they were registered in, but they may be invoked using any case. + * + * This function should be called after odph_cli_init() and before + * odph_cli_start(). + * + * @param name Command name (case-insensitive) + * @param func Command function + * @param help Help or description for the command. This appears in the output + * of the "help" command. May be NULL. + * @retval 0 Success + * @retval <0 Failure + */ +int odph_cli_register_command(const char *name, odph_cli_user_cmd_func_t func, + const char *help); + +/** * Start CLI server * * Upon successful return from this function, the CLI server will be * accepting client connections. This function spawns a new thread of * type ODP_THREAD_CONTROL using odp_cpumask_default_control(). * - * @param instance ODP instance - * @param param CLI server parameters to use + * This function should be called after odph_cli_init() and after any + * odph_cli_register_command() calls. + * * @retval 0 Success * @retval <0 Failure */ -int odph_cli_start(const odp_instance_t instance, - const odph_cli_param_t *param); +int odph_cli_start(void); /** * Stop CLI server @@ -82,6 +129,31 @@ int odph_cli_start(const odp_instance_t instance, int odph_cli_stop(void); /** + * Print to CLI + * + * A user defined command may call this function to print to the CLI client. + * This function should only be called in a user defined command (see + * odph_cli_register_command()). If called anywhere else, the behavior is + * undefined. + * + * @param fmt printf-style message format + * @return On success, the number of characters printed or buffered, without + * accounting for any line feed conversions. If an error is encountered, + * a negative value is returned. + */ +int odph_cli_log(const char *fmt, ...); + +/** + * Terminate CLI helper + * + * Free any resources allocated by the CLI helper. + * + * @retval 0 Success + * @retval <0 Failure + */ +int odph_cli_term(void); + +/** * @} */ diff --git a/helper/ipsec.c b/helper/ipsec.c index e2d24840e..41daefbfb 100644 --- a/helper/ipsec.c +++ b/helper/ipsec.c @@ -108,7 +108,7 @@ int odph_ipsec_alg_check(odp_ipsec_capability_t capa, } /* Check whether requested cipher key length is supported */ - max_capa = odp_crypto_cipher_capability(cipher_alg, NULL, 0); + max_capa = odp_ipsec_cipher_capability(cipher_alg, NULL, 0); if (max_capa <= 0) return -1; @@ -134,7 +134,7 @@ int odph_ipsec_alg_check(odp_ipsec_capability_t capa, } /* Check whether requested auth key length is supported */ - max_capa = odp_crypto_auth_capability(auth_alg, NULL, 0); + max_capa = odp_ipsec_auth_capability(auth_alg, NULL, 0); if (max_capa <= 0) return max_capa; diff --git a/helper/test/cli.c b/helper/test/cli.c index ff3ea2f53..e7ed0e06f 100644 --- a/helper/test/cli.c +++ b/helper/test/cli.c @@ -38,7 +38,12 @@ int main(int argc, char *argv[]) odph_cli_param_init(&cli_param); - if (odph_cli_start(instance, &cli_param)) { + if (odph_cli_init(instance, &cli_param)) { + ODPH_ERR("Error: odph_cli_init() failed.\n"); + exit(EXIT_FAILURE); + } + + if (odph_cli_start()) { ODPH_ERR("Error: odph_cli_start() failed.\n"); exit(EXIT_FAILURE); } @@ -48,6 +53,11 @@ int main(int argc, char *argv[]) exit(EXIT_FAILURE); } + if (odph_cli_term()) { + ODPH_ERR("Error: odph_cli_term() failed.\n"); + exit(EXIT_FAILURE); + } + if (odp_term_local()) { ODPH_ERR("Error: ODP local term failed.\n"); exit(EXIT_FAILURE); diff --git a/include/odp/api/spec/ipsec.h b/include/odp/api/spec/ipsec.h index 5c4ee03ab..2030b19e8 100644 --- a/include/odp/api/spec/ipsec.h +++ b/include/odp/api/spec/ipsec.h @@ -937,6 +937,15 @@ typedef struct odp_ipsec_stats_t { /** Number of packets with hard lifetime(packets) expired */ uint64_t hard_exp_pkts_err; + + /** Total bytes of packet data processed by IPsec SA in success cases + * + * The range of packet bytes included in the success_bytes count is + * implementation defined but includes at least the bytes input for + * encryption or bytes output after decryption in ESP or the bytes + * authenticated in AH. + */ + uint64_t success_bytes; } odp_ipsec_stats_t; /** diff --git a/include/odp/api/spec/packet_io.h b/include/odp/api/spec/packet_io.h index fcb0a39c3..1f4ac84f6 100644 --- a/include/odp/api/spec/packet_io.h +++ b/include/odp/api/spec/packet_io.h @@ -1074,8 +1074,10 @@ int odp_pktout_queue_config(odp_pktio_t pktio, * output. If return value (N) is less than 'num', only queues[0 ... N-1] have * been written. * - * Packets (and other events) from these queues are received with - * odp_queue_deq(), odp_schedule(), etc calls. + * In addition to packet input, application and other parts of ODP (e.g. timer) + * may enqueue events into these queues. Depending on the queue mode, application + * uses either odp_queue_deq() or odp_schedule() (or variants of those) to receive + * packets and other events from these queues. * * @param pktio Packet IO handle * @param[out] queues Points to an array of queue handles for output @@ -1117,7 +1119,7 @@ int odp_pktin_queue(odp_pktio_t pktio, odp_pktin_queue_t queues[], int num); * * Packets are enqueued to these queues with odp_queue_enq() or * odp_queue_enq_multi(). Behaviour is undefined if other events than packets - * are enqueued. + * are enqueued. Application cannot dequeue from these queues. * * @param pktio Packet IO handle * @param[out] queues Points to an array of queue handles for output diff --git a/include/odp/api/spec/time.h b/include/odp/api/spec/time.h index c5756e492..c25338a51 100644 --- a/include/odp/api/spec/time.h +++ b/include/odp/api/spec/time.h @@ -1,5 +1,5 @@ /* Copyright (c) 2013-2018, Linaro Limited - * Copyright (c) 2020, Nokia + * Copyright (c) 2020-2021, Nokia * All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause @@ -66,6 +66,35 @@ extern "C" { odp_time_t odp_time_local(void); /** + * Current local time in nanoseconds + * + * Like odp_time_local(), but the time stamp value is converted into nanoseconds. + * + * @return Local time stamp in nanoseconds + */ +uint64_t odp_time_local_ns(void); + +/** + * Current local time (strict) + * + * Like odp_time_local(), but reads the time stamp value more strictly in the program order. + * The function may decrease CPU performance around the call, as it may include additional + * barrier instructions or otherwise limit out-of-order execution. + * + * @return Local time stamp + */ +odp_time_t odp_time_local_strict(void); + +/** + * Current local time in nanoseconds (strict) + * + * Like odp_time_local_strict(), but the time stamp value is converted into nanoseconds. + * + * @return Local time stamp in nanoseconds + */ +uint64_t odp_time_local_strict_ns(void); + +/** * Current global time * * Returns current global time stamp value. The global time source provides high @@ -78,22 +107,32 @@ odp_time_t odp_time_local(void); odp_time_t odp_time_global(void); /** - * Current local time in nanoseconds + * Current global time in nanoseconds * - * Like odp_time_local(), but the time stamp value is converted into nanoseconds. + * Like odp_time_global(), but the time stamp value is converted into nanoseconds. * - * @return Local time stamp in nanoseconds + * @return Global time stamp in nanoseconds */ -uint64_t odp_time_local_ns(void); +uint64_t odp_time_global_ns(void); /** - * Current global time in nanoseconds + * Current global time (strict) * - * Like odp_time_global(), but the time stamp value is converted into nanoseconds. + * Like odp_time_global(), but reads the time stamp value more strictly (see + * odp_time_local_strict() documentation) in the program order. + * + * @return Global time stamp + */ +odp_time_t odp_time_global_strict(void); + +/** + * Current global time in nanoseconds (strict) + * + * Like odp_time_global_strict(), but the time stamp value is converted into nanoseconds. * * @return Global time stamp in nanoseconds */ -uint64_t odp_time_global_ns(void); +uint64_t odp_time_global_strict_ns(void); /** * Time difference diff --git a/include/odp/api/spec/timer.h b/include/odp/api/spec/timer.h index 62151e485..a90fb9b07 100644 --- a/include/odp/api/spec/timer.h +++ b/include/odp/api/spec/timer.h @@ -1,5 +1,5 @@ /* Copyright (c) 2013-2018, Linaro Limited - * Copyright (c) 2019-2020, Nokia + * Copyright (c) 2019-2021, Nokia * * All rights reserved. * @@ -36,16 +36,47 @@ extern "C" { */ /** - * Clock sources for timers in timer pool. + * Clock sources for timer pools + * + * ODP_CLOCK_DEFAULT is the default clock source and it is supported always. It is implementation + * defined which other clock sources are supported. See from implementation documentation how the + * supported clock sources are mapped into these enumerations. */ typedef enum { - /** Use CPU clock as clock source for timers */ - ODP_CLOCK_CPU, - /** Use external clock as clock source for timers */ - ODP_CLOCK_EXT - /* Platform dependent which other clock sources exist */ + /** Clock source number 0 */ + ODP_CLOCK_SRC_0, + + /** Clock source number 1 */ + ODP_CLOCK_SRC_1, + + /** Clock source number 2 */ + ODP_CLOCK_SRC_2, + + /** Clock source number 3 */ + ODP_CLOCK_SRC_3, + + /** Clock source number 4 */ + ODP_CLOCK_SRC_4, + + /** Clock source number 5 */ + ODP_CLOCK_SRC_5, + + /** Number of clock source enumerations */ + ODP_CLOCK_NUM_SRC + } odp_timer_clk_src_t; +/** The default clock source */ +#define ODP_CLOCK_DEFAULT ODP_CLOCK_SRC_0 + +/** For backwards compatibility, ODP_CLOCK_CPU is synonym of ODP_CLOCK_DEFAULT. + * This will be deprecated in the future. */ +#define ODP_CLOCK_CPU ODP_CLOCK_DEFAULT + +/** For backwards compatibility, ODP_CLOCK_EXT is synonym of ODP_CLOCK_SRC_1. + * This will be deprecated in the future. */ +#define ODP_CLOCK_EXT ODP_CLOCK_SRC_1 + /** * @typedef odp_timer_t * ODP timer handle @@ -70,31 +101,34 @@ typedef enum { * Return values of timer set calls. */ typedef enum { - /** - * Timer set operation succeeded - */ + /** Timer set operation succeeded */ ODP_TIMER_SUCCESS = 0, - /** - * Timer set operation failed, expiration too early. - * Either retry with a later expiration time or process the timeout - * immediately. */ - ODP_TIMER_TOOEARLY = -1, + /** Timer set operation failed because expiration time is too near to + * the current time. */ + ODP_TIMER_TOO_NEAR = -1, - /** - * Timer set operation failed, expiration too late. - * Truncate the expiration time against the maximum timeout for the - * timer pool. */ - ODP_TIMER_TOOLATE = -2, + /** Timer set operation failed because expiration time is too far from + * the current time. */ + ODP_TIMER_TOO_FAR = -2, - /** - * Timer set operation failed because no event specified and no event - * present in the timer (timer inactive/expired). - */ - ODP_TIMER_NOEVENT = -3 + /** Timer set operation failed */ + ODP_TIMER_FAIL = -3 } odp_timer_set_t; +/** For backwards compatibility, ODP_TIMER_TOOEARLY is synonym of ODP_TIMER_TOO_NEAR. + * This will be deprecated in the future. */ +#define ODP_TIMER_TOOEARLY ODP_TIMER_TOO_NEAR + +/** For backwards compatibility, ODP_TIMER_TOOLATE is synonym of ODP_TIMER_TOO_FAR. + * This will be deprecated in the future. */ +#define ODP_TIMER_TOOLATE ODP_TIMER_TOO_FAR + +/** For backwards compatibility, ODP_TIMER_NOEVENT is synonym of ODP_TIMER_FAIL. + * This will be deprecated in the future. */ +#define ODP_TIMER_NOEVENT ODP_TIMER_FAIL + /** * @def ODP_TIMER_POOL_NAME_LEN * Maximum timer pool name length in chars including null char @@ -240,18 +274,19 @@ typedef struct { } odp_timer_capability_t; /** - * Query timer capabilities + * Query timer capabilities per clock source * - * Outputs timer capabilities on success. + * Outputs timer capabilities on success. Returns -1 if the clock source + * is not supported. * * @param clk_src Clock source for timers * @param[out] capa Pointer to capability structure for output * - * @retval 0 on success - * @retval <0 on failure + * @retval 0 on success + * @retval -1 when the clock source is not supported + * @retval <-1 on other failures */ -int odp_timer_capability(odp_timer_clk_src_t clk_src, - odp_timer_capability_t *capa); +int odp_timer_capability(odp_timer_clk_src_t clk_src, odp_timer_capability_t *capa); /** * Timer resolution capability @@ -423,11 +458,11 @@ odp_event_t odp_timer_free(odp_timer_t timer); * outputs the old event here. * * @retval ODP_TIMER_SUCCESS Success - * @retval ODP_TIMER_TOOEARLY Failure. Expiration time is too near to + * @retval ODP_TIMER_TOO_NEAR Failure. Expiration time is too near to * the current time. - * @retval ODP_TIMER_TOOLATE Failure. Expiration time is too far from + * @retval ODP_TIMER_TOO_FAR Failure. Expiration time is too far from * the current time. - * @retval ODP_TIMER_NOEVENT Failure. Set operation: No event provided. + * @retval ODP_TIMER_FAIL Failure. Set operation: No event provided. * Reset operation: Too late to reset the timer. * * @see odp_timer_set_rel(), odp_timer_alloc(), odp_timer_cancel() @@ -451,11 +486,11 @@ int odp_timer_set_abs(odp_timer_t timer, uint64_t abs_tick, * outputs the old event here. * * @retval ODP_TIMER_SUCCESS Success - * @retval ODP_TIMER_TOOEARLY Failure. Expiration time is too near to + * @retval ODP_TIMER_TOO_NEAR Failure. Expiration time is too near to * the current time. - * @retval ODP_TIMER_TOOLATE Failure. Expiration time is too far from + * @retval ODP_TIMER_TOO_FAR Failure. Expiration time is too far from * the current time. - * @retval ODP_TIMER_NOEVENT Failure. Set operation: No event provided. + * @retval ODP_TIMER_FAIL Failure. Set operation: No event provided. * Reset operation: Too late to reset the timer. * * @see odp_timer_set_abs(), odp_timer_alloc(), odp_timer_cancel() diff --git a/include/odp/api/spec/traffic_mngr.h b/include/odp/api/spec/traffic_mngr.h index 04848a0ea..699d0bb26 100644 --- a/include/odp/api/spec/traffic_mngr.h +++ b/include/odp/api/spec/traffic_mngr.h @@ -224,6 +224,10 @@ typedef struct { * all support TM shaping, */ odp_bool_t tm_node_shaper_supported; + /** tm_node_shaper_packet_mode indicates that tm_nodes at this level + * support shaper in packet mode */ + odp_bool_t tm_node_shaper_packet_mode; + /** tm_node_wred_supported indicates that the tm_nodes at this level * support some form of Random Early Detection. */ odp_bool_t tm_node_wred_supported; @@ -285,6 +289,10 @@ typedef struct { * expected to do. */ odp_bool_t tm_queue_shaper_supported; + /** tm_queue_shaper_packet_mode indicates that tm_queues support + * shaper in packet mode */ + odp_bool_t tm_queue_shaper_packet_mode; + /** tm_queue_wred_supported indicates that the tm_queues support some * form of Random Early Detection. */ odp_bool_t tm_queue_wred_supported; @@ -331,6 +339,52 @@ typedef struct { /** The per_level array specifies the TM system capabilities that * can vary based upon the tm_node level. */ odp_tm_level_capabilities_t per_level[ODP_TM_MAX_LEVELS]; + + /** dynamic_topology_update indicates support for TM system dynamic + * topology update. A dynamic topology update is defined as update to + * a TM system topology while TM system is not in stopped state. + * When TRUE, application can update topology dynamically + * without bringing the TM system to stopped state. When FALSE, + * application has to call odp_tm_stop() before updating the + * topology and odp_tm_start() after completing the update. + */ + odp_bool_t dynamic_topology_update; + + /** dynamic_shaper_update indicates support for TM system's dynamic + * shaper profile changes. When TRUE, application can update shaper + * profile of a TM queue or TM node dynamically. + * When FALSE, it implies that TM system should be brought to + * stopped state before changing the shaper profile or updating + * the parameters of the shaper profile of any TM node or TM queue. + */ + odp_bool_t dynamic_shaper_update; + + /** dynamic_sched_update indicates support for TM system's dynamic + * sched profile changes. When TRUE, application can update sched + * profile of a TM queue or TM node dynamically. + * When FALSE, it implies that TM system should be brought to + * stopped state before changing the sched profile or updating + * the parameters of the sched profile of any TM node or TM queue. + */ + odp_bool_t dynamic_sched_update; + + /** dynamic_wred_update indicates support for TM system's dynamic + * wred profile changes. When TRUE, application can update wred + * profile of a TM queue or TM node dynamically. + * When FALSE, it implies that TM system should be brought to + * stopped state before changing the wred profile or updating + * the parameters of the wred profile of any TM node or TM queue. + */ + odp_bool_t dynamic_wred_update; + + /** dynamic_threshold_update indicates support for TM system's dynamic + * threshold profile changes. When TRUE, application can update + * threshold profile of a TM queue or TM node dynamically. + * When FALSE, it implies that TM system should be brought to + * stopped state before changing the threshold profile or updating + * the parameters of the threshold profile of any TM node or TM queue. + */ + odp_bool_t dynamic_threshold_update; } odp_tm_capabilities_t; /** Per Level Requirements @@ -605,6 +659,48 @@ odp_tm_t odp_tm_find(const char *name, */ int odp_tm_capability(odp_tm_t odp_tm, odp_tm_capabilities_t *capabilities); +/** + * Start a TM system + * + * odp_tm_start() needs to be used to start an already created or found TM + * system. By default, all the TM systems are in stopped state. + * + * @param tm TM system to be started + * + * @retval 0 on success + * @retval <0 on failure + */ +int odp_tm_start(odp_tm_t tm); + +/** + * Stop a TM system + * + * odp_tm_stop() can to used to stop a TM system that is already started for the + * purpose of reconfiguration that cannot be done dynamically. + * + * When TM is in the stopped state, + * - New packets must not be sent to the TM either directly by TM API or indirectly + * via IPsec outbound inline API. New packets can only be enqueued after + * starting the TM system using odp_tm_start(). + * - Packets already inflight inside TM or IPSec for transmit may get silently dropped + * or may get transmitted with unspecified TM treatment. + * + * A following call to odp_tm_start() restarts TM system and its scheduling/shaping + * on existing and new packets. + * + * @param tm TM system to be stopped + * + * @retval 0 on success + * @retval <0 on failure + * + * @see odp_tm_capabilities_t::dynamic_topology_update + * @see odp_tm_capabilities_t::dynamic_shaper_update + * @see odp_tm_capabilities_t::dynamic_sched_update + * @see odp_tm_capabilities_t::dynamic_wred_update + * @see odp_tm_capabilities_t::dynamic_threshold_update + */ +int odp_tm_stop(odp_tm_t tm); + /** Destroy a TM system. * * odp_tm_destroy() may be used to destroy TM systems created via @@ -746,20 +842,34 @@ typedef enum { */ typedef struct { /** The committed information rate for this shaper profile. The units - * for this integer are always in bits per second. */ - uint64_t commit_bps; + * for this integer is in bits per second when packet_mode is + * not TRUE while packets per second when packet mode is TRUE. + */ + union { + /**< @deprecated Use commit_rate instead */ + uint64_t ODP_DEPRECATE(commit_bps); + uint64_t commit_rate; /**< Commit information rate */ + }; /** The peak information rate for this shaper profile. The units for - * this integer are always in bits per second. */ - uint64_t peak_bps; + * this integer is in bits per second when packet_mode is + * not TRUE while in packets per second when packet mode is TRUE. + */ + union { + /**< @deprecated Use peak_rate instead */ + uint64_t ODP_DEPRECATE(peak_bps); + uint64_t peak_rate; /**< Peak information rate */ + }; /** The commit burst tolerance for this shaper profile. The units for - * this field are always bits. This value sets an upper limit for the + * this field is bits when packet_mode is not TRUE and packets when + * packet_mode is TRUE. This value sets an upper limit for the * size of the commitCnt. */ uint32_t commit_burst; /** The peak burst tolerance for this shaper profile. The units for - * this field are always bits. This value sets an upper limit for the + * this field in bits when packet_mode is not TRUE and packets + * when packet_mode is TRUE. This value sets an upper limit for the * size of the peakCnt. */ uint32_t peak_burst; @@ -771,7 +881,9 @@ typedef struct { * to a value approximating the "time" (in units of bytes) taken by * the Ethernet preamble and Inter Frame Gap. Traditionally this * would be the value 20 (8 + 12), but in same cases can be as low as - * 9 (4 + 5). */ + * 9 (4 + 5). + * This field is ignored when packet_mode is TRUE. + */ int8_t shaper_len_adjust; /** If dual_rate is TRUE it indicates the desire for the @@ -780,6 +892,12 @@ typedef struct { * implementation specific, but in any case require a non-zero set of * both commit and peak parameters. */ odp_bool_t dual_rate; + + /** If packet_mode is TRUE it indicates that shaper should work + * in packet mode ignoring lengths of packet and hence shaping + * traffic in packet's per second as opposed to bits per second. + */ + odp_bool_t packet_mode; } odp_tm_shaper_params_t; /** odp_tm_shaper_params_init() must be called to initialize any diff --git a/platform/linux-dpdk/Makefile.am b/platform/linux-dpdk/Makefile.am index 6967be8cf..8cdb84b15 100644 --- a/platform/linux-dpdk/Makefile.am +++ b/platform/linux-dpdk/Makefile.am @@ -259,7 +259,7 @@ __LIB__libodp_dpdk_la_SOURCES += arch/aarch64/odp_atomic.c \ arch/default/odp_hash_crc32.c \ arch/aarch64/odp_sysinfo_parse.c odpapiabiarchinclude_HEADERS += arch/default/odp/api/abi/cpu_inlines.h \ - arch/default/odp/api/abi/cpu_time.h \ + arch/aarch64/odp/api/abi/cpu_time.h \ arch/aarch64/odp/api/abi/hash_crc32.h if !ODP_ABI_COMPAT odpapiabiarchinclude_HEADERS += arch/default/odp/api/abi/atomic_generic.h \ diff --git a/platform/linux-dpdk/include/odp/api/plat/time_inlines.h b/platform/linux-dpdk/include/odp/api/plat/time_inlines.h index 5032b0fcb..c007c5ce9 100644 --- a/platform/linux-dpdk/include/odp/api/plat/time_inlines.h +++ b/platform/linux-dpdk/include/odp/api/plat/time_inlines.h @@ -1,5 +1,5 @@ /* Copyright (c) 2018, Linaro Limited - * Copyright (c) 2020, Nokia + * Copyright (c) 2020-2021, Nokia * All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause @@ -21,11 +21,13 @@ #define _ODP_TIME_GIGA_HZ 1000000000ULL typedef odp_time_t (*time_cur_fn)(void); +typedef odp_time_t (*time_cur_strict_fn)(void); typedef uint64_t (*time_res_fn)(void); typedef struct time_handler_ { - time_cur_fn time_cur; - time_res_fn time_res; + time_cur_fn time_cur; + time_cur_strict_fn time_cur_strict; + time_res_fn time_res; } time_handler_t; @@ -58,11 +60,28 @@ static inline odp_time_t _odp_time_cur_gen(void) return _odp_timespec_cur(); } +static inline odp_time_t _odp_time_cur_gen_strict(void) +{ + if (_odp_time_glob.use_hw) { + odp_time_t time; + + time.count = _odp_cpu_global_time_strict() - _odp_time_glob.hw_start; + return time; + } + + return _odp_timespec_cur(); +} + static inline odp_time_t _odp_time_cur(void) { return _odp_time_glob.handler.time_cur(); } +static inline odp_time_t _odp_time_cur_strict(void) +{ + return _odp_time_glob.handler.time_cur_strict(); +} + static inline uint64_t _odp_time_hw_to_ns(odp_time_t time) { uint64_t nsec; @@ -96,6 +115,12 @@ static inline uint64_t _odp_time_convert_to_ns(odp_time_t time) #define odp_time_to_ns __odp_time_to_ns #define odp_time_local_ns __odp_time_local_ns #define odp_time_global_ns __odp_time_global_ns + + #define odp_time_local_strict __odp_time_local_strict + #define odp_time_global_strict __odp_time_global_strict + #define odp_time_local_strict_ns __odp_time_local_strict_ns + #define odp_time_global_strict_ns __odp_time_global_strict_ns + #define odp_time_cmp __odp_time_cmp #define odp_time_diff __odp_time_diff #define odp_time_sum __odp_time_sum @@ -114,9 +139,14 @@ _ODP_INLINE odp_time_t odp_time_global(void) return _odp_time_cur(); } -_ODP_INLINE uint64_t odp_time_to_ns(odp_time_t time) +_ODP_INLINE odp_time_t odp_time_local_strict(void) { - return _odp_time_convert_to_ns(time); + return _odp_time_cur_strict(); +} + +_ODP_INLINE odp_time_t odp_time_global_strict(void) +{ + return _odp_time_cur_strict(); } _ODP_INLINE uint64_t odp_time_local_ns(void) @@ -129,6 +159,21 @@ _ODP_INLINE uint64_t odp_time_global_ns(void) return _odp_time_convert_to_ns(_odp_time_cur()); } +_ODP_INLINE uint64_t odp_time_local_strict_ns(void) +{ + return _odp_time_convert_to_ns(_odp_time_cur_strict()); +} + +_ODP_INLINE uint64_t odp_time_global_strict_ns(void) +{ + return _odp_time_convert_to_ns(_odp_time_cur_strict()); +} + +_ODP_INLINE uint64_t odp_time_to_ns(odp_time_t time) +{ + return _odp_time_convert_to_ns(time); +} + _ODP_INLINE int odp_time_cmp(odp_time_t t2, odp_time_t t1) { if (odp_likely(t2.u64 > t1.u64)) diff --git a/platform/linux-dpdk/include/odp_packet_io_internal.h b/platform/linux-dpdk/include/odp_packet_io_internal.h index e52eb9840..0d2782101 100644 --- a/platform/linux-dpdk/include/odp_packet_io_internal.h +++ b/platform/linux-dpdk/include/odp_packet_io_internal.h @@ -32,6 +32,7 @@ extern "C" { #include <linux/if_ether.h> #include <sys/select.h> +#include <inttypes.h> #define PKTIO_MAX_QUEUES 64 #define PKTIO_LSO_PROFILES 16 @@ -218,7 +219,7 @@ static inline pktio_entry_t *get_pktio_entry(odp_pktio_t pktio) return NULL; if (odp_unlikely(_odp_typeval(pktio) > ODP_CONFIG_PKTIO_ENTRIES)) { - ODP_DBG("pktio limit %d/%d exceed\n", + ODP_DBG("pktio limit %" PRIuPTR "/%d exceed\n", _odp_typeval(pktio), ODP_CONFIG_PKTIO_ENTRIES); return NULL; } @@ -274,6 +275,10 @@ _odp_sock_recv_mq_tmo_try_int_driven(const struct odp_pktin_queue_t queues[], return 0; } +/* Setup PKTOUT with single queue for TM */ +int _odp_pktio_pktout_tm_config(odp_pktio_t pktio_hdl, + odp_pktout_queue_t *queue, bool reconf); + #ifdef __cplusplus } #endif diff --git a/platform/linux-dpdk/m4/configure.m4 b/platform/linux-dpdk/m4/configure.m4 index 3d50f2edc..1e6e8306c 100644 --- a/platform/linux-dpdk/m4/configure.m4 +++ b/platform/linux-dpdk/m4/configure.m4 @@ -83,6 +83,8 @@ AC_CONFIG_FILES([platform/linux-dpdk/Makefile platform/linux-dpdk/test/example/Makefile platform/linux-dpdk/test/example/classifier/Makefile platform/linux-dpdk/test/example/generator/Makefile + platform/linux-dpdk/test/example/ipsec_api/Makefile + platform/linux-dpdk/test/example/ipsec_crypto/Makefile platform/linux-dpdk/test/example/l2fwd_simple/Makefile platform/linux-dpdk/test/example/l3fwd/Makefile platform/linux-dpdk/test/example/packet/Makefile diff --git a/platform/linux-dpdk/m4/odp_libconfig.m4 b/platform/linux-dpdk/m4/odp_libconfig.m4 index f56946ec5..f2aa36946 100644 --- a/platform/linux-dpdk/m4/odp_libconfig.m4 +++ b/platform/linux-dpdk/m4/odp_libconfig.m4 @@ -3,7 +3,7 @@ ########################################################################## m4_define([_odp_config_version_generation], [0]) m4_define([_odp_config_version_major], [1]) -m4_define([_odp_config_version_minor], [11]) +m4_define([_odp_config_version_minor], [12]) m4_define([_odp_config_version], [_odp_config_version_generation._odp_config_version_major._odp_config_version_minor]) diff --git a/platform/linux-dpdk/odp_packet.c b/platform/linux-dpdk/odp_packet.c index 8030728dd..b0225629d 100644 --- a/platform/linux-dpdk/odp_packet.c +++ b/platform/linux-dpdk/odp_packet.c @@ -400,6 +400,7 @@ int odp_packet_trunc_head(odp_packet_t *pkt, uint32_t len, void **data_ptr, _copy_head_metadata(newhead, mb); prev->next = NULL; rte_pktmbuf_free(mb); + mb = newhead; *pkt = (odp_packet_t)newhead; packet_hdr(*pkt)->buf_hdr.totsize -= totsize_change; } else { diff --git a/platform/linux-dpdk/odp_pool.c b/platform/linux-dpdk/odp_pool.c index 24c9c2aec..3ac6abd03 100644 --- a/platform/linux-dpdk/odp_pool.c +++ b/platform/linux-dpdk/odp_pool.c @@ -679,7 +679,7 @@ odp_pool_t odp_pool_create(const char *name, const odp_pool_param_t *params) event_type = ODP_EVENT_PACKET; ODP_DBG("type: packet, name: %s, num: %u, len: %u, blk_size: %u, " - "uarea_size: %d, hdr_size: %d\n", pool_name, num, params->pkt.len, + "uarea_size: %d, hdr_size: %zu\n", pool_name, num, params->pkt.len, blk_size, params->pkt.uarea_size, hdr_size); break; case ODP_POOL_TIMEOUT: diff --git a/platform/linux-dpdk/odp_queue_basic.c b/platform/linux-dpdk/odp_queue_basic.c index 4a4388b2b..7145fb2ce 100644 --- a/platform/linux-dpdk/odp_queue_basic.c +++ b/platform/linux-dpdk/odp_queue_basic.c @@ -166,7 +166,7 @@ static int queue_init_global(void) queue_capa(&capa, 0); ODP_DBG("... done.\n"); - ODP_DBG(" queue_entry_t size %u\n", sizeof(queue_entry_t)); + ODP_DBG(" queue_entry_t size %zu\n", sizeof(queue_entry_t)); ODP_DBG(" max num queues %u\n", capa.max_queues); ODP_DBG(" max queue size %u\n", capa.plain.max_size); ODP_DBG(" max num lockfree %u\n", capa.plain.lockfree.max_num); @@ -697,7 +697,7 @@ static void queue_print(odp_queue_t handle) if (!odp_pktio_info(queue->s.pktout.pktio, &pktio_info)) ODP_PRINT(" pktout %s\n", pktio_info.name); } - ODP_PRINT(" timers %" PRIu32 "\n", + ODP_PRINT(" timers %" PRIu64 "\n", odp_atomic_load_u64(&queue->s.num_timers)); ODP_PRINT(" status %s\n", queue->s.status == QUEUE_STATUS_READY ? "ready" : diff --git a/platform/linux-dpdk/odp_queue_eventdev.c b/platform/linux-dpdk/odp_queue_eventdev.c index 5233031f6..96baffa6f 100644 --- a/platform/linux-dpdk/odp_queue_eventdev.c +++ b/platform/linux-dpdk/odp_queue_eventdev.c @@ -558,7 +558,7 @@ static int queue_init_global(void) queue_capa(&capa, 0); - ODP_DBG(" queue_entry_t size %u\n", sizeof(queue_entry_t)); + ODP_DBG(" queue_entry_t size %zu\n", sizeof(queue_entry_t)); ODP_DBG(" max num queues %u\n", capa.max_queues); ODP_DBG(" max plain queue size %u\n", capa.plain.max_size); ODP_DBG(" max num lockfree %u\n", capa.plain.lockfree.max_num); @@ -1048,7 +1048,7 @@ static void queue_print(odp_queue_t handle) if (!odp_pktio_info(queue->s.pktout.pktio, &pktio_info)) ODP_PRINT(" pktout %s\n", pktio_info.name); } - ODP_PRINT(" timers %" PRIu32 "\n", + ODP_PRINT(" timers %" PRIu64 "\n", odp_atomic_load_u64(&queue->s.num_timers)); ODP_PRINT(" status %s\n", queue->s.status == QUEUE_STATUS_READY ? "ready" : diff --git a/platform/linux-dpdk/odp_system_info.c b/platform/linux-dpdk/odp_system_info.c index b48275233..af07f387a 100644 --- a/platform/linux-dpdk/odp_system_info.c +++ b/platform/linux-dpdk/odp_system_info.c @@ -95,7 +95,7 @@ static uint64_t default_huge_page_size(void) while (fgets(str, sizeof(str), file) != NULL) { if (sscanf(str, "Hugepagesize: %8lu kB", &sz) == 1) { - ODP_DBG("defaut hp size is %" PRIu64 " kB\n", sz); + ODP_DBG("default hp size is %lu kB\n", sz); fclose(file); return (uint64_t)sz * 1024; } diff --git a/platform/linux-dpdk/odp_time.c b/platform/linux-dpdk/odp_time.c index 59aaf1c1a..1f3fb2719 100644 --- a/platform/linux-dpdk/odp_time.c +++ b/platform/linux-dpdk/odp_time.c @@ -1,4 +1,5 @@ /* Copyright (c) 2013-2018, Linaro Limited + * Copyright (c) 2021, Nokia * All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause @@ -17,6 +18,7 @@ #include <odp/api/plat/time_inlines.h> #include <rte_config.h> +#include <rte_atomic.h> #include <rte_cycles.h> ODP_STATIC_ASSERT(_ODP_TIMESPEC_SIZE >= (sizeof(struct timespec)), @@ -148,6 +150,16 @@ static inline odp_time_t time_cur_dpdk(void) return time; } +static inline odp_time_t time_cur_dpdk_strict(void) +{ + odp_time_t time; + + rte_mb(); + time.u64 = rte_get_timer_cycles() - _odp_time_glob.hw_start; + + return time; +} + static inline uint64_t time_res_dpdk(void) { return rte_get_timer_hz(); @@ -259,6 +271,7 @@ int _odp_time_init_global(void) if (is_dpdk_timer_cycles_support()) { _odp_time_glob.handler.time_cur = time_cur_dpdk; + _odp_time_glob.handler.time_cur_strict = time_cur_dpdk_strict; _odp_time_glob.handler.time_res = time_res_dpdk; _odp_time_glob.hw_freq_hz = time_res_dpdk(); _odp_time_glob.use_hw = 1; @@ -270,6 +283,7 @@ int _odp_time_init_global(void) } _odp_time_glob.handler.time_cur = _odp_time_cur_gen; + _odp_time_glob.handler.time_cur_strict = _odp_time_cur_gen_strict; _odp_time_glob.handler.time_res = time_res; if (_odp_cpu_has_global_time()) { diff --git a/platform/linux-dpdk/odp_timer.c b/platform/linux-dpdk/odp_timer.c index 28b4b17a9..b5367b4c2 100644 --- a/platform/linux-dpdk/odp_timer.c +++ b/platform/linux-dpdk/odp_timer.c @@ -259,8 +259,8 @@ int odp_timer_capability(odp_timer_clk_src_t clk_src, { uint64_t min_tmo = tmo_ticks_to_ns_round_up(MIN_TMO_CYCLES); - if (clk_src != ODP_CLOCK_CPU) { - ODP_ERR("Clock source not supported\n"); + if (clk_src != ODP_CLOCK_DEFAULT) { + ODP_ERR("Only ODP_CLOCK_DEFAULT supported. Requested %i.\n", clk_src); return -1; } @@ -289,8 +289,8 @@ int odp_timer_res_capability(odp_timer_clk_src_t clk_src, { uint64_t min_tmo = tmo_ticks_to_ns_round_up(MIN_TMO_CYCLES); - if (clk_src != ODP_CLOCK_CPU) { - ODP_ERR("Only CPU clock source supported\n"); + if (clk_src != ODP_CLOCK_DEFAULT) { + ODP_ERR("Only ODP_CLOCK_DEFAULT supported. Requested %i.\n", clk_src); return -1; } @@ -655,7 +655,7 @@ retry: ODP_DBG(" cur_tick %" PRIu64 ", abs_tick %" PRIu64 "\n", cur_tick, abs_tick); ODP_DBG(" num_retry %i\n", num_retry); - return ODP_TIMER_TOOEARLY; + return ODP_TIMER_TOO_NEAR; } odp_ticketlock_lock(&timer->lock); @@ -665,7 +665,7 @@ retry: odp_ticketlock_unlock(&timer->lock); /* Event missing, or timer already expired and * enqueued the event. */ - return ODP_TIMER_NOEVENT; + return ODP_TIMER_FAIL; } if (odp_unlikely(rte_timer_reset(&timer->rte_timer, rel_tick, SINGLE, @@ -699,7 +699,7 @@ retry: /* Timer was just about to expire. Too late to reset this timer. * Return code is NOEVENT, even when application did give * an event. */ - return ODP_TIMER_NOEVENT; + return ODP_TIMER_FAIL; } if (event) { diff --git a/platform/linux-dpdk/test/Makefile.am b/platform/linux-dpdk/test/Makefile.am index b21fd5314..1496c0558 100644 --- a/platform/linux-dpdk/test/Makefile.am +++ b/platform/linux-dpdk/test/Makefile.am @@ -1,10 +1,17 @@ include $(top_srcdir)/test/Makefile.inc TESTS_ENVIRONMENT += TEST_DIR=${top_builddir}/test/validation +if WITH_OPENSSL +TESTS_ENVIRONMENT += WITH_OPENSSL=1 +else +TESTS_ENVIRONMENT += WITH_OPENSSL=0 +endif + SUBDIRS = +TESTS = if test_vald -TESTS = validation/api/pktio/pktio_run.sh +TESTS += validation/api/pktio/pktio_run.sh test_SCRIPTS = $(dist_check_SCRIPTS) @@ -36,25 +43,3 @@ if test_installdir installcheck-local: $(DESTDIR)/$(testdir)/run-test.sh $(TESTNAME) endif - -# If building out-of-tree, make check will not copy the scripts and data to the -# $(builddir) assuming that all commands are run locally. However this prevents -# running tests on a remote target using LOG_COMPILER. -# So copy all script and data files explicitly here. -all-local: - if [ "x$(srcdir)" != "x$(builddir)" ]; then \ - for f in $(dist_check_SCRIPTS); do \ - if [ -e $(srcdir)/$$f ]; then \ - mkdir -p $(builddir)/$$(dirname $$f); \ - cp -f $(srcdir)/$$f $(builddir)/$$f; \ - fi \ - done \ - fi -clean-local: - if [ "x$(srcdir)" != "x$(builddir)" ]; then \ - for f in $(dist_check_SCRIPTS); do \ - rm -f $(builddir)/$$f; \ - done \ - fi - -.NOTPARALLEL: diff --git a/platform/linux-dpdk/test/example/Makefile.am b/platform/linux-dpdk/test/example/Makefile.am index 22b254cd7..947647cd4 100644 --- a/platform/linux-dpdk/test/example/Makefile.am +++ b/platform/linux-dpdk/test/example/Makefile.am @@ -1,6 +1,8 @@ SUBDIRS = \ classifier \ generator \ + ipsec_api \ + ipsec_crypto \ l2fwd_simple \ l3fwd \ packet \ diff --git a/platform/linux-dpdk/test/example/ipsec_api/Makefile.am b/platform/linux-dpdk/test/example/ipsec_api/Makefile.am new file mode 100644 index 000000000..101c97cdf --- /dev/null +++ b/platform/linux-dpdk/test/example/ipsec_api/Makefile.am @@ -0,0 +1,23 @@ +EXTRA_DIST = pktio_env + +# If building out-of-tree, make check will not copy the scripts and data to the +# $(builddir) assuming that all commands are run locally. However this prevents +# running tests on a remote target using LOG_COMPILER. +# So copy all script and data files explicitly here. +all-local: + if [ "x$(srcdir)" != "x$(builddir)" ]; then \ + for f in $(EXTRA_DIST); do \ + if [ -e $(srcdir)/$$f ]; then \ + mkdir -p $(builddir)/$$(dirname $$f); \ + cp -f $(srcdir)/$$f $(builddir)/$$f; \ + fi \ + done \ + fi +clean-local: + if [ "x$(srcdir)" != "x$(builddir)" ]; then \ + for f in $(EXTRA_DIST); do \ + rm -f $(builddir)/$$f; \ + done \ + fi + +.NOTPARALLEL: diff --git a/platform/linux-dpdk/test/example/ipsec_api/pktio_env b/platform/linux-dpdk/test/example/ipsec_api/pktio_env new file mode 100644 index 000000000..c647f6bf2 --- /dev/null +++ b/platform/linux-dpdk/test/example/ipsec_api/pktio_env @@ -0,0 +1,66 @@ +#!/bin/sh +# +# Copyright (C) 2021, Marvell +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +# Script to setup interfaces used for running application on linux-dpdk. +# +# ipsec_api application uses two loop devices loop0 and loop1. +# + +if [ "$0" == "$BASH_SOURCE" ]; then + echo "Error: Platform specific env file has to be sourced." + exit 1 +fi + +# Absolute path to the .env file. +LINUX_ENV_PATH=$PWD/../../platform/linux-dpdk/test + +TESTENV="tests-linux-dpdk.env" + +if [ -f $LINUX_ENV_PATH/$TESTENV ]; then + source $LINUX_ENV_PATH/$TESTENV +else + echo "BUG: unable to find $TESTENV!" + echo "$TESTENV has to be in following directory: " + echo " $LINUX_ENV_PATH" + exit 1 +fi + +# Skip IPsec example tests when there's no OpenSSL. +if [ -n "$WITH_OPENSSL" ] && [ ${WITH_OPENSSL} -eq 0 ]; then + echo "Crypto not supported. Skipping." + exit 77 +fi + +IF0=p7p1 +IF1=p8p1 + +NEXT_HOP_MAC0=08:00:27:76:B5:E0 +NEXT_HOP_MAC1=08:00:27:F5:8B:DB + +LIF0=loop1 +LIF1=loop2 + +IF_LIST=$LIF0,$LIF1 +ROUTE_IF_INB=$LIF0 +ROUTE_IF_OUTB=$LIF1 +OUT_IF=$LIF1 +IN_IF=$LIF0 + +validate_result() +{ + return 0 +} + +setup_interfaces() +{ + return 0 +} + +cleanup_interfaces() +{ + return 0 +} diff --git a/platform/linux-dpdk/test/example/ipsec_crypto/Makefile.am b/platform/linux-dpdk/test/example/ipsec_crypto/Makefile.am new file mode 100644 index 000000000..101c97cdf --- /dev/null +++ b/platform/linux-dpdk/test/example/ipsec_crypto/Makefile.am @@ -0,0 +1,23 @@ +EXTRA_DIST = pktio_env + +# If building out-of-tree, make check will not copy the scripts and data to the +# $(builddir) assuming that all commands are run locally. However this prevents +# running tests on a remote target using LOG_COMPILER. +# So copy all script and data files explicitly here. +all-local: + if [ "x$(srcdir)" != "x$(builddir)" ]; then \ + for f in $(EXTRA_DIST); do \ + if [ -e $(srcdir)/$$f ]; then \ + mkdir -p $(builddir)/$$(dirname $$f); \ + cp -f $(srcdir)/$$f $(builddir)/$$f; \ + fi \ + done \ + fi +clean-local: + if [ "x$(srcdir)" != "x$(builddir)" ]; then \ + for f in $(EXTRA_DIST); do \ + rm -f $(builddir)/$$f; \ + done \ + fi + +.NOTPARALLEL: diff --git a/platform/linux-dpdk/test/example/ipsec_crypto/pktio_env b/platform/linux-dpdk/test/example/ipsec_crypto/pktio_env new file mode 100644 index 000000000..1c6e7d172 --- /dev/null +++ b/platform/linux-dpdk/test/example/ipsec_crypto/pktio_env @@ -0,0 +1,72 @@ +#!/bin/sh +# +# Copyright (C) 2021, Marvell +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +# Script to setup interfaces used for running application on linux-dpdk. +# +# ipsec_api application uses two loop devices loop0 and loop1. +# + +if [ "$0" == "$BASH_SOURCE" ]; then + echo "Error: Platform specific env file has to be sourced." + exit 1 +fi + +# Absolute path to the .env file. +LINUX_ENV_PATH=$PWD/../../platform/linux-dpdk/test + +TESTENV="tests-linux-dpdk.env" + +if [ -f $LINUX_ENV_PATH/$TESTENV ]; then + source $LINUX_ENV_PATH/$TESTENV +else + echo "BUG: unable to find $TESTENV!" + echo "$TESTENV has to be in following directory: " + echo " $LINUX_ENV_PATH" + exit 1 +fi + +# Skip IPsec example tests when there's no OpenSSL. +if [ -n "$WITH_OPENSSL" ] && [ ${WITH_OPENSSL} -eq 0 ]; then + echo "Crypto not supported. Skipping." + exit 77 +fi + +# Skip live and router mode tests. +if [ ${IPSEC_APP_MODE} -eq 1 ] || [ ${IPSEC_APP_MODE} -eq 2 ]; then + echo "Live / Router mode test. Skipping." + exit 77 +fi + +IF0=p7p1 +IF1=p8p1 + +NEXT_HOP_MAC0=08:00:27:76:B5:E0 +NEXT_HOP_MAC1=08:00:27:F5:8B:DB + +LIF0=loop1 +LIF1=loop2 + +IF_LIST=$LIF0,$LIF1 +ROUTE_IF_INB=$LIF0 +ROUTE_IF_OUTB=$LIF1 +OUT_IF=$LIF1 +IN_IF=$LIF0 + +validate_result() +{ + return 0 +} + +setup_interfaces() +{ + return 0 +} + +cleanup_interfaces() +{ + return 0 +} diff --git a/platform/linux-dpdk/test/sched-basic.conf b/platform/linux-dpdk/test/sched-basic.conf index c54089a0d..8a46a3ccc 100644 --- a/platform/linux-dpdk/test/sched-basic.conf +++ b/platform/linux-dpdk/test/sched-basic.conf @@ -1,6 +1,6 @@ # Mandatory fields odp_implementation = "linux-dpdk" -config_file_version = "0.1.11" +config_file_version = "0.1.12" sched_basic: { # Test scheduler with an odd spread value diff --git a/platform/linux-generic/Makefile.am b/platform/linux-generic/Makefile.am index 2181abd26..e654381e6 100644 --- a/platform/linux-generic/Makefile.am +++ b/platform/linux-generic/Makefile.am @@ -293,7 +293,7 @@ __LIB__libodp_linux_la_SOURCES += arch/aarch64/odp_atomic.c \ arch/default/odp_hash_crc32.c \ arch/aarch64/odp_sysinfo_parse.c odpapiabiarchinclude_HEADERS += arch/default/odp/api/abi/cpu_inlines.h \ - arch/default/odp/api/abi/cpu_time.h \ + arch/aarch64/odp/api/abi/cpu_time.h \ arch/aarch64/odp/api/abi/hash_crc32.h if !ODP_ABI_COMPAT odpapiabiarchinclude_HEADERS += arch/default/odp/api/abi/atomic_generic.h \ diff --git a/platform/linux-generic/arch/aarch64/odp/api/abi/cpu_time.h b/platform/linux-generic/arch/aarch64/odp/api/abi/cpu_time.h new file mode 100644 index 000000000..781ee683c --- /dev/null +++ b/platform/linux-generic/arch/aarch64/odp/api/abi/cpu_time.h @@ -0,0 +1,50 @@ +/* Copyright (c) 2021, Nokia + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ODP_API_ABI_CPU_TIME_H_ +#define ODP_API_ABI_CPU_TIME_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdint.h> + +static inline uint64_t _odp_cpu_global_time(void) +{ + uint64_t cntvct; + + __asm__ volatile("mrs %0, cntvct_el0" : "=r"(cntvct) : : "memory"); + + return cntvct; +} + +static inline uint64_t _odp_cpu_global_time_strict(void) +{ + uint64_t cntvct; + + __asm__ volatile("isb" ::: "memory"); + __asm__ volatile("mrs %0, cntvct_el0" : "=r"(cntvct) : : "memory"); + + return cntvct; +} + +static inline uint64_t _odp_cpu_global_time_freq(void) +{ + uint64_t cntfrq; + + __asm__ volatile("mrs %0, cntfrq_el0" : "=r"(cntfrq) : : ); + + return cntfrq; +} + +int _odp_cpu_has_global_time(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/platform/linux-generic/arch/aarch64/odp_global_time.c b/platform/linux-generic/arch/aarch64/odp_global_time.c index fa59f5a15..53561b00c 100644 --- a/platform/linux-generic/arch/aarch64/odp_global_time.c +++ b/platform/linux-generic/arch/aarch64/odp_global_time.c @@ -4,33 +4,8 @@ * SPDX-License-Identifier: BSD-3-Clause */ -#include <odp_posix_extensions.h> - -#include <time.h> - -#include <odp_debug_internal.h> #include <odp/api/abi/cpu_time.h> -#include <odp/visibility_begin.h> - -uint64_t _odp_cpu_global_time(void) -{ - uint64_t cntvct; - - /* - * To be consistent with other architectures, do not issue a - * serializing instruction, e.g. ISB, before reading this - * sys reg. - */ - - /* Memory clobber to minimize optimization around load from sys reg. */ - __asm__ volatile("mrs %0, cntvct_el0" : "=r"(cntvct) : : "memory"); - - return cntvct; -} - -#include <odp/visibility_end.h> - int _odp_cpu_has_global_time(void) { uint64_t hz = _odp_cpu_global_time_freq(); @@ -48,12 +23,3 @@ int _odp_cpu_has_global_time(void) */ return hz >= 1000000 && hz <= 6000000000; } - -uint64_t _odp_cpu_global_time_freq(void) -{ - uint64_t cntfrq; - - __asm__ volatile("mrs %0, cntfrq_el0" : "=r"(cntfrq) : : ); - - return cntfrq; -} diff --git a/platform/linux-generic/arch/default/odp/api/abi/cpu_time.h b/platform/linux-generic/arch/default/odp/api/abi/cpu_time.h index 09138e70a..24e1c7d33 100644 --- a/platform/linux-generic/arch/default/odp/api/abi/cpu_time.h +++ b/platform/linux-generic/arch/default/odp/api/abi/cpu_time.h @@ -15,6 +15,7 @@ extern "C" { int _odp_cpu_has_global_time(void); uint64_t _odp_cpu_global_time(void); +uint64_t _odp_cpu_global_time_strict(void); uint64_t _odp_cpu_global_time_freq(void); #ifdef __cplusplus diff --git a/platform/linux-generic/arch/default/odp_global_time.c b/platform/linux-generic/arch/default/odp_global_time.c index facffea7d..ee835413f 100644 --- a/platform/linux-generic/arch/default/odp_global_time.c +++ b/platform/linux-generic/arch/default/odp_global_time.c @@ -13,6 +13,11 @@ uint64_t _odp_cpu_global_time(void) return 0; } +uint64_t _odp_cpu_global_time_strict(void) +{ + return 0; +} + #include <odp/visibility_end.h> int _odp_cpu_has_global_time(void) diff --git a/platform/linux-generic/arch/x86/odp/api/abi/cpu_time.h b/platform/linux-generic/arch/x86/odp/api/abi/cpu_time.h index 05ff0db94..c74c4d606 100644 --- a/platform/linux-generic/arch/x86/odp/api/abi/cpu_time.h +++ b/platform/linux-generic/arch/x86/odp/api/abi/cpu_time.h @@ -19,6 +19,12 @@ static inline uint64_t _odp_cpu_global_time(void) return _odp_cpu_rdtsc(); } +static inline uint64_t _odp_cpu_global_time_strict(void) +{ + __atomic_thread_fence(__ATOMIC_SEQ_CST); + return _odp_cpu_rdtsc(); +} + int _odp_cpu_has_global_time(void); uint64_t _odp_cpu_global_time_freq(void); diff --git a/platform/linux-generic/include/odp/api/plat/time_inlines.h b/platform/linux-generic/include/odp/api/plat/time_inlines.h index 1ca495065..bb2913532 100644 --- a/platform/linux-generic/include/odp/api/plat/time_inlines.h +++ b/platform/linux-generic/include/odp/api/plat/time_inlines.h @@ -1,5 +1,5 @@ /* Copyright (c) 2018, Linaro Limited - * Copyright (c) 2020, Nokia + * Copyright (c) 2020-2021, Nokia * All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause @@ -46,6 +46,18 @@ static inline odp_time_t _odp_time_cur(void) return _odp_timespec_cur(); } +static inline odp_time_t _odp_time_cur_strict(void) +{ + if (_odp_time_glob.use_hw) { + odp_time_t time; + + time.count = _odp_cpu_global_time_strict() - _odp_time_glob.hw_start; + return time; + } + + return _odp_timespec_cur(); +} + static inline uint64_t _odp_time_hw_to_ns(odp_time_t time) { uint64_t nsec; @@ -79,6 +91,12 @@ static inline uint64_t _odp_time_convert_to_ns(odp_time_t time) #define odp_time_to_ns __odp_time_to_ns #define odp_time_local_ns __odp_time_local_ns #define odp_time_global_ns __odp_time_global_ns + + #define odp_time_local_strict __odp_time_local_strict + #define odp_time_global_strict __odp_time_global_strict + #define odp_time_local_strict_ns __odp_time_local_strict_ns + #define odp_time_global_strict_ns __odp_time_global_strict_ns + #define odp_time_cmp __odp_time_cmp #define odp_time_diff __odp_time_diff #define odp_time_sum __odp_time_sum @@ -97,9 +115,14 @@ _ODP_INLINE odp_time_t odp_time_global(void) return _odp_time_cur(); } -_ODP_INLINE uint64_t odp_time_to_ns(odp_time_t time) +_ODP_INLINE odp_time_t odp_time_local_strict(void) { - return _odp_time_convert_to_ns(time); + return _odp_time_cur_strict(); +} + +_ODP_INLINE odp_time_t odp_time_global_strict(void) +{ + return _odp_time_cur_strict(); } _ODP_INLINE uint64_t odp_time_local_ns(void) @@ -112,6 +135,21 @@ _ODP_INLINE uint64_t odp_time_global_ns(void) return _odp_time_convert_to_ns(_odp_time_cur()); } +_ODP_INLINE uint64_t odp_time_local_strict_ns(void) +{ + return _odp_time_convert_to_ns(_odp_time_cur_strict()); +} + +_ODP_INLINE uint64_t odp_time_global_strict_ns(void) +{ + return _odp_time_convert_to_ns(_odp_time_cur_strict()); +} + +_ODP_INLINE uint64_t odp_time_to_ns(odp_time_t time) +{ + return _odp_time_convert_to_ns(time); +} + _ODP_INLINE int odp_time_cmp(odp_time_t t2, odp_time_t t1) { if (odp_likely(t2.u64 > t1.u64)) diff --git a/platform/linux-generic/include/odp_debug_internal.h b/platform/linux-generic/include/odp_debug_internal.h index dfad95b19..5027cfe4a 100644 --- a/platform/linux-generic/include/odp_debug_internal.h +++ b/platform/linux-generic/include/odp_debug_internal.h @@ -33,8 +33,15 @@ extern "C" { * level 0 to N. */ #define CONFIG_DEBUG_LEVEL 0 +ODP_PRINTF_FORMAT(1, 2) +static inline void check_printf_format(const char *fmt, ...) +{ + (void)fmt; +} + #define _ODP_LOG_FN(level, fmt, ...) \ do { \ + check_printf_format(fmt, ##__VA_ARGS__); \ if (_odp_this_thread && _odp_this_thread->log_fn) \ _odp_this_thread->log_fn(level, fmt, ##__VA_ARGS__); \ else \ diff --git a/platform/linux-generic/include/odp_ipsec_internal.h b/platform/linux-generic/include/odp_ipsec_internal.h index 2509d22ab..96153007f 100644 --- a/platform/linux-generic/include/odp_ipsec_internal.h +++ b/platform/linux-generic/include/odp_ipsec_internal.h @@ -1,4 +1,5 @@ /* Copyright (c) 2017-2018, Linaro Limited + * Copyright (c) 2018, 2020-2021, Nokia * All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause @@ -169,7 +170,7 @@ struct ipsec_sa_s { struct { odp_ipsec_frag_mode_t frag_mode; - uint32_t mtu; + odp_atomic_u32_t mtu; union { struct { @@ -196,13 +197,15 @@ struct ipsec_sa_s { odp_atomic_u64_t hard_exp_pkts_err; /* - * Track error packets after lifetime check is done. + * Track error packets and bytes after lifetime check is done. * Required since, the stats tracking lifetime is being * used for SA success packets stats. */ odp_atomic_u64_t post_lifetime_err_pkts; + odp_atomic_u64_t post_lifetime_err_bytes; } stats; + uint32_t next_sa; odp_ipsec_sa_param_t param; }; @@ -302,10 +305,16 @@ uint16_t _odp_ipsec_sa_alloc_ipv4_id(ipsec_sa_t *ipsec_sa); int _odp_ipsec_try_inline(odp_packet_t *pkt); /** - * Get number of packets successfully processed by the SA + * Populate number of packets and bytes of data successfully processed by the SA + * in the odp_ipsec_stats_t structure passed. * */ -uint64_t _odp_ipsec_sa_stats_pkts(ipsec_sa_t *sa); +void _odp_ipsec_sa_stats_pkts(ipsec_sa_t *sa, odp_ipsec_stats_t *stats); + +/** + * Return true if IPsec operates in sync mode in the given direction. + */ +odp_bool_t _odp_ipsec_is_sync_mode(odp_ipsec_dir_t dir); /** * @} diff --git a/platform/linux-generic/include/odp_packet_io_internal.h b/platform/linux-generic/include/odp_packet_io_internal.h index 7bbd78ab0..c5a51d11d 100644 --- a/platform/linux-generic/include/odp_packet_io_internal.h +++ b/platform/linux-generic/include/odp_packet_io_internal.h @@ -36,6 +36,7 @@ extern "C" { #include <net/if.h> #include <linux/if_ether.h> #include <sys/select.h> +#include <inttypes.h> #define PKTIO_MAX_QUEUES 64 #define PKTIO_LSO_PROFILES 16 @@ -237,7 +238,7 @@ static inline pktio_entry_t *get_pktio_entry(odp_pktio_t pktio) return NULL; if (odp_unlikely(_odp_typeval(pktio) > ODP_CONFIG_PKTIO_ENTRIES)) { - ODP_DBG("pktio limit %d/%d exceed\n", + ODP_DBG("pktio limit %" PRIuPTR "/%d exceed\n", _odp_typeval(pktio), ODP_CONFIG_PKTIO_ENTRIES); return NULL; } @@ -302,6 +303,10 @@ int _odp_sock_recv_mq_tmo_try_int_driven(const struct odp_pktin_queue_t queues[] uint64_t usecs, int *trial_successful); +/* Setup PKTOUT with single queue for TM */ +int _odp_pktio_pktout_tm_config(odp_pktio_t pktio_hdl, + odp_pktout_queue_t *queue, bool reconf); + #ifdef __cplusplus } #endif diff --git a/platform/linux-generic/m4/configure.m4 b/platform/linux-generic/m4/configure.m4 index 535d43608..01593baea 100644 --- a/platform/linux-generic/m4/configure.m4 +++ b/platform/linux-generic/m4/configure.m4 @@ -45,6 +45,8 @@ AC_CONFIG_FILES([platform/linux-generic/Makefile platform/linux-generic/test/example/Makefile platform/linux-generic/test/example/classifier/Makefile platform/linux-generic/test/example/generator/Makefile + platform/linux-generic/test/example/ipsec_api/Makefile + platform/linux-generic/test/example/ipsec_crypto/Makefile platform/linux-generic/test/example/l2fwd_simple/Makefile platform/linux-generic/test/example/l3fwd/Makefile platform/linux-generic/test/example/packet/Makefile diff --git a/platform/linux-generic/m4/odp_libconfig.m4 b/platform/linux-generic/m4/odp_libconfig.m4 index 7a0b45497..ecfb28b7f 100644 --- a/platform/linux-generic/m4/odp_libconfig.m4 +++ b/platform/linux-generic/m4/odp_libconfig.m4 @@ -3,7 +3,7 @@ ########################################################################## m4_define([_odp_config_version_generation], [0]) m4_define([_odp_config_version_major], [1]) -m4_define([_odp_config_version_minor], [15]) +m4_define([_odp_config_version_minor], [16]) m4_define([_odp_config_version], [_odp_config_version_generation._odp_config_version_major._odp_config_version_minor]) diff --git a/platform/linux-generic/odp_comp.c b/platform/linux-generic/odp_comp.c index 8e1de69c2..685c9098a 100644 --- a/platform/linux-generic/odp_comp.c +++ b/platform/linux-generic/odp_comp.c @@ -133,7 +133,7 @@ static void process_input(odp_packet_t pkt_out, do { out_data = odp_packet_offset(pkt_out, start, &out_len, &cur_seg); - ODP_DBG("out_data 0x%x seg_data_ptr 0x%x out_len %d seg 0x%x\n", + ODP_DBG("out_data %p seg_data_ptr %p out_len %d seg %p\n", out_data, odp_packet_seg_data(pkt_out, cur_seg), out_len, cur_seg); @@ -258,7 +258,7 @@ static int deflate_comp(odp_packet_t pkt_in, read, &in_len, &in_seg); - ODP_DBG("data 0x%x in_len %d seg 0x%x len %d\n", + ODP_DBG("data %p in_len %d seg %p len %d\n", data, in_len, in_seg, len); if (in_len > len) diff --git a/platform/linux-generic/odp_fdserver.c b/platform/linux-generic/odp_fdserver.c index 9e0d75de3..3103ddd5c 100644 --- a/platform/linux-generic/odp_fdserver.c +++ b/platform/linux-generic/odp_fdserver.c @@ -246,10 +246,14 @@ static int get_socket(void) int len; /* construct the named socket path: */ - snprintf(sockpath, FDSERVER_SOCKPATH_MAXLEN, FDSERVER_SOCK_FORMAT, - odp_global_ro.shm_dir, - odp_global_ro.uid, - odp_global_ro.main_pid); + len = snprintf(sockpath, FDSERVER_SOCKPATH_MAXLEN, FDSERVER_SOCK_FORMAT, + odp_global_ro.shm_dir, odp_global_ro.uid, + odp_global_ro.main_pid); + + if (len >= FDSERVER_SOCKPATH_MAXLEN || len >= (int)sizeof(remote.sun_path)) { + ODP_ERR("path too long\n"); + return -1; + } s_sock = socket(AF_UNIX, SOCK_STREAM, 0); if (s_sock == -1) { @@ -561,7 +565,7 @@ int _odp_fdserver_init_global(void) int sock; struct sockaddr_un local; pid_t server_pid; - int res; + int len, res; snprintf(sockpath, FDSERVER_SOCKPATH_MAXLEN, FDSERVER_SOCKDIR_FORMAT, odp_global_ro.shm_dir, @@ -570,10 +574,14 @@ int _odp_fdserver_init_global(void) mkdir(sockpath, 0744); /* construct the server named socket path: */ - snprintf(sockpath, FDSERVER_SOCKPATH_MAXLEN, FDSERVER_SOCK_FORMAT, - odp_global_ro.shm_dir, - odp_global_ro.uid, - odp_global_ro.main_pid); + len = snprintf(sockpath, FDSERVER_SOCKPATH_MAXLEN, FDSERVER_SOCK_FORMAT, + odp_global_ro.shm_dir, odp_global_ro.uid, + odp_global_ro.main_pid); + + if (len >= FDSERVER_SOCKPATH_MAXLEN || len >= (int)sizeof(local.sun_path)) { + ODP_ERR("path too long\n"); + return -1; + } /* create UNIX domain socket: */ sock = socket(AF_UNIX, SOCK_STREAM, 0); diff --git a/platform/linux-generic/odp_ipsec.c b/platform/linux-generic/odp_ipsec.c index 5379a23d0..ed19392c9 100644 --- a/platform/linux-generic/odp_ipsec.c +++ b/platform/linux-generic/odp_ipsec.c @@ -19,6 +19,7 @@ #include <odp_ipsec_internal.h> #include <odp/api/plat/queue_inlines.h> #include <odp_classification_internal.h> +#include <odp_libconfig_internal.h> #include <protocols/eth.h> #include <protocols/ip.h> @@ -28,9 +29,42 @@ #include <errno.h> #include <string.h> +typedef enum { + IPSEC_ORDERING_NONE = 0, + IPSEC_ORDERING_SIMPLE, +} ordering_mode_t; + +typedef struct { + ordering_mode_t inbound_ordering_mode; + ordering_mode_t outbound_ordering_mode; + odp_ipsec_config_t ipsec_config; +} ipsec_global_t; + +static ipsec_global_t *ipsec_global; + static odp_ipsec_config_t *ipsec_config; /* + * Wait until the ordered scheduling context of this thread corresponds + * to the head of its input queue. Do nothing if ordering is not requested + * or if not holding an ordered context. + */ +static void wait_for_order(ordering_mode_t mode) +{ + if (mode == IPSEC_ORDERING_NONE) + return; + _odp_sched_fn->order_lock(); + /* + * We rely on the unlock being no-op, so let's not even bother + * calling it. Unlock cannot really be anything but a no-op since + * the scheduler cannot let other threads to continue until at + * scheduling context release time. + * + * _odp_sched_fn->order_unlock(); + */ +} + +/* * Set cabability bits for algorithms that are defined for use with IPsec * and for which the IPsec crypto or auth capability function returns * at least one supported instance. @@ -240,6 +274,14 @@ int odp_ipsec_config(const odp_ipsec_config_t *config) return 0; } +odp_bool_t _odp_ipsec_is_sync_mode(odp_ipsec_dir_t dir) +{ + return ((dir == ODP_IPSEC_DIR_INBOUND && + ipsec_config->inbound_mode == ODP_IPSEC_OP_MODE_SYNC) || + (dir == ODP_IPSEC_DIR_OUTBOUND && + ipsec_config->outbound_mode == ODP_IPSEC_OP_MODE_SYNC)); +} + static odp_ipsec_packet_result_t *ipsec_pkt_result(odp_packet_t packet) { ODP_ASSERT(ODP_EVENT_PACKET_IPSEC == @@ -409,7 +451,7 @@ static inline ipsec_sa_t *ipsec_get_sa(odp_ipsec_sa_t sa, return NULL; } } else { - ipsec_sa = _odp_ipsec_sa_use(sa); + ipsec_sa = _odp_ipsec_sa_entry_from_hdl(sa); ODP_ASSERT(NULL != ipsec_sa); if (ipsec_sa->proto != proto || ipsec_sa->spi != spi) { @@ -710,6 +752,7 @@ ipsec_sa_err_stats_update(ipsec_sa_t *sa, odp_ipsec_op_status_t *status) static ipsec_sa_t *ipsec_in_single(odp_packet_t pkt, odp_ipsec_sa_t sa, odp_packet_t *pkt_out, + odp_bool_t enqueue_op, odp_ipsec_op_status_t *status) { ipsec_state_t state; @@ -796,10 +839,15 @@ static ipsec_sa_t *ipsec_in_single(odp_packet_t pkt, goto exit; } - if (_odp_ipsec_sa_replay_update(ipsec_sa, - state.in.seq_no, - status) < 0) - goto exit; + if (ipsec_sa->antireplay) { + if (enqueue_op) + wait_for_order(ipsec_global->inbound_ordering_mode); + + if (_odp_ipsec_sa_replay_update(ipsec_sa, + state.in.seq_no, + status) < 0) + goto exit; + } if (_odp_ipsec_sa_lifetime_update(ipsec_sa, state.stats_length, @@ -908,8 +956,11 @@ static ipsec_sa_t *ipsec_in_single(odp_packet_t pkt, goto exit; post_lifetime_err_cnt_update: - if (ipsec_config->stats_en) + if (ipsec_config->stats_en) { odp_atomic_inc_u64(&ipsec_sa->stats.post_lifetime_err_pkts); + odp_atomic_add_u64(&ipsec_sa->stats.post_lifetime_err_bytes, + state.stats_length); + } exit: *pkt_out = pkt; @@ -1159,6 +1210,7 @@ static int ipsec_out_esp(odp_packet_t *pkt, odp_crypto_packet_op_param_t *param, odp_ipsec_op_status_t *status, uint32_t mtu, + odp_bool_t enqueue_op, const odp_ipsec_out_opt_t *opt) { _odp_esphdr_t esp; @@ -1204,6 +1256,8 @@ static int ipsec_out_esp(odp_packet_t *pkt, return -1; } + if (enqueue_op) + wait_for_order(ipsec_global->outbound_ordering_mode); seq_no = ipsec_seq_no(ipsec_sa); if (ipsec_out_iv(state, ipsec_sa, seq_no) < 0) { @@ -1331,7 +1385,8 @@ static int ipsec_out_ah(odp_packet_t *pkt, ipsec_sa_t *ipsec_sa, odp_crypto_packet_op_param_t *param, odp_ipsec_op_status_t *status, - uint32_t mtu) + uint32_t mtu, + odp_bool_t enqueue_op) { _odp_ahhdr_t ah; unsigned hdr_len = _ODP_AHHDR_LEN + ipsec_sa->esp_iv_len + @@ -1345,6 +1400,8 @@ static int ipsec_out_ah(odp_packet_t *pkt, return -1; } + if (enqueue_op) + wait_for_order(ipsec_global->outbound_ordering_mode); seq_no = ipsec_seq_no(ipsec_sa); memset(&ah, 0, sizeof(ah)); @@ -1489,6 +1546,7 @@ static ipsec_sa_t *ipsec_out_single(odp_packet_t pkt, odp_ipsec_sa_t sa, odp_packet_t *pkt_out, const odp_ipsec_out_opt_t *opt, + odp_bool_t enqueue_op, odp_ipsec_op_status_t *status) { ipsec_state_t state; @@ -1533,7 +1591,7 @@ static ipsec_sa_t *ipsec_out_single(odp_packet_t pkt, frag_mode = opt->flag.frag_mode ? opt->frag_mode : ipsec_sa->out.frag_mode; if (frag_mode == ODP_IPSEC_FRAG_CHECK) - mtu = ipsec_sa->out.mtu; + mtu = odp_atomic_load_u32(&ipsec_sa->out.mtu); else mtu = UINT32_MAX; @@ -1594,9 +1652,10 @@ static ipsec_sa_t *ipsec_out_single(odp_packet_t pkt, if (ODP_IPSEC_ESP == ipsec_sa->proto) { rc = ipsec_out_esp(&pkt, &state, ipsec_sa, ¶m, status, mtu, - opt); + enqueue_op, opt); } else if (ODP_IPSEC_AH == ipsec_sa->proto) { - rc = ipsec_out_ah(&pkt, &state, ipsec_sa, ¶m, status, mtu); + rc = ipsec_out_ah(&pkt, &state, ipsec_sa, ¶m, status, mtu, + enqueue_op); } else { status->error.alg = 1; goto exit; @@ -1652,8 +1711,11 @@ static ipsec_sa_t *ipsec_out_single(odp_packet_t pkt, goto exit; post_lifetime_err_cnt_update: - if (ipsec_config->stats_en) + if (ipsec_config->stats_en) { odp_atomic_inc_u64(&ipsec_sa->stats.post_lifetime_err_pkts); + odp_atomic_add_u64(&ipsec_sa->stats.post_lifetime_err_bytes, + state.stats_length); + } exit: *pkt_out = pkt; @@ -1686,7 +1748,7 @@ int odp_ipsec_in(const odp_packet_t pkt_in[], int num_in, ODP_ASSERT(ODP_IPSEC_SA_INVALID != sa); } - ipsec_sa = ipsec_in_single(pkt, sa, &pkt, &status); + ipsec_sa = ipsec_in_single(pkt, sa, &pkt, false, &status); packet_subtype_set(pkt, ODP_EVENT_PACKET_IPSEC); result = ipsec_pkt_result(pkt); @@ -1702,8 +1764,12 @@ int odp_ipsec_in(const odp_packet_t pkt_in[], int num_in, out_pkt++; sa_idx += sa_inc; - /* Last thing */ - if (NULL != ipsec_sa) + /* + * We need to decrease SA use count only if the SA was not + * provided to us by the caller but was found through our own + * SA lookup that increased the use count. + */ + if (sa == ODP_IPSEC_SA_INVALID && ipsec_sa) _odp_ipsec_sa_unuse(ipsec_sa); } @@ -1746,7 +1812,7 @@ int odp_ipsec_out(const odp_packet_t pkt_in[], int num_in, else opt = ¶m->opt[opt_idx]; - ipsec_sa = ipsec_out_single(pkt, sa, &pkt, opt, &status); + ipsec_sa = ipsec_out_single(pkt, sa, &pkt, opt, false, &status); ODP_ASSERT(NULL != ipsec_sa); packet_subtype_set(pkt, ODP_EVENT_PACKET_IPSEC); @@ -1794,7 +1860,7 @@ int odp_ipsec_in_enq(const odp_packet_t pkt_in[], int num_in, ODP_ASSERT(ODP_IPSEC_SA_INVALID != sa); } - ipsec_sa = ipsec_in_single(pkt, sa, &pkt, &status); + ipsec_sa = ipsec_in_single(pkt, sa, &pkt, true, &status); packet_subtype_set(pkt, ODP_EVENT_PACKET_IPSEC); result = ipsec_pkt_result(pkt); @@ -1815,8 +1881,12 @@ int odp_ipsec_in_enq(const odp_packet_t pkt_in[], int num_in, in_pkt++; sa_idx += sa_inc; - /* Last thing */ - if (NULL != ipsec_sa) + /* + * We need to decrease SA use count only if the SA was not + * provided to us by the caller but was found through our own + * SA lookup that increased the use count. + */ + if (sa == ODP_IPSEC_SA_INVALID && ipsec_sa) _odp_ipsec_sa_unuse(ipsec_sa); } @@ -1853,7 +1923,7 @@ int odp_ipsec_out_enq(const odp_packet_t pkt_in[], int num_in, else opt = ¶m->opt[opt_idx]; - ipsec_sa = ipsec_out_single(pkt, sa, &pkt, opt, &status); + ipsec_sa = ipsec_out_single(pkt, sa, &pkt, opt, true, &status); ODP_ASSERT(NULL != ipsec_sa); packet_subtype_set(pkt, ODP_EVENT_PACKET_IPSEC); @@ -1890,7 +1960,8 @@ int _odp_ipsec_try_inline(odp_packet_t *pkt) memset(&status, 0, sizeof(status)); - ipsec_sa = ipsec_in_single(*pkt, ODP_IPSEC_SA_INVALID, pkt, &status); + ipsec_sa = ipsec_in_single(*pkt, ODP_IPSEC_SA_INVALID, pkt, false, + &status); /* * Route packet back in case of lookup failure or early error before * lookup @@ -1977,7 +2048,7 @@ int odp_ipsec_out_inline(const odp_packet_t pkt_in[], int num_in, else opt = ¶m->opt[opt_idx]; - ipsec_sa = ipsec_out_single(pkt, sa, &pkt, opt, &status); + ipsec_sa = ipsec_out_single(pkt, sa, &pkt, opt, true, &status); ODP_ASSERT(NULL != ipsec_sa); offset = odp_packet_l3_offset(pkt); @@ -2110,7 +2181,7 @@ int odp_ipsec_stats(odp_ipsec_sa_t sa, odp_ipsec_stats_t *stats) ipsec_sa = _odp_ipsec_sa_entry_from_hdl(sa); ODP_ASSERT(NULL != ipsec_sa); - stats->success = _odp_ipsec_sa_stats_pkts(ipsec_sa); + _odp_ipsec_sa_stats_pkts(ipsec_sa, stats); stats->proto_err = odp_atomic_load_u64(&ipsec_sa->stats.proto_err); stats->auth_err = odp_atomic_load_u64(&ipsec_sa->stats.auth_err); stats->antireplay_err = odp_atomic_load_u64(&ipsec_sa->stats.antireplay_err); @@ -2122,6 +2193,27 @@ int odp_ipsec_stats(odp_ipsec_sa_t sa, odp_ipsec_stats_t *stats) return 0; } +static int read_config_file(ipsec_global_t *global) +{ + const char *str_i = "ipsec.ordering.async_inbound"; + const char *str_o = "ipsec.ordering.async_outbound"; + int val; + + if (!_odp_libconfig_lookup_int(str_i, &val)) { + ODP_ERR("Config option '%s' not found.\n", str_i); + return -1; + } + global->inbound_ordering_mode = val; + + if (!_odp_libconfig_lookup_int(str_o, &val)) { + ODP_ERR("Config option '%s' not found.\n", str_o); + return -1; + } + global->outbound_ordering_mode = val; + + return 0; +} + int _odp_ipsec_init_global(void) { odp_shm_t shm; @@ -2129,17 +2221,25 @@ int _odp_ipsec_init_global(void) if (odp_global_ro.disable.ipsec) return 0; - shm = odp_shm_reserve("_odp_ipsec", sizeof(odp_ipsec_config_t), + shm = odp_shm_reserve("_odp_ipsec", sizeof(*ipsec_global), ODP_CACHE_LINE_SIZE, 0); - - ipsec_config = odp_shm_addr(shm); - - if (ipsec_config == NULL) { + if (shm == ODP_SHM_INVALID) { ODP_ERR("Shm reserve failed for odp_ipsec\n"); return -1; } + ipsec_global = odp_shm_addr(shm); + if (ipsec_global == NULL) { + ODP_ERR("ipsec: odp_shm_addr() failed\n"); + odp_shm_free(shm); + return -1; + } + memset(ipsec_global, 0, sizeof(*ipsec_global)); + ipsec_config = &ipsec_global->ipsec_config; - odp_ipsec_config_init(ipsec_config); + if (read_config_file(ipsec_global)) { + odp_shm_free(shm); + return -1; + } memset(&default_out_opt, 0, sizeof(default_out_opt)); diff --git a/platform/linux-generic/odp_ipsec_sad.c b/platform/linux-generic/odp_ipsec_sad.c index da8232b01..d0367bf63 100644 --- a/platform/linux-generic/odp_ipsec_sad.c +++ b/platform/linux-generic/odp_ipsec_sad.c @@ -22,9 +22,24 @@ #include <string.h> -#define IPSEC_SA_STATE_DISABLE 0x40000000 -#define IPSEC_SA_STATE_FREE 0xc0000000 -#define IPSEC_SA_STATE_RESERVED 0x80000000 +/* + * SA state consists of state value in the high order bits of ipsec_sa_t::state + * and use counter in the low order bits. + * + * An SA cannot be destroyed if its use count is higher than one. Use counter + * is needed for the case SA lookup is done by us and not the application. + * In the latter case we rely on the fact that the application may not pass + * the SA as a parameter to an IPsec operation concurrently with a call + * to odp_ipsec_sa_disable(). + * + * SAs that are free or being disabled cannot be found in SA lookup by ODP. + */ +#define IPSEC_SA_STATE_ACTIVE 0x00000000 /* SA is in use */ +#define IPSEC_SA_STATE_DISABLE 0x40000000 /* SA is being disabled */ +#define IPSEC_SA_STATE_FREE 0xc0000000 /* SA is unused and free */ +#define IPSEC_SA_STATE_MASK 0xc0000000 /* mask of state bits */ + +#define SA_IDX_NONE UINT32_MAX /* * We do not have global IPv4 ID counter that is accessed for every outbound @@ -68,7 +83,7 @@ typedef struct sa_thread_local_s { * Bytes that can be processed in this thread before looking at * the SA-global byte counter and checking hard and soft limits. */ - uint32_t byte_quota; + odp_atomic_u32_t byte_quota; /* * Life time status when this thread last checked the global * counter(s). @@ -88,6 +103,10 @@ typedef struct ipsec_sa_table_t { ring_mpmc_t ipv4_id_ring; uint32_t ipv4_id_data[IPV4_ID_RING_SIZE] ODP_ALIGNED_CACHE; } hot; + struct { + uint32_t head; + odp_spinlock_t lock; + } sa_freelist; uint32_t max_num_sa; odp_shm_t shm; ipsec_thread_local_t per_thread[]; @@ -130,7 +149,7 @@ static void init_sa_thread_local(ipsec_sa_t *sa) for (n = 0; n < thread_count_max; n++) { sa_tl = &ipsec_sa_tbl->per_thread[n].sa[sa->ipsec_sa_idx]; odp_atomic_init_u32(&sa_tl->packet_quota, 0); - sa_tl->byte_quota = 0; + odp_atomic_init_u32(&sa_tl->byte_quota, 0); sa_tl->lifetime_status.all = 0; } } @@ -199,10 +218,15 @@ int _odp_ipsec_sad_init_global(void) ipsec_sa->ipsec_sa_hdl = ipsec_sa_index_to_handle(i); ipsec_sa->ipsec_sa_idx = i; + ipsec_sa->next_sa = i + 1; + if (i == ipsec_sa_tbl->max_num_sa - 1) + ipsec_sa->next_sa = SA_IDX_NONE; odp_atomic_init_u32(&ipsec_sa->state, IPSEC_SA_STATE_FREE); odp_atomic_init_u64(&ipsec_sa->hot.bytes, 0); odp_atomic_init_u64(&ipsec_sa->hot.packets, 0); } + ipsec_sa_tbl->sa_freelist.head = 0; + odp_spinlock_init(&ipsec_sa_tbl->sa_freelist.lock); return 0; } @@ -245,31 +269,32 @@ uint32_t _odp_ipsec_max_num_sa(void) static ipsec_sa_t *ipsec_sa_reserve(void) { - uint32_t i; - ipsec_sa_t *ipsec_sa; - - for (i = 0; i < ipsec_sa_tbl->max_num_sa; i++) { - uint32_t state = IPSEC_SA_STATE_FREE; - - ipsec_sa = ipsec_sa_entry(i); - - if (odp_atomic_cas_acq_u32(&ipsec_sa->state, &state, - IPSEC_SA_STATE_RESERVED)) - return ipsec_sa; + ipsec_sa_t *ipsec_sa = NULL; + uint32_t sa_idx; + + odp_spinlock_lock(&ipsec_sa_tbl->sa_freelist.lock); + sa_idx = ipsec_sa_tbl->sa_freelist.head; + if (sa_idx != SA_IDX_NONE) { + ipsec_sa = ipsec_sa_entry(sa_idx); + ipsec_sa_tbl->sa_freelist.head = ipsec_sa->next_sa; } - - return NULL; + odp_spinlock_unlock(&ipsec_sa_tbl->sa_freelist.lock); + return ipsec_sa; } static void ipsec_sa_release(ipsec_sa_t *ipsec_sa) { - odp_atomic_store_rel_u32(&ipsec_sa->state, IPSEC_SA_STATE_FREE); + odp_spinlock_lock(&ipsec_sa_tbl->sa_freelist.lock); + ipsec_sa->next_sa = ipsec_sa_tbl->sa_freelist.head; + ipsec_sa_tbl->sa_freelist.head = ipsec_sa->ipsec_sa_idx; + odp_atomic_store_u32(&ipsec_sa->state, IPSEC_SA_STATE_FREE); + odp_spinlock_unlock(&ipsec_sa_tbl->sa_freelist.lock); } /* Mark reserved SA as available now */ static void ipsec_sa_publish(ipsec_sa_t *ipsec_sa) { - odp_atomic_store_rel_u32(&ipsec_sa->state, 0); + odp_atomic_store_rel_u32(&ipsec_sa->state, IPSEC_SA_STATE_ACTIVE); } static int ipsec_sa_lock(ipsec_sa_t *ipsec_sa) @@ -280,11 +305,9 @@ static int ipsec_sa_lock(ipsec_sa_t *ipsec_sa) while (0 == cas) { /* * This can be called from lookup path, so we really need this - * check. Thanks to the way flags are defined we actually test - * that the SA is not DISABLED, FREE or RESERVED using just one - * condition. + * check. */ - if (state & IPSEC_SA_STATE_FREE) + if ((state & IPSEC_SA_STATE_MASK) != IPSEC_SA_STATE_ACTIVE) return -1; cas = odp_atomic_cas_acq_u32(&ipsec_sa->state, &state, @@ -440,6 +463,10 @@ odp_ipsec_sa_t odp_ipsec_sa_create(const odp_ipsec_sa_param_t *param) ipsec_sa->spi = param->spi; ipsec_sa->context = param->context; ipsec_sa->queue = param->dest_queue; + if (_odp_ipsec_is_sync_mode(param->dir)) { + /* Invalid queue indicates sync mode */ + ipsec_sa->queue = ODP_QUEUE_INVALID; + } ipsec_sa->mode = param->mode; ipsec_sa->flags = 0; if (param->opt.esn) { @@ -469,7 +496,7 @@ odp_ipsec_sa_t odp_ipsec_sa_create(const odp_ipsec_sa_param_t *param) ipsec_sa->lookup_mode = ODP_IPSEC_LOOKUP_DISABLED; odp_atomic_init_u64(&ipsec_sa->hot.out.seq, 1); ipsec_sa->out.frag_mode = param->outbound.frag_mode; - ipsec_sa->out.mtu = param->outbound.mtu; + odp_atomic_init_u32(&ipsec_sa->out.mtu, param->outbound.mtu); } ipsec_sa->dec_ttl = param->opt.dec_ttl; ipsec_sa->copy_dscp = param->opt.copy_dscp; @@ -492,6 +519,7 @@ odp_ipsec_sa_t odp_ipsec_sa_create(const odp_ipsec_sa_param_t *param) odp_atomic_init_u64(&ipsec_sa->stats.hard_exp_bytes_err, 0); odp_atomic_init_u64(&ipsec_sa->stats.hard_exp_pkts_err, 0); odp_atomic_init_u64(&ipsec_sa->stats.post_lifetime_err_pkts, 0); + odp_atomic_init_u64(&ipsec_sa->stats.post_lifetime_err_bytes, 0); /* Copy application provided parameter values. */ ipsec_sa->param = *param; @@ -770,13 +798,9 @@ int odp_ipsec_sa_mtu_update(odp_ipsec_sa_t sa, uint32_t mtu) { ipsec_sa_t *ipsec_sa; - ipsec_sa = _odp_ipsec_sa_use(sa); + ipsec_sa = ipsec_sa_entry_from_hdl(sa); ODP_ASSERT(NULL != ipsec_sa); - - ipsec_sa->out.mtu = mtu; - - _odp_ipsec_sa_unuse(ipsec_sa); - + odp_atomic_store_u32(&ipsec_sa->out.mtu, mtu); return 0; } @@ -835,6 +859,7 @@ int _odp_ipsec_sa_lifetime_update(ipsec_sa_t *ipsec_sa, uint32_t len, { sa_thread_local_t *sa_tl = ipsec_sa_thread_local(ipsec_sa); uint64_t packets, bytes; + uint32_t tl_byte_quota; uint32_t tl_pkt_quota; tl_pkt_quota = odp_atomic_load_u32(&sa_tl->packet_quota); @@ -855,11 +880,12 @@ int _odp_ipsec_sa_lifetime_update(ipsec_sa_t *ipsec_sa, uint32_t len, tl_pkt_quota--; odp_atomic_store_u32(&sa_tl->packet_quota, tl_pkt_quota); - if (odp_unlikely(sa_tl->byte_quota < len)) { + tl_byte_quota = odp_atomic_load_u32(&sa_tl->byte_quota); + if (odp_unlikely(tl_byte_quota < len)) { bytes = odp_atomic_fetch_add_u64(&ipsec_sa->hot.bytes, len + SA_LIFE_BYTES_PREALLOC); bytes += len + SA_LIFE_BYTES_PREALLOC; - sa_tl->byte_quota += len + SA_LIFE_BYTES_PREALLOC; + tl_byte_quota += len + SA_LIFE_BYTES_PREALLOC; if (ipsec_sa->soft_limit_bytes > 0 && bytes >= ipsec_sa->soft_limit_bytes) @@ -869,7 +895,9 @@ int _odp_ipsec_sa_lifetime_update(ipsec_sa_t *ipsec_sa, uint32_t len, bytes >= ipsec_sa->hard_limit_bytes) sa_tl->lifetime_status.error.hard_exp_bytes = 1; } - sa_tl->byte_quota -= len; + tl_byte_quota -= len; + odp_atomic_store_u32(&sa_tl->byte_quota, tl_byte_quota); + status->all |= sa_tl->lifetime_status.all; @@ -909,9 +937,6 @@ int _odp_ipsec_sa_replay_update(ipsec_sa_t *ipsec_sa, uint32_t seq, int cas = 0; uint64_t state, new_state; - if (!ipsec_sa->antireplay) - return 0; - state = odp_atomic_load_u64(&ipsec_sa->hot.in.antireplay); while (0 == cas) { @@ -973,9 +998,10 @@ uint16_t _odp_ipsec_sa_alloc_ipv4_id(ipsec_sa_t *ipsec_sa) return tl->next_ipv4_id++; } -uint64_t _odp_ipsec_sa_stats_pkts(ipsec_sa_t *sa) +void _odp_ipsec_sa_stats_pkts(ipsec_sa_t *sa, odp_ipsec_stats_t *stats) { int thread_count_max = odp_thread_count_max(); + uint64_t tl_byte_quota = 0; uint64_t tl_pkt_quota = 0; sa_thread_local_t *sa_tl; int n; @@ -994,11 +1020,20 @@ uint64_t _odp_ipsec_sa_stats_pkts(ipsec_sa_t *sa) for (n = 0; n < thread_count_max; n++) { sa_tl = &ipsec_sa_tbl->per_thread[n].sa[sa->ipsec_sa_idx]; tl_pkt_quota += odp_atomic_load_u32(&sa_tl->packet_quota); + tl_byte_quota += odp_atomic_load_u32(&sa_tl->byte_quota); } - return odp_atomic_load_u64(&sa->hot.packets) + stats->success = + odp_atomic_load_u64(&sa->hot.packets) - odp_atomic_load_u64(&sa->stats.post_lifetime_err_pkts) - tl_pkt_quota; + + stats->success_bytes = + odp_atomic_load_u64(&sa->hot.bytes) + - odp_atomic_load_u64(&sa->stats.post_lifetime_err_bytes) + - tl_byte_quota; + + return; } static void ipsec_out_sa_info(ipsec_sa_t *ipsec_sa, odp_ipsec_sa_info_t *sa_info) diff --git a/platform/linux-generic/odp_ishm.c b/platform/linux-generic/odp_ishm.c index 0014f3c34..7041cd2b5 100644 --- a/platform/linux-generic/odp_ishm.c +++ b/platform/linux-generic/odp_ishm.c @@ -1995,7 +1995,7 @@ int _odp_ishm_status(const char *title) } ODP_PRINT("%s\n", title); - ODP_PRINT(" %-*s flag %-29s %-08s %-08s %-3s %-3s %-3s file\n", + ODP_PRINT(" %-*s flag %-29s %-8s %-8s %-3s %-3s %-3s file\n", max_name_len, "name", "range", "user_len", "unused", "seq", "ref", "fd"); @@ -2045,8 +2045,8 @@ int _odp_ishm_status(const char *title) entry_fd = ishm_proctable->entry[proc_index].fd; } - ODP_PRINT("%2i %-*s %s%c %p-%p %-08" PRIu64 " " - "%-08" PRIu64 " %-3" PRIu64 " %-3" PRIu64 " " + ODP_PRINT("%2i %-*s %s%c %p-%p %-8" PRIu64 " " + "%-8" PRIu64 " %-3" PRIu64 " %-3" PRIu64 " " "%-3d %s\n", i, max_name_len, ishm_tbl->block[i].name, flags, huge, start_addr, end_addr, @@ -2059,7 +2059,7 @@ int _odp_ishm_status(const char *title) ishm_tbl->block[i].filename : "(none)"); } - ODP_PRINT("TOTAL: %58s%-08" PRIu64 " %2s%-08" PRIu64 "\n", + ODP_PRINT("TOTAL: %58s%-8" PRIu64 " %2s%-8" PRIu64 "\n", "", len_total, "", lost_total); ODP_PRINT("%65s(%" PRIu64 "MB) %4s(%" PRIu64 "MB)\n", @@ -2072,15 +2072,15 @@ int _odp_ishm_status(const char *title) fragmnt; fragmnt = fragmnt->next) { if (fragmnt->block_index >= 0) { nb_allocated_frgments++; - ODP_PRINT(" %08p - %08p: ALLOCATED by block:%d\n", - (uintptr_t)fragmnt->start, - (uintptr_t)fragmnt->start + fragmnt->len - 1, + ODP_PRINT(" %8p - %8p: ALLOCATED by block:%d\n", + fragmnt->start, + (void *)((uintptr_t)fragmnt->start + fragmnt->len - 1), fragmnt->block_index); consecutive_unallocated = 0; } else { - ODP_PRINT(" %08p - %08p: NOT ALLOCATED\n", - (uintptr_t)fragmnt->start, - (uintptr_t)fragmnt->start + fragmnt->len - 1); + ODP_PRINT(" %8p - %8p: NOT ALLOCATED\n", + fragmnt->start, + (void *)((uintptr_t)fragmnt->start + fragmnt->len - 1)); if (consecutive_unallocated++) ODP_ERR("defragmentation error\n"); } diff --git a/platform/linux-generic/odp_ishmpool.c b/platform/linux-generic/odp_ishmpool.c index 4b593a4bc..818b0a132 100644 --- a/platform/linux-generic/odp_ishmpool.c +++ b/platform/linux-generic/odp_ishmpool.c @@ -280,7 +280,7 @@ static void *_odp_ishmbud_alloc(pool_t *bpool, uint64_t size) uintptr_t nr; /* if size is zero or too big reject: */ - if ((!size) && (size > (1U << bpool->ctrl.order))) { + if ((!size) && (size > (1ULL << bpool->ctrl.order))) { ODP_ERR("Invalid alloc size (0 or larger than whole pool)\n"); return NULL; } diff --git a/platform/linux-generic/odp_name_table.c b/platform/linux-generic/odp_name_table.c index 3697bc877..9c1814cae 100644 --- a/platform/linux-generic/odp_name_table.c +++ b/platform/linux-generic/odp_name_table.c @@ -376,6 +376,7 @@ static void name_tbl_entry_free(name_tbl_entry_t *name_tbl_entry) memset(name_tbl_entry, 0, sizeof(name_tbl_entry_t)); name_tbl_entry->next_entry = name_tbl->free_list_head; name_tbl->free_list_head = name_tbl_entry; + name_tbl_entry->name_tbl_id = name_tbl_id; } static hash_tbl_entry_t make_hash_tbl_entry(name_tbl_entry_t *name_tbl_entry, diff --git a/platform/linux-generic/odp_packet_io.c b/platform/linux-generic/odp_packet_io.c index 711e5f8a6..694b0a741 100644 --- a/platform/linux-generic/odp_packet_io.c +++ b/platform/linux-generic/odp_packet_io.c @@ -377,7 +377,7 @@ static const char *driver_name(odp_pktio_t hdl) entry = get_pktio_entry(hdl); if (entry == NULL) { - ODP_ERR("pktio entry %d does not exist\n", hdl); + ODP_ERR("pktio entry %" PRIuPTR " does not exist\n", (uintptr_t)hdl); return "bad handle"; } @@ -1253,7 +1253,7 @@ static inline uint32_t pktio_maxlen(odp_pktio_t hdl) entry = get_pktio_entry(hdl); if (entry == NULL) { - ODP_DBG("pktio entry %d does not exist\n", hdl); + ODP_DBG("pktio entry %" PRIuPTR " does not exist\n", (uintptr_t)hdl); return 0; } @@ -1296,7 +1296,7 @@ int odp_pktio_maxlen_set(odp_pktio_t hdl, uint32_t maxlen_input, entry = get_pktio_entry(hdl); if (entry == NULL) { - ODP_ERR("Pktio entry %d does not exist\n", hdl); + ODP_ERR("Pktio entry %" PRIuPTR " does not exist\n", (uintptr_t)hdl); return -1; } @@ -1360,7 +1360,7 @@ int odp_pktio_promisc_mode_set(odp_pktio_t hdl, odp_bool_t enable) entry = get_pktio_entry(hdl); if (entry == NULL) { - ODP_DBG("pktio entry %d does not exist\n", hdl); + ODP_DBG("pktio entry %" PRIuPTR " does not exist\n", (uintptr_t)hdl); return -1; } @@ -1390,7 +1390,7 @@ int odp_pktio_promisc_mode(odp_pktio_t hdl) entry = get_pktio_entry(hdl); if (entry == NULL) { - ODP_DBG("pktio entry %d does not exist\n", hdl); + ODP_DBG("pktio entry %" PRIuPTR " does not exist\n", (uintptr_t)hdl); return -1; } @@ -1421,7 +1421,7 @@ int odp_pktio_mac_addr(odp_pktio_t hdl, void *mac_addr, int addr_size) entry = get_pktio_entry(hdl); if (entry == NULL) { - ODP_DBG("pktio entry %d does not exist\n", hdl); + ODP_DBG("pktio entry %" PRIuPTR " does not exist\n", (uintptr_t)hdl); return -1; } @@ -1456,7 +1456,7 @@ int odp_pktio_mac_addr_set(odp_pktio_t hdl, const void *mac_addr, int addr_size) entry = get_pktio_entry(hdl); if (entry == NULL) { - ODP_DBG("pktio entry %d does not exist\n", hdl); + ODP_DBG("pktio entry %" PRIuPTR " does not exist\n", (uintptr_t)hdl); return -1; } @@ -1487,7 +1487,7 @@ odp_pktio_link_status_t odp_pktio_link_status(odp_pktio_t hdl) entry = get_pktio_entry(hdl); if (entry == NULL) { - ODP_DBG("pktio entry %d does not exist\n", hdl); + ODP_DBG("pktio entry %" PRIuPTR " does not exist\n", (uintptr_t)hdl); return ODP_PKTIO_LINK_STATUS_UNKNOWN; } @@ -1543,7 +1543,7 @@ int odp_pktio_info(odp_pktio_t hdl, odp_pktio_info_t *info) entry = get_pktio_entry(hdl); if (entry == NULL) { - ODP_DBG("pktio entry %d does not exist\n", hdl); + ODP_DBG("pktio entry %" PRIuPTR " does not exist\n", (uintptr_t)hdl); return -1; } @@ -1563,7 +1563,7 @@ int odp_pktio_link_info(odp_pktio_t hdl, odp_pktio_link_info_t *info) entry = get_pktio_entry(hdl); if (entry == NULL) { - ODP_DBG("pktio entry %d does not exist\n", hdl); + ODP_DBG("pktio entry %" PRIuPTR " does not exist\n", (uintptr_t)hdl); return -1; } @@ -1579,7 +1579,7 @@ uint64_t odp_pktio_ts_res(odp_pktio_t hdl) entry = get_pktio_entry(hdl); if (entry == NULL) { - ODP_ERR("pktio entry %d does not exist\n", hdl); + ODP_ERR("pktio entry %" PRIuPTR " does not exist\n", (uintptr_t)hdl); return 0; } @@ -1596,7 +1596,7 @@ odp_time_t odp_pktio_ts_from_ns(odp_pktio_t hdl, uint64_t ns) entry = get_pktio_entry(hdl); if (entry == NULL) { - ODP_ERR("pktio entry %d does not exist\n", hdl); + ODP_ERR("pktio entry %" PRIuPTR " does not exist\n", (uintptr_t)hdl); return ODP_TIME_NULL; } @@ -1613,7 +1613,7 @@ odp_time_t odp_pktio_time(odp_pktio_t hdl, odp_time_t *global_ts) entry = get_pktio_entry(hdl); if (entry == NULL) { - ODP_ERR("pktio entry %d does not exist\n", hdl); + ODP_ERR("pktio entry %" PRIuPTR " does not exist\n", (uintptr_t)hdl); return ODP_TIME_NULL; } @@ -1652,7 +1652,7 @@ void odp_pktio_print(odp_pktio_t hdl) entry = get_pktio_entry(hdl); if (entry == NULL) { - ODP_DBG("pktio entry %d does not exist\n", hdl); + ODP_DBG("pktio entry %" PRIuPTR " does not exist\n", (uintptr_t)hdl); return; } @@ -1781,7 +1781,7 @@ int odp_pktio_capability(odp_pktio_t pktio, odp_pktio_capability_t *capa) entry = get_pktio_entry(pktio); if (entry == NULL) { - ODP_DBG("pktio entry %d does not exist\n", pktio); + ODP_DBG("pktio entry %" PRIuPTR " does not exist\n", (uintptr_t)pktio); return -1; } @@ -1850,7 +1850,7 @@ int odp_pktio_stats(odp_pktio_t pktio, entry = get_pktio_entry(pktio); if (entry == NULL) { - ODP_DBG("pktio entry %d does not exist\n", pktio); + ODP_DBG("pktio entry %" PRIuPTR " does not exist\n", (uintptr_t)pktio); return -1; } @@ -1880,7 +1880,7 @@ int odp_pktio_stats_reset(odp_pktio_t pktio) entry = get_pktio_entry(pktio); if (entry == NULL) { - ODP_DBG("pktio entry %d does not exist\n", pktio); + ODP_DBG("pktio entry %" PRIuPTR " does not exist\n", (uintptr_t)pktio); return -1; } @@ -1920,7 +1920,7 @@ int odp_pktin_queue_config(odp_pktio_t pktio, entry = get_pktio_entry(pktio); if (entry == NULL) { - ODP_DBG("pktio entry %d does not exist\n", pktio); + ODP_DBG("pktio entry %" PRIuPTR " does not exist\n", (uintptr_t)pktio); return -1; } @@ -2065,6 +2065,77 @@ int odp_pktin_queue_config(odp_pktio_t pktio, return 0; } +int _odp_pktio_pktout_tm_config(odp_pktio_t pktio_hdl, + odp_pktout_queue_t *queue, bool reconf) +{ + odp_pktout_queue_param_t param; + bool pktio_started = false; + odp_pktout_mode_t mode; + pktio_entry_t *entry; + unsigned int i; + int rc = 0; + + odp_pktout_queue_param_init(¶m); + param.num_queues = 1; + + entry = get_pktio_entry(pktio_hdl); + if (entry == NULL) { + ODP_DBG("pktio entry %" PRIuPTR " does not exist\n", (uintptr_t)pktio_hdl); + return -1; + } + + rc = -ENOTSUP; + mode = entry->s.param.out_mode; + /* Don't proceed further if mode is not TM */ + if (mode != ODP_PKTOUT_MODE_TM) + return rc; + + /* Don't reconfigure unless requested */ + if (entry->s.num_out_queue && !reconf) { + *queue = entry->s.out_queue[0].pktout; + return 0; + } + + if (entry->s.state == PKTIO_STATE_STARTED) { + pktio_started = true; + rc = odp_pktio_stop(pktio_hdl); + if (rc) { + ODP_ERR("Unable to stop pktio, rc=%d\n", rc); + return rc; + } + } + + /* If re-configuring, destroy old queues */ + if (entry->s.num_out_queue) { + destroy_out_queues(entry, entry->s.num_out_queue); + entry->s.num_out_queue = 0; + } + + init_out_queues(entry); + for (i = 0; i < param.num_queues; i++) { + entry->s.out_queue[i].pktout.index = i; + entry->s.out_queue[i].pktout.pktio = pktio_hdl; + } + + entry->s.num_out_queue = param.num_queues; + + rc = 0; + if (entry->s.ops->output_queues_config) { + rc = entry->s.ops->output_queues_config(entry, ¶m); + if (rc) + ODP_ERR("Unable to setup output queues, rc=%d\n", rc); + } + + /* Return pktout queue on success */ + if (!rc) + *queue = entry->s.out_queue[0].pktout; + + /* Take pktio back to its previous state */ + if (pktio_started) + rc |= odp_pktio_start(pktio_hdl); + return rc; +} + int odp_pktout_queue_config(odp_pktio_t pktio, const odp_pktout_queue_param_t *param) { @@ -2083,7 +2154,7 @@ int odp_pktout_queue_config(odp_pktio_t pktio, entry = get_pktio_entry(pktio); if (entry == NULL) { - ODP_DBG("pktio entry %d does not exist\n", pktio); + ODP_DBG("pktio entry %" PRIuPTR " does not exist\n", (uintptr_t)pktio); return -1; } @@ -2189,7 +2260,7 @@ int odp_pktin_event_queue(odp_pktio_t pktio, odp_queue_t queues[], int num) entry = get_pktio_entry(pktio); if (entry == NULL) { - ODP_DBG("pktio entry %d does not exist\n", pktio); + ODP_DBG("pktio entry %" PRIuPTR " does not exist\n", (uintptr_t)pktio); return -1; } @@ -2229,7 +2300,7 @@ int odp_pktin_queue(odp_pktio_t pktio, odp_pktin_queue_t queues[], int num) entry = get_pktio_entry(pktio); if (entry == NULL) { - ODP_DBG("pktio entry %d does not exist\n", pktio); + ODP_DBG("pktio entry %" PRIuPTR " does not exist\n", (uintptr_t)pktio); return -1; } @@ -2268,7 +2339,7 @@ int odp_pktout_event_queue(odp_pktio_t pktio, odp_queue_t queues[], int num) entry = get_pktio_entry(pktio); if (entry == NULL) { - ODP_DBG("pktio entry %d does not exist\n", pktio); + ODP_DBG("pktio entry %" PRIuPTR " does not exist\n", (uintptr_t)pktio); return -1; } @@ -2299,7 +2370,7 @@ int odp_pktout_queue(odp_pktio_t pktio, odp_pktout_queue_t queues[], int num) entry = get_pktio_entry(pktio); if (entry == NULL) { - ODP_DBG("pktio entry %d does not exist\n", pktio); + ODP_DBG("pktio entry %" PRIuPTR " does not exist\n", (uintptr_t)pktio); return -1; } @@ -2336,7 +2407,7 @@ int odp_pktin_recv(odp_pktin_queue_t queue, odp_packet_t packets[], int num) entry = get_pktio_entry(pktio); if (entry == NULL) { - ODP_DBG("pktio entry %d does not exist\n", pktio); + ODP_DBG("pktio entry %" PRIuPTR " does not exist\n", (uintptr_t)pktio); return -1; } @@ -2365,7 +2436,7 @@ int odp_pktin_recv_tmo(odp_pktin_queue_t queue, odp_packet_t packets[], int num, entry = get_pktio_entry(queue.pktio); if (entry == NULL) { - ODP_DBG("pktio entry %d does not exist\n", queue.pktio); + ODP_DBG("pktio entry %" PRIuPTR " does not exist\n", (uintptr_t)queue.pktio); return -1; } @@ -2520,7 +2591,7 @@ int odp_pktout_send(odp_pktout_queue_t queue, const odp_packet_t packets[], entry = get_pktio_entry(pktio); if (entry == NULL) { - ODP_DBG("pktio entry %d does not exist\n", pktio); + ODP_DBG("pktio entry %" PRIuPTR " does not exist\n", (uintptr_t)pktio); return -1; } @@ -2546,7 +2617,7 @@ int odp_pktout_ts_read(odp_pktio_t hdl, odp_time_t *ts) entry = get_pktio_entry(hdl); if (odp_unlikely(entry == NULL)) { - ODP_ERR("pktio entry %d does not exist\n", hdl); + ODP_ERR("pktio entry %" PRIuPTR " does not exist\n", (uintptr_t)hdl); return -1; } diff --git a/platform/linux-generic/odp_queue_basic.c b/platform/linux-generic/odp_queue_basic.c index 8dc10467a..428022ec8 100644 --- a/platform/linux-generic/odp_queue_basic.c +++ b/platform/linux-generic/odp_queue_basic.c @@ -180,7 +180,7 @@ static int queue_init_global(void) queue_capa(&capa, 0); ODP_DBG("... done.\n"); - ODP_DBG(" queue_entry_t size %u\n", sizeof(queue_entry_t)); + ODP_DBG(" queue_entry_t size %zu\n", sizeof(queue_entry_t)); ODP_DBG(" max num queues %u\n", capa.max_queues); ODP_DBG(" max queue size %u\n", capa.plain.max_size); ODP_DBG(" max num lockfree %u\n", capa.plain.lockfree.max_num); @@ -740,7 +740,7 @@ static void queue_print(odp_queue_t handle) if (!odp_pktio_info(queue->s.pktout.pktio, &pktio_info)) ODP_PRINT(" pktout %s\n", pktio_info.name); } - ODP_PRINT(" timers %" PRIu32 "\n", + ODP_PRINT(" timers %" PRIu64 "\n", odp_atomic_load_u64(&queue->s.num_timers)); ODP_PRINT(" status %s\n", queue->s.status == QUEUE_STATUS_READY ? "ready" : diff --git a/platform/linux-generic/odp_queue_scalable.c b/platform/linux-generic/odp_queue_scalable.c index 248855be4..ad7807bf9 100644 --- a/platform/linux-generic/odp_queue_scalable.c +++ b/platform/linux-generic/odp_queue_scalable.c @@ -1000,7 +1000,7 @@ static void queue_print(odp_queue_t handle) if (!odp_pktio_info(queue->s.pktout.pktio, &pktio_info)) ODP_PRINT(" pktout %s\n", pktio_info.name); } - ODP_PRINT(" timers %" PRIu32 "\n", + ODP_PRINT(" timers %" PRIu64 "\n", odp_atomic_load_u64(&queue->s.num_timers)); ODP_PRINT(" param.size %" PRIu32 "\n", queue->s.param.size); ODP_PRINT("\n"); diff --git a/platform/linux-generic/odp_system_info.c b/platform/linux-generic/odp_system_info.c index 9bef6fd7f..27c591a9c 100644 --- a/platform/linux-generic/odp_system_info.c +++ b/platform/linux-generic/odp_system_info.c @@ -91,7 +91,7 @@ static uint64_t default_huge_page_size(void) while (fgets(str, sizeof(str), file) != NULL) { if (sscanf(str, "Hugepagesize: %8lu kB", &sz) == 1) { - ODP_DBG("defaut hp size is %" PRIu64 " kB\n", sz); + ODP_DBG("defaut hp size is %lu kB\n", sz); fclose(file); return (uint64_t)sz * 1024; } diff --git a/platform/linux-generic/odp_timer.c b/platform/linux-generic/odp_timer.c index 2db5bc7b1..f75fbd522 100644 --- a/platform/linux-generic/odp_timer.c +++ b/platform/linux-generic/odp_timer.c @@ -1,5 +1,5 @@ /* Copyright (c) 2013-2018, Linaro Limited - * Copyright (c) 2019-2020, Nokia + * Copyright (c) 2019-2021, Nokia * All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause @@ -244,7 +244,7 @@ static inline timer_pool_t *handle_to_tp(odp_timer_t hdl) if (odp_likely(tp != NULL)) return timer_global->timer_pool[tp_idx]; } - ODP_ABORT("Invalid timer handle %#x\n", hdl); + ODP_ABORT("Invalid timer handle %p\n", hdl); } static inline uint32_t handle_to_idx(odp_timer_t hdl, @@ -255,7 +255,7 @@ static inline uint32_t handle_to_idx(odp_timer_t hdl, __builtin_prefetch(&tp->tick_buf[idx], 0, 0); if (odp_likely(idx < odp_atomic_load_u32(&tp->high_wm))) return idx; - ODP_ABORT("Invalid timer handle %#x\n", hdl); + ODP_ABORT("Invalid timer handle %p\n", hdl); } static inline odp_timer_t tp_idx_to_handle(timer_pool_t *tp, @@ -399,7 +399,7 @@ static odp_timer_pool_t timer_pool_new(const char *name, odp_ticketlock_unlock(&timer_global->lock); if (!odp_global_rw->inline_timers) { - if (tp->param.clk_src == ODP_CLOCK_CPU) + if (tp->param.clk_src == ODP_CLOCK_DEFAULT) itimer_init(tp); } else { /* Update the highest index for inline timer scan */ @@ -441,7 +441,7 @@ static void odp_timer_pool_del(timer_pool_t *tp) if (!odp_global_rw->inline_timers) { /* Stop POSIX itimer signals */ - if (tp->param.clk_src == ODP_CLOCK_CPU) + if (tp->param.clk_src == ODP_CLOCK_DEFAULT) itimer_fini(tp); stop_timer_thread(tp); @@ -1220,8 +1220,8 @@ static void itimer_fini(timer_pool_t *tp) int odp_timer_capability(odp_timer_clk_src_t clk_src, odp_timer_capability_t *capa) { - if (clk_src != ODP_CLOCK_CPU) { - ODP_ERR("Only CPU clock source supported\n"); + if (clk_src != ODP_CLOCK_DEFAULT) { + ODP_ERR("Only ODP_CLOCK_DEFAULT supported. Requested %i.\n", clk_src); return -1; } @@ -1248,8 +1248,8 @@ int odp_timer_capability(odp_timer_clk_src_t clk_src, int odp_timer_res_capability(odp_timer_clk_src_t clk_src, odp_timer_res_capability_t *res_capa) { - if (clk_src != ODP_CLOCK_CPU) { - ODP_ERR("Only CPU clock source supported\n"); + if (clk_src != ODP_CLOCK_DEFAULT) { + ODP_ERR("Only ODP_CLOCK_DEFAULT supported. Requested %i.\n", clk_src); return -1; } @@ -1385,13 +1385,13 @@ int odp_timer_set_abs(odp_timer_t hdl, uint32_t idx = handle_to_idx(hdl, tp); if (odp_unlikely(abs_tck < cur_tick + tp->min_rel_tck)) - return ODP_TIMER_TOOEARLY; + return ODP_TIMER_TOO_NEAR; if (odp_unlikely(abs_tck > cur_tick + tp->max_rel_tck)) - return ODP_TIMER_TOOLATE; + return ODP_TIMER_TOO_FAR; if (timer_reset(idx, abs_tck, (odp_buffer_t *)tmo_ev, tp)) return ODP_TIMER_SUCCESS; else - return ODP_TIMER_NOEVENT; + return ODP_TIMER_FAIL; } int odp_timer_set_rel(odp_timer_t hdl, @@ -1404,13 +1404,13 @@ int odp_timer_set_rel(odp_timer_t hdl, uint32_t idx = handle_to_idx(hdl, tp); if (odp_unlikely(rel_tck < tp->min_rel_tck)) - return ODP_TIMER_TOOEARLY; + return ODP_TIMER_TOO_NEAR; if (odp_unlikely(rel_tck > tp->max_rel_tck)) - return ODP_TIMER_TOOLATE; + return ODP_TIMER_TOO_FAR; if (timer_reset(idx, abs_tck, (odp_buffer_t *)tmo_ev, tp)) return ODP_TIMER_SUCCESS; else - return ODP_TIMER_NOEVENT; + return ODP_TIMER_FAIL; } int odp_timer_cancel(odp_timer_t hdl, odp_event_t *tmo_ev) diff --git a/platform/linux-generic/odp_traffic_mngr.c b/platform/linux-generic/odp_traffic_mngr.c index 1633bc454..cd7a9ecd9 100644 --- a/platform/linux-generic/odp_traffic_mngr.c +++ b/platform/linux-generic/odp_traffic_mngr.c @@ -22,6 +22,7 @@ #include <odp/api/std_types.h> #include <protocols/eth.h> #include <protocols/ip.h> +#include <odp_packet_io_internal.h> #include <odp_traffic_mngr_internal.h> #include <odp/api/plat/packet_inlines.h> #include <odp/api/plat/byteorder_inlines.h> @@ -610,8 +611,8 @@ static void tm_shaper_params_cvt_to(const odp_tm_shaper_params_t *shaper_params, uint32_t min_time_delta; int64_t commit_burst, peak_burst; - commit_rate = tm_bps_to_rate(shaper_params->commit_bps); - if ((shaper_params->commit_bps == 0) || (commit_rate == 0)) { + commit_rate = tm_bps_to_rate(shaper_params->commit_rate); + if ((shaper_params->commit_rate == 0) || (commit_rate == 0)) { tm_shaper_params->max_commit_time_delta = 0; tm_shaper_params->max_peak_time_delta = 0; tm_shaper_params->commit_rate = 0; @@ -628,8 +629,8 @@ static void tm_shaper_params_cvt_to(const odp_tm_shaper_params_t *shaper_params, max_commit_time_delta = tm_max_time_delta(commit_rate); commit_burst = (int64_t)shaper_params->commit_burst; - peak_rate = tm_bps_to_rate(shaper_params->peak_bps); - if ((shaper_params->peak_bps == 0) || (peak_rate == 0)) { + peak_rate = tm_bps_to_rate(shaper_params->peak_rate); + if ((shaper_params->peak_rate == 0) || (peak_rate == 0)) { peak_rate = 0; max_peak_time_delta = 0; peak_burst = 0; @@ -669,8 +670,8 @@ static void tm_shaper_params_cvt_from(tm_shaper_params_t *tm_shaper_params, commit_burst = tm_shaper_params->max_commit >> (26 - 3); peak_burst = tm_shaper_params->max_peak >> (26 - 3); - odp_shaper_params->commit_bps = commit_bps; - odp_shaper_params->peak_bps = peak_bps; + odp_shaper_params->commit_rate = commit_bps; + odp_shaper_params->peak_rate = peak_bps; odp_shaper_params->commit_burst = (uint32_t)commit_burst; odp_shaper_params->peak_burst = (uint32_t)peak_burst; odp_shaper_params->shaper_len_adjust = tm_shaper_params->len_adjust; @@ -2565,6 +2566,12 @@ int odp_tm_capabilities(odp_tm_capabilities_t capabilities[] ODP_UNUSED, cap_ptr->ecn_marking_supported = true; cap_ptr->drop_prec_marking_supported = true; + cap_ptr->dynamic_topology_update = true; + cap_ptr->dynamic_shaper_update = true; + cap_ptr->dynamic_sched_update = true; + cap_ptr->dynamic_wred_update = true; + cap_ptr->dynamic_threshold_update = true; + for (color = 0; color < ODP_NUM_PACKET_COLORS; color++) cap_ptr->marking_colors_supported[color] = true; @@ -2618,6 +2625,12 @@ static void tm_system_capabilities_set(odp_tm_capabilities_t *cap_ptr, cap_ptr->drop_prec_marking_supported = req_ptr->drop_prec_marking_needed; + cap_ptr->dynamic_topology_update = true; + cap_ptr->dynamic_shaper_update = true; + cap_ptr->dynamic_sched_update = true; + cap_ptr->dynamic_wred_update = true; + cap_ptr->dynamic_threshold_update = true; + for (color = 0; color < ODP_NUM_PACKET_COLORS; color++) cap_ptr->marking_colors_supported[color] = req_ptr->marking_colors_needed[color]; @@ -2919,15 +2932,20 @@ odp_tm_t odp_tm_create(const char *name, return ODP_TM_INVALID; } + odp_ticketlock_lock(&tm_glb->create_lock); + /* If we are using pktio output (usual case) get the first associated * pktout_queue for this pktio and fail if there isn't one. */ - if (egress->egress_kind == ODP_TM_EGRESS_PKT_IO && - odp_pktout_queue(egress->pktio, &pktout, 1) != 1) - return ODP_TM_INVALID; + if (egress->egress_kind == ODP_TM_EGRESS_PKT_IO) { + rc = _odp_pktio_pktout_tm_config(egress->pktio, &pktout, false); + if (rc) { + odp_ticketlock_unlock(&tm_glb->create_lock); + return ODP_TM_INVALID; + } + } /* Allocate tm_system_t record. */ - odp_ticketlock_lock(&tm_glb->create_lock); tm_system = tm_system_alloc(); if (!tm_system) { odp_ticketlock_unlock(&tm_glb->create_lock); @@ -3042,6 +3060,22 @@ int odp_tm_capability(odp_tm_t odp_tm, odp_tm_capabilities_t *capabilities) return 0; } +int odp_tm_start(odp_tm_t odp_tm) +{ + (void)odp_tm; + + /* Nothing more to do after TM create */ + return 0; +} + +int odp_tm_stop(odp_tm_t odp_tm) +{ + (void)odp_tm; + + /* Nothing more to do for topology changes */ + return 0; +} + int odp_tm_destroy(odp_tm_t odp_tm) { tm_system_t *tm_system; @@ -3065,6 +3099,7 @@ int odp_tm_destroy(odp_tm_t odp_tm) _odp_queue_pool_destroy(tm_system->_odp_int_queue_pool); _odp_timer_wheel_destroy(tm_system->_odp_int_timer_wheel); + _odp_int_name_tbl_delete(tm_system->name_tbl_id); tm_system_free(tm_system); return 0; } @@ -3204,6 +3239,10 @@ odp_tm_shaper_t odp_tm_shaper_create(const char *name, odp_tm_shaper_t shaper_handle; _odp_int_name_t name_tbl_id; + /* We don't support shaper in packet mode */ + if (params->packet_mode) + return ODP_TM_INVALID; + profile_obj = tm_common_profile_create(name, TM_SHAPER_PROFILE, &shaper_handle, &name_tbl_id); if (!profile_obj) @@ -3573,7 +3612,7 @@ int odp_tm_wred_destroy(odp_tm_wred_t wred_profile) return -1; return tm_common_profile_destroy(wred_profile, - ODP_INVALID_NAME); + wred_params->name_tbl_id); } int odp_tm_wred_params_read(odp_tm_wred_t wred_profile, @@ -4685,10 +4724,10 @@ void odp_tm_stats_print(odp_tm_t odp_tm) ODP_PRINT("odp_tm_stats_print - tm_system=0x%" PRIX64 " tm_idx=%u\n", odp_tm, tm_system->tm_idx); - ODP_PRINT(" input_work_queue size=%u current cnt=%u peak cnt=%u\n", - INPUT_WORK_RING_SIZE, input_work_queue->queue_cnt, + ODP_PRINT(" input_work_queue size=%u current cnt=%" PRIu64 " peak cnt=%" PRIu32 "\n", + INPUT_WORK_RING_SIZE, odp_atomic_load_u64(&input_work_queue->queue_cnt), input_work_queue->peak_cnt); - ODP_PRINT(" input_work_queue enqueues=%" PRIu64 " dequeues=% " PRIu64 + ODP_PRINT(" input_work_queue enqueues=%" PRIu64 " dequeues=%" PRIu64 " fail_cnt=%" PRIu64 "\n", input_work_queue->total_enqueues, input_work_queue->total_dequeues, input_work_queue->enqueue_fail_cnt); diff --git a/platform/linux-generic/pktio/dpdk.c b/platform/linux-generic/pktio/dpdk.c index 6b349293a..5d5fead16 100644 --- a/platform/linux-generic/pktio/dpdk.c +++ b/platform/linux-generic/pktio/dpdk.c @@ -1286,7 +1286,7 @@ static int dpdk_pktio_init(void) masklen = odp_cpumask_to_str(&mask, mask_str, ODP_CPUMASK_STR_SIZE); if (masklen < 0) { - ODP_ERR("CPU mask error: d\n", masklen); + ODP_ERR("CPU mask error: %" PRId32 "\n", masklen); return -1; } diff --git a/platform/linux-generic/pktio/ipc.c b/platform/linux-generic/pktio/ipc.c index e0c8cba3b..ad633e231 100644 --- a/platform/linux-generic/pktio/ipc.c +++ b/platform/linux-generic/pktio/ipc.c @@ -322,7 +322,7 @@ static int _ipc_init_master(pktio_entry_t *pktio_entry, pinfo = pktio_ipc->pinfo; pool_name = _ipc_odp_buffer_pool_shm_name(pool_hdl); if (strlen(pool_name) > ODP_POOL_NAME_LEN) { - ODP_ERR("pid %d ipc pool name %s is too big %d\n", + ODP_ERR("pid %d ipc pool name %s is too big %zu\n", getpid(), pool_name, strlen(pool_name)); goto free_s_prod; } @@ -742,7 +742,7 @@ static int ipc_pktio_recv_lockless(pktio_entry_t *pktio_entry, ring_ptr_enq_multi(r_p, ring_mask, ipcbufs_p, pkts); for (i = 0; i < pkts; i++) { - IPC_ODP_DBG("%d/%d send to be free packet offset %x\n", + IPC_ODP_DBG("%d/%d send to be free packet offset %" PRIuPTR "\n", i, pkts, offsets[i]); } @@ -820,7 +820,7 @@ static int ipc_pktio_send_lockless(pktio_entry_t *pktio_entry, /* compile all function code even if ipc disabled with config */ IPC_ODP_DBG("%d/%d send packet %" PRIu64 ", pool %" PRIu64 "," - "phdr = %p, offset %x, sendoff %x, addr %p iaddr " + "phdr = %p, offset %td, sendoff %" PRIxPTR ", addr %p iaddr " "%p\n", i, num, odp_packet_to_u64(pkt), odp_pool_to_u64(pool_hdl), pkt_hdr, (uint8_t *)pkt_hdr->seg_data - diff --git a/platform/linux-generic/pktio/pktio_common.c b/platform/linux-generic/pktio/pktio_common.c index 4090f8063..d2f4d7219 100644 --- a/platform/linux-generic/pktio/pktio_common.c +++ b/platform/linux-generic/pktio/pktio_common.c @@ -7,6 +7,7 @@ #include <odp_packet_io_internal.h> #include <errno.h> +#include <inttypes.h> static int sock_recv_mq_tmo_select(pktio_entry_t * const *entry, const int index[], @@ -71,8 +72,8 @@ int _odp_sock_recv_mq_tmo_try_int_driven(const struct odp_pktin_queue_t queues[] entry[i] = get_pktio_entry(queues[i].pktio); index[i] = queues[i].index; if (entry[i] == NULL) { - ODP_DBG("pktio entry %d does not exist\n", - queues[i].pktio); + ODP_DBG("pktio entry %" PRIuPTR " does not exist\n", + (uintptr_t)queues[i].pktio); *trial_successful = 0; return -1; } diff --git a/platform/linux-generic/test/Makefile.am b/platform/linux-generic/test/Makefile.am index 1f7ae611e..049ce2187 100644 --- a/platform/linux-generic/test/Makefile.am +++ b/platform/linux-generic/test/Makefile.am @@ -8,25 +8,13 @@ TESTS_ENVIRONMENT += WITH_OPENSSL=0 endif SUBDIRS = - -if WITH_EXAMPLES -TESTS = ipsec/ipsec_api_example.sh \ - ipsec/ipsec_crypto_example.sh - -dist_check_SCRIPTS = ipsec/ipsec_api_example.sh \ - ipsec/ipsec_crypto_example.sh -else TESTS = -dist_check_SCRIPTS = -endif if test_vald TESTS += validation/api/pktio/pktio_run.sh \ validation/api/pktio/pktio_run_tap.sh \ validation/api/shmem/shmem_linux$(EXEEXT) -test_SCRIPTS = $(dist_check_SCRIPTS) - SUBDIRS += validation/api/pktio\ validation/api/shmem\ pktio_ipc \ @@ -69,25 +57,3 @@ if test_installdir installcheck-local: $(DESTDIR)/$(testdir)/run-test.sh $(TESTNAME) endif - -# If building out-of-tree, make check will not copy the scripts and data to the -# $(builddir) assuming that all commands are run locally. However this prevents -# running tests on a remote target using LOG_COMPILER. -# So copy all script and data files explicitly here. -all-local: - if [ "x$(srcdir)" != "x$(builddir)" ]; then \ - for f in $(dist_check_SCRIPTS); do \ - if [ -e $(srcdir)/$$f ]; then \ - mkdir -p $(builddir)/$$(dirname $$f); \ - cp -f $(srcdir)/$$f $(builddir)/$$f; \ - fi \ - done \ - fi -clean-local: - if [ "x$(srcdir)" != "x$(builddir)" ]; then \ - for f in $(dist_check_SCRIPTS); do \ - rm -f $(builddir)/$$f; \ - done \ - fi - -.NOTPARALLEL: diff --git a/platform/linux-generic/test/example/Makefile.am b/platform/linux-generic/test/example/Makefile.am index 22b254cd7..947647cd4 100644 --- a/platform/linux-generic/test/example/Makefile.am +++ b/platform/linux-generic/test/example/Makefile.am @@ -1,6 +1,8 @@ SUBDIRS = \ classifier \ generator \ + ipsec_api \ + ipsec_crypto \ l2fwd_simple \ l3fwd \ packet \ diff --git a/platform/linux-generic/test/example/ipsec_api/Makefile.am b/platform/linux-generic/test/example/ipsec_api/Makefile.am new file mode 100644 index 000000000..101c97cdf --- /dev/null +++ b/platform/linux-generic/test/example/ipsec_api/Makefile.am @@ -0,0 +1,23 @@ +EXTRA_DIST = pktio_env + +# If building out-of-tree, make check will not copy the scripts and data to the +# $(builddir) assuming that all commands are run locally. However this prevents +# running tests on a remote target using LOG_COMPILER. +# So copy all script and data files explicitly here. +all-local: + if [ "x$(srcdir)" != "x$(builddir)" ]; then \ + for f in $(EXTRA_DIST); do \ + if [ -e $(srcdir)/$$f ]; then \ + mkdir -p $(builddir)/$$(dirname $$f); \ + cp -f $(srcdir)/$$f $(builddir)/$$f; \ + fi \ + done \ + fi +clean-local: + if [ "x$(srcdir)" != "x$(builddir)" ]; then \ + for f in $(EXTRA_DIST); do \ + rm -f $(builddir)/$$f; \ + done \ + fi + +.NOTPARALLEL: diff --git a/platform/linux-generic/test/example/ipsec_api/pktio_env b/platform/linux-generic/test/example/ipsec_api/pktio_env new file mode 100644 index 000000000..a16002326 --- /dev/null +++ b/platform/linux-generic/test/example/ipsec_api/pktio_env @@ -0,0 +1,66 @@ +#!/bin/sh +# +# Copyright (C) 2021, Marvell +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +# Script to setup interfaces used for running application on linux-generic. +# +# ipsec_api application uses two loop devices loop0 and loop1. +# + +if [ "$0" == "$BASH_SOURCE" ]; then + echo "Error: Platform specific env file has to be sourced." + exit 1 +fi + +# Absolute path to the .env file. +LINUX_ENV_PATH=$PWD/../../platform/linux-generic/test + +TESTENV="tests-linux-generic.env" + +if [ -f $LINUX_ENV_PATH/$TESTENV ]; then + source $LINUX_ENV_PATH/$TESTENV +else + echo "BUG: unable to find $TESTENV!" + echo "$TESTENV has to be in following directory: " + echo " $LINUX_ENV_PATH" + exit 1 +fi + +# Skip IPsec example tests when there's no OpenSSL. +if [ -n "$WITH_OPENSSL" ] && [ ${WITH_OPENSSL} -eq 0 ]; then + echo "Crypto not supported. Skipping." + exit 77 +fi + +IF0=p7p1 +IF1=p8p1 + +NEXT_HOP_MAC0=08:00:27:76:B5:E0 +NEXT_HOP_MAC1=08:00:27:F5:8B:DB + +LIF0=loop1 +LIF1=loop2 + +IF_LIST=$LIF0,$LIF1 +ROUTE_IF_INB=$LIF0 +ROUTE_IF_OUTB=$LIF1 +OUT_IF=$LIF1 +IN_IF=$LIF0 + +validate_result() +{ + return 0 +} + +setup_interfaces() +{ + return 0 +} + +cleanup_interfaces() +{ + return 0 +} diff --git a/platform/linux-generic/test/example/ipsec_crypto/Makefile.am b/platform/linux-generic/test/example/ipsec_crypto/Makefile.am new file mode 100644 index 000000000..101c97cdf --- /dev/null +++ b/platform/linux-generic/test/example/ipsec_crypto/Makefile.am @@ -0,0 +1,23 @@ +EXTRA_DIST = pktio_env + +# If building out-of-tree, make check will not copy the scripts and data to the +# $(builddir) assuming that all commands are run locally. However this prevents +# running tests on a remote target using LOG_COMPILER. +# So copy all script and data files explicitly here. +all-local: + if [ "x$(srcdir)" != "x$(builddir)" ]; then \ + for f in $(EXTRA_DIST); do \ + if [ -e $(srcdir)/$$f ]; then \ + mkdir -p $(builddir)/$$(dirname $$f); \ + cp -f $(srcdir)/$$f $(builddir)/$$f; \ + fi \ + done \ + fi +clean-local: + if [ "x$(srcdir)" != "x$(builddir)" ]; then \ + for f in $(EXTRA_DIST); do \ + rm -f $(builddir)/$$f; \ + done \ + fi + +.NOTPARALLEL: diff --git a/platform/linux-generic/test/example/ipsec_crypto/pktio_env b/platform/linux-generic/test/example/ipsec_crypto/pktio_env new file mode 100644 index 000000000..99a1ac42b --- /dev/null +++ b/platform/linux-generic/test/example/ipsec_crypto/pktio_env @@ -0,0 +1,72 @@ +#!/bin/sh +# +# Copyright (C) 2021, Marvell +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +# Script to setup interfaces used for running application on linux-generic. +# +# ipsec_api application uses two loop devices loop0 and loop1. +# + +if [ "$0" == "$BASH_SOURCE" ]; then + echo "Error: Platform specific env file has to be sourced." + exit 1 +fi + +# Absolute path to the .env file. +LINUX_ENV_PATH=$PWD/../../platform/linux-generic/test + +TESTENV="tests-linux-generic.env" + +if [ -f $LINUX_ENV_PATH/$TESTENV ]; then + source $LINUX_ENV_PATH/$TESTENV +else + echo "BUG: unable to find $TESTENV!" + echo "$TESTENV has to be in following directory: " + echo " $LINUX_ENV_PATH" + exit 1 +fi + +# Skip IPsec example tests when there's no OpenSSL. +if [ -n "$WITH_OPENSSL" ] && [ ${WITH_OPENSSL} -eq 0 ]; then + echo "Crypto not supported. Skipping." + exit 77 +fi + +# Skip live and router mode tests. +if [ ${IPSEC_APP_MODE} -eq 1 ] || [ ${IPSEC_APP_MODE} -eq 2 ]; then + echo "Live / Router mode test. Skipping." + exit 77 +fi + +IF0=p7p1 +IF1=p8p1 + +NEXT_HOP_MAC0=08:00:27:76:B5:E0 +NEXT_HOP_MAC1=08:00:27:F5:8B:DB + +LIF0=loop1 +LIF1=loop2 + +IF_LIST=$LIF0,$LIF1 +ROUTE_IF_INB=$LIF0 +ROUTE_IF_OUTB=$LIF1 +OUT_IF=$LIF1 +IN_IF=$LIF0 + +validate_result() +{ + return 0 +} + +setup_interfaces() +{ + return 0 +} + +cleanup_interfaces() +{ + return 0 +} diff --git a/platform/linux-generic/test/inline-timer.conf b/platform/linux-generic/test/inline-timer.conf index e4d4af307..93195f5a8 100644 --- a/platform/linux-generic/test/inline-timer.conf +++ b/platform/linux-generic/test/inline-timer.conf @@ -1,6 +1,6 @@ # Mandatory fields odp_implementation = "linux-generic" -config_file_version = "0.1.15" +config_file_version = "0.1.16" timer: { # Enable inline timer implementation diff --git a/platform/linux-generic/test/ipsec/ipsec_api_example.sh b/platform/linux-generic/test/ipsec/ipsec_api_example.sh deleted file mode 100755 index 82fd193d9..000000000 --- a/platform/linux-generic/test/ipsec/ipsec_api_example.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/bash -# -# Copyright (c) 2019, Nokia -# All rights reserved. -# -# SPDX-License-Identifier: BSD-3-Clause -# - -# Skip IPsec example tests when there's no OpenSSL. -if [ -n "$WITH_OPENSSL" ] && [ ${WITH_OPENSSL} -eq 0 ]; then -echo "Crypto not supported. Skipping." -exit 77 -fi - -# Absolute path to the example binary. This is needed during distcheck, which -# keeps scripts and binaries in different directories (scripts are not copied -# into the distribution directory). -export IPSEC_EXAMPLE_PATH=$(pwd)/../../../example/ipsec_api - -declare -i RESULT=0 - -pushd $(dirname $0)/../../../../example/ipsec_api - -./odp_ipsec_api_run_simple.sh -RESULT+=$? - -./odp_ipsec_api_run_esp_out.sh -RESULT+=$? - -popd - -exit ${RESULT} diff --git a/platform/linux-generic/test/ipsec/ipsec_crypto_example.sh b/platform/linux-generic/test/ipsec/ipsec_crypto_example.sh deleted file mode 100755 index d99fc3bd2..000000000 --- a/platform/linux-generic/test/ipsec/ipsec_crypto_example.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/bash -# -# Copyright (c) 2019, Nokia -# All rights reserved. -# -# SPDX-License-Identifier: BSD-3-Clause -# - -# Skip IPsec example tests when there's no OpenSSL. -if [ -n "$WITH_OPENSSL" ] && [ ${WITH_OPENSSL} -eq 0 ]; then -echo "Crypto not supported. Skipping." -exit 77 -fi - -# Absolute path to the example binary. This is needed during distcheck, which -# keeps scripts and binaries in different directories (scripts are not copied -# into the distribution directory). -export IPSEC_EXAMPLE_PATH=$(pwd)/../../../example/ipsec_crypto - -declare -i RESULT=0 - -pushd $(dirname $0)/../../../../example/ipsec_crypto - -./odp_ipsec_crypto_run_simple.sh -RESULT+=$? - -./odp_ipsec_crypto_run_esp_out.sh -RESULT+=$? - -popd - -exit ${RESULT} diff --git a/platform/linux-generic/test/packet_align.conf b/platform/linux-generic/test/packet_align.conf index 9b37752ba..58a73f2df 100644 --- a/platform/linux-generic/test/packet_align.conf +++ b/platform/linux-generic/test/packet_align.conf @@ -1,6 +1,6 @@ # Mandatory fields odp_implementation = "linux-generic" -config_file_version = "0.1.15" +config_file_version = "0.1.16" pool: { pkt: { diff --git a/platform/linux-generic/test/process-mode.conf b/platform/linux-generic/test/process-mode.conf index 5354cae2f..a6e6080d2 100644 --- a/platform/linux-generic/test/process-mode.conf +++ b/platform/linux-generic/test/process-mode.conf @@ -1,6 +1,6 @@ # Mandatory fields odp_implementation = "linux-generic" -config_file_version = "0.1.15" +config_file_version = "0.1.16" # Shared memory options shm: { diff --git a/platform/linux-generic/test/sched-basic.conf b/platform/linux-generic/test/sched-basic.conf index 57a8a772c..79537b454 100644 --- a/platform/linux-generic/test/sched-basic.conf +++ b/platform/linux-generic/test/sched-basic.conf @@ -1,6 +1,6 @@ # Mandatory fields odp_implementation = "linux-generic" -config_file_version = "0.1.15" +config_file_version = "0.1.16" sched_basic: { # Test scheduler with an odd spread value diff --git a/scripts/ci/build.sh b/scripts/ci/build.sh index ae50bf065..38127edc1 100755 --- a/scripts/ci/build.sh +++ b/scripts/ci/build.sh @@ -4,7 +4,7 @@ set -e cd "$(dirname "$0")"/../.. ./bootstrap ./configure \ - --host=${TARGET_ARCH} --build=x86_64-linux-gnu \ + --host=${TARGET_ARCH} --build=${BUILD_ARCH:-x86_64-linux-gnu} \ --prefix=/opt/odp \ ${CONF} @@ -47,7 +47,7 @@ sysctl vm.nr_hugepages=1000 mkdir -p /mnt/huge mount -t hugetlbfs nodev /mnt/huge -if [ "$TARGET_ARCH" = "x86_64-linux-gnu" ] +if [ -z "$TARGET_ARCH" ] || [ "$TARGET_ARCH" == "$BUILD_ARCH" ] then LD_LIBRARY_PATH="/opt/odp/lib:$LD_LIBRARY_PATH" ./odp_hello_inst_dynamic fi diff --git a/scripts/ci/build_arm64.sh b/scripts/ci/build_arm64.sh index abdc5acb8..ad3b95e75 100755 --- a/scripts/ci/build_arm64.sh +++ b/scripts/ci/build_arm64.sh @@ -2,6 +2,10 @@ set -e export TARGET_ARCH=aarch64-linux-gnu +if [[ $(uname -m) =~ ^(arm64|aarch64)$ ]]; then + export BUILD_ARCH=aarch64-linux-gnu +fi + if [ "${CC#clang}" != "${CC}" ] ; then export CC="clang --target=${TARGET_ARCH}" export CXX="clang++ --target=${TARGET_ARCH}" diff --git a/scripts/ci/check.sh b/scripts/ci/check.sh index a181a184b..7b22db066 100755 --- a/scripts/ci/check.sh +++ b/scripts/ci/check.sh @@ -5,7 +5,7 @@ echo 1500 | tee /proc/sys/vm/nr_hugepages mkdir -p /mnt/huge mount -t hugetlbfs nodev /mnt/huge -"`dirname "$0"`"/build_x86_64.sh +"`dirname "$0"`"/build_${ARCH}.sh cd "$(dirname "$0")"/../.. diff --git a/scripts/ci/check_inline_timer.sh b/scripts/ci/check_inline_timer.sh index d2eff7145..1fa9c21f5 100755 --- a/scripts/ci/check_inline_timer.sh +++ b/scripts/ci/check_inline_timer.sh @@ -1,7 +1,7 @@ #!/bin/bash set -e -"`dirname "$0"`"/build_x86_64.sh +"`dirname "$0"`"/build_${ARCH}.sh cd "$(dirname "$0")"/../.. diff --git a/scripts/ci/check_pktio.sh b/scripts/ci/check_pktio.sh index d82fe8aad..e61bacc98 100755 --- a/scripts/ci/check_pktio.sh +++ b/scripts/ci/check_pktio.sh @@ -1,7 +1,7 @@ #!/bin/bash set -e -"`dirname "$0"`"/build_x86_64.sh +"`dirname "$0"`"/build_${ARCH}.sh cd "$(dirname "$0")"/../.. diff --git a/scripts/ci/coverage.sh b/scripts/ci/coverage.sh index e413c28fb..cdcddfe93 100755 --- a/scripts/ci/coverage.sh +++ b/scripts/ci/coverage.sh @@ -8,7 +8,7 @@ fi cd "$(dirname "$0")"/../.. ./bootstrap ./configure \ - CFLAGS="-O0 -coverage $CLFAGS" CXXFLAGS="-O0 -coverage $CXXFLAGS" LDFLAGS="--coverage $LDFLAGS" \ + CFLAGS="-O0 -coverage $CFLAGS" CXXFLAGS="-O0 -coverage $CXXFLAGS" LDFLAGS="--coverage $LDFLAGS" \ --enable-debug=full --enable-helper-linux export CCACHE_DISABLE=1 make -j $(nproc) diff --git a/scripts/shippable-post.sh b/scripts/shippable-post.sh deleted file mode 100755 index 9d59da3f8..000000000 --- a/scripts/shippable-post.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh - -wget https://raw.githubusercontent.com/shawnliang/cunit-to-junit/master/cunit-to-junit.xsl - -mkdir -p "$SHIPPABLE_BUILD_DIR/shippable/testresults" - -SCHED=${1:-default} -echo $SCHED - -for FILE in `find ./test ./platform/ -name "*.xml"`; do - bname="`basename $FILE`"; - echo Processing $FILE as ${SCHED}-${bname} - xsltproc --novalid cunit-to-junit.xsl "$FILE" > \ - "$SHIPPABLE_BUILD_DIR/shippable/testresults/${SCHED}-${bname}" -done diff --git a/test/common/odp_cunit_common.c b/test/common/odp_cunit_common.c index 62418c356..f5c437344 100644 --- a/test/common/odp_cunit_common.c +++ b/test/common/odp_cunit_common.c @@ -259,7 +259,8 @@ int odp_cunit_print_inactive(void) continue; if (first) { - printf("\n\n Inactive tests:\n"); + printf("\n\nSuite: %s\n", sinfo->name); + printf(" Inactive tests:\n"); first = 0; } @@ -269,6 +270,34 @@ int odp_cunit_print_inactive(void) return 0; } +int odp_cunit_set_inactive(void) +{ + CU_pSuite cur_suite; + CU_pTest ptest; + odp_suiteinfo_t *sinfo; + odp_testinfo_t *tinfo; + + cur_suite = CU_get_current_suite(); + if (cur_suite == NULL) + return -1; + + sinfo = cunit_get_suite_info(cur_suite->pName); + if (sinfo == NULL) + return -1; + + for (tinfo = sinfo->testinfo_tbl; tinfo->name; tinfo++) { + ptest = CU_get_test_by_name(tinfo->name, cur_suite); + if (ptest == NULL) { + fprintf(stderr, "%s: test not found: %s\n", + __func__, tinfo->name); + return -1; + } + CU_set_test_active(ptest, false); + } + + return 0; +} + static int default_term_func(void) { return odp_cunit_print_inactive(); @@ -526,3 +555,17 @@ int odp_cunit_ret(int val) { return allow_skip_result ? 0 : val; } + +int odp_cunit_ci_skip(const char *test_name) +{ + const char *ci_skip; + const char *found; + + ci_skip = getenv("CI_SKIP"); + if (ci_skip == NULL) + return 0; + + found = strstr(ci_skip, test_name); + + return found != NULL; +} diff --git a/test/common/odp_cunit_common.h b/test/common/odp_cunit_common.h index 55e52ce1c..3e06ba10c 100644 --- a/test/common/odp_cunit_common.h +++ b/test/common/odp_cunit_common.h @@ -105,6 +105,10 @@ void odp_cunit_register_global_term(int (*func_term_ptr)(odp_instance_t inst)); int odp_cunit_ret(int val); int odp_cunit_print_inactive(void); +int odp_cunit_set_inactive(void); + +/* Check from CI_SKIP environment variable if the test case should be skipped by CI */ +int odp_cunit_ci_skip(const char *test_name); /* * Wrapper for CU_ASSERT_FATAL implementation to show the compiler that diff --git a/test/performance/odp_ipsec.c b/test/performance/odp_ipsec.c index 2e283a63b..05a22ff0d 100644 --- a/test/performance/odp_ipsec.c +++ b/test/performance/odp_ipsec.c @@ -866,7 +866,12 @@ run_measure_one_config(ipsec_args_t *cargs, odp_ipsec_status_t status; while (1) { - odp_event_t event = odp_queue_deq(out_queue); + odp_event_t event; + + if (cargs->poll) + event = odp_queue_deq(out_queue); + else + event = odp_schedule(NULL, ODP_SCHED_NO_WAIT); if (event != ODP_EVENT_INVALID && odp_event_type(event) == ODP_EVENT_IPSEC_STATUS && diff --git a/test/performance/odp_sched_pktio.c b/test/performance/odp_sched_pktio.c index c752e2a91..cbdbdf4aa 100644 --- a/test/performance/odp_sched_pktio.c +++ b/test/performance/odp_sched_pktio.c @@ -490,7 +490,7 @@ static int worker_thread_timers(void *arg) ret = odp_timer_set_rel(timer, tick, NULL); if (odp_unlikely(ret != ODP_TIMER_SUCCESS && - ret != ODP_TIMER_NOEVENT)) { + ret != ODP_TIMER_FAIL)) { /* Tick period is too short or long. Normally, * reset either succeeds or fails due to timer * expiration, in which case timeout event will @@ -1253,7 +1253,7 @@ static int create_timers(test_global_t *test_global) if (test_global->opt.timeout_us == 0) return 0; - if (odp_timer_capability(ODP_CLOCK_CPU, &timer_capa)) { + if (odp_timer_capability(ODP_CLOCK_DEFAULT, &timer_capa)) { printf("Timer capa failed\n"); return -1; } @@ -1272,7 +1272,7 @@ static int create_timers(test_global_t *test_global) timer_param.min_tmo = timeout_ns; timer_param.max_tmo = timeout_ns; timer_param.num_timers = num_timer; - timer_param.clk_src = ODP_CLOCK_CPU; + timer_param.clk_src = ODP_CLOCK_DEFAULT; timer_pool = odp_timer_pool_create("sched_pktio_timer", &timer_param); diff --git a/test/performance/odp_timer_perf.c b/test/performance/odp_timer_perf.c index 4b8318557..6989d0d4c 100644 --- a/test/performance/odp_timer_perf.c +++ b/test/performance/odp_timer_perf.c @@ -307,14 +307,14 @@ static int create_timer_pools(test_global_t *global) global->timer[i][j] = ODP_TIMER_INVALID; } - if (odp_timer_capability(ODP_CLOCK_CPU, &timer_capa)) { + if (odp_timer_capability(ODP_CLOCK_DEFAULT, &timer_capa)) { ODPH_ERR("Timer capability failed\n"); return -1; } memset(&timer_res_capa, 0, sizeof(odp_timer_res_capability_t)); timer_res_capa.res_ns = res_ns; - if (odp_timer_res_capability(ODP_CLOCK_CPU, &timer_res_capa)) { + if (odp_timer_res_capability(ODP_CLOCK_DEFAULT, &timer_res_capa)) { ODPH_ERR("Timer resolution capability failed\n"); return -1; } @@ -352,7 +352,7 @@ static int create_timer_pools(test_global_t *global) timer_pool_param.max_tmo = max_tmo_ns; timer_pool_param.num_timers = num_timer; timer_pool_param.priv = priv; - timer_pool_param.clk_src = ODP_CLOCK_CPU; + timer_pool_param.clk_src = ODP_CLOCK_DEFAULT; odp_pool_param_init(&pool_param); pool_param.type = ODP_POOL_TIMEOUT; diff --git a/test/validation/api/ipsec/ipsec.c b/test/validation/api/ipsec/ipsec.c index a76bac973..981bc9155 100644 --- a/test/validation/api/ipsec/ipsec.c +++ b/test/validation/api/ipsec/ipsec.c @@ -217,20 +217,17 @@ int ipsec_check_esp_aes_gcm_256(void) int ipsec_check_ah_aes_gmac_128(void) { - return ipsec_check_esp(ODP_CIPHER_ALG_NULL, 0, - ODP_AUTH_ALG_AES_GMAC, 128); + return ipsec_check_ah(ODP_AUTH_ALG_AES_GMAC, 128); } int ipsec_check_ah_aes_gmac_192(void) { - return ipsec_check_esp(ODP_CIPHER_ALG_NULL, 0, - ODP_AUTH_ALG_AES_GMAC, 192); + return ipsec_check_ah(ODP_AUTH_ALG_AES_GMAC, 192); } int ipsec_check_ah_aes_gmac_256(void) { - return ipsec_check_esp(ODP_CIPHER_ALG_NULL, 0, - ODP_AUTH_ALG_AES_GMAC, 256); + return ipsec_check_ah(ODP_AUTH_ALG_AES_GMAC, 256); } int ipsec_check_esp_null_aes_gmac_128(void) diff --git a/test/validation/api/ipsec/ipsec.h b/test/validation/api/ipsec/ipsec.h index 161835a33..b899fce48 100644 --- a/test/validation/api/ipsec/ipsec.h +++ b/test/validation/api/ipsec/ipsec.h @@ -16,6 +16,8 @@ ((c) << 8) | \ ((d) << 0)) +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) + /* test arrays: */ extern odp_testinfo_t ipsec_in_suite[]; extern odp_testinfo_t ipsec_out_suite[]; diff --git a/test/validation/api/ipsec/ipsec_test_in.c b/test/validation/api/ipsec/ipsec_test_in.c index 4eafed6a9..08512c8fb 100644 --- a/test/validation/api/ipsec/ipsec_test_in.c +++ b/test/validation/api/ipsec/ipsec_test_in.c @@ -1,10 +1,13 @@ /* Copyright (c) 2017-2018, Linaro Limited * Copyright (c) 2020-2021, Marvell + * Copyright (c) 2021, Nokia * All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ +#include <odp/helper/odph_api.h> + #include "ipsec.h" #include "reass_test_vectors.h" @@ -1764,132 +1767,109 @@ static void test_ipsec_sa_print(void) ipsec_sa_destroy(in_sa); } -static void test_in_ipv4_esp_reass_success_two_frags(odp_ipsec_sa_t out_sa, - odp_ipsec_sa_t in_sa) +static void test_multi_out_in(odp_ipsec_sa_t out_sa, + odp_ipsec_sa_t in_sa, + uint8_t tunnel_ip_ver, + int num_input_packets, + ipsec_test_packet *input_packets[], + ipsec_test_packet *result_packet) { - ipsec_test_part test_out[MAX_FRAGS], test_in[MAX_FRAGS]; + uint8_t ver_ihl = result_packet->data[result_packet->l3_offset]; + odp_bool_t is_result_ipv6 = (ODPH_IPV4HDR_VER(ver_ihl) == ODPH_IPV6); int i; - memset(test_in, 0, sizeof(test_in)); - - CU_ASSERT(MAX_FRAGS >= 2); - - part_prep_esp(test_out, 2, false); - - test_out[0].pkt_in = &pkt_ipv4_udp_p1_f1; - test_out[1].pkt_in = &pkt_ipv4_udp_p1_f2; - - part_prep_plain(&test_in[1], 1, false, true); - test_in[1].out[0].pkt_res = &pkt_ipv4_udp_p1; - - for (i = 0; i < 2; i++) { + for (i = 0; i < num_input_packets; i++) { + ipsec_test_part test_out; + ipsec_test_part test_in; ipsec_test_packet test_pkt; odp_packet_t pkt; - CU_ASSERT_EQUAL(ipsec_check_out(&test_out[i], out_sa, &pkt), 1); - + /* + * Convert plain text packet to IPsec packet through + * outbound IPsec processing. + */ + part_prep_esp(&test_out, 1, tunnel_ip_ver == ODPH_IPV6); + test_out.pkt_in = input_packets[i]; + CU_ASSERT_EQUAL(ipsec_check_out(&test_out, out_sa, &pkt), 1); + + /* + * Perform inbound IPsec processing for the IPsec packet. + * Expect result packet only for the last packet. + */ + memset(&test_in, 0, sizeof(test_in)); + if (i == num_input_packets - 1) { + part_prep_plain(&test_in, 1, is_result_ipv6, true); + test_in.out[0].pkt_res = result_packet; + } ipsec_test_packet_from_pkt(&test_pkt, &pkt); - test_in[i].pkt_in = &test_pkt; + test_in.pkt_in = &test_pkt; - ipsec_check_in_one(&test_in[i], in_sa); + ipsec_check_in_one(&test_in, in_sa); } } -static void test_in_ipv4_esp_reass_success_four_frags(odp_ipsec_sa_t out_sa, - odp_ipsec_sa_t in_sa) +static void test_in_ipv4_esp_reass_success_two_frags(odp_ipsec_sa_t out_sa, + odp_ipsec_sa_t in_sa) { - ipsec_test_part test_out[MAX_FRAGS], test_in[MAX_FRAGS]; - int i; - - memset(test_in, 0, sizeof(test_in)); - - CU_ASSERT(MAX_FRAGS >= 4); - - part_prep_esp(test_out, 4, false); - - test_out[0].pkt_in = &pkt_ipv4_udp_p2_f1; - test_out[1].pkt_in = &pkt_ipv4_udp_p2_f2; - test_out[2].pkt_in = &pkt_ipv4_udp_p2_f3; - test_out[3].pkt_in = &pkt_ipv4_udp_p2_f4; - - part_prep_plain(&test_in[3], 1, false, true); - test_in[3].out[0].pkt_res = &pkt_ipv4_udp_p2; - - for (i = 0; i < 4; i++) { - ipsec_test_packet test_pkt; - odp_packet_t pkt; + ipsec_test_packet *input_packets[] = { + &pkt_ipv4_udp_p1_f1, + &pkt_ipv4_udp_p1_f2, + }; + ipsec_test_packet *result_packet = &pkt_ipv4_udp_p1; - CU_ASSERT_EQUAL(ipsec_check_out(&test_out[i], out_sa, &pkt), 1); + test_multi_out_in(out_sa, in_sa, ODPH_IPV4, + ARRAY_SIZE(input_packets), + input_packets, + result_packet); +} - ipsec_test_packet_from_pkt(&test_pkt, &pkt); - test_in[i].pkt_in = &test_pkt; +static void test_in_ipv4_esp_reass_success_four_frags(odp_ipsec_sa_t out_sa, + odp_ipsec_sa_t in_sa) +{ + ipsec_test_packet *input_packets[] = { + &pkt_ipv4_udp_p2_f1, + &pkt_ipv4_udp_p2_f2, + &pkt_ipv4_udp_p2_f3, + &pkt_ipv4_udp_p2_f4, + }; + ipsec_test_packet *result_packet = &pkt_ipv4_udp_p2; - ipsec_check_in_one(&test_in[i], in_sa); - } + test_multi_out_in(out_sa, in_sa, ODPH_IPV4, + ARRAY_SIZE(input_packets), + input_packets, + result_packet); } static void test_in_ipv4_esp_reass_success_two_frags_ooo(odp_ipsec_sa_t out_sa, odp_ipsec_sa_t in_sa) { - ipsec_test_part test_out[MAX_FRAGS], test_in[MAX_FRAGS]; - int i; - - memset(test_in, 0, sizeof(test_in)); - - CU_ASSERT(MAX_FRAGS >= 2); - - part_prep_esp(test_out, 2, false); - - test_out[0].pkt_in = &pkt_ipv4_udp_p1_f2; - test_out[1].pkt_in = &pkt_ipv4_udp_p1_f1; - - part_prep_plain(&test_in[1], 1, false, true); - test_in[1].out[0].pkt_res = &pkt_ipv4_udp_p1; - - for (i = 0; i < 2; i++) { - ipsec_test_packet test_pkt; - odp_packet_t pkt; - - CU_ASSERT_EQUAL(ipsec_check_out(&test_out[i], out_sa, &pkt), 1); - - ipsec_test_packet_from_pkt(&test_pkt, &pkt); - test_in[i].pkt_in = &test_pkt; + ipsec_test_packet *input_packets[] = { + &pkt_ipv4_udp_p1_f2, + &pkt_ipv4_udp_p1_f1, + }; + ipsec_test_packet *result_packet = &pkt_ipv4_udp_p1; - ipsec_check_in_one(&test_in[i], in_sa); - } + test_multi_out_in(out_sa, in_sa, ODPH_IPV4, + ARRAY_SIZE(input_packets), + input_packets, + result_packet); } static void test_in_ipv4_esp_reass_success_four_frags_ooo(odp_ipsec_sa_t out_sa, odp_ipsec_sa_t in_sa) { - ipsec_test_part test_out[MAX_FRAGS], test_in[MAX_FRAGS]; - int i; - - memset(test_in, 0, sizeof(test_in)); - - CU_ASSERT(MAX_FRAGS >= 4); - - part_prep_esp(test_out, 4, false); - - test_out[0].pkt_in = &pkt_ipv4_udp_p2_f4; - test_out[1].pkt_in = &pkt_ipv4_udp_p2_f1; - test_out[2].pkt_in = &pkt_ipv4_udp_p2_f2; - test_out[3].pkt_in = &pkt_ipv4_udp_p2_f3; - - part_prep_plain(&test_in[3], 1, false, true); - test_in[3].out[0].pkt_res = &pkt_ipv4_udp_p2; - - for (i = 0; i < 4; i++) { - ipsec_test_packet test_pkt; - odp_packet_t pkt; - - CU_ASSERT_EQUAL(ipsec_check_out(&test_out[i], out_sa, &pkt), 1); - - ipsec_test_packet_from_pkt(&test_pkt, &pkt); - test_in[i].pkt_in = &test_pkt; + ipsec_test_packet *input_packets[] = { + &pkt_ipv4_udp_p2_f4, + &pkt_ipv4_udp_p2_f1, + &pkt_ipv4_udp_p2_f2, + &pkt_ipv4_udp_p2_f3, + }; + ipsec_test_packet *result_packet = &pkt_ipv4_udp_p2; - ipsec_check_in_one(&test_in[i], in_sa); - } + test_multi_out_in(out_sa, in_sa, ODPH_IPV4, + ARRAY_SIZE(input_packets), + input_packets, + result_packet); } static void test_in_ipv4_esp_reass_incomp_missing(odp_ipsec_sa_t out_sa, @@ -2024,129 +2004,65 @@ static void test_in_ipv4_esp_reass_incomp(void) static void test_in_ipv6_esp_reass_success_two_frags(odp_ipsec_sa_t out_sa, odp_ipsec_sa_t in_sa) { - ipsec_test_part test_out[MAX_FRAGS], test_in[MAX_FRAGS]; - int i; - - memset(test_in, 0, sizeof(test_in)); - - CU_ASSERT(MAX_FRAGS >= 2); - - part_prep_esp(test_out, 2, true); - - test_out[0].pkt_in = &pkt_ipv6_udp_p1_f1; - test_out[1].pkt_in = &pkt_ipv6_udp_p1_f2; - - part_prep_plain(&test_in[1], 1, true, true); - test_in[1].out[0].pkt_res = &pkt_ipv6_udp_p1; - - for (i = 0; i < 2; i++) { - ipsec_test_packet test_pkt; - odp_packet_t pkt; - - CU_ASSERT_EQUAL(ipsec_check_out(&test_out[i], out_sa, &pkt), 1); - - ipsec_test_packet_from_pkt(&test_pkt, &pkt); - test_in[i].pkt_in = &test_pkt; + ipsec_test_packet *input_packets[] = { + &pkt_ipv6_udp_p1_f1, + &pkt_ipv6_udp_p1_f2, + }; + ipsec_test_packet *result_packet = &pkt_ipv6_udp_p1; - ipsec_check_in_one(&test_in[i], in_sa); - } + test_multi_out_in(out_sa, in_sa, ODPH_IPV6, + ARRAY_SIZE(input_packets), + input_packets, + result_packet); } static void test_in_ipv6_esp_reass_success_four_frags(odp_ipsec_sa_t out_sa, odp_ipsec_sa_t in_sa) { - ipsec_test_part test_out[MAX_FRAGS], test_in[MAX_FRAGS]; - int i; - - memset(test_in, 0, sizeof(test_in)); - - CU_ASSERT(MAX_FRAGS >= 4); - - part_prep_esp(test_out, 4, true); - - test_out[0].pkt_in = &pkt_ipv6_udp_p2_f1; - test_out[1].pkt_in = &pkt_ipv6_udp_p2_f2; - test_out[2].pkt_in = &pkt_ipv6_udp_p2_f3; - test_out[3].pkt_in = &pkt_ipv6_udp_p2_f4; - - part_prep_plain(&test_in[3], 1, true, true); - test_in[3].out[0].pkt_res = &pkt_ipv6_udp_p2; - - for (i = 0; i < 4; i++) { - ipsec_test_packet test_pkt; - odp_packet_t pkt; - - CU_ASSERT_EQUAL(ipsec_check_out(&test_out[i], out_sa, &pkt), 1); - - ipsec_test_packet_from_pkt(&test_pkt, &pkt); - test_in[i].pkt_in = &test_pkt; + ipsec_test_packet *input_packets[] = { + &pkt_ipv6_udp_p2_f1, + &pkt_ipv6_udp_p2_f2, + &pkt_ipv6_udp_p2_f3, + &pkt_ipv6_udp_p2_f4, + }; + ipsec_test_packet *result_packet = &pkt_ipv6_udp_p2; - ipsec_check_in_one(&test_in[i], in_sa); - } + test_multi_out_in(out_sa, in_sa, ODPH_IPV6, + ARRAY_SIZE(input_packets), + input_packets, + result_packet); } static void test_in_ipv6_esp_reass_success_two_frags_ooo(odp_ipsec_sa_t out_sa, odp_ipsec_sa_t in_sa) { - ipsec_test_part test_out[MAX_FRAGS], test_in[MAX_FRAGS]; - int i; - - memset(test_in, 0, sizeof(test_in)); - - CU_ASSERT(MAX_FRAGS >= 2); - - part_prep_esp(test_out, 2, true); - - test_out[0].pkt_in = &pkt_ipv6_udp_p1_f2; - test_out[1].pkt_in = &pkt_ipv6_udp_p1_f1; - - part_prep_plain(&test_in[1], 1, true, true); - test_in[1].out[0].pkt_res = &pkt_ipv6_udp_p1; - - for (i = 0; i < 2; i++) { - ipsec_test_packet test_pkt; - odp_packet_t pkt; - - CU_ASSERT_EQUAL(ipsec_check_out(&test_out[i], out_sa, &pkt), 1); - - ipsec_test_packet_from_pkt(&test_pkt, &pkt); - test_in[i].pkt_in = &test_pkt; + ipsec_test_packet *input_packets[] = { + &pkt_ipv6_udp_p1_f2, + &pkt_ipv6_udp_p1_f1, + }; + ipsec_test_packet *result_packet = &pkt_ipv6_udp_p1; - ipsec_check_in_one(&test_in[i], in_sa); - } + test_multi_out_in(out_sa, in_sa, ODPH_IPV6, + ARRAY_SIZE(input_packets), + input_packets, + result_packet); } static void test_in_ipv6_esp_reass_success_four_frags_ooo(odp_ipsec_sa_t out_sa, odp_ipsec_sa_t in_sa) { - ipsec_test_part test_out[MAX_FRAGS], test_in[MAX_FRAGS]; - int i; - - memset(test_in, 0, sizeof(test_in)); - - CU_ASSERT(MAX_FRAGS >= 4); - - part_prep_esp(test_out, 4, true); - - test_out[1].pkt_in = &pkt_ipv6_udp_p2_f2; - test_out[2].pkt_in = &pkt_ipv6_udp_p2_f3; - test_out[3].pkt_in = &pkt_ipv6_udp_p2_f4; - test_out[0].pkt_in = &pkt_ipv6_udp_p2_f1; - - part_prep_plain(&test_in[3], 1, true, true); - test_in[3].out[0].pkt_res = &pkt_ipv6_udp_p2; - - for (i = 0; i < 4; i++) { - ipsec_test_packet test_pkt; - odp_packet_t pkt; - - CU_ASSERT_EQUAL(ipsec_check_out(&test_out[i], out_sa, &pkt), 1); - - ipsec_test_packet_from_pkt(&test_pkt, &pkt); - test_in[i].pkt_in = &test_pkt; + ipsec_test_packet *input_packets[] = { + &pkt_ipv6_udp_p2_f2, + &pkt_ipv6_udp_p2_f3, + &pkt_ipv6_udp_p2_f4, + &pkt_ipv6_udp_p2_f1, + }; + ipsec_test_packet *result_packet = &pkt_ipv6_udp_p2; - ipsec_check_in_one(&test_in[i], in_sa); - } + test_multi_out_in(out_sa, in_sa, ODPH_IPV6, + ARRAY_SIZE(input_packets), + input_packets, + result_packet); } static void test_in_ipv6_esp_reass_incomp_missing(odp_ipsec_sa_t out_sa, diff --git a/test/validation/api/ipsec/ipsec_test_out.c b/test/validation/api/ipsec/ipsec_test_out.c index b48dd0d6c..7c1121579 100644 --- a/test/validation/api/ipsec/ipsec_test_out.c +++ b/test/validation/api/ipsec/ipsec_test_out.c @@ -119,8 +119,6 @@ static struct cipher_auth_comb_param cipher_auth_comb[] = { }, }; -#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) - static void test_out_ipv4_ah_sha256(void) { odp_ipsec_sa_param_t param; @@ -361,17 +359,19 @@ static void test_ipsec_stats_zero_assert(odp_ipsec_stats_t *stats) CU_ASSERT_EQUAL(stats->mtu_err, 0); CU_ASSERT_EQUAL(stats->hard_exp_bytes_err, 0); CU_ASSERT_EQUAL(stats->hard_exp_pkts_err, 0); + CU_ASSERT_EQUAL(stats->success_bytes, 0); } static void test_ipsec_stats_test_assert(odp_ipsec_stats_t *stats, - enum ipsec_test_stats test) + enum ipsec_test_stats test, + uint64_t succ_bytes) { if (test == IPSEC_TEST_STATS_SUCCESS) { - /* Braces needed by CU macro */ CU_ASSERT_EQUAL(stats->success, 1); + CU_ASSERT(stats->success_bytes >= succ_bytes); } else { - /* Braces needed by CU macro */ CU_ASSERT_EQUAL(stats->success, 0); + CU_ASSERT_EQUAL(stats->success_bytes, 0); } if (test == IPSEC_TEST_STATS_PROTO_ERR) { @@ -608,20 +608,36 @@ static void test_out_in_common(const ipsec_test_flags *flags, ipsec_check_out_in_one(&test_out, &test_in, sa_out, sa_in, flags); - if (flags->stats == IPSEC_TEST_STATS_SUCCESS) { - CU_ASSERT_EQUAL(odp_ipsec_stats(sa_in, &stats), 0); - test_ipsec_stats_test_assert(&stats, flags->stats); - } - if (flags->stats != IPSEC_TEST_STATS_NONE) { + uint64_t succ_bytes = 0; + + /* Minimum bytes to be counted for stats.success_bytes */ + if (!flags->ah) { + succ_bytes = test_out.pkt_in[0].len - + test_out.pkt_in[0].l4_offset; + + if (flags->tunnel) + succ_bytes += test_out.pkt_in[0].l4_offset - + test_out.pkt_in[0].l3_offset; + } else { + succ_bytes = test_out.pkt_in[0].len - + test_out.pkt_in[0].l3_offset; + + if (flags->tunnel) + succ_bytes += (flags->tunnel_is_v6 ? + ODPH_IPV6HDR_LEN : + ODPH_IPV4HDR_LEN); + } + /* All stats tests have outbound operation success and inbound * varying. */ CU_ASSERT_EQUAL(odp_ipsec_stats(sa_out, &stats), 0); - test_ipsec_stats_test_assert(&stats, IPSEC_TEST_STATS_SUCCESS); + test_ipsec_stats_test_assert(&stats, IPSEC_TEST_STATS_SUCCESS, + succ_bytes); CU_ASSERT_EQUAL(odp_ipsec_stats(sa_in, &stats), 0); - test_ipsec_stats_test_assert(&stats, flags->stats); + test_ipsec_stats_test_assert(&stats, flags->stats, succ_bytes); } ipsec_sa_destroy(sa_out); diff --git a/test/validation/api/packet/packet.c b/test/validation/api/packet/packet.c index cd3009ce3..e25260b1d 100644 --- a/test/validation/api/packet/packet.c +++ b/test/validation/api/packet/packet.c @@ -929,13 +929,7 @@ static void _verify_headroom_shift(odp_packet_t *pkt, CU_ASSERT_PTR_NOT_NULL(data); if (extended) { CU_ASSERT(rc >= 0); - if (shift >= 0) { - CU_ASSERT(odp_packet_seg_len(*pkt) == shift - room); - } else { - CU_ASSERT(odp_packet_headroom(*pkt) >= - (uint32_t)abs(shift) - seg_data_len); - } - CU_ASSERT(odp_packet_head(*pkt) != head_orig); + CU_ASSERT(odp_packet_seg_len(*pkt) == seg_len); } else { CU_ASSERT(odp_packet_headroom(*pkt) == room - shift); CU_ASSERT(odp_packet_seg_len(*pkt) == seg_data_len + shift); @@ -1032,15 +1026,13 @@ static void _verify_tailroom_shift(odp_packet_t *pkt, CU_ASSERT_PTR_NOT_NULL(tail); if (extended) { CU_ASSERT(rc >= 0); - CU_ASSERT(odp_packet_last_seg(*pkt) != seg); - seg = odp_packet_last_seg(*pkt); - if (shift > 0) { - CU_ASSERT(odp_packet_seg_data_len(*pkt, seg) == - shift - room); + + if (shift >= 0) { + if (rc == 0) + CU_ASSERT(tail == tail_orig); } else { - CU_ASSERT(odp_packet_tailroom(*pkt) >= - (uint32_t)abs(shift) - seg_data_len); - CU_ASSERT(seg_len == odp_packet_tailroom(*pkt)); + CU_ASSERT(odp_packet_tail(*pkt) == tail); + CU_ASSERT(odp_packet_tailroom(*pkt) == seg_len); } } else { CU_ASSERT(odp_packet_seg_data_len(*pkt, seg) == @@ -1049,19 +1041,15 @@ static void _verify_tailroom_shift(odp_packet_t *pkt, if (room == 0 || (room - shift) == 0) return; if (shift >= 0) { - CU_ASSERT(odp_packet_tail(*pkt) == - tail_orig + shift); + CU_ASSERT(odp_packet_tail(*pkt) == tail_orig + shift); + CU_ASSERT(tail == tail_orig); } else { + CU_ASSERT(odp_packet_tail(*pkt) == tail); CU_ASSERT(tail == tail_orig + shift); } } CU_ASSERT(odp_packet_len(*pkt) == pkt_data_len + shift); - if (shift >= 0) { - CU_ASSERT(tail == tail_orig); - } else { - CU_ASSERT(odp_packet_tail(*pkt) == tail); - } } static void packet_test_tailroom(void) diff --git a/test/validation/api/pktio/pktio.c b/test/validation/api/pktio/pktio.c index 7549e16ef..9a47dbe8c 100644 --- a/test/validation/api/pktio/pktio.c +++ b/test/validation/api/pktio/pktio.c @@ -3810,6 +3810,169 @@ static void pktio_test_pktout_aging_tmo(void) } } +static void pktio_test_pktin_event_queue(odp_pktin_mode_t pktin_mode) +{ + odp_pktio_t pktio_tx, pktio_rx; + odp_pktin_queue_param_t in_queue_param; + odp_pktout_queue_param_t out_queue_param; + odp_pktout_queue_t pktout_queue; + odp_queue_t queue, from; + odp_pool_t buf_pool; + odp_pool_param_t pool_param; + odp_packet_t pkt_tbl[TX_BATCH_LEN]; + odp_packet_t pkt; + odp_buffer_t buf; + odp_event_t ev; + uint32_t pkt_seq[TX_BATCH_LEN]; + int ret, i; + odp_time_t t1, t2; + int inactive = 0; + int num_pkt = 0; + int num_buf = 0; + int num_bad = 0; + odp_pktio_t pktio[MAX_NUM_IFACES] = {0}; + uint64_t wait_sec = odp_schedule_wait_time(ODP_TIME_SEC_IN_NS); + + CU_ASSERT_FATAL(num_ifaces >= 1); + + odp_pool_param_init(&pool_param); + pool_param.type = ODP_POOL_BUFFER; + pool_param.buf.num = 2 * TX_BATCH_LEN; + pool_param.buf.size = 100; + + buf_pool = odp_pool_create("buffer pool", &pool_param); + CU_ASSERT_FATAL(buf_pool != ODP_POOL_INVALID); + + buf = odp_buffer_alloc(buf_pool); + CU_ASSERT_FATAL(buf != ODP_BUFFER_INVALID); + + odp_pktin_queue_param_init(&in_queue_param); + in_queue_param.num_queues = 1; + in_queue_param.hash_enable = 0; + in_queue_param.classifier_enable = 0; + + if (pktin_mode == ODP_PKTIN_MODE_SCHED) { + in_queue_param.queue_param.type = ODP_QUEUE_TYPE_SCHED; + in_queue_param.queue_param.sched.prio = ODP_SCHED_PRIO_DEFAULT; + in_queue_param.queue_param.sched.sync = ODP_SCHED_SYNC_ATOMIC; + in_queue_param.queue_param.sched.group = ODP_SCHED_GROUP_ALL; + } + + odp_pktout_queue_param_init(&out_queue_param); + out_queue_param.num_queues = 1; + + /* Open and configure interfaces */ + for (i = 0; i < num_ifaces; ++i) { + pktio[i] = create_pktio(i, pktin_mode, ODP_PKTOUT_MODE_DIRECT); + CU_ASSERT_FATAL(pktio[i] != ODP_PKTIO_INVALID); + + ret = odp_pktin_queue_config(pktio[i], &in_queue_param); + CU_ASSERT_FATAL(ret == 0); + + ret = odp_pktout_queue_config(pktio[i], &out_queue_param); + CU_ASSERT_FATAL(ret == 0); + + CU_ASSERT_FATAL(odp_pktio_start(pktio[i]) == 0); + } + + for (i = 0; i < num_ifaces; ++i) + _pktio_wait_linkup(pktio[i]); + + pktio_tx = pktio[0]; + if (num_ifaces > 1) + pktio_rx = pktio[1]; + else + pktio_rx = pktio_tx; + + CU_ASSERT_FATAL(odp_pktin_event_queue(pktio_rx, &queue, 1) == 1); + CU_ASSERT_FATAL(odp_pktout_queue(pktio_tx, &pktout_queue, 1) == 1); + + /* Allocate and initialize test packets */ + ret = create_packets(pkt_tbl, pkt_seq, TX_BATCH_LEN, pktio_tx, pktio_rx); + if (ret != TX_BATCH_LEN) { + CU_FAIL("Failed to generate test packets"); + return; + } + + /* Send packets */ + ret = odp_pktout_send(pktout_queue, pkt_tbl, TX_BATCH_LEN); + CU_ASSERT_FATAL(ret == TX_BATCH_LEN); + + /* Send buffer event */ + ret = odp_queue_enq(queue, odp_buffer_to_event(buf)); + CU_ASSERT_FATAL(ret == 0); + + /* Receive events */ + while (1) { + /* Break after 1 sec of inactivity */ + if (pktin_mode == ODP_PKTIN_MODE_SCHED) { + ev = odp_schedule(&from, wait_sec); + + if (ev == ODP_EVENT_INVALID) + break; + + CU_ASSERT(from == queue); + } else { + ev = odp_queue_deq(queue); + + if (ev == ODP_EVENT_INVALID) { + if (inactive == 0) { + inactive = 1; + t1 = odp_time_local(); + continue; + } else { + t2 = odp_time_local(); + if (odp_time_diff_ns(t2, t1) > ODP_TIME_SEC_IN_NS) + break; + + continue; + } + } + + inactive = 0; + } + + if (odp_event_type(ev) == ODP_EVENT_PACKET) { + pkt = odp_packet_from_event(ev); + + if (pktio_pkt_seq(pkt) != TEST_SEQ_INVALID) + num_pkt++; + + } else if (odp_event_type(ev) == ODP_EVENT_BUFFER) { + num_buf++; + } else { + CU_FAIL("Bad event type"); + num_bad++; + } + + odp_event_free(ev); + } + + CU_ASSERT(num_pkt == TX_BATCH_LEN); + CU_ASSERT(num_buf == 1); + CU_ASSERT(num_bad == 0); + + for (i = 0; i < num_ifaces; i++) { + CU_ASSERT_FATAL(odp_pktio_stop(pktio[i]) == 0); + CU_ASSERT_FATAL(odp_pktio_close(pktio[i]) == 0); + } + + CU_ASSERT_FATAL(odp_pool_destroy(buf_pool) == 0); +} + +static void pktio_test_pktin_event_sched(void) +{ + pktio_test_pktin_event_queue(ODP_PKTIN_MODE_SCHED); +} + +static int pktio_check_pktin_event_sched(void) +{ + if (odp_cunit_ci_skip("pktio_test_pktin_event_sched")) + return ODP_TEST_INACTIVE; + + return ODP_TEST_ACTIVE; +} + static int pktio_suite_init(void) { int i; @@ -3965,6 +4128,8 @@ odp_testinfo_t pktio_suite_unsegmented[] = { ODP_TEST_INFO(pktio_test_plain_multi_event), ODP_TEST_INFO(pktio_test_sched_multi_event), ODP_TEST_INFO(pktio_test_recv_multi_event), + ODP_TEST_INFO_CONDITIONAL(pktio_test_pktin_event_sched, + pktio_check_pktin_event_sched), ODP_TEST_INFO_CONDITIONAL(pktio_test_statistics_counters, pktio_check_statistics_counters), ODP_TEST_INFO_CONDITIONAL(pktio_test_pktin_ts, diff --git a/test/validation/api/scheduler/scheduler.c b/test/validation/api/scheduler/scheduler.c index 8800350f2..37f3b4f0b 100644 --- a/test/validation/api/scheduler/scheduler.c +++ b/test/validation/api/scheduler/scheduler.c @@ -59,6 +59,7 @@ #define WAIT_1MS_RETRIES 1000 #define SCHED_AND_PLAIN_ROUNDS 10000 +#define ATOMICITY_ROUNDS 100 /* Test global variables */ typedef struct { @@ -77,6 +78,10 @@ typedef struct { odp_spinlock_t atomic_lock; struct { odp_queue_t handle; + odp_atomic_u32_t state; + } atomicity_q; + struct { + odp_queue_t handle; char name[ODP_QUEUE_NAME_LEN]; } chaos_q[CHAOS_NUM_QUEUES]; struct { @@ -145,10 +150,13 @@ static void scheduler_test_init(void) odp_schedule_config_init(&default_config); + CU_ASSERT(default_config.max_flow_id == 0); + CU_ASSERT(default_config.sched_group.all); CU_ASSERT(default_config.sched_group.control); CU_ASSERT(default_config.sched_group.worker); } + static void scheduler_test_capa(void) { odp_schedule_capability_t sched_capa; @@ -2481,6 +2489,121 @@ static void scheduler_test_ordered_and_plain(void) scheduler_test_sched_and_plain(ODP_SCHED_SYNC_ORDERED); } +static int atomicity_test_run(void *arg) +{ + thread_args_t *args = (thread_args_t *)arg; + odp_event_t ev; + odp_queue_t atomic_queue = args->globals->atomicity_q.handle; + odp_queue_t from; + odp_atomic_u32_t *state; + uint32_t old; + uint32_t num_processed = 0; + + if (args->num_workers > 1) + odp_barrier_wait(&globals->barrier); + + while (num_processed < ATOMICITY_ROUNDS) { + ev = odp_schedule(&from, ODP_SCHED_NO_WAIT); + if (ev == ODP_EVENT_INVALID) + continue; + + CU_ASSERT(from == atomic_queue); + if (from != atomic_queue) { + odp_event_free(ev); + continue; + } + + state = odp_queue_context(from); + CU_ASSERT_FATAL(state != NULL); + + old = 0; + CU_ASSERT_FATAL(odp_atomic_cas_acq_rel_u32(state, &old, 1)); + + /* Hold atomic context a while to better reveal possible atomicity bugs */ + odp_time_wait_ns(ODP_TIME_MSEC_IN_NS); + + old = 1; + CU_ASSERT_FATAL(odp_atomic_cas_acq_rel_u32(state, &old, 0)); + + CU_ASSERT_FATAL(odp_queue_enq(from, ev) == 0); + + num_processed++; + } + + /* Release atomic context and get rid of possible prescheduled events */ + odp_schedule_pause(); + while ((ev = odp_schedule(NULL, ODP_SCHED_NO_WAIT)) != ODP_EVENT_INVALID) + CU_ASSERT_FATAL(odp_queue_enq(atomic_queue, ev) == 0); + + if (args->num_workers > 1) + odp_barrier_wait(&globals->barrier); + + odp_schedule_resume(); + drain_queues(); + + return 0; +} + +static void scheduler_test_atomicity(void) +{ + odp_shm_t shm; + test_globals_t *globals; + thread_args_t *args; + odp_pool_t pool; + odp_queue_t queue; + odp_queue_param_t queue_param; + int i; + + shm = odp_shm_lookup(GLOBALS_SHM_NAME); + CU_ASSERT_FATAL(shm != ODP_SHM_INVALID); + globals = odp_shm_addr(shm); + CU_ASSERT_FATAL(globals != NULL); + + shm = odp_shm_lookup(SHM_THR_ARGS_NAME); + CU_ASSERT_FATAL(shm != ODP_SHM_INVALID); + args = odp_shm_addr(shm); + CU_ASSERT_FATAL(args != NULL); + + pool = odp_pool_lookup(MSG_POOL_NAME); + CU_ASSERT_FATAL(pool != ODP_POOL_INVALID); + + odp_queue_param_init(&queue_param); + queue_param.type = ODP_QUEUE_TYPE_SCHED; + queue_param.sched.sync = ODP_SCHED_SYNC_ATOMIC; + queue_param.sched.group = ODP_SCHED_GROUP_ALL; + queue_param.size = globals->max_sched_queue_size; + queue_param.context = &globals->atomicity_q.state; + queue_param.context_len = sizeof(globals->atomicity_q.state); + + queue = odp_queue_create("atomicity_test", &queue_param); + CU_ASSERT_FATAL(queue != ODP_QUEUE_INVALID); + + for (i = 0; i < BUFS_PER_QUEUE; i++) { + odp_buffer_t buf = odp_buffer_alloc(pool); + + CU_ASSERT_FATAL(buf != ODP_BUFFER_INVALID); + + CU_ASSERT_FATAL(odp_queue_enq(queue, odp_buffer_to_event(buf)) == 0); + } + globals->atomicity_q.handle = queue; + odp_atomic_init_u32(&globals->atomicity_q.state, 0); + + /* Create and launch worker threads */ + /* Test runs also on the main thread */ + args->num_workers = globals->num_workers; + args->cu_thr.numthrds = globals->num_workers - 1; + if (args->cu_thr.numthrds > 0) + odp_cunit_thread_create(atomicity_test_run, &args->cu_thr); + + atomicity_test_run(args); + + /* Wait for worker threads to terminate */ + if (args->cu_thr.numthrds > 0) + odp_cunit_thread_exit(&args->cu_thr); + + odp_queue_destroy(globals->atomicity_q.handle); +} + static int create_queues(test_globals_t *globals) { int i, j, prios, rc; @@ -3048,6 +3171,7 @@ odp_testinfo_t scheduler_basic_suite[] = { ODP_TEST_INFO(scheduler_test_ordered), ODP_TEST_INFO(scheduler_test_atomic_and_plain), ODP_TEST_INFO(scheduler_test_ordered_and_plain), + ODP_TEST_INFO(scheduler_test_atomicity), ODP_TEST_INFO_NULL }; diff --git a/test/validation/api/time/time.c b/test/validation/api/time/time.c index 2b1efa8af..4974dcb5d 100644 --- a/test/validation/api/time/time.c +++ b/test/validation/api/time/time.c @@ -223,6 +223,16 @@ static void time_test_global_cmp(void) time_test_cmp(odp_time_global, odp_time_global_from_ns); } +static void time_test_local_strict_cmp(void) +{ + time_test_cmp(odp_time_local_strict, odp_time_local_from_ns); +} + +static void time_test_global_strict_cmp(void) +{ + time_test_cmp(odp_time_global_strict, odp_time_global_from_ns); +} + /* check that a time difference gives a reasonable result */ static void time_test_diff(time_cb time_cur, time_from_ns_cb time_from_ns, @@ -318,6 +328,16 @@ static void time_test_global_diff(void) time_test_diff(odp_time_global, odp_time_global_from_ns, global_res); } +static void time_test_local_strict_diff(void) +{ + time_test_diff(odp_time_local_strict, odp_time_local_from_ns, local_res); +} + +static void time_test_global_strict_diff(void) +{ + time_test_diff(odp_time_global_strict, odp_time_global_from_ns, global_res); +} + /* check that a time sum gives a reasonable result */ static void time_test_sum(time_cb time_cur, time_from_ns_cb time_from_ns, @@ -370,6 +390,16 @@ static void time_test_global_sum(void) time_test_sum(odp_time_global, odp_time_global_from_ns, global_res); } +static void time_test_local_strict_sum(void) +{ + time_test_sum(odp_time_local_strict, odp_time_local_from_ns, local_res); +} + +static void time_test_global_strict_sum(void) +{ + time_test_sum(odp_time_global_strict, odp_time_global_from_ns, global_res); +} + static void time_test_wait_until(time_cb time_cur, time_from_ns_cb time_from_ns) { int i; @@ -488,16 +518,6 @@ static void time_test_accuracy(time_cb time_cur, time_from_ns_cb time_from_ns) CU_ASSERT(sec_t > sec_c * 0.95); } -static void time_test_local_accuracy(void) -{ - time_test_accuracy(odp_time_local, odp_time_local_from_ns); -} - -static void time_test_global_accuracy(void) -{ - time_test_accuracy(odp_time_global, odp_time_global_from_ns); -} - static void time_test_accuracy_nsec(time_nsec_cb time_nsec) { uint64_t t1, t2, diff; @@ -533,6 +553,26 @@ static void time_test_accuracy_nsec(time_nsec_cb time_nsec) CU_ASSERT(sec_t > sec_c * 0.95); } +static void time_test_local_accuracy(void) +{ + time_test_accuracy(odp_time_local, odp_time_local_from_ns); +} + +static void time_test_global_accuracy(void) +{ + time_test_accuracy(odp_time_global, odp_time_global_from_ns); +} + +static void time_test_local_strict_accuracy(void) +{ + time_test_accuracy(odp_time_local_strict, odp_time_local_from_ns); +} + +static void time_test_global_strict_accuracy(void) +{ + time_test_accuracy(odp_time_global_strict, odp_time_global_from_ns); +} + static void time_test_local_accuracy_nsec(void) { time_test_accuracy_nsec(odp_time_local_ns); @@ -543,26 +583,46 @@ static void time_test_global_accuracy_nsec(void) time_test_accuracy_nsec(odp_time_global_ns); } +static void time_test_local_strict_accuracy_nsec(void) +{ + time_test_accuracy_nsec(odp_time_local_strict_ns); +} + +static void time_test_global_strict_accuracy_nsec(void) +{ + time_test_accuracy_nsec(odp_time_global_strict_ns); +} + odp_testinfo_t time_suite_time[] = { ODP_TEST_INFO(time_test_constants), ODP_TEST_INFO(time_test_local_res), ODP_TEST_INFO(time_test_local_conversion), - ODP_TEST_INFO(time_test_monotony), ODP_TEST_INFO(time_test_local_cmp), ODP_TEST_INFO(time_test_local_diff), ODP_TEST_INFO(time_test_local_sum), - ODP_TEST_INFO(time_test_local_wait_until), - ODP_TEST_INFO(time_test_wait_ns), - ODP_TEST_INFO(time_test_local_accuracy), ODP_TEST_INFO(time_test_global_res), ODP_TEST_INFO(time_test_global_conversion), ODP_TEST_INFO(time_test_global_cmp), ODP_TEST_INFO(time_test_global_diff), ODP_TEST_INFO(time_test_global_sum), + ODP_TEST_INFO(time_test_wait_ns), + ODP_TEST_INFO(time_test_monotony), + ODP_TEST_INFO(time_test_local_wait_until), ODP_TEST_INFO(time_test_global_wait_until), + ODP_TEST_INFO(time_test_local_accuracy), ODP_TEST_INFO(time_test_global_accuracy), ODP_TEST_INFO(time_test_local_accuracy_nsec), ODP_TEST_INFO(time_test_global_accuracy_nsec), + ODP_TEST_INFO(time_test_local_strict_diff), + ODP_TEST_INFO(time_test_local_strict_sum), + ODP_TEST_INFO(time_test_local_strict_cmp), + ODP_TEST_INFO(time_test_global_strict_diff), + ODP_TEST_INFO(time_test_global_strict_sum), + ODP_TEST_INFO(time_test_global_strict_cmp), + ODP_TEST_INFO(time_test_local_strict_accuracy), + ODP_TEST_INFO(time_test_global_strict_accuracy), + ODP_TEST_INFO(time_test_local_strict_accuracy_nsec), + ODP_TEST_INFO(time_test_global_strict_accuracy_nsec), ODP_TEST_INFO_NULL }; diff --git a/test/validation/api/timer/timer.c b/test/validation/api/timer/timer.c index f2cc93cb8..177f6f82b 100644 --- a/test/validation/api/timer/timer.c +++ b/test/validation/api/timer/timer.c @@ -47,6 +47,9 @@ struct thread_args { }; typedef struct { + /* Clock source support flags */ + uint8_t clk_supported[ODP_CLOCK_NUM_SRC]; + /* Default resolution / timeout parameters */ struct { uint64_t res_ns; @@ -88,6 +91,7 @@ static int timer_global_init(odp_instance_t *inst) odp_timer_res_capability_t res_capa; uint64_t res_ns, min_tmo, max_tmo; unsigned int range; + int i; if (odph_options(&helper_options)) { fprintf(stderr, "error: odph_options() failed.\n"); @@ -121,7 +125,7 @@ static int timer_global_init(odp_instance_t *inst) odp_schedule_config(NULL); memset(&capa, 0, sizeof(capa)); - if (odp_timer_capability(ODP_CLOCK_CPU, &capa)) { + if (odp_timer_capability(ODP_CLOCK_DEFAULT, &capa)) { fprintf(stderr, "Timer capability failed\n"); return -1; } @@ -134,7 +138,7 @@ static int timer_global_init(odp_instance_t *inst) memset(&res_capa, 0, sizeof(res_capa)); res_capa.res_ns = res_ns; - if (odp_timer_res_capability(ODP_CLOCK_CPU, &res_capa)) { + if (odp_timer_res_capability(ODP_CLOCK_DEFAULT, &res_capa)) { fprintf(stderr, "Timer resolution capability failed\n"); return -1; } @@ -156,12 +160,19 @@ static int timer_global_init(odp_instance_t *inst) } /* Default parameters for test cases */ + global_mem->clk_supported[0] = 1; global_mem->param.res_ns = res_ns; global_mem->param.min_tmo = min_tmo; global_mem->param.max_tmo = max_tmo; global_mem->param.queue_type_plain = capa.queue_type_plain; global_mem->param.queue_type_sched = capa.queue_type_sched; + /* Check which other source clocks are supported */ + for (i = 1; i < ODP_CLOCK_NUM_SRC; i++) { + if (odp_timer_capability(ODP_CLOCK_SRC_0 + i, &capa) == 0) + global_mem->clk_supported[i] = 1; + } + return 0; } @@ -206,14 +217,14 @@ check_plain_queue_support(void) return ODP_TEST_INACTIVE; } -static void timer_test_capa(void) +static void timer_test_capa_run(odp_timer_clk_src_t clk_src) { odp_timer_capability_t capa; odp_timer_res_capability_t res_capa; int ret; memset(&capa, 0, sizeof(capa)); - ret = odp_timer_capability(ODP_CLOCK_CPU, &capa); + ret = odp_timer_capability(clk_src, &capa); CU_ASSERT_FATAL(ret == 0); CU_ASSERT(capa.highest_res_ns == capa.max_res.res_ns); @@ -234,7 +245,7 @@ static void timer_test_capa(void) memset(&res_capa, 0, sizeof(res_capa)); res_capa.res_ns = capa.max_res.res_ns; - ret = odp_timer_res_capability(ODP_CLOCK_CPU, &res_capa); + ret = odp_timer_res_capability(clk_src, &res_capa); CU_ASSERT_FATAL(ret == 0); CU_ASSERT(res_capa.res_ns == capa.max_res.res_ns); CU_ASSERT(res_capa.min_tmo == capa.max_res.min_tmo); @@ -244,7 +255,7 @@ static void timer_test_capa(void) memset(&res_capa, 0, sizeof(res_capa)); res_capa.res_hz = capa.max_res.res_hz; - ret = odp_timer_res_capability(ODP_CLOCK_CPU, &res_capa); + ret = odp_timer_res_capability(clk_src, &res_capa); CU_ASSERT_FATAL(ret == 0); CU_ASSERT(res_capa.res_hz == capa.max_res.res_hz); CU_ASSERT(res_capa.min_tmo == capa.max_res.min_tmo); @@ -254,7 +265,7 @@ static void timer_test_capa(void) memset(&res_capa, 0, sizeof(res_capa)); res_capa.max_tmo = capa.max_tmo.max_tmo; - ret = odp_timer_res_capability(ODP_CLOCK_CPU, &res_capa); + ret = odp_timer_res_capability(clk_src, &res_capa); CU_ASSERT_FATAL(ret == 0); CU_ASSERT(res_capa.max_tmo == capa.max_tmo.max_tmo); CU_ASSERT(res_capa.min_tmo == capa.max_tmo.min_tmo); @@ -262,6 +273,31 @@ static void timer_test_capa(void) CU_ASSERT(res_capa.res_hz == capa.max_tmo.res_hz); } +static void timer_test_capa(void) +{ + odp_timer_clk_src_t clk_src; + int i; + + /* Check that all API clock source enumeration values exist */ + CU_ASSERT_FATAL(ODP_CLOCK_DEFAULT == ODP_CLOCK_SRC_0); + CU_ASSERT_FATAL(ODP_CLOCK_SRC_0 + 1 == ODP_CLOCK_SRC_1); + CU_ASSERT_FATAL(ODP_CLOCK_SRC_0 + 2 == ODP_CLOCK_SRC_2); + CU_ASSERT_FATAL(ODP_CLOCK_SRC_0 + 3 == ODP_CLOCK_SRC_3); + CU_ASSERT_FATAL(ODP_CLOCK_SRC_0 + 4 == ODP_CLOCK_SRC_4); + CU_ASSERT_FATAL(ODP_CLOCK_SRC_0 + 5 == ODP_CLOCK_SRC_5); + CU_ASSERT_FATAL(ODP_CLOCK_SRC_5 + 1 == ODP_CLOCK_NUM_SRC); + CU_ASSERT_FATAL(ODP_CLOCK_CPU == ODP_CLOCK_DEFAULT); + CU_ASSERT_FATAL(ODP_CLOCK_EXT == ODP_CLOCK_SRC_1); + + for (i = 0; i < ODP_CLOCK_NUM_SRC; i++) { + clk_src = ODP_CLOCK_SRC_0 + i; + if (global_mem->clk_supported[i]) { + ODPH_DBG("\nTesting clock source: %i\n", clk_src); + timer_test_capa_run(clk_src); + } + } +} + static void timer_test_timeout_pool_alloc(void) { odp_pool_t pool; @@ -359,7 +395,7 @@ static void timer_pool_create_destroy(void) int ret; memset(&capa, 0, sizeof(capa)); - ret = odp_timer_capability(ODP_CLOCK_CPU, &capa); + ret = odp_timer_capability(ODP_CLOCK_DEFAULT, &capa); CU_ASSERT_FATAL(ret == 0); odp_queue_param_init(&queue_param); @@ -378,7 +414,7 @@ static void timer_pool_create_destroy(void) tparam.max_tmo = global_mem->param.max_tmo; tparam.num_timers = 100; tparam.priv = 0; - tparam.clk_src = ODP_CLOCK_CPU; + tparam.clk_src = ODP_CLOCK_DEFAULT; tp[0] = odp_timer_pool_create("timer_pool_a", &tparam); CU_ASSERT(tp[0] != ODP_TIMER_POOL_INVALID); @@ -444,7 +480,7 @@ static void timer_pool_max_res(void) int ret, i; memset(&capa, 0, sizeof(capa)); - ret = odp_timer_capability(ODP_CLOCK_CPU, &capa); + ret = odp_timer_capability(ODP_CLOCK_DEFAULT, &capa); CU_ASSERT_FATAL(ret == 0); odp_pool_param_init(&pool_param); @@ -481,7 +517,7 @@ static void timer_pool_max_res(void) tp_param.max_tmo = capa.max_res.max_tmo; tp_param.num_timers = 100; tp_param.priv = 0; - tp_param.clk_src = ODP_CLOCK_CPU; + tp_param.clk_src = ODP_CLOCK_DEFAULT; tp = odp_timer_pool_create("high_res_tp", &tp_param); CU_ASSERT_FATAL(tp != ODP_TIMER_POOL_INVALID); @@ -545,7 +581,7 @@ static void timer_test_event_type(odp_queue_type_t queue_type, period_ns = 2 * global_mem->param.min_tmo; timer_param.max_tmo = global_mem->param.max_tmo; timer_param.num_timers = num; - timer_param.clk_src = ODP_CLOCK_CPU; + timer_param.clk_src = ODP_CLOCK_DEFAULT; timer_pool = odp_timer_pool_create("timer_pool", &timer_param); if (timer_pool == ODP_TIMER_POOL_INVALID) @@ -614,12 +650,12 @@ static void timer_test_event_type(odp_queue_type_t queue_type, ret = odp_timer_set_rel(timer[i], (i + 1) * period_tick, &ev); - if (ret == ODP_TIMER_TOOEARLY) - ODPH_DBG("Too early %i\n", i); - else if (ret == ODP_TIMER_TOOLATE) - ODPH_DBG("Too late %i\n", i); - else if (ret == ODP_TIMER_NOEVENT) - ODPH_DBG("No event %i\n", i); + if (ret == ODP_TIMER_TOO_NEAR) + ODPH_DBG("Timer set failed. Too near %i.\n", i); + else if (ret == ODP_TIMER_TOO_FAR) + ODPH_DBG("Timer set failed. Too far %i.\n", i); + else if (ret == ODP_TIMER_FAIL) + ODPH_DBG("Timer set failed %i\n", i); CU_ASSERT(ret == ODP_TIMER_SUCCESS); } @@ -740,7 +776,7 @@ static void timer_test_queue_type(odp_queue_type_t queue_type, int priv) tparam.max_tmo = global_mem->param.max_tmo; tparam.num_timers = num + 1; tparam.priv = priv; - tparam.clk_src = ODP_CLOCK_CPU; + tparam.clk_src = ODP_CLOCK_DEFAULT; ODPH_DBG("\nTimer pool parameters:\n"); ODPH_DBG(" res_ns %" PRIu64 "\n", tparam.res_ns); @@ -792,12 +828,12 @@ static void timer_test_queue_type(odp_queue_type_t queue_type, int priv) target_tick[i] = tick; ODPH_DBG("abs timer tick %" PRIu64 "\n", tick); - if (ret == ODP_TIMER_TOOEARLY) - ODPH_DBG("Too early %" PRIu64 "\n", tick); - else if (ret == ODP_TIMER_TOOLATE) - ODPH_DBG("Too late %" PRIu64 "\n", tick); - else if (ret == ODP_TIMER_NOEVENT) - ODPH_DBG("No event %" PRIu64 "\n", tick); + if (ret == ODP_TIMER_TOO_NEAR) + ODPH_DBG("Timer set failed. Too near %" PRIu64 ".\n", tick); + else if (ret == ODP_TIMER_TOO_FAR) + ODPH_DBG("Timer set failed. Too far %" PRIu64 ".\n", tick); + else if (ret == ODP_TIMER_FAIL) + ODPH_DBG("Timer set failed %" PRIu64 "\n", tick); CU_ASSERT(ret == ODP_TIMER_SUCCESS); } @@ -902,7 +938,7 @@ static void timer_test_cancel(void) int ret; memset(&capa, 0, sizeof(capa)); - ret = odp_timer_capability(ODP_CLOCK_CPU, &capa); + ret = odp_timer_capability(ODP_CLOCK_DEFAULT, &capa); CU_ASSERT_FATAL(ret == 0); odp_pool_param_init(¶ms); @@ -920,7 +956,7 @@ static void timer_test_cancel(void) tparam.max_tmo = global_mem->param.max_tmo; tparam.num_timers = 1; tparam.priv = 0; - tparam.clk_src = ODP_CLOCK_CPU; + tparam.clk_src = ODP_CLOCK_DEFAULT; tp = odp_timer_pool_create(NULL, &tparam); if (tp == ODP_TIMER_POOL_INVALID) CU_FAIL_FATAL("Timer pool create failed"); @@ -1008,7 +1044,7 @@ static void timer_test_tmo_limit(odp_queue_type_t queue_type, odp_timer_t timer[num]; memset(&timer_capa, 0, sizeof(timer_capa)); - ret = odp_timer_capability(ODP_CLOCK_CPU, &timer_capa); + ret = odp_timer_capability(ODP_CLOCK_DEFAULT, &timer_capa); CU_ASSERT_FATAL(ret == 0); if (max_res) { @@ -1028,7 +1064,7 @@ static void timer_test_tmo_limit(odp_queue_type_t queue_type, timer_param.min_tmo = min_tmo; timer_param.max_tmo = max_tmo; timer_param.num_timers = num; - timer_param.clk_src = ODP_CLOCK_CPU; + timer_param.clk_src = ODP_CLOCK_DEFAULT; timer_pool = odp_timer_pool_create("timer_pool", &timer_param); if (timer_pool == ODP_TIMER_POOL_INVALID) @@ -1085,12 +1121,12 @@ static void timer_test_tmo_limit(odp_queue_type_t queue_type, t1 = odp_time_local(); ret = odp_timer_set_rel(timer[i], tmo_tick, &ev); - if (ret == ODP_TIMER_TOOEARLY) - ODPH_DBG("Too early %i\n", i); - else if (ret == ODP_TIMER_TOOLATE) - ODPH_DBG("Too late %i\n", i); - else if (ret == ODP_TIMER_NOEVENT) - ODPH_DBG("No event %i\n", i); + if (ret == ODP_TIMER_TOO_NEAR) + ODPH_DBG("Timer set failed. Too near %i.\n", i); + else if (ret == ODP_TIMER_TOO_FAR) + ODPH_DBG("Timer set failed. Too late %i.\n", i); + else if (ret == ODP_TIMER_FAIL) + ODPH_DBG("Timer set failed %i\n", i); CU_ASSERT(ret == ODP_TIMER_SUCCESS); @@ -1364,7 +1400,7 @@ static int worker_entrypoint(void *arg) tck = odp_timer_current_tick(tp) + odp_timer_ns_to_tick(tp, nsec); timer_rc = odp_timer_set_abs(tt[i].tim, tck, &tt[i].ev); - if (timer_rc == ODP_TIMER_TOOEARLY) { + if (timer_rc == ODP_TIMER_TOO_NEAR) { ODPH_ERR("Missed tick, setting timer\n"); } else if (timer_rc != ODP_TIMER_SUCCESS) { ODPH_ERR("Failed to set timer: %d\n", timer_rc); @@ -1431,11 +1467,11 @@ static int worker_entrypoint(void *arg) cur_tick = odp_timer_current_tick(tp); rc = odp_timer_set_rel(tt[i].tim, tck, &tt[i].ev); - if (rc == ODP_TIMER_TOOEARLY) { - CU_FAIL("Failed to set timer: TOO EARLY"); - } else if (rc == ODP_TIMER_TOOLATE) { - CU_FAIL("Failed to set timer: TOO LATE"); - } else if (rc == ODP_TIMER_NOEVENT) { + if (rc == ODP_TIMER_TOO_NEAR) { + CU_FAIL("Failed to set timer: TOO NEAR"); + } else if (rc == ODP_TIMER_TOO_FAR) { + CU_FAIL("Failed to set timer: TOO FAR"); + } else if (rc == ODP_TIMER_FAIL) { /* Set/reset failed, timer already expired */ ntoolate++; } else if (rc == ODP_TIMER_SUCCESS) { @@ -1561,7 +1597,7 @@ static void timer_test_all(odp_queue_type_t queue_type) num_workers = 1; num_timers = num_workers * NTIMERS; - CU_ASSERT_FATAL(!odp_timer_capability(ODP_CLOCK_CPU, &timer_capa)); + CU_ASSERT_FATAL(!odp_timer_capability(ODP_CLOCK_DEFAULT, &timer_capa)); if (timer_capa.max_timers && timer_capa.max_timers < num_timers) num_timers = timer_capa.max_timers; @@ -1594,7 +1630,7 @@ static void timer_test_all(odp_queue_type_t queue_type) tparam.max_tmo = max_tmo; tparam.num_timers = num_timers; tparam.priv = 0; - tparam.clk_src = ODP_CLOCK_CPU; + tparam.clk_src = ODP_CLOCK_DEFAULT; global_mem->tp = odp_timer_pool_create(NAME, &tparam); if (global_mem->tp == ODP_TIMER_POOL_INVALID) CU_FAIL_FATAL("Timer pool create failed"); diff --git a/test/validation/api/traffic_mngr/traffic_mngr.c b/test/validation/api/traffic_mngr/traffic_mngr.c index 13f39457d..55004692d 100644 --- a/test/validation/api/traffic_mngr/traffic_mngr.c +++ b/test/validation/api/traffic_mngr/traffic_mngr.c @@ -113,6 +113,8 @@ #define TM_PERCENT(percent) ((uint32_t)(100 * percent)) +#define ARRAY_SIZE(a) (sizeof((a)) / sizeof((a)[0])) + typedef enum { SHAPER_PROFILE, SCHED_PROFILE, THRESHOLD_PROFILE, WRED_PROFILE } profile_kind_t; @@ -281,6 +283,11 @@ static uint32_t num_odp_tm_systems; static odp_tm_capabilities_t tm_capabilities; +static bool dynamic_shaper_update = true; +static bool dynamic_sched_update = true; +static bool dynamic_threshold_update = true; +static bool dynamic_wred_update = true; + static odp_tm_shaper_t shaper_profiles[NUM_SHAPER_PROFILES]; static odp_tm_sched_t sched_profiles[NUM_SCHED_PROFILES]; static odp_tm_threshold_t threshold_profiles[NUM_THRESHOLD_PROFILES]; @@ -317,8 +324,8 @@ static uint32_t num_ifaces; static odp_pool_t pools[MAX_NUM_IFACES] = {ODP_POOL_INVALID, ODP_POOL_INVALID}; static odp_pktio_t pktios[MAX_NUM_IFACES]; +static odp_bool_t pktio_started[MAX_NUM_IFACES]; static odp_pktin_queue_t pktins[MAX_NUM_IFACES]; -static odp_pktout_queue_t pktouts[MAX_NUM_IFACES]; static odp_pktin_queue_t rcv_pktin; static odp_pktio_t xmt_pktio; @@ -328,6 +335,8 @@ static odph_ethaddr_t dst_mac; static uint32_t cpu_unique_id; static uint32_t cpu_tcp_seq_num; +static int8_t suite_inactive; + static void busy_wait(uint64_t nanoseconds) { odp_time_t start_time, end_time; @@ -481,7 +490,6 @@ static int open_pktios(void) odp_pktio_param_init(&pktio_param); pktio_param.in_mode = ODP_PKTIN_MODE_DIRECT; - pktio_param.out_mode = ODP_PKTOUT_MODE_DIRECT; for (iface = 0; iface < num_ifaces; iface++) { snprintf(pool_name, sizeof(pool_name), "pkt_pool_%s", @@ -494,10 +502,37 @@ static int open_pktios(void) } pools[iface] = pkt_pool; - pktio = odp_pktio_open(iface_name[iface], pkt_pool, - &pktio_param); - if (pktio == ODP_PKTIO_INVALID) - pktio = odp_pktio_lookup(iface_name[iface]); + + /* Zero'th device is always PKTOUT TM as we use it from XMIT */ + if (iface == 0) { + pktio_param.out_mode = ODP_PKTOUT_MODE_TM; + + pktio = odp_pktio_open(iface_name[iface], pkt_pool, + &pktio_param); + + /* On failure check if pktio can be opened in non-TM mode. + * If non-TM mode works, then we can assume that PKTIO + * does not support TM + */ + if (pktio == ODP_PKTIO_INVALID) { + pktio_param.out_mode = ODP_PKTOUT_MODE_DIRECT; + pktio = odp_pktio_open(iface_name[iface], pkt_pool, + &pktio_param); + + /* Return >0 to indicate no TM support */ + if (pktio != ODP_PKTIO_INVALID) { + odp_pktio_close(pktio); + return 1; + } + } + } else { + pktio_param.out_mode = ODP_PKTOUT_MODE_DISABLED; + + pktio = odp_pktio_open(iface_name[iface], pkt_pool, + &pktio_param); + } + + pktios[iface] = pktio; if (pktio == ODP_PKTIO_INVALID) { ODPH_ERR("odp_pktio_open() failed\n"); return -1; @@ -505,25 +540,16 @@ static int open_pktios(void) /* Set defaults for PktIn and PktOut queues */ (void)odp_pktin_queue_config(pktio, NULL); - (void)odp_pktout_queue_config(pktio, NULL); rc = odp_pktio_promisc_mode_set(pktio, true); if (rc != 0) printf("****** promisc_mode_set failed ******\n"); - pktios[iface] = pktio; - if (odp_pktin_queue(pktio, &pktins[iface], 1) != 1) { odp_pktio_close(pktio); ODPH_ERR("odp_pktio_open() failed: no pktin queue\n"); return -1; } - if (odp_pktout_queue(pktio, &pktouts[iface], 1) != 1) { - odp_pktio_close(pktio); - ODPH_ERR("odp_pktio_open() failed: no pktout queue\n"); - return -1; - } - rc = -1; if (iface == 0) rc = odp_pktio_mac_addr(pktio, &src_mac, @@ -547,6 +573,7 @@ static int open_pktios(void) ODPH_ERR("odp_pktio_start() failed\n"); return -1; } + pktio_started[1] = true; } else { xmt_pktio = pktios[0]; rcv_pktin = pktins[0]; @@ -557,6 +584,7 @@ static int open_pktios(void) ODPH_ERR("odp_pktio_start() failed\n"); return -1; } + pktio_started[0] = true; /* Now wait until the link or links are up. */ rc = wait_linkup(pktios[0]); @@ -1658,12 +1686,26 @@ static int create_tm_system(void) return -1; } + /* Update dynamic capability flags from created tm system */ + dynamic_shaper_update = tm_capabilities.dynamic_shaper_update; + dynamic_sched_update = tm_capabilities.dynamic_sched_update; + dynamic_threshold_update = tm_capabilities.dynamic_threshold_update; + dynamic_wred_update = tm_capabilities.dynamic_wred_update; + found_odp_tm = odp_tm_find(tm_name, &requirements, &egress); if ((found_odp_tm == ODP_TM_INVALID) || (found_odp_tm != odp_tm)) { ODPH_ERR("odp_tm_find() failed\n"); return -1; } + /* Start TM system */ + CU_ASSERT((rc = odp_tm_start(odp_tm)) == 0); + if (rc != 0) { + ODPH_ERR("odp_tm_start() failed for tm: %" PRIx64 "\n", + odp_tm_to_u64(odp_tm)); + return -1; + } + return 0; } @@ -2042,11 +2084,16 @@ static int destroy_tm_systems(void) /* Close/free the TM systems. */ for (idx = 0; idx < num_odp_tm_systems; idx++) { + if (odp_tm_stop(odp_tm_systems[idx]) != 0) + return -1; + if (destroy_tm_subtree(root_node_descs[idx]) != 0) return -1; if (odp_tm_destroy(odp_tm_systems[idx]) != 0) return -1; + + odp_tm_systems[idx] = ODP_TM_INVALID; } /* Close/free the TM profiles. */ @@ -2058,7 +2105,9 @@ static int destroy_tm_systems(void) static int traffic_mngr_suite_init(void) { + odp_tm_capabilities_t capabilities_array[MAX_CAPABILITIES]; uint32_t payload_len, copy_len; + int ret, i; /* Initialize some global variables. */ num_pkts_made = 0; @@ -2094,9 +2143,45 @@ static int traffic_mngr_suite_init(void) iface_name[0], iface_name[1]); } - if (open_pktios() != 0) + pktios[0] = ODP_PKTIO_INVALID; + pktios[1] = ODP_PKTIO_INVALID; + + ret = open_pktios(); + if (ret < 0) + return -1; + + /* Positive return indicates, that pktio open failed with out mode as TM + * but succeeded with direct mode. + */ + if (ret > 0) + goto skip_tests; + + /* Fetch initial dynamic update capabilities, it will be updated + * later after TM system is created. + */ + ret = odp_tm_capabilities(capabilities_array, MAX_CAPABILITIES); + if (ret <= 0) return -1; + for (i = 0; i < ret; i++) { + if (!capabilities_array[i].dynamic_shaper_update) + dynamic_shaper_update = false; + + if (!capabilities_array[i].dynamic_sched_update) + dynamic_sched_update = false; + + if (!capabilities_array[i].dynamic_threshold_update) + dynamic_threshold_update = false; + + if (!capabilities_array[i].dynamic_wred_update) + dynamic_wred_update = false; + } + + return 0; +skip_tests: + /* Mark all tests as inactive under this suite */ + odp_cunit_set_inactive(); + suite_inactive++; return 0; } @@ -2107,14 +2192,22 @@ static int traffic_mngr_suite_term(void) /* Close the pktios and associated packet pools. */ free_rcvd_pkts(); for (iface = 0; iface < num_ifaces; iface++) { - if (odp_pktio_stop(pktios[iface]) != 0) - return -1; + /* Skip pktios not initialized */ + if (pktios[iface] != ODP_PKTIO_INVALID) { + if (pktio_started[iface] && + odp_pktio_stop(pktios[iface]) != 0) + return -1; - if (odp_pktio_close(pktios[iface]) != 0) - return -1; + if (odp_pktio_close(pktios[iface]) != 0) + return -1; + pktios[iface] = ODP_PKTIO_INVALID; + pktio_started[iface] = false; + } if (odp_pool_destroy(pools[iface]) != 0) return -1; + + pools[iface] = ODP_POOL_INVALID; } if (odp_cunit_print_inactive()) @@ -2138,9 +2231,9 @@ static void check_shaper_profile(char *shaper_name, uint32_t shaper_idx) memset(&shaper_params, 0, sizeof(shaper_params)); rc = odp_tm_shaper_params_read(profile, &shaper_params); CU_ASSERT(rc == 0); - CU_ASSERT(approx_eq64(shaper_params.commit_bps, + CU_ASSERT(approx_eq64(shaper_params.commit_rate, shaper_idx * MIN_COMMIT_BW)); - CU_ASSERT(approx_eq64(shaper_params.peak_bps, + CU_ASSERT(approx_eq64(shaper_params.peak_rate, shaper_idx * MIN_PEAK_BW)); CU_ASSERT(approx_eq32(shaper_params.commit_burst, shaper_idx * MIN_COMMIT_BURST)); @@ -2165,8 +2258,8 @@ static void traffic_mngr_test_shaper_profile(void) for (idx = 1; idx <= NUM_SHAPER_TEST_PROFILES; idx++) { snprintf(shaper_name, sizeof(shaper_name), "shaper_profile_%" PRIu32, idx); - shaper_params.commit_bps = idx * MIN_COMMIT_BW; - shaper_params.peak_bps = idx * MIN_PEAK_BW; + shaper_params.commit_rate = idx * MIN_COMMIT_BW; + shaper_params.peak_rate = idx * MIN_PEAK_BW; shaper_params.commit_burst = idx * MIN_COMMIT_BURST; shaper_params.peak_burst = idx * MIN_PEAK_BURST; @@ -2415,6 +2508,7 @@ static int set_shaper(const char *node_name, odp_tm_shaper_params_t shaper_params; odp_tm_shaper_t shaper_profile; odp_tm_node_t tm_node; + int rc; tm_node = find_tm_node(0, node_name); if (tm_node == ODP_TM_INVALID) { @@ -2424,13 +2518,20 @@ static int set_shaper(const char *node_name, } odp_tm_shaper_params_init(&shaper_params); - shaper_params.commit_bps = commit_bps; - shaper_params.peak_bps = 0; + shaper_params.commit_rate = commit_bps; + shaper_params.peak_rate = 0; shaper_params.commit_burst = commit_burst_in_bits; shaper_params.peak_burst = 0; shaper_params.shaper_len_adjust = 0; shaper_params.dual_rate = 0; + if (!dynamic_shaper_update) { + /* Stop TM system before update when dynamic update is not + * supported. + */ + CU_ASSERT_FATAL(odp_tm_stop(odp_tm_systems[0]) == 0); + } + /* First see if a shaper profile already exists with this name, in * which case we use that profile, else create a new one. */ shaper_profile = odp_tm_shaper_lookup(shaper_name); @@ -2443,7 +2544,13 @@ static int set_shaper(const char *node_name, num_shaper_profiles++; } - return odp_tm_node_shaper_config(tm_node, shaper_profile); + rc = odp_tm_node_shaper_config(tm_node, shaper_profile); + + if (!dynamic_shaper_update) { + /* Start TM system, post update */ + CU_ASSERT_FATAL(odp_tm_start(odp_tm_systems[0]) == 0); + } + return rc; } static int traffic_mngr_check_shaper(void) @@ -2617,6 +2724,13 @@ static int set_sched_fanin(const char *node_name, if (node_desc == NULL) return -1; + if (!dynamic_sched_update) { + /* Stop TM system before update when dynamic update is not + * supported. + */ + CU_ASSERT_FATAL(odp_tm_stop(odp_tm_systems[0]) == 0); + } + fanin_cnt = MIN(node_desc->num_children, FANIN_RATIO); for (fanin = 0; fanin < fanin_cnt; fanin++) { odp_tm_sched_params_init(&sched_params); @@ -2653,10 +2767,15 @@ static int set_sched_fanin(const char *node_name, rc = odp_tm_node_sched_config(tm_node, fanin_node, sched_profile); if (rc != 0) - return -1; + goto exit; } - return 0; +exit: + if (!dynamic_sched_update) { + /* Start TM system, post update */ + CU_ASSERT_FATAL(odp_tm_start(odp_tm_systems[0]) == 0); + } + return rc; } static int test_sched_queue_priority(const char *shaper_name, @@ -2711,8 +2830,13 @@ static int test_sched_queue_priority(const char *shaper_name, busy_wait(100 * ODP_TIME_MSEC_IN_NS); - /* Disable the shaper, so as to get the pkts out quicker. */ - set_shaper(node_name, shaper_name, 0, 0); + /* Disable the shaper, so as to get the pkts out quicker. + * We cannot do this if dynamic shaper update is not supported. Without + * dynamic update support set_shaper() can cause packet drops due to + * start/stop. + */ + if (dynamic_shaper_update) + set_shaper(node_name, shaper_name, 0, 0); num_rcv_pkts = receive_pkts(odp_tm_systems[0], rcv_pktin, pkt_cnt + 4, 64 * 1000); @@ -2730,6 +2854,8 @@ static int test_sched_queue_priority(const char *shaper_name, CU_ASSERT(pkts_in_order == pkt_cnt); + /* Disable shaper in case it is still enabled */ + set_shaper(node_name, shaper_name, 0, 0); flush_leftover_pkts(odp_tm_systems[0], rcv_pktin); CU_ASSERT(odp_tm_is_idle(odp_tm_systems[0])); return 0; @@ -2817,8 +2943,13 @@ static int test_sched_node_priority(const char *shaper_name, busy_wait(100 * ODP_TIME_MSEC_IN_NS); - /* Disable the shaper, so as to get the pkts out quicker. */ - set_shaper(node_name, shaper_name, 0, 0); + /* Disable the shaper, so as to get the pkts out quicker. + * We cannot do this if dynamic shaper update is not supported. Without + * dynamic update support set_shaper() can cause packet drops due to + * start/stop. + */ + if (dynamic_shaper_update) + set_shaper(node_name, shaper_name, 0, 0); num_rcv_pkts = receive_pkts(odp_tm_systems[0], rcv_pktin, pkts_sent, 64 * 1000); @@ -2830,6 +2961,8 @@ static int test_sched_node_priority(const char *shaper_name, 0, false, false); CU_ASSERT(pkts_in_order == total_pkt_cnt); + /* Disable shaper in case it is still enabled */ + set_shaper(node_name, shaper_name, 0, 0); flush_leftover_pkts(odp_tm_systems[0], rcv_pktin); CU_ASSERT(odp_tm_is_idle(odp_tm_systems[0])); return 0; @@ -2910,8 +3043,13 @@ static int test_sched_wfq(const char *sched_base_name, busy_wait(1000000); /* wait 1 millisecond */ - /* Disable the shaper, so as to get the pkts out quicker. */ - set_shaper(node_name, shaper_name, 0, 0); + /* Disable the shaper, so as to get the pkts out quicker. + * We cannot do this if dynamic shaper update is not supported. Without + * dynamic update support set_shaper() can cause packet drops due to + * start/stop. + */ + if (dynamic_shaper_update) + set_shaper(node_name, shaper_name, 0, 0); num_rcv_pkts = receive_pkts(odp_tm_systems[0], rcv_pktin, pkt_cnt + 4, 64 * 1000); @@ -2923,6 +3061,8 @@ static int test_sched_wfq(const char *sched_base_name, CU_ASSERT(rcv_rate_stats(&rcv_stats[fanin], pkt_class) == 0); } + /* Disable shaper in case it is still enabled */ + set_shaper(node_name, shaper_name, 0, 0); flush_leftover_pkts(odp_tm_systems[0], rcv_pktin); CU_ASSERT(odp_tm_is_idle(odp_tm_systems[0])); return 0; @@ -2935,6 +3075,13 @@ static int set_queue_thresholds(odp_tm_queue_t tm_queue, odp_tm_threshold_t threshold_profile; int ret; + if (!dynamic_threshold_update) { + /* Stop TM system before update when dynamic update is not + * supported. + */ + CU_ASSERT_FATAL(odp_tm_stop(odp_tm_systems[0]) == 0); + } + /* First see if a threshold profile already exists with this name, in * which case we use that profile, else create a new one. */ threshold_profile = odp_tm_thresholds_lookup(threshold_name); @@ -2942,17 +3089,25 @@ static int set_queue_thresholds(odp_tm_queue_t tm_queue, ret = odp_tm_thresholds_params_update(threshold_profile, threshold_params); if (ret) - return ret; + goto exit; } else { threshold_profile = odp_tm_threshold_create(threshold_name, threshold_params); - if (threshold_profile == ODP_TM_INVALID) - return -1; + if (threshold_profile == ODP_TM_INVALID) { + ret = -1; + goto exit; + } threshold_profiles[num_threshold_profiles] = threshold_profile; num_threshold_profiles++; } - return odp_tm_queue_threshold_config(tm_queue, threshold_profile); + ret = odp_tm_queue_threshold_config(tm_queue, threshold_profile); +exit: + if (!dynamic_threshold_update) { + /* Start TM system, post update */ + CU_ASSERT_FATAL(odp_tm_start(odp_tm_systems[0]) == 0); + } + return ret; } static int test_threshold(const char *threshold_name, @@ -3049,6 +3204,7 @@ static int set_queue_wred(odp_tm_queue_t tm_queue, { odp_tm_wred_params_t wred_params; odp_tm_wred_t wred_profile; + int rc; odp_tm_wred_params_init(&wred_params); if (use_dual_slope) { @@ -3066,6 +3222,13 @@ static int set_queue_wred(odp_tm_queue_t tm_queue, wred_params.enable_wred = true; wred_params.use_byte_fullness = use_byte_fullness; + if (!dynamic_wred_update) { + /* Stop TM system before update when dynamic update is not + * supported. + */ + CU_ASSERT_FATAL(odp_tm_stop(odp_tm_systems[0]) == 0); + } + /* First see if a wred profile already exists with this name, in * which case we use that profile, else create a new one. */ wred_profile = odp_tm_wred_lookup(wred_name); @@ -3084,7 +3247,14 @@ static int set_queue_wred(odp_tm_queue_t tm_queue, } } - return odp_tm_queue_wred_config(tm_queue, pkt_color, wred_profile); + rc = odp_tm_queue_wred_config(tm_queue, pkt_color, wred_profile); + + if (!dynamic_wred_update) { + /* Start TM system, post update */ + CU_ASSERT_FATAL(odp_tm_start(odp_tm_systems[0]) == 0); + } + return rc; + } static int test_byte_wred(const char *wred_name, @@ -3149,8 +3319,14 @@ static int test_byte_wred(const char *wred_name, pkts_sent = send_pkts(tm_queue, num_test_pkts); - /* Disable the shaper, so as to get the pkts out quicker. */ - set_shaper(node_name, shaper_name, 0, 0); + /* Disable the shaper, so as to get the pkts out quicker. + * We cannot do this if dynamic shaper update is not supported. Without + * dynamic update support set_shaper() can cause packet drops due to + * start/stop. + */ + if (dynamic_shaper_update) + set_shaper(node_name, shaper_name, 0, 0); + num_rcv_pkts = receive_pkts(odp_tm_systems[0], rcv_pktin, num_fill_pkts + pkts_sent, 64 * 1000); @@ -3160,6 +3336,8 @@ static int test_byte_wred(const char *wred_name, if (wred_pkt_cnts == NULL) return -1; + /* Disable shaper in case it is still enabled */ + set_shaper(node_name, shaper_name, 0, 0); flush_leftover_pkts(odp_tm_systems[0], rcv_pktin); CU_ASSERT(odp_tm_is_idle(odp_tm_systems[0])); @@ -3234,8 +3412,14 @@ static int test_pkt_wred(const char *wred_name, pkts_sent = send_pkts(tm_queue, num_test_pkts); - /* Disable the shaper, so as to get the pkts out quicker. */ - set_shaper(node_name, shaper_name, 0, 0); + /* Disable the shaper, so as to get the pkts out quicker. + * We cannot do this if dynamic shaper update is not supported. Without + * dynamic update support set_shaper() can cause packet drops due to + * start/stop. + */ + if (dynamic_shaper_update) + set_shaper(node_name, shaper_name, 0, 0); + ret = receive_pkts(odp_tm_systems[0], rcv_pktin, num_fill_pkts + pkts_sent, 64 * 1000); if (ret < 0) @@ -3249,6 +3433,8 @@ static int test_pkt_wred(const char *wred_name, if (wred_pkt_cnts == NULL) return -1; + /* Disable shaper in case it is still enabled */ + set_shaper(node_name, shaper_name, 0, 0); flush_leftover_pkts(odp_tm_systems[0], rcv_pktin); CU_ASSERT(odp_tm_is_idle(odp_tm_systems[0])); @@ -4099,5 +4285,8 @@ int main(int argc, char *argv[]) if (ret == 0) ret = odp_cunit_run(); + /* Exit with 77 in order to indicate that test is skipped completely */ + if (!ret && suite_inactive == (ARRAY_SIZE(traffic_mngr_suites) - 1)) + return 77; return ret; } |