[修改] 增加freeRTOS

1. 版本FreeRTOSv202212.01,命名为kernel;
This commit is contained in:
2023-05-06 16:43:01 +00:00
commit a345df017b
20944 changed files with 11094377 additions and 0 deletions

View File

@ -0,0 +1,63 @@
# Contributing Guidelines
Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional
documentation, we greatly value feedback and contributions from our community.
Please read through this document before submitting any issues or pull requests to ensure we have all the necessary
information to effectively respond to your bug report or contribution.
## Reporting Bugs/Feature Requests
We welcome you to use the GitHub issue tracker to report bugs or suggest features.
When filing an issue, please check [existing open](https://github.com/FreeRTOS/backoffAlgorithm/issues), or [recently closed](https://github.com/FreeRTOS/backoffAlgorithm/issues?q=is%3Aissue+is%3Aclosed), issues to make sure somebody else hasn't already
reported the issue. Please try to include as much information as you can. Details like these are incredibly useful:
* A reproducible test case or series of steps
* The version of our code being used
* Any modifications you've made relevant to the bug
* Anything unusual about your environment or deployment
## Contributing via Pull Requests
Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that:
1. You are working against the latest source on the *main* branch.
1. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already.
1. You open an issue to discuss any significant work - we would hate for your time to be wasted.
To send us a pull request, please:
1. Fork the repository.
1. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change.
1. Ensure that your contributions conform to the [style guide](https://docs.aws.amazon.com/embedded-csdk/202011.00/lib-ref/docs/doxygen/output/html/guide_developer_styleguide.html).
1. Format your code with uncrustify, using the config available in [FreeRTOS/CI-CD-Github-Actions](https://github.com/FreeRTOS/CI-CD-Github-Actions/blob/main/formatting/uncrustify.cfg).
1. Ensure local tests pass.
1. Commit to your fork using clear commit messages.
1. Send us a pull request, answering any default questions in the pull request interface.
1. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation.
GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and
[creating a pull request](https://help.github.com/articles/creating-a-pull-request/).
## Finding contributions to work on
Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels ((enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any ['help wanted'](https://github.com/FreeRTOS/backoffAlgorithm/labels?q=help+wanted) issues is a great place to start.
## Code of Conduct
This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct).
For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact
opensource-codeofconduct@amazon.com with any additional questions or comments.
## Security issue notifications
If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](https://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue.
## Licensing
See the [LICENSE](../LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution.
We may ask you to sign a [Contributor License Agreement (CLA)](https://en.wikipedia.org/wiki/Contributor_License_Agreement) for larger changes.

View File

@ -0,0 +1,9 @@
{
"lib_name": "backoffAlgorithm",
"src": [
"source/backoff_algorithm.c"
],
"include": [
"source/include"
]
}

View File

@ -0,0 +1,124 @@
name: CI Checks
on:
push:
branches: ["**"]
pull_request:
branches: [main]
workflow_dispatch:
jobs:
unittest:
runs-on: ubuntu-latest
steps:
- name: Clone This Repo
uses: actions/checkout@v2
- name: Build
run: |
sudo apt-get install -y lcov sed
cmake -S test -B build/ \
-G "Unix Makefiles" \
-DCMAKE_BUILD_TYPE=Debug \
-DBUILD_UNIT_TESTS=ON \
-DCMAKE_C_FLAGS='--coverage -Wall -Wextra -Werror'
make -C build/ all
- name: Test
run: |
cd build/
ctest -E system --output-on-failure
cd ..
- name: Run Coverage
run: |
make -C build/ coverage
declare -a EXCLUDE=("\*test\*" "\*CMakeCCompilerId\*" "\*mocks\*")
echo ${EXCLUDE[@]} | xargs lcov --rc lcov_branch_coverage=1 -r build/coverage.info -o build/coverage.info
lcov --rc lcov_branch_coverage=1 --list build/coverage.info
- name: Check Coverage
uses: FreeRTOS/CI-CD-Github-Actions/coverage-cop@main
with:
path: ./build/coverage.info
build-code-example:
runs-on: ubuntu-latest
steps:
- name: Clone This Repo
uses: actions/checkout@v2
- name: Build code example
run: |
cmake -S test -B Build -DBUILD_CODE_EXAMPLE=ON
make -C Build code_example_posix -j8
complexity:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Check complexity
uses: FreeRTOS/CI-CD-Github-Actions/complexity@main
with:
path: ./
doxygen:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
- name: Run doxygen build
uses: FreeRTOS/CI-CD-Github-Actions/doxygen@main
with:
path: ./
spell-check:
runs-on: ubuntu-latest
steps:
- name: Clone This Repo
uses: actions/checkout@v2
- name: Run spellings check
uses: FreeRTOS/CI-CD-Github-Actions/spellings@main
with:
path: ./
formatting:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Check formatting
uses: FreeRTOS/CI-CD-Github-Actions/formatting@main
with:
path: ./
git-secrets:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Checkout awslabs/git-secrets
uses: actions/checkout@v2
with:
repository: awslabs/git-secrets
ref: master
path: git-secrets
- name: Install git-secrets
run: cd git-secrets && sudo make install && cd ..
- name: Run git-secrets
run: |
git-secrets --register-aws
git-secrets --scan
custom-standard-c-header:
runs-on: ubuntu-latest
steps:
- name: Clone This Repo
uses: actions/checkout@v2
- name: Build
run: |
mkdir -p override-include
cp source/include/stdint.readme override-include/stdint.h
cmake -S test -B build/ \
-G "Unix Makefiles" \
-DBUILD_CLONE_SUBMODULES=ON \
-DCMAKE_C_FLAGS='-Wall -Wextra -Werror -I../override-include'
make -C build/ coverity_analysis
memory_statistics:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
submodules: 'recursive'
- name: Install Python3
uses: actions/setup-python@v2
with:
python-version: '3.7.10'
- name: Measure sizes
uses: FreeRTOS/CI-CD-Github-Actions/memory_statistics@main
with:
config: .github/memory_statistics_config.json
check_against: docs/doxygen/include/size_table.md

View File

@ -0,0 +1,11 @@
name: Doxygen Generation
on:
push:
branches: [main]
workflow_dispatch:
jobs:
doxygen-generation:
runs-on: ubuntu-latest
steps:
- name: Doxygen generation
uses: FreeRTOS/CI-CD-Github-Actions/doxygen-generation@main

View File

@ -0,0 +1,139 @@
name: Release automation
on:
workflow_dispatch:
inputs:
commit_id:
description: 'Commit ID to tag and create a release for'
required: true
version_number:
description: 'Release Version Number (Eg, v1.0.0)'
required: true
jobs:
tag-commit:
name: Tag commit
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
with:
ref: ${{ github.event.inputs.commit_id }}
- name: Configure git identity
run: |
git config --global user.name ${{ github.actor }}
git config --global user.email ${{ github.actor }}@users.noreply.github.com
- name: create a new branch that references commit id
run: git checkout -b ${{ github.event.inputs.version_number }} ${{ github.event.inputs.commit_id }}
- name: Generate SBOM
uses: FreeRTOS/CI-CD-Github-Actions/sbom-generator@main
with:
repo_path: ./
source_path: ./source
- name: commit SBOM file
run: |
git add .
git commit -m 'Update SBOM'
git push -u origin ${{ github.event.inputs.version_number }}
- name: Tag Commit and Push to remote
run: |
git tag ${{ github.event.inputs.version_number }} -a -m "backoffAlgorithm Library ${{ github.event.inputs.version_number }}"
git push origin --tags
- name: Verify tag on remote
run: |
git tag -d ${{ github.event.inputs.version_number }}
git remote update
git checkout tags/${{ github.event.inputs.version_number }}
git diff ${{ github.event.inputs.commit_id }} tags/${{ github.event.inputs.version_number }}
create-zip:
needs: tag-commit
name: Create ZIP and verify package for release asset.
runs-on: ubuntu-latest
steps:
- name: Install ZIP tools
run: sudo apt-get install zip unzip
- name: Checkout code
uses: actions/checkout@v2
with:
ref: ${{ github.event.inputs.commit_id }}
path: backoffAlgorithm
submodules: recursive
- name: Checkout disabled submodules
run: |
cd backoffAlgorithm
git submodule update --init --checkout --recursive
- name: Create ZIP
run: |
zip -r backoffAlgorithm-${{ github.event.inputs.version_number }}.zip backoffAlgorithm -x "*.git*"
ls ./
- name: Validate created ZIP
run: |
mkdir zip-check
mv backoffAlgorithm-${{ github.event.inputs.version_number }}.zip zip-check
cd zip-check
unzip backoffAlgorithm-${{ github.event.inputs.version_number }}.zip -d backoffAlgorithm-${{ github.event.inputs.version_number }}
ls backoffAlgorithm-${{ github.event.inputs.version_number }}
diff -r -x "*.git*" backoffAlgorithm-${{ github.event.inputs.version_number }}/backoffAlgorithm/ ../backoffAlgorithm/
cd ../
- name: Build
run: |
cd zip-check/backoffAlgorithm-${{ github.event.inputs.version_number }}/backoffAlgorithm
sudo apt-get install -y lcov
cmake -S test -B build/ \
-G "Unix Makefiles" \
-DCMAKE_BUILD_TYPE=Debug \
-DBUILD_CLONE_SUBMODULES=ON \
-DCMAKE_C_FLAGS='--coverage -Wall -Wextra -Werror'
make -C build/ all
- name: Test
run: |
cd zip-check/backoffAlgorithm-${{ github.event.inputs.version_number }}/backoffAlgorithm/build/
ctest -E system --output-on-failure
cd ..
- name: Create artifact of ZIP
uses: actions/upload-artifact@v2
with:
name: backoffAlgorithm-${{ github.event.inputs.version_number }}.zip
path: zip-check/backoffAlgorithm-${{ github.event.inputs.version_number }}.zip
deploy-doxygen:
needs: tag-commit
name: Deploy doxygen documentation
runs-on: ubuntu-latest
steps:
- name: Doxygen generation
uses: FreeRTOS/CI-CD-Github-Actions/doxygen-generation@main
with:
ref: ${{ github.event.inputs.version_number }}
add_release: "true"
create-release:
needs:
- create-zip
- deploy-doxygen
name: Create Release and Upload Release Asset
runs-on: ubuntu-latest
steps:
- name: Create Release
id: create_release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.event.inputs.version_number }}
release_name: ${{ github.event.inputs.version_number }}
body: Release ${{ github.event.inputs.version_number }} of the backoffAlgorithm Library.
draft: false
prerelease: false
- name: Download ZIP artifact
uses: actions/download-artifact@v2
with:
name: backoffAlgorithm-${{ github.event.inputs.version_number }}.zip
- name: Upload Release Asset
id: upload-release-asset
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./backoffAlgorithm-${{ github.event.inputs.version_number }}.zip
asset_name: backoffAlgorithm-${{ github.event.inputs.version_number }}.zip
asset_content_type: application/zip

View File

@ -0,0 +1,13 @@
# Ignore documentation output.
**/docs/**/output/*
# Ignore CMake build directory.
build/
# Ignore build artifacts
*.o
# Ignore code coverage artifacts
*.gcda
*.gcno
*.gcov

View File

@ -0,0 +1,4 @@
[submodule "test/unit-test/Unity"]
path = test/unit-test/Unity
url = https://github.com/ThrowTheSwitch/Unity
update = none

View File

@ -0,0 +1,36 @@
# Changelog for backoffAlgorithm Library
## v1.3.0 (October 2022)
### Changes
- [#38](https://github.com/FreeRTOS/backoffAlgorithm/pull/38) MISRA compliance update
## v1.2.0 (November 2021)
### Changes
- [#31](https://github.com/FreeRTOS/backoffAlgorithm/pull/31) Update doxygen version for documentation.
- [#30](https://github.com/FreeRTOS/backoffAlgorithm/pull/30) Add code examples to documentation.
## v1.1.0 (July 2021)
### Changes
- [#29](https://github.com/FreeRTOS/backoffAlgorithm/pull/29) Set BACKOFF_ALGORITHM_RETRY_FOREVER to be nonzero and add header guards for C++ linkage.
- [#27](https://github.com/FreeRTOS/backoffAlgorithm/pull/27) Fix incorrect comment about use of BACKOFF_ALGORITHM_RETRY_FOREVER constant in BackoffAlgorithm_GetNextBackoff API.
## v1.0.1 (February 2021)
### Changes
- [#24](https://github.com/FreeRTOS/backoffAlgorithm/pull/24) Fix MISRA 10.4 and 10.7 rule violations, and add documentation of MISRA compliance.
- [#18](https://github.com/FreeRTOS/backoffAlgorithm/pull/18), [#19](https://github.com/FreeRTOS/backoffAlgorithm/pull/19), and [#20](https://github.com/FreeRTOS/backoffAlgorithm/pull/20) Documentation fixes.
## v1.0.0 (December 2020)
This is the first release of the backoffAlgorithm library in this repository.
The backoffAlgorithm library is a utility library to calculate backoff period using an exponential backoff with jitter algorithm for retrying network operations (like failed network connection with server).
This library uses the "Full Jitter" strategy for the exponential backoff with jitter algorithm.
More information about the algorithm can be seen in the [Exponential Backoff and Jitter](https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/) AWS blog.

View File

@ -0,0 +1,19 @@
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,16 @@
# MISRA Compliance
The backoffAlgorithm library files conform to the [MISRA C:2012](https://www.misra.org.uk)
guidelines, with some noted exceptions. Compliance is checked with Coverity static analysis.
The specific deviations, suppressed inline, are listed below.
Additionally, [MISRA configuration file](https://github.com/FreeRTOS/backoffAlgorithm/blob/main/tools/coverity/misra.config) contains the project wide deviations.
### Suppressed with Coverity Comments
To find the violation references in the source files run grep on the source code
with ( Assuming rule 11.4 violation; with justification in point 2 ):
```
grep 'MISRA Ref 11.4.2' . -rI
```
*None.*

View File

@ -0,0 +1,160 @@
## backoffAlgorithm Library
This repository contains the backoffAlgorithm library, a utility library to calculate backoff period using an exponential backoff with jitter algorithm for retrying network operations (like failed network connection with server).
This library uses the "Full Jitter" strategy for the exponential backoff with jitter algorithm.
More information about the algorithm can be seen in the [Exponential Backoff and Jitter](https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/) AWS blog.
The backoffAlgorithm library is distributed under the [MIT Open Source License](LICENSE).
Exponential backoff with jitter is typically used when retrying a failed network
connection or operation request with the server. An exponential backoff with jitter helps to
mitigate failed network operations with servers, that are caused due to network congestion or high request load on
the server, by spreading out retry requests across multiple devices attempting network operations.
Besides, in an environment with poor connectivity, a client can get disconnected at any time.
A backoff strategy helps the client to conserve battery by not repeatedly attempting reconnections when they are
unlikely to succeed.
See memory requirements for this library [here](./docs/doxygen/include/size_table.md).
**backoffAlgorithm v1.3.0 [source code](https://github.com/FreeRTOS/backoffAlgorithm/tree/v1.3.0/source) is part of the [FreeRTOS 202210.00 LTS](https://github.com/FreeRTOS/FreeRTOS-LTS/tree/202210.00-LTS) release.**
**backoffAlgorithm v1.0.0 [source code](https://github.com/FreeRTOS/backoffAlgorithm/tree/v1.0.0/source) is part of the [FreeRTOS 202012.00 LTS](https://github.com/FreeRTOS/FreeRTOS-LTS/tree/202012.00-LTS) release.**
## Reference example
The example below shows how to use the backoffAlgorithm library on a POSIX platform to retry a DNS resolution query for `amazon.com`.
```c
#include "backoff_algorithm.h"
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <unistd.h>
#include <time.h>
/* The maximum number of retries for the example code. */
#define RETRY_MAX_ATTEMPTS ( 5U )
/* The maximum back-off delay (in milliseconds) for between retries in the example. */
#define RETRY_MAX_BACKOFF_DELAY_MS ( 5000U )
/* The base back-off delay (in milliseconds) for retry configuration in the example. */
#define RETRY_BACKOFF_BASE_MS ( 500U )
int main()
{
/* Variables used in this example. */
BackoffAlgorithmStatus_t retryStatus = BackoffAlgorithmSuccess;
BackoffAlgorithmContext_t retryParams;
char serverAddress[] = "amazon.com";
uint16_t nextRetryBackoff = 0;
int32_t dnsStatus = -1;
struct addrinfo hints;
struct addrinfo ** pListHead = NULL;
struct timespec tp;
/* Add hints to retrieve only TCP sockets in getaddrinfo. */
( void ) memset( &hints, 0, sizeof( hints ) );
/* Address family of either IPv4 or IPv6. */
hints.ai_family = AF_UNSPEC;
/* TCP Socket. */
hints.ai_socktype = ( int32_t ) SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
/* Initialize reconnect attempts and interval. */
BackoffAlgorithm_InitializeParams( &retryParams,
RETRY_BACKOFF_BASE_MS,
RETRY_MAX_BACKOFF_DELAY_MS,
RETRY_MAX_ATTEMPTS );
/* Seed the pseudo random number generator used in this example (with call to
* rand() function provided by ISO C standard library) for use in backoff period
* calculation when retrying failed DNS resolution. */
/* Get current time to seed pseudo random number generator. */
( void ) clock_gettime( CLOCK_REALTIME, &tp );
/* Seed pseudo random number generator with seconds. */
srand( tp.tv_sec );
do
{
/* Perform a DNS lookup on the given host name. */
dnsStatus = getaddrinfo( serverAddress, NULL, &hints, pListHead );
/* Retry if DNS resolution query failed. */
if( dnsStatus != 0 )
{
/* Generate a random number and get back-off value (in milliseconds) for the next retry.
* Note: It is recommended to use a random number generator that is seeded with
* device-specific entropy source so that backoff calculation across devices is different
* and possibility of network collision between devices attempting retries can be avoided.
*
* For the simplicity of this code example, the pseudo random number generator, rand()
* function is used. */
retryStatus = BackoffAlgorithm_GetNextBackoff( &retryParams, rand(), &nextRetryBackoff );
/* Wait for the calculated backoff period before the next retry attempt of querying DNS.
* As usleep() takes nanoseconds as the parameter, we multiply the backoff period by 1000. */
( void ) usleep( nextRetryBackoff * 1000U );
}
} while( ( dnsStatus != 0 ) && ( retryStatus != BackoffAlgorithmRetriesExhausted ) );
return dnsStatus;
}
```
## Building the library
A compiler that supports **C90 or later** such as *gcc* is required to build the library.
Additionally, the library uses a header file introduced in ISO C99, `stdint.h`. For compilers that do not provide this header file, the [source/include](source/include) directory contains [stdint.readme](source/include/stdint.readme), which can be renamed to `stdint.h` to
build the backoffAlgorithm library.
For instance, if the example above is copied to a file named `example.c`, *gcc* can be used like so:
```bash
gcc -I source/include example.c source/backoff_algorithm.c -o example
./example
```
*gcc* can also produce an output file to be linked:
```bash
gcc -I source/include -c source/backoff_algorithm.c
```
## Building unit tests
### Checkout Unity Submodule
By default, the submodules in this repository are configured with `update=none` in [.gitmodules](.gitmodules), to avoid increasing clone time and disk space usage of other repositories (like [amazon-freertos](https://github.com/aws/amazon-freertos) that submodules this repository).
To build unit tests, the submodule dependency of Unity is required. Use the following command to clone the submodule:
```
git submodule update --checkout --init --recursive test/unit-test/Unity
```
### Platform Prerequisites
- For running unit tests
- C89 or later compiler like gcc
- CMake 3.13.0 or later
- For running the coverage target, gcov is additionally required.
### Steps to build Unit Tests
1. Go to the root directory of this repository. (Make sure that the **Unity** submodule is cloned as described [above](#checkout-unity-submodule).)
1. Create build directory: `mkdir build && cd build`
1. Run *cmake* while inside build directory: `cmake -S ../test`
1. Run this command to build the library and unit tests: `make all`
1. The generated test executables will be present in `build/bin/tests` folder.
1. Run `ctest` to execute all tests and view the test run summary.
## Contributing
See [CONTRIBUTING.md](./.github/CONTRIBUTING.md) for information on contributing.

View File

@ -0,0 +1,5 @@
## Reporting a Vulnerability
If you discover a potential security issue in this project, we ask that you notify AWS/Amazon Security
via our [vulnerability reporting page](https://aws.amazon.com/security/vulnerability-reporting/) or directly via email to aws-security@amazon.com.
Please do **not** create a public github issue.

View File

@ -0,0 +1,14 @@
# This file is to add source files and include directories
# into variables so that it can be reused from different repositories
# in their Cmake based build system by including this file.
#
# Files specific to the repository such as test runner, platform tests
# are not added to the variables.
# Backoff Algorithm library source files.
set( BACKOFF_ALGORITHM_SOURCES
"${CMAKE_CURRENT_LIST_DIR}/source/backoff_algorithm.c" )
# Backoff Algorithm library Public Include directories.
set( BACKOFF_ALGORITHM_INCLUDE_PUBLIC_DIRS
"${CMAKE_CURRENT_LIST_DIR}/source/include" )

View File

@ -0,0 +1,84 @@
#include "backoff_algorithm.h"
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <unistd.h>
#include <time.h>
/* The maximum number of retries for the example code. */
#define RETRY_MAX_ATTEMPTS ( 5U )
/* The maximum back-off delay (in milliseconds) for between retries in the example. */
#define RETRY_MAX_BACKOFF_DELAY_MS ( 5000U )
/* The base back-off delay (in milliseconds) for retry configuration in the example. */
#define RETRY_BACKOFF_BASE_MS ( 500U )
int main()
{
/* @[code_example_backoffalgorithm_initializeparams] */
/* Variables used in this example. */
BackoffAlgorithmStatus_t retryStatus = BackoffAlgorithmSuccess;
BackoffAlgorithmContext_t retryParams;
char serverAddress[] = "amazon.com";
uint16_t nextRetryBackoff = 0;
/* Initialize reconnect attempts and interval. */
BackoffAlgorithm_InitializeParams( &retryParams,
RETRY_BACKOFF_BASE_MS,
RETRY_MAX_BACKOFF_DELAY_MS,
RETRY_MAX_ATTEMPTS );
/* @[code_example_backoffalgorithm_initializeparams] */
int32_t dnsStatus = -1;
struct addrinfo hints;
struct addrinfo ** pListHead = NULL;
struct timespec tp;
/* Add hints to retrieve only TCP sockets in getaddrinfo. */
( void ) memset( &hints, 0, sizeof( hints ) );
/* Address family of either IPv4 or IPv6. */
hints.ai_family = AF_UNSPEC;
/* TCP Socket. */
hints.ai_socktype = ( int32_t ) SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
/* @[code_example_backoffalgorithm_getnextbackoff] */
/* Seed the pseudo random number generator used in this example (with call to
* rand() function provided by ISO C standard library) for use in backoff period
* calculation when retrying failed DNS resolution. */
/* Get current time to seed pseudo random number generator. */
( void ) clock_gettime( CLOCK_REALTIME, &tp );
/* Seed pseudo random number generator with seconds. */
srand( tp.tv_sec );
do
{
/* Perform a DNS lookup on the given host name. */
dnsStatus = getaddrinfo( serverAddress, NULL, &hints, pListHead );
/* Retry if DNS resolution query failed. */
if( dnsStatus != 0 )
{
/* Generate a random number and get back-off value (in milliseconds) for the next retry.
* Note: It is recommended to use a random number generator that is seeded with
* device-specific entropy source so that backoff calculation across devices is different
* and possibility of network collision between devices attempting retries can be avoided.
*
* For the simplicity of this code example, the pseudo random number generator, rand()
* function is used. */
retryStatus = BackoffAlgorithm_GetNextBackoff( &retryParams, rand(), &nextRetryBackoff );
/* Wait for the calculated backoff period before the next retry attempt of querying DNS.
* As usleep() takes nanoseconds as the parameter, we multiply the backoff period by 1000. */
( void ) usleep( nextRetryBackoff * 1000U );
}
} while( ( dnsStatus != 0 ) && ( retryStatus != BackoffAlgorithmRetriesExhausted ) );
/* @[code_example_backoffalgorithm_getnextbackoff] */
return dnsStatus;
}

View File

@ -0,0 +1,20 @@
<table>
<tr>
<td colspan="3"><center><b>Code Size of backoffAlgorithm (example generated with GCC for ARM Cortex-M)</b></center></td>
</tr>
<tr>
<td><b>File</b></td>
<td><b><center>With -O1 Optimization</center></b></td>
<td><b><center>With -Os Optimization</center></b></td>
</tr>
<tr>
<td>backoff_algorithm.c</td>
<td><center>0.1K</center></td>
<td><center>0.1K</center></td>
</tr>
<tr>
<td><b>Total estimates</b></td>
<td><b><center>0.1K</center></b></td>
<td><b><center>0.1K</center></b></td>
</tr>
</table>

View File

@ -0,0 +1,228 @@
<doxygenlayout version="1.0">
<!-- Generated by doxygen 1.8.20 -->
<!-- Navigation index tabs for HTML output -->
<navindex>
<tab type="mainpage" visible="yes" title=""/>
<tab type="pages" visible="yes" title="" intro=""/>
<!-- Hide the default "Data Structures" tab and use the "Modules" tab for data
structures. This allows internal data structures to be hidden. -->
<tab type="modules" visible="yes" title="Data types and Constants" intro="This library defines the following data types and constants."/>
<tab type="namespaces" visible="yes" title="">
<tab type="namespacelist" visible="yes" title="" intro=""/>
<tab type="namespacemembers" visible="yes" title="" intro=""/>
</tab>
<tab type="interfaces" visible="no" title="">
<tab type="interfacelist" visible="no" title="" intro=""/>
<tab type="interfaceindex" visible="no" title=""/>
<tab type="interfacehierarchy" visible="yes" title="" intro=""/>
</tab>
<tab type="classes" visible="no" title="">
<tab type="classlist" visible="no" title="" intro=""/>
<tab type="classindex" visible="no" title=""/>
<tab type="hierarchy" visible="no" title="" intro=""/>
<tab type="classmembers" visible="no" title="" intro=""/>
</tab>
<tab type="structs" visible="no" title="">
<tab type="structlist" visible="no" title="" intro=""/>
<tab type="structindex" visible="no" title=""/>
</tab>
<tab type="exceptions" visible="no" title="">
<tab type="exceptionlist" visible="no" title="" intro=""/>
<tab type="exceptionindex" visible="no" title=""/>
<tab type="exceptionhierarchy" visible="yes" title="" intro=""/>
</tab>
<tab type="files" visible="no" title="">
<tab type="filelist" visible="yes" title="Files" intro="The following files are associated with this library."/>
<tab type="globals" visible="no" title="" intro=""/>
</tab>
<tab type="examples" visible="yes" title="" intro=""/>
</navindex>
<!-- Layout definition for a class page -->
<class>
<briefdescription visible="yes"/>
<includes visible="$SHOW_INCLUDE_FILES"/>
<inheritancegraph visible="$CLASS_GRAPH"/>
<collaborationgraph visible="$COLLABORATION_GRAPH"/>
<memberdecl>
<nestedclasses visible="yes" title=""/>
<publictypes title=""/>
<services title=""/>
<interfaces title=""/>
<publicslots title=""/>
<signals title=""/>
<publicmethods title=""/>
<publicstaticmethods title=""/>
<publicattributes title=""/>
<publicstaticattributes title=""/>
<protectedtypes title=""/>
<protectedslots title=""/>
<protectedmethods title=""/>
<protectedstaticmethods title=""/>
<protectedattributes title=""/>
<protectedstaticattributes title=""/>
<packagetypes title=""/>
<packagemethods title=""/>
<packagestaticmethods title=""/>
<packageattributes title=""/>
<packagestaticattributes title=""/>
<properties title=""/>
<events title=""/>
<privatetypes title=""/>
<privateslots title=""/>
<privatemethods title=""/>
<privatestaticmethods title=""/>
<privateattributes title=""/>
<privatestaticattributes title=""/>
<friends title=""/>
<related title="" subtitle=""/>
<membergroups visible="yes"/>
</memberdecl>
<detaileddescription title=""/>
<memberdef>
<inlineclasses title=""/>
<typedefs title=""/>
<enums title=""/>
<services title=""/>
<interfaces title=""/>
<constructors title=""/>
<functions title=""/>
<related title=""/>
<variables title=""/>
<properties title=""/>
<events title=""/>
</memberdef>
<allmemberslink visible="yes"/>
<usedfiles visible="$SHOW_USED_FILES"/>
<authorsection visible="yes"/>
</class>
<!-- Layout definition for a namespace page -->
<namespace>
<briefdescription visible="yes"/>
<memberdecl>
<nestednamespaces visible="yes" title=""/>
<constantgroups visible="yes" title=""/>
<interfaces visible="yes" title=""/>
<classes visible="yes" title=""/>
<structs visible="yes" title=""/>
<exceptions visible="yes" title=""/>
<typedefs title=""/>
<sequences title=""/>
<dictionaries title=""/>
<enums title=""/>
<functions title=""/>
<variables title=""/>
<membergroups visible="yes"/>
</memberdecl>
<detaileddescription title=""/>
<memberdef>
<inlineclasses title=""/>
<typedefs title=""/>
<sequences title=""/>
<dictionaries title=""/>
<enums title=""/>
<functions title=""/>
<variables title=""/>
</memberdef>
<authorsection visible="yes"/>
</namespace>
<!-- Layout definition for a file page -->
<file>
<briefdescription visible="yes"/>
<includes visible="$SHOW_INCLUDE_FILES"/>
<includegraph visible="$INCLUDE_GRAPH"/>
<includedbygraph visible="$INCLUDED_BY_GRAPH"/>
<sourcelink visible="yes"/>
<memberdecl>
<interfaces visible="yes" title=""/>
<classes visible="yes" title=""/>
<structs visible="yes" title=""/>
<exceptions visible="yes" title=""/>
<namespaces visible="yes" title=""/>
<constantgroups visible="yes" title=""/>
<defines title=""/>
<typedefs title=""/>
<sequences title=""/>
<dictionaries title=""/>
<enums title=""/>
<functions title=""/>
<variables title=""/>
<membergroups visible="yes"/>
</memberdecl>
<detaileddescription title=""/>
<memberdef>
<inlineclasses title=""/>
<defines title=""/>
<typedefs title=""/>
<sequences title=""/>
<dictionaries title=""/>
<enums title=""/>
<functions title=""/>
<variables title=""/>
</memberdef>
<authorsection/>
</file>
<!-- Layout definition for a group page -->
<group>
<briefdescription visible="yes"/>
<groupgraph visible="$GROUP_GRAPHS"/>
<memberdecl>
<nestedgroups visible="yes" title=""/>
<dirs visible="yes" title=""/>
<files visible="yes" title=""/>
<namespaces visible="yes" title=""/>
<classes visible="yes" title=""/>
<defines title=""/>
<typedefs title=""/>
<sequences title=""/>
<dictionaries title=""/>
<enums title=""/>
<enumvalues title=""/>
<functions title=""/>
<variables title=""/>
<signals title=""/>
<publicslots title=""/>
<protectedslots title=""/>
<privateslots title=""/>
<events title=""/>
<properties title=""/>
<friends title=""/>
<membergroups visible="yes"/>
</memberdecl>
<detaileddescription title=""/>
<memberdef>
<pagedocs/>
<inlineclasses title=""/>
<defines title=""/>
<typedefs title=""/>
<sequences title=""/>
<dictionaries title=""/>
<enums title=""/>
<enumvalues title=""/>
<functions title=""/>
<variables title=""/>
<signals title=""/>
<publicslots title=""/>
<protectedslots title=""/>
<privateslots title=""/>
<events title=""/>
<properties title=""/>
<friends title=""/>
</memberdef>
<authorsection visible="yes"/>
</group>
<!-- Layout definition for a directory page -->
<directory>
<briefdescription visible="yes"/>
<directorygraph visible="yes"/>
<memberdecl>
<dirs visible="yes"/>
<files visible="yes"/>
</memberdecl>
<detaileddescription title=""/>
</directory>
</doxygenlayout>

View File

@ -0,0 +1,109 @@
/**
@mainpage Overview
@anchor BackOff Algorithm
@brief backoffAlgorithm Library
<p>
A library that calculates the back-off period for a retry attempt using exponential back-off with jitter algorithm.
This library uses the "Full Jitter" strategy for the exponential back-off with jitter algorithm.
More information about the algorithm can be seen in the [Exponential Backoff and Jitter](https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/) AWS blog.
Exponential backoff with jitter is typically used when retrying a failed network
connection or operation request with the server. An exponential backoff with jitter helps to
mitigate failed network operations with servers, that are caused due to network congestion or high request load on
the server, by spreading out retry requests across multiple devices attempting network operations.
Besides, in an environment with poor connectivity, a client can get disconnected at any time.
A backoff strategy helps the client to conserve battery by not repeatedly attempting reconnections when they are
unlikely to succeed.
Before retrying the failed communication to the server, there is a delay period.
In this delay period, the task that is retrying must sleep for some random amount
of milliseconds between 0 and the lesser of the backoff window (related to the retry attempt)
and a predefined maximum delay value. The backoff window is doubled with each retry
attempt until the maximum delay value is reached.<br>
> sleep_ms = random_between( 0, min( 2<sup>attempts_count</sup> * base_ms, maximum_ms ) )
The library is written in C and designed to be compliant with ISO C90 and MISRA C:2012.
For a reference example of using the library, refer to the related README section in the repository [here](https://github.com/FreeRTOS/backoffAlgorithm#reference-example).
</p>
@section backoff_algorithm_memory_requirements Memory Requirements
@brief Memory requirements of the backoffAlgorithm library.
@include{doc} size_table.md
@section backoff_algorithm_design Design
@brief backoffAlgorithm Library Design
<h3>Memory Usage</h3>
<p>
All functions in the backoffAlgorithm library operate only on the buffer provided and use only
local variables on the stack.
</p>
<h3>Random Number Generation</h3>
<p>
The library takes a random number each time it calculates the backoff period value for the
retry attempt. To avoid calculation of the same random numbers across your fleet of devices
attempting retry of network operations, it is RECOMMENDED to generate the random number with
a random number generator that is seeded with an entropy source unique to the device.
</p>
<h3>Compliance & Coverage</h3>
<p>
The backoffAlgorithm library is designed to be compliant with ISO C90 and MISRA C:2012.
All functions are written to have minimal complexity. Unit tests are written to cover
every path of execution and achieve 100% branch coverage.
</p>
*/
/**
@page backoff_algorithm_example Code Example for backoffAlgorithm API
@brief Example POSIX application that retries DNS resolution operation with exponential backoff-and-jitter using the backoffAlgorithm library.
@include backoff_algorithm_posix.c
*/
/**
@page backoff_algorithm_functions Functions
@brief Primary functions of the backoffAlgorithm library:<br><br>
@subpage define_backoffalgorithm_initializeparams <br>
@subpage define_backoffalgorithm_getnextbackoff <br>
<b>For a code example </b> of using backoffAlgorithm library for retrying operations with exponential back-off and jitter, refer to @ref backoff_algorithm_example.
@page define_backoffalgorithm_initializeparams BackoffAlgorithm_InitializeParams
@snippet backoff_algorithm.h define_backoffalgorithm_initializeparams
@copydoc BackoffAlgorithm_InitializeParams
From the @ref backoff_algorithm_example, following is the part relevant to the @ref BackoffAlgorithm_InitializeParams API.
@snippet backoff_algorithm_posix.c code_example_backoffalgorithm_initializeparams
@page define_backoffalgorithm_getnextbackoff BackoffAlgorithm_GetNextBackoff
@copydoc BackoffAlgorithm_GetNextBackoff
From the @ref backoff_algorithm_example, following is the part relevant to the @ref BackoffAlgorithm_GetNextBackoff API.
@snippet backoff_algorithm_posix.c code_example_backoffalgorithm_getnextbackoff
*/
<!-- We do not use doxygen ALIASes here because there have been issues in the past versions with "^^" newlines within the alias definition. -->
/**
@defgroup backoff_algorithm_struct_types Parameter Structure
@brief Structure passed as parameter to [backoffAlgorithm library functions](@ref backoff_algorithm_functions)
*/
/**
@defgroup backoff_algorithm_enum_types Enumerated Types
@brief Enumerated types of the backoffAlgorithm library
*/
/**
@defgroup backoff_algorithm_constants Constants
@brief Constants defined in the backoffAlgorithm library
*/

View File

@ -0,0 +1,132 @@
/*
* Stylesheet for Doxygen HTML output.
*
* This file defines styles for custom elements in the header/footer and
* overrides some of the default Doxygen styles.
*
* Styles in this file do not affect the treeview sidebar.
*/
/* Set the margins to place a small amount of whitespace on the left and right
* side of the page. */
div.contents {
margin-left:4em;
margin-right:4em;
}
/* Justify text in paragraphs. */
p {
text-align: justify;
}
/* Style of section headings. */
h1 {
border-bottom: 1px solid #879ECB;
color: #354C7B;
font-size: 160%;
font-weight: normal;
padding-bottom: 4px;
padding-top: 8px;
}
/* Style of subsection headings. */
h2:not(.memtitle):not(.groupheader) {
font-size: 125%;
margin-bottom: 0px;
margin-top: 16px;
padding: 0px;
}
/* Style of paragraphs immediately after subsection headings. */
h2 + p {
margin: 0px;
padding: 0px;
}
/* Style of subsection headings. */
h3 {
font-size: 100%;
margin-bottom: 0px;
margin-left: 2em;
margin-right: 2em;
}
/* Style of paragraphs immediately after subsubsection headings. */
h3 + p {
margin-top: 0px;
margin-left: 2em;
margin-right: 2em;
}
/* Style of the prefix "AWS IoT Device SDK C" that appears in the header. */
#csdkprefix {
color: #757575;
}
/* Style of the "Return to main page" link that appears in the header. */
#returntomain {
padding: 0.5em;
}
/* Style of the dividers on Configuration Settings pages. */
div.configpagedivider {
margin-left: 0px !important;
margin-right: 0px !important;
margin-top: 20px !important;
}
/* Style of configuration setting names. */
dl.section.user ~ h1 {
border-bottom: none;
color: #000000;
font-family: monospace, fixed;
font-size: 16px;
margin-bottom: 0px;
margin-left: 2em;
margin-top: 1.5em;
}
/* Style of paragraphs on a configuration settings page. */
dl.section.user ~ * {
margin-bottom: 10px;
margin-left: 4em;
margin-right: 4em;
margin-top: 0px;
}
/* Hide the configuration setting marker. */
dl.section.user {
display: none;
}
/* Overrides for code fragments and lines. */
div.fragment {
background: #ffffff;
border: none;
padding: 5px;
}
div.line {
color: #3a3a3a;
}
/* Overrides for code syntax highlighting colors. */
span.comment {
color: #008000;
}
span.keyword, span.keywordtype, span.keywordflow {
color: #0000ff;
}
span.preprocessor {
color: #50015a;
}
span.stringliteral, span.charliteral {
color: #800c0c;
}
a.code, a.code:visited, a.line, a.line:visited {
color: #496194;
}

View File

@ -0,0 +1,65 @@
api
apis
aws
backoff
backoff
backoffalgorithm
backoffalgorithmretriesexhausted
backoffalgorithmrngfailure
backoffalgorithmsuccess
backoffbase
br
colspan
com
copydoc
defgroup
dns
endif
fd
freertos
gcc
getaddrinfo
github
html
https
ifdef
ifndef
inc
ingroup
iot
iso
longjmp
mainpage
maxattempts
maxbackoff
maxretryattempts
md
min
misra
mit
mockrng
noninfringement
os
param
pcontext
pnextbackoff
posix
pretrycontext
pretryparams
prng
rand
randomvalue
readme
rm
rng
sdk
spdx
shouldn
stderr
sublicense
tcp
td
toolchain
tr
trng
usleep

View File

@ -0,0 +1,5 @@
name : "backoffAlgorithm"
version: "v1.3.0"
description: |
"Algorithm for calculating exponential backoff with jitter for network retry attempts.\n"
license: "MIT"

View File

@ -0,0 +1,29 @@
SPDXVersion: SPDX-2.2
DataLicense: CC0-1.0
SPDXID: SPDXRef-DOCUMENT
DocumentName: backoffAlgorithm
DocumentNamespace: https://github.com/FreeRTOS/backoffAlgorithm/blob/v1.3.0/sbom.spdx
Creator: Amazon Web Services
Created: 2022-10-14T15:39:49Z
CreatorComment: NOASSERTION
DocumentComment: NOASSERTION
PackageName: backoffAlgorithm
SPDXID: SPDXRef-Package-backoffAlgorithm
PackageVersion: v1.3.0
PackageDownloadLocation: https://github.com/FreeRTOS/backoffAlgorithm/tree/v1.3.0
PackageLicenseConcluded: MIT
FilesAnalyzed: True
PackageVerificationCode: 8cf87c7d09f62a054172b8f82227e3c116b08388
PackageCopyrightText: NOASSERTION
PackageSummary: NOASSERTION
PackageDescription: "Algorithm for calculating exponential backoff with jitter for network retry attempts.\n"
FileName: ./backoff_algorithm.c
SPDXID: SPDXRef-File-backoff_algorithm.c
FileChecksum: SHA1: ee94d75f7a99e11628734dd306e209913ea3058e
LicenseConcluded: MIT
FileCopyrightText: NOASSERTION
FileComment: NOASSERTION

View File

@ -0,0 +1,103 @@
/*
* backoffAlgorithm v1.3.0
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* @file backoff_algorithm.c
* @brief Implementation of the backoff algorithm API for a "Full Jitter" exponential backoff
* with jitter strategy.
*/
/* Standard includes. */
#include <assert.h>
#include <stddef.h>
/* Include API header. */
#include "backoff_algorithm.h"
/*-----------------------------------------------------------*/
BackoffAlgorithmStatus_t BackoffAlgorithm_GetNextBackoff( BackoffAlgorithmContext_t * pRetryContext,
uint32_t randomValue,
uint16_t * pNextBackOff )
{
BackoffAlgorithmStatus_t status = BackoffAlgorithmSuccess;
assert( pRetryContext != NULL );
assert( pNextBackOff != NULL );
/* If maxRetryAttempts state of the context is set to the maximum, retry forever. */
if( ( pRetryContext->maxRetryAttempts == BACKOFF_ALGORITHM_RETRY_FOREVER ) ||
( pRetryContext->attemptsDone < pRetryContext->maxRetryAttempts ) )
{
/* The next backoff value is a random value between 0 and the maximum jitter value
* for the retry attempt. */
/* Choose a random value for back-off time between 0 and the max jitter value. */
*pNextBackOff = ( uint16_t ) ( randomValue % ( pRetryContext->nextJitterMax + ( uint32_t ) 1U ) );
/* Increment the retry attempt. */
pRetryContext->attemptsDone++;
/* Double the max jitter value for the next retry attempt, only
* if the new value will be less than the max backoff time value. */
if( pRetryContext->nextJitterMax < ( pRetryContext->maxBackoffDelay / 2U ) )
{
pRetryContext->nextJitterMax += pRetryContext->nextJitterMax;
}
else
{
pRetryContext->nextJitterMax = pRetryContext->maxBackoffDelay;
}
}
else
{
/* When max retry attempts are exhausted, let application know by
* returning BackoffAlgorithmRetriesExhausted. Application may choose to
* restart the retry process after calling BackoffAlgorithm_InitializeParams(). */
status = BackoffAlgorithmRetriesExhausted;
}
return status;
}
/*-----------------------------------------------------------*/
void BackoffAlgorithm_InitializeParams( BackoffAlgorithmContext_t * pContext,
uint16_t backOffBase,
uint16_t maxBackOff,
uint32_t maxAttempts )
{
assert( pContext != NULL );
/* Initialize the context with parameters used in calculating the backoff
* value for the next retry attempt. */
pContext->nextJitterMax = backOffBase;
pContext->maxBackoffDelay = maxBackOff;
pContext->maxRetryAttempts = maxAttempts;
/* The total number of retry attempts is zero at initialization. */
pContext->attemptsDone = 0;
}
/*-----------------------------------------------------------*/

View File

@ -0,0 +1,147 @@
/*
* backoffAlgorithm v1.3.0
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* @file backoff_algorithm.h
* @brief API for calculating backoff period for retry attempts using
* exponential backoff with jitter algorithm.
* This library represents the "Full Jitter" backoff strategy explained in the
* following document.
* https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/
*
*/
#ifndef BACKOFF_ALGORITHM_H_
#define BACKOFF_ALGORITHM_H_
/* Standard include. */
#include <stdint.h>
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
/**
* @ingroup backoff_algorithm_constants
* @brief Constant to represent unlimited number of retry attempts.
*/
#define BACKOFF_ALGORITHM_RETRY_FOREVER ( UINT32_MAX )
/**
* @ingroup backoff_algorithm_enum_types
* @brief Status for @ref BackoffAlgorithm_GetNextBackoff.
*/
typedef enum BackoffAlgorithmStatus
{
BackoffAlgorithmSuccess = 0, /**< @brief The function successfully calculated the next back-off value. */
BackoffAlgorithmRetriesExhausted /**< @brief The function exhausted all retry attempts. */
} BackoffAlgorithmStatus_t;
/**
* @ingroup backoff_algorithm_struct_types
* @brief Represents parameters required for calculating the back-off delay for the
* next retry attempt.
*/
typedef struct BackoffAlgorithmContext
{
/**
* @brief The maximum backoff delay (in milliseconds) between consecutive retry attempts.
*/
uint16_t maxBackoffDelay;
/**
* @brief The total number of retry attempts completed.
* This value is incremented on every call to #BackoffAlgorithm_GetNextBackoff API.
*/
uint32_t attemptsDone;
/**
* @brief The maximum backoff value (in milliseconds) for the next retry attempt.
*/
uint16_t nextJitterMax;
/**
* @brief The maximum number of retry attempts.
*/
uint32_t maxRetryAttempts;
} BackoffAlgorithmContext_t;
/**
* @brief Initializes the context for using backoff algorithm. The parameters
* are required for calculating the next retry backoff delay.
* This function must be called by the application before the first new retry attempt.
*
* @param[out] pContext The context to initialize with parameters required
* for the next backoff delay calculation function.
* @param[in] maxBackOff The maximum backoff delay (in milliseconds) between
* consecutive retry attempts.
* @param[in] backOffBase The base value (in milliseconds) of backoff delay to
* use in the exponential backoff and jitter model.
* @param[in] maxAttempts The maximum number of retry attempts. Set the value to
* #BACKOFF_ALGORITHM_RETRY_FOREVER to retry for ever.
*/
/* @[define_backoffalgorithm_initializeparams] */
void BackoffAlgorithm_InitializeParams( BackoffAlgorithmContext_t * pContext,
uint16_t backOffBase,
uint16_t maxBackOff,
uint32_t maxAttempts );
/* @[define_backoffalgorithm_initializeparams] */
/**
* @brief Simple exponential backoff and jitter function that provides the
* delay value for the next retry attempt.
* After a failure of an operation that needs to be retried, the application
* should use this function to obtain the backoff delay value for the next retry,
* and then wait for the backoff time period before retrying the operation.
*
* @param[in, out] pRetryContext Structure containing parameters for the next backoff
* value calculation.
* @param[in] randomValue The random value to use for calculation of the backoff period.
* The random value should be in the range of [0, UINT32_MAX].
* @param[out] pNextBackOff This will be populated with the backoff value (in milliseconds)
* for the next retry attempt. The value does not exceed the maximum backoff delay
* configured in the context.
*
* @note For generating a random number, it is recommended to use a Random Number Generator
* that is seeded with a device-specific entropy source so that possibility of collisions
* between multiple devices retrying the network operations can be mitigated.
*
* @return #BackoffAlgorithmSuccess after a successful sleep;
* #BackoffAlgorithmRetriesExhausted when all attempts are exhausted.
*/
/* @[define_backoffalgorithm_getnextbackoff] */
BackoffAlgorithmStatus_t BackoffAlgorithm_GetNextBackoff( BackoffAlgorithmContext_t * pRetryContext,
uint32_t randomValue,
uint16_t * pNextBackOff );
/* @[define_backoffalgorithm_getnextbackoff] */
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* ifndef BACKOFF_ALGORITHM_H_ */

View File

@ -0,0 +1,37 @@
#ifndef _STDINT_H
#define _STDINT_H
/*******************************************************************************
* THIS IS NOT A FULL stdint.h IMPLEMENTATION - It only contains the definitions
* necessary to build the library code. It is provided to allow the library to
* be built using compilers that do not provide their own stdint.h definition.
*
* To use this file:
*
* 1) Copy this file into a directory that is in your compiler's include path.
* The directory must be part of the include path for system header file,
* for example passed using gcc's "-I" or "-isystem" options.
*
* 2) Rename the copied file stdint.h.
*
*/
typedef signed char int8_t;
typedef unsigned char uint8_t;
typedef short int16_t;
typedef unsigned short uint16_t;
typedef long int32_t;
typedef unsigned long uint32_t;
typedef long long int64_t;
typedef unsigned long long uint64_t;
#define INT8_MAX ( ( signed char ) 127 )
#define UINT8_MAX ( ( unsigned char ) 255 )
#define INT16_MAX ( ( short ) 32767 )
#define UINT16_MAX ( ( unsigned short ) 65535 )
#define INT32_MAX 2147483647L
#define UINT32_MAX 4294967295UL
#define INT64_MAX 9223372036854775807LL
#define UINT64_MAX 18446744073709551615ULL
#endif /* _STDINT_H */

View File

@ -0,0 +1,102 @@
cmake_minimum_required( VERSION 3.13.0 )
project( "backoffAlgorithm unit test"
VERSION 1.0.0
LANGUAGES C )
# Allow the project to be organized into folders.
set_property( GLOBAL PROPERTY USE_FOLDERS ON )
# Use C90.
set( CMAKE_C_STANDARD 90 )
set( CMAKE_C_STANDARD_REQUIRED ON )
# Do not allow in-source build.
if( ${PROJECT_SOURCE_DIR} STREQUAL ${PROJECT_BINARY_DIR} )
message( FATAL_ERROR "In-source build is not allowed. Please build in a separate directory, such as ${PROJECT_SOURCE_DIR}/build." )
endif()
# Set global path variables.
get_filename_component(__MODULE_ROOT_DIR "${CMAKE_CURRENT_LIST_DIR}/.." ABSOLUTE)
set( MODULE_ROOT_DIR ${__MODULE_ROOT_DIR} CACHE INTERNAL "backoffAlgorithm source root." )
set( UNIT_TEST_DIR ${MODULE_ROOT_DIR}/test/unit-test CACHE INTERNAL "backoffAlgorithm unit test directory." )
set( UNITY_DIR ${UNIT_TEST_DIR}/Unity CACHE INTERNAL "Unity library source directory." )
# Configure options to always show in CMake GUI.
option( BUILD_UNIT_TESTS
"Set this to ON to build unit tests. This will clone the required Unity test framework submodule if it is not cloned already."
OFF )
# Set output directories.
set( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin )
set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib )
set( CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib )
# ================================ Coverity Analysis Configuration =================================
# Include filepaths for source and include.
include( ${MODULE_ROOT_DIR}/backoffAlgorithmFilePaths.cmake )
# Target for Coverity analysis that builds the library.
add_library( coverity_analysis
${BACKOFF_ALGORITHM_SOURCES} )
# Backoff Algorithm library public include path.
target_include_directories( coverity_analysis
PUBLIC
${BACKOFF_ALGORITHM_INCLUDE_PUBLIC_DIRS} )
# Disable logging/assert() calls when building the Coverity analysis target
target_compile_options(coverity_analysis PUBLIC -DNDEBUG )
# ==================================== Unit Test Configuration ====================================
if(${BUILD_CODE_EXAMPLE})
# Target for code example binary.
add_executable( code_example_posix
${MODULE_ROOT_DIR}/docs/doxygen/code_examples/backoff_algorithm_posix.c )
target_link_libraries( code_example_posix coverity_analysis )
endif()
# ==================================== Unit Test Configuration ====================================
if(${BUILD_UNIT_TESTS})
# Include Unity build configuration.
include( unit-test/unity_build.cmake )
# Check if the Unity source directory exists, and if not present, clone the submodule
# if BUILD_CLONE_SUBMODULES configuration is enabled.
if( NOT EXISTS ${UNITY_DIR}/src )
# Attempt to clone Unity.
clone_unity()
endif()
# Add unit test and coverage configuration.
# Use CTest utility for managing test runs. This has to be added BEFORE
# defining test targets with add_test()
enable_testing()
# Add build targets for Unity and Unit, required for unit testing.
add_unity_targets()
# Add function to enable Unity based tests and coverage.
include( ${MODULE_ROOT_DIR}/tools/unity/create_test.cmake )
# Include build configuration for unit tests.
add_subdirectory( unit-test )
# ==================================== Coverage Analysis configuration ============================
# Add a target for running coverage on tests.
add_custom_target( coverage
COMMAND ${CMAKE_COMMAND} -DUNITY_DIR=${UNITY_DIR}
-P ${MODULE_ROOT_DIR}/tools/unity/coverage.cmake
DEPENDS unity backoff_algorithm_utest
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
)
endif()

View File

@ -0,0 +1,71 @@
# Include file path configuration for backoff algorithm library.
include(${MODULE_ROOT_DIR}/backoffAlgorithmFilePaths.cmake)
project ("backoff algorithm unit test")
cmake_minimum_required (VERSION 3.2.0)
# ==================== Define your project name (edit) ========================
set(project_name "backoff_algorithm")
# ===================== Create your mock here (edit) ========================
# list the files to mock here
list(APPEND mock_list
""
)
# list the directories your mocks need
list(APPEND mock_include_list
""
)
#list the definitions of your mocks to control what to be included
list(APPEND mock_define_list
""
)
# ================= Create the library under test here (edit) ==================
# list the files you would like to test here
list(APPEND real_source_files
${BACKOFF_ALGORITHM_SOURCES}
)
# list the directories the module under test includes
list(APPEND real_include_directories
${BACKOFF_ALGORITHM_INCLUDE_PUBLIC_DIRS}
)
# ===================== Create UnitTest Code here (edit) =====================
# list the directories your test needs to include
list(APPEND test_include_directories
${BACKOFF_ALGORITHM_INCLUDE_PUBLIC_DIRS}
${CMAKE_CURRENT_LIST_DIR}
)
# ============================= (end edit) ===================================
set(mock_name "${project_name}_mock")
set(real_name "${project_name}_real")
create_real_library(${real_name}
"${real_source_files}"
"${real_include_directories}"
""
)
list(APPEND utest_link_list
lib${real_name}.a
)
list(APPEND utest_dep_list
${real_name}
)
set(utest_name "${project_name}_utest")
set(utest_source "${project_name}_utest.c")
create_test(${utest_name}
${utest_source}
"${utest_link_list}"
"${utest_dep_list}"
"${test_include_directories}"
)

View File

@ -0,0 +1,350 @@
/*
* backoffAlgorithm v1.3.0
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <string.h>
#include <stdbool.h>
#include <stdlib.h>
/* Unity include. */
#include "unity.h"
/* Include utility for catching assert failures. */
#include "catch_assert.h"
/* Backoff Algorithm library include */
#include "backoff_algorithm.h"
#define TEST_BACKOFF_BASE_VALUE ( 1000 )
#define TEST_BACKOFF_MAX_VALUE ( 10000 )
#define TEST_MAX_ATTEMPTS ( 5 )
/* Parameters to track the next max jitter or number of attempts done. */
static BackoffAlgorithmContext_t retryParams;
/* Return value of #BackoffAlgorithm_GetNextBackoff. */
static BackoffAlgorithmStatus_t BackoffAlgorithmStatus;
static uint16_t nextBackoff;
static uint32_t testRandomVal;
/* ============================ UNITY FIXTURES ============================ */
/* Called before each test method. */
void setUp()
{
/* Initialize context. */
BackoffAlgorithm_InitializeParams( &retryParams,
TEST_BACKOFF_BASE_VALUE,
TEST_BACKOFF_MAX_VALUE,
TEST_MAX_ATTEMPTS );
}
/* Called after each test method. */
void tearDown()
{
testRandomVal = 0;
BackoffAlgorithmStatus = BackoffAlgorithmSuccess;
nextBackoff = 0;
}
/* Called at the beginning of the whole suite. */
void suiteSetUp()
{
}
/* Called at the end of the whole suite. */
int suiteTearDown( int numFailures )
{
return numFailures;
}
/* ========================================================================== */
/**
* @brief Helper method to make assertions on data of the context object.
*/
static void verifyContextData( BackoffAlgorithmContext_t * pContext,
uint32_t expectedAttemptsDone,
uint16_t expectedNextJitterMax,
uint16_t expectedMaxBackoff,
uint32_t expectedMaxAttempts )
{
TEST_ASSERT_EQUAL( expectedNextJitterMax, pContext->nextJitterMax );
TEST_ASSERT_EQUAL( expectedAttemptsDone, pContext->attemptsDone );
TEST_ASSERT_EQUAL( expectedMaxAttempts, pContext->maxRetryAttempts );
TEST_ASSERT_EQUAL( expectedMaxBackoff, pContext->maxBackoffDelay );
}
/**
* @brief Test that #BackoffAlgorithm_InitializeParams encounters an assert
* failure when a NULL context parameter is passed.
*/
void test_BackoffAlgorithm_InitializeParams_Invalid_Context( void )
{
catch_assert( BackoffAlgorithm_InitializeParams( NULL /* Invalid context */,
TEST_BACKOFF_BASE_VALUE,
TEST_BACKOFF_MAX_VALUE,
TEST_MAX_ATTEMPTS ) );
}
/**
* @brief Test that #BackoffAlgorithm_InitializeParams initializes the context
* data as expected.
*/
void test_BackoffAlgorithm_InitializeParams_Sets_Jitter_Correctly( void )
{
BackoffAlgorithm_InitializeParams( &retryParams,
TEST_BACKOFF_BASE_VALUE,
TEST_BACKOFF_MAX_VALUE,
TEST_MAX_ATTEMPTS );
verifyContextData( &retryParams,
0,
TEST_BACKOFF_BASE_VALUE,
TEST_BACKOFF_MAX_VALUE,
TEST_MAX_ATTEMPTS );
}
/**
* @brief Test that #BackoffAlgorithm_GetNextBackoff returns the expected next back-off
* value and updates the contents of the context as expected when the random value
* generated is lower than the max jitter value for the retry attempts.
*
* This test assumes that the max jitter value has not reached the configured
* maximum back-off value.
*/
void test_BackoffAlgorithm_GetNextBackoff_Success_RandVal_Less_Than_Jitter_Max( void )
{
int iter = 1;
uint16_t expectedAttemptsDone = 0;
uint16_t expectedNextJitterMax = TEST_BACKOFF_BASE_VALUE;
uint16_t expectedNextBackoff = 0;
for( ; iter < 2; iter++ )
{
/* Set the random value as a value lower than
* the jitter max value for the next retry attempt. */
testRandomVal = retryParams.nextJitterMax / 2;
/* As the random value is less than the max jitter value, the expected
* next backoff value should remain the same as the random value. */
expectedNextBackoff = testRandomVal;
/* The jitter max value should double with the above call for use in next call. */
expectedNextJitterMax *= 2;
/* The number of attempts should be updated by the above API call. */
expectedAttemptsDone++;
TEST_ASSERT_LESS_THAN( TEST_BACKOFF_MAX_VALUE, expectedNextJitterMax );
/* Call the BackoffAlgorithm_GetNextBackoff API a couple times. */
TEST_ASSERT_EQUAL( BackoffAlgorithmSuccess,
BackoffAlgorithm_GetNextBackoff( &retryParams, testRandomVal, &nextBackoff ) );
TEST_ASSERT_EQUAL( expectedNextBackoff, nextBackoff );
/* Verify that the context data for expected data after the API call. */
verifyContextData( &retryParams,
expectedAttemptsDone,
expectedNextJitterMax,
TEST_BACKOFF_MAX_VALUE,
TEST_MAX_ATTEMPTS );
}
}
/**
* @brief Test that #BackoffAlgorithm_GetNextBackoff returns the expected next back-off
* value and updates the contents of the context when the random value generated
* is higher than the max jitter value for the retry attempts.
*
* This test assumes that the max jitter value has not reached the configured
* maximum back-off value.
*/
void test_BackoffAlgorithm_GetNextBackoff_Success_RandVal_More_Than_Jitter_Max( void )
{
int iter = 1;
uint16_t expectedAttemptsDone = 0;
uint16_t expectedNextJitterMax = TEST_BACKOFF_BASE_VALUE;
for( ; iter < 2; iter++ )
{
/* Set the random value as a value greater than
* the jitter max value for the next retry attempt. */
testRandomVal = retryParams.nextJitterMax + 1;
/* The jitter max value should double with the above call for use in next call. */
expectedNextJitterMax *= 2;
TEST_ASSERT_LESS_THAN( TEST_BACKOFF_MAX_VALUE, expectedNextJitterMax );
/* The number of attempts should be updated by the above API call. */
expectedAttemptsDone++;
/* As the random value is greater than the jitter max value, the expected
* next backoff value should be truncated to a value within the jitter window
* for the retry attempt. */
uint16_t expectedNextBackoff = ( testRandomVal % ( retryParams.nextJitterMax + 1U ) );
/* Call the BackoffAlgorithm_GetNextBackoff API a couple times. */
TEST_ASSERT_EQUAL( BackoffAlgorithmSuccess,
BackoffAlgorithm_GetNextBackoff( &retryParams, testRandomVal, &nextBackoff ) );
TEST_ASSERT_EQUAL( expectedNextBackoff, nextBackoff );
/* Verify that the context data for expected data after the API call. */
verifyContextData( &retryParams,
expectedAttemptsDone,
expectedNextJitterMax,
TEST_BACKOFF_MAX_VALUE,
TEST_MAX_ATTEMPTS );
}
}
/**
* @brief Tests the #BackoffAlgorithm_GetNextBackoff API when the next back-off value
* is requested for exhausted retry attempts.
*/
void test_BackoffAlgorithm_GetNextBackoff_Attempts_Exhausted()
{
/* Update the context data to represent that maximum configured number of
* retry attempts have been completed. */
retryParams.attemptsDone = TEST_MAX_ATTEMPTS;
/* Call the BackoffAlgorithm_GetNextBackoff API. */
TEST_ASSERT_EQUAL( BackoffAlgorithmRetriesExhausted,
BackoffAlgorithm_GetNextBackoff( &retryParams, testRandomVal, &nextBackoff ) );
/* Make sure that the value of the output parameter has not changed. */
TEST_ASSERT_EQUAL( 0, nextBackoff );
/* Make sure that the context data has not changed as the call to
* BackoffAlgorithm_GetNextBackoff failed. */
verifyContextData( &retryParams,
TEST_MAX_ATTEMPTS /* Number of attempts shouldn't change */,
TEST_BACKOFF_BASE_VALUE,
TEST_BACKOFF_MAX_VALUE,
TEST_MAX_ATTEMPTS );
}
/**
* @brief Tests that the #BackoffAlgorithm_GetNextBackoff API does not calculate a backoff period
* beyond the configured maximum backoff period.
*/
void test_BackoffAlgorithm_GetNextBackoff_Returns_Cap_Backoff( void )
{
/* Initialize to 0 attempts, so the max value of next jitter will increase. */
retryParams.attemptsDone = 0U;
/* Update the next jitter value to greater than half the maximum backoff so
* that the BackoffAlgorithm_GetNextBackoff API updates the next jitter value to
* the configured maximum backoff value. */
retryParams.nextJitterMax = ( TEST_BACKOFF_MAX_VALUE / 2U ) + 1;
/* Set the random value equal to the current jitter max value.
* Thus, the BackoffAlgorithm_GetNextBackoff API should return the random value as
* the next back-off value. */
testRandomVal = retryParams.nextJitterMax;
uint16_t expectedBackoffVal = testRandomVal;
/* Call the BackoffAlgorithm_GetNextBackoff API. */
TEST_ASSERT_EQUAL( BackoffAlgorithmSuccess,
BackoffAlgorithm_GetNextBackoff( &retryParams, testRandomVal, &nextBackoff ) );
/* Make sure that the expected value is returned for the next backoff. */
TEST_ASSERT_EQUAL( expectedBackoffVal, nextBackoff );
/* Verify that the next jitter max value has been set to the cap back-off value
* configured in the context. */
verifyContextData( &retryParams,
1,
TEST_BACKOFF_MAX_VALUE /* New jitter max */,
TEST_BACKOFF_MAX_VALUE,
TEST_MAX_ATTEMPTS );
/* Now, set the random value as the maximum back-off value to
* expect that the next back-off value returned by the API is the maximum
* back-off value.*/
testRandomVal = TEST_BACKOFF_MAX_VALUE;
/* Call BackoffAlgorithm_GetNextBackoff API again to verify that it now returns the
* cap value as the next back-off value. */
TEST_ASSERT_EQUAL( BackoffAlgorithmSuccess,
BackoffAlgorithm_GetNextBackoff( &retryParams, testRandomVal, &nextBackoff ) );
/* Make sure that the capped backoff value is returned as the next backoff value . */
TEST_ASSERT_EQUAL( TEST_BACKOFF_MAX_VALUE, nextBackoff );
/* Verify that the context data for expected data after the API call. */
verifyContextData( &retryParams,
2,
TEST_BACKOFF_MAX_VALUE /* jitter max remains unchanged */,
TEST_BACKOFF_MAX_VALUE,
TEST_MAX_ATTEMPTS );
}
/**
* @brief Tests the #BackoffAlgorithm_GetNextBackoff API when the next jitter max value
* is one lower than half of the maximum backoff value. This tests that the API does not
* update the next jitter max to the maximum backoff value in this case.
*/
void test_BackoffAlgorithm_GetNextBackoff_NextJitterMax_Below_Cap_Backoff( void )
{
/* Initialize context.
* Use the configuration constant of retrying forever to achieve branch coverage in tests
* for the configuration. */
BackoffAlgorithm_InitializeParams( &retryParams,
TEST_BACKOFF_BASE_VALUE,
TEST_BACKOFF_MAX_VALUE,
BACKOFF_ALGORITHM_RETRY_FOREVER );
/* Initialize to 0 attempts, so the max value of next jitter will increase. */
retryParams.attemptsDone = 0U;
/* Set the random value to zero to test that the BackoffAlgorithm_GetNextBackoff
* API will return zero as the next back-off value.*/
testRandomVal = 0;
/* Update the next jitter max value to one less than half of max backoff
* to make sure that the BackoffAlgorithm_GetNextBackoff API does not update it
* to the cap value in the call.*/
retryParams.nextJitterMax = ( TEST_BACKOFF_MAX_VALUE / 2U ) - 1;
/* Call the BackoffAlgorithm_GetNextBackoff API. */
TEST_ASSERT_EQUAL( BackoffAlgorithmSuccess,
BackoffAlgorithm_GetNextBackoff( &retryParams, testRandomVal, &nextBackoff ) );
/* Make sure that zero is returned as the next backoff value . */
TEST_ASSERT_EQUAL( 0, nextBackoff );
/* Verify that the context data for expected data after the API call. */
verifyContextData( &retryParams,
1,
TEST_BACKOFF_MAX_VALUE - 2U /* next jitter max value */,
TEST_BACKOFF_MAX_VALUE,
BACKOFF_ALGORITHM_RETRY_FOREVER );
}
/**
* @brief Tests that the #BackoffAlgorithm_GetNextBackoff API encounters assert failures
* when called with invalid parameters.
*/
void test_BackoffAlgorithm_GetNextBackoff_Invalid_Params()
{
/* Invalid context. */
catch_assert( BackoffAlgorithm_GetNextBackoff( NULL, testRandomVal, &nextBackoff ) );
/* Invalid output parameter for next back-off. */
catch_assert( BackoffAlgorithm_GetNextBackoff( &retryParams, testRandomVal, NULL ) );
}

View File

@ -0,0 +1,80 @@
/*
* backoffAlgorithm v1.3.0
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* How to catch an assert:
* - save a jump buffer where execution will resume after the assert
* - setup a handler for the abort signal, call longjmp within
* - optional - close stderr ( fd 2 ) to discard the assert message
*
* Unity also does a longjmp within its TEST_ASSERT* macros,
* so the macro below restores stderr and the prior abort handler
* before calling the Unity macro.
*/
#ifndef CATCH_ASSERT_H_
#define CATCH_ASSERT_H_
#include <setjmp.h>
#include <signal.h>
#include <unistd.h>
#ifndef CATCH_JMPBUF
#define CATCH_JMPBUF waypoint_
#endif
jmp_buf CATCH_JMPBUF;
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-function"
static void catchHandler_( int signal )
{
longjmp( CATCH_JMPBUF, signal );
}
#pragma GCC diagnostic pop
#define catch_assert( x ) \
do { \
int try = 0, catch = 0; \
int saveFd = dup( 2 ); \
struct sigaction sa = { 0 }, saveSa; \
sa.sa_handler = catchHandler_; \
sigaction( SIGABRT, &sa, &saveSa ); \
close( 2 ); \
if( setjmp( CATCH_JMPBUF ) == 0 ) \
{ \
try++; \
x; \
} \
else \
{ \
catch++; \
} \
sigaction( SIGABRT, &saveSa, NULL ); \
dup2( saveFd, 2 ); \
close( saveFd ); \
TEST_ASSERT_EQUAL( try, catch ); \
} while( 0 )
#endif /* ifndef CATCH_ASSERT_H_ */

View File

@ -0,0 +1,38 @@
# Macro utility to clone the Unity submodule.
macro( clone_unity )
find_package( Git REQUIRED )
message( "Cloning submodule Unity." )
execute_process( COMMAND rm -rf ${UNITY_DIR}
COMMAND ${GIT_EXECUTABLE} submodule update --checkout --init --recursive ${UNITY_DIR}
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
RESULT_VARIABLE UNITY_CLONE_RESULT )
if( NOT ${UNITY_CLONE_RESULT} STREQUAL "0" )
message( FATAL_ERROR "Failed to clone Unity submodule." )
endif()
endmacro()
# Macro utility to add library targets for Unity and Unity to build configuration.
macro( add_unity_targets )
# Build Configuration for Unity and Unity libraries.
list( APPEND UNITY_INCLUDE_DIRS
"${UNITY_DIR}/src/"
"${UNITY_DIR}/extras/fixture/src"
"${UNITY_DIR}/extras/memory/src"
)
add_library( unity STATIC
"${UNITY_DIR}/src/unity.c"
"${UNITY_DIR}/extras/fixture/src/unity_fixture.c"
"${UNITY_DIR}/extras/memory/src/unity_memory.c"
)
set_target_properties( unity PROPERTIES
ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib
POSITION_INDEPENDENT_CODE ON
)
target_include_directories( unity PUBLIC
${UNITY_INCLUDE_DIRS}
)
endmacro()

View File

@ -0,0 +1,79 @@
# Static code analysis for backoffAlgorithm library
This directory is made for the purpose of statically testing the MISRA C:2012 compliance of backoffAlgorithm using
[Synopsys Coverity](https://www.synopsys.com/software-integrity/security-testing/static-analysis-sast.html) static analysis tool.
To that end, this directory provides a [configuration file](https://github.com/FreeRTOS/backoffAlgorithm/blob/main/tools/coverity/misra.config) to use when
building a binary for the tool to analyze.
> **Note**
For generating the report as outlined below, we have used Coverity version 2018.09.
For details regarding the suppressed violations in the report (which can be generated using the instructions described below), please
see the [MISRA.md](https://github.com/FreeRTOS/backoffAlgorithm/blob/main/MISRA.md) file.
## Getting Started
### Prerequisites
You can run this on a platform supported by Coverity. The list and other details can be found [here](https://sig-docs.synopsys.com/polaris/topics/c_coverity-compatible-platforms.html).
To compile and run the Coverity target successfully, you must have the following:
1. CMake version > 3.13.0 (You can check whether you have this by typing `cmake --version`)
2. GCC compiler
- You can see the downloading and installation instructions [here](https://gcc.gnu.org/install/).
3. Download the repo and include the submodules using the following commands.
- `git clone --recurse-submodules git@github.com:FreeRTOS/backoffAlgorithm.git ./backoffAlgorithm`
- `cd ./backoffAlgorithm`
- `git submodule update --checkout --init --recursive`
### To build and run coverity:
Go to the root directory of the library and run the following commands in terminal:
1. Update the compiler configuration in Coverity
~~~
cov-configure --force --compiler cc --comptype gcc
~~~
2. Create the build files using CMake in a `build` directory
~~~
cmake -B build -S test
~~~
3. Go to the build directory and copy the coverity configuration file
~~~
cd build/
~~~
4. Build the static analysis target
~~~
cov-build --emit-complementary-info --dir cov-out make coverity_analysis
~~~
5. Go to the Coverity output directory (`cov-out`) and begin Coverity static analysis
~~~
cd cov-out/
cov-analyze --dir . --coding-standard-config ../../tools/coverity/misra.config --tu-pattern "file('.*/source/.*')"
~~~
6. Format the errors in HTML format so that it is more readable while removing the test and build directory from the report
~~~
cov-format-errors --dir . --file "source" --exclude-files '(/build/|/test/)' --html-output html-out;
~~~
7. Format the errors in JSON format to perform a jq query to get a simplified list of any exceptions.
NOTE: A blank output means there are no defects that aren't being suppressed by the config or inline comments.
~~~
cov-format-errors --dir . --file "source" --exclude-files '(/build/|/test/)' --json-output-v2 defects.json;
echo -e "\n-------------------------Non-Suppresed Deviations, if any, Listed Below-------------------------\n";
jq '.issues[] | .events[] | .eventTag ' defects.json | sort | uniq -c | sort -nr;
echo -e "\n-------------------------Non-Suppresed Deviations, if any, Listed Above-------------------------\n";
~~~
For your convenience the commands above are below to be copy/pasted into a UNIX command friendly terminal.
~~~
cov-configure --force --compiler cc --comptype gcc;
cmake -B build -S test;
cd build/;
cov-build --emit-complementary-info --dir cov-out make coverity_analysis;
cd cov-out/
cov-analyze --dir . --coding-standard-config ../../tools/coverity/misra.config;
cov-format-errors --dir . --file "source" --exclude-files '(/build/|/test/)' --html-output html-out;
cov-format-errors --dir . --file "source" --exclude-files '(/build/|/test/)' --json-output-v2 defects.json;
echo -e "\n-------------------------Non-Suppresed Deviations, if any, Listed Below-------------------------\n";
jq '.issues[] | .events[] | .eventTag ' defects.json | sort | uniq -c | sort -nr;
echo -e "\n-------------------------Non-Suppresed Deviations, if any, Listed Above-------------------------\n";
cd ../../;
~~~
You should now have the HTML formatted violations list in a directory named `build/cov-out/html-output`.
With the current configuration and the provided project, you should not see any deviations.

View File

@ -0,0 +1,26 @@
// MISRA C-2012 Rules
{
version : "2.0",
standard : "c2012",
title: "Coverity MISRA Configuration",
deviations : [
// Disable the following rules.
{
deviation: "Directive 4.9",
reason: "Allow inclusion of function like macros. Logging is done using function like macros."
},
{
deviation: "Rule 2.4",
reason: "Allow unused tags. Some compilers warn if types are not tagged."
},
{
deviation: "Rule 3.1",
reason: "Allow nested comments. Documentation blocks contain comments for example code."
},
{
deviation: "Rule 8.7",
reason: "API functions are not used by library. They must be externally visible in order to be used by the application."
},
]
}

View File

@ -0,0 +1,70 @@
# Taken from amazon-freertos repository
cmake_minimum_required(VERSION 3.13)
set(BINARY_DIR ${CMAKE_BINARY_DIR})
# reset coverage counters
execute_process(
COMMAND lcov --directory ${CMAKE_BINARY_DIR}
--base-directory ${CMAKE_BINARY_DIR}
--zerocounters
COMMAND mkdir -p ${CMAKE_BINARY_DIR}/coverage
)
# make the initial/baseline capture a zeroed out files
execute_process( COMMAND lcov --directory ${CMAKE_BINARY_DIR}
--base-directory ${CMAKE_BINARY_DIR}
--initial
--capture
--rc lcov_branch_coverage=1
--rc genhtml_branch_coverage=1
--output-file=${CMAKE_BINARY_DIR}/base_coverage.info
)
file(GLOB files "${CMAKE_BINARY_DIR}/bin/tests/*")
set(REPORT_FILE ${CMAKE_BINARY_DIR}/utest_report.txt)
file(WRITE ${REPORT_FILE} "")
# execute all files in bin directory, gathering the output to show it in CI
foreach(testname ${files})
get_filename_component(test
${testname}
NAME_WLE
)
message("Running ${testname}")
execute_process(COMMAND ${testname} OUTPUT_FILE ${CMAKE_BINARY_DIR}/${test}_out.txt)
file(READ ${CMAKE_BINARY_DIR}/${test}_out.txt CONTENTS)
file(APPEND ${REPORT_FILE} "${CONTENTS}")
endforeach()
# generate Junit style xml output
execute_process(COMMAND ruby
${UNITY_DIR}/auto/parse_output.rb
-xml ${REPORT_FILE}
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
)
# capture data after running the tests
execute_process(
COMMAND lcov --capture
--rc lcov_branch_coverage=1
--rc genhtml_branch_coverage=1
--base-directory ${CMAKE_BINARY_DIR}
--directory ${CMAKE_BINARY_DIR}
--output-file ${CMAKE_BINARY_DIR}/second_coverage.info
)
# combile baseline results (zeros) with the one after running the tests
execute_process(
COMMAND lcov --base-directory ${CMAKE_BINARY_DIR}
--directory ${CMAKE_BINARY_DIR}
--add-tracefile ${CMAKE_BINARY_DIR}/base_coverage.info
--add-tracefile ${CMAKE_BINARY_DIR}/second_coverage.info
--output-file ${CMAKE_BINARY_DIR}/coverage.info
--no-external
--rc lcov_branch_coverage=1
)
execute_process(
COMMAND genhtml --rc lcov_branch_coverage=1
--branch-coverage
--output-directory ${CMAKE_BINARY_DIR}/coverage
${CMAKE_BINARY_DIR}/coverage.info
)

View File

@ -0,0 +1,73 @@
# Taken from amazon-freertos repository
#function to create the test executable
function(create_test test_name
test_src
link_list
dep_list
include_list)
include (CTest)
get_filename_component(test_src_absolute ${test_src} ABSOLUTE)
add_custom_command(OUTPUT ${test_name}_runner.c
COMMAND ruby
${UNITY_DIR}/auto/generate_test_runner.rb
${MODULE_ROOT_DIR}/tools/unity/project.yml
${test_src_absolute}
${test_name}_runner.c
DEPENDS ${test_src}
)
add_executable(${test_name} ${test_src} ${test_name}_runner.c)
set_target_properties(${test_name} PROPERTIES
COMPILE_FLAG "-O0 -ggdb"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/tests"
INSTALL_RPATH_USE_LINK_PATH TRUE
LINK_FLAGS " \
-Wl,-rpath,${CMAKE_BINARY_DIR}/lib \
-Wl,-rpath,${CMAKE_CURRENT_BINARY_DIR}/lib"
)
target_include_directories(${test_name} PUBLIC
${include_list}
)
target_link_directories(${test_name} PUBLIC
${CMAKE_CURRENT_BINARY_DIR}
)
# link all libraries sent through parameters
foreach(link IN LISTS link_list)
target_link_libraries(${test_name} ${link})
endforeach()
# add dependency to all the dep_list parameter
foreach(dependency IN LISTS dep_list)
add_dependencies(${test_name} ${dependency})
target_link_libraries(${test_name} ${dependency})
endforeach()
target_link_libraries(${test_name} -lgcov unity)
target_link_directories(${test_name} PUBLIC
${CMAKE_CURRENT_BINARY_DIR}/lib
)
add_test(NAME ${test_name}
COMMAND ${CMAKE_BINARY_DIR}/bin/tests/${test_name}
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
)
endfunction()
function(create_real_library target
src_file
real_include_list)
add_library(${target} STATIC
${src_file}
)
target_include_directories(${target} PUBLIC
${real_include_list}
)
set_target_properties(${target} PROPERTIES
COMPILE_FLAGS "-Wextra -Wpedantic \
-fprofile-arcs -ftest-coverage -fprofile-generate \
-Wno-unused-but-set-variable"
LINK_FLAGS "-fprofile-arcs -ftest-coverage \
-fprofile-generate "
ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/lib
)
endfunction()

View File

@ -0,0 +1,12 @@
:unity:
:when_no_prototypes: :warn
:enforce_strict_ordering: TRUE
:treat_as:
uint8: HEX8
uint16: HEX16
uint32: UINT32
int8: INT8
bool: UINT8
:treat_externs: :exclude
:weak: __attribute__((weak))
:treat_externs: :include

View File

@ -0,0 +1,5 @@
[{000214A0-0000-0000-C000-000000000046}]
Prop3=19,11
[InternetShortcut]
IDList=
URL=https://www.freertos.org/logging.html

View File

@ -0,0 +1,52 @@
/*
* FreeRTOS V202212.01
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/
#ifndef DEMO_LOGGING_H
#define DEMO_LOGGING_H
#include "FreeRTOS.h"
/*
* Initialize a logging system that can be used from FreeRTOS tasks and Win32
* threads. Do not call printf() directly while the scheduler is running.
*
* Set xLogToStdout, xLogToFile and xLogToUDP to either pdTRUE or pdFALSE to
* lot to stdout, a disk file and a UDP port respectively.
*
* If xLogToUDP is pdTRUE then ulRemoteIPAddress and usRemotePort must be set
* to the IP address and port number to which UDP log messages will be sent.
*/
void vLoggingInit( BaseType_t xLogToStdout,
BaseType_t xLogToFile,
BaseType_t xLogToUDP,
uint32_t ulRemoteIPAddress,
uint16_t usRemotePort );
void vPlatformInitLogging(void);
void vLoggingPrintf(const char* pcFormat, ...);
#endif /* DEMO_LOGGING_H */

View File

@ -0,0 +1,113 @@
/*
* FreeRTOS V202212.01
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
* https://aws.amazon.com/freertos
*
*/
/**
* @file logging_levels.h
* @brief Defines the configuration constants for all logging verbosity levels.
*/
#ifndef LOGGING_LEVELS_H
#define LOGGING_LEVELS_H
/**
* @constantspage{logging,logging library}
*
* @section logging_constants_levels Log levels
* @brief Log levels for the libraries in this SDK.
*
* Each library should specify a log level by setting @ref LIBRARY_LOG_LEVEL.
* All log messages with a level at or below the specified level will be printed
* for that library.
*
* Currently, there are 4 log levels. In the order of lowest to highest, they are:
* - #LOG_NONE <br>
* @copybrief LOG_NONE
* - #LOG_ERROR <br>
* @copybrief LOG_ERROR
* - #LOG_WARN <br>
* @copybrief LOG_WARN
* - #LOG_INFO <br>
* @copybrief LOG_INFO
* - #LOG_DEBUG <br>
* @copybrief LOG_DEBUG
*/
/**
* @brief No log messages.
*
* When @ref LIBRARY_LOG_LEVEL is #LOG_NONE, logging is disabled and no
* logging messages are printed.
*/
#define LOG_NONE 0
/**
* @brief Represents erroneous application state or event.
*
* These messages describe the situations when a library encounters an error from
* which it cannot recover.
*
* These messages are printed when @ref LIBRARY_LOG_LEVEL is defined as either
* of #LOG_ERROR, #LOG_WARN, #LOG_INFO or #LOG_DEBUG.
*/
#define LOG_ERROR 1
/**
* @brief Message about an abnormal event.
*
* These messages describe the situations when a library encounters
* abnormal event that may be indicative of an error. Libraries continue
* execution after logging a warning.
*
* These messages are printed when @ref LIBRARY_LOG_LEVEL is defined as either
* of #LOG_WARN, #LOG_INFO or #LOG_DEBUG.
*/
#define LOG_WARN 2
/**
* @brief A helpful, informational message.
*
* These messages describe normal execution of a library. They provide
* the progress of the program at a coarse-grained level.
*
* These messages are printed when @ref LIBRARY_LOG_LEVEL is defined as either
* of #LOG_INFO or #LOG_DEBUG.
*/
#define LOG_INFO 3
/**
* @brief Detailed and excessive debug information.
*
* Debug log messages are used to provide the
* progress of the program at a fine-grained level. These are mostly used
* for debugging and may contain excessive information such as internal
* variables, buffers, or other specific information.
*
* These messages are only printed when @ref LIBRARY_LOG_LEVEL is defined as
* #LOG_DEBUG.
*/
#define LOG_DEBUG 4
#endif /* ifndef LOGGING_LEVELS_H */

View File

@ -0,0 +1,132 @@
/*
* FreeRTOS V202212.01
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/
/**
* @file logging_stack.h
* @brief Utility header file that exposes macros for configuring logging implementation of logging macros (LogError, LogWarn, LogInfo, LogDebug).
*/
#ifndef LOGGING_STACK_H
#define LOGGING_STACK_H
/* Include header for logging level macros. */
#include "logging_levels.h"
#include "logging.h"
/* Standard Include. */
#include <stdio.h>
#include <stdint.h>
/**
* @brief The name of the library or demo to add as metadata in log messages
* from the library or demo.
*
* This metadata aids in identifying the module source of log messages.
* The metadata is logged in the format `[ <LIBRARY-NAME> ]` as a prefix to the
* log messages.
* Refer to #LOG_METADATA_FORMAT for the complete format of the metadata prefix in
* log messages.
*/
/* Check if LIBRARY_LOG_NAME macro has been defined. */
#if !defined( LIBRARY_LOG_NAME )
#error "Please define LIBRARY_LOG_NAME for the library."
#endif
/* Metadata information to prepend to every log message. */
#ifndef LOG_METADATA_FORMAT
#define LOG_METADATA_FORMAT "[%s:%d] " /**< @brief Format of metadata prefix in log messages. */
#endif
#ifndef LOG_METADATA_ARGS
#define LOG_METADATA_ARGS __FUNCTION__, __LINE__ /**< @brief Arguments into the metadata logging prefix format. */
#endif
/**
* @brief Common macro that maps all the logging interfaces,
* (#LogDebug, #LogInfo, #LogWarn, #LogError) to the platform-specific logging
* function.
*
* @note The default definition of this macro generates logging via a printf-like
* vLoggingPrintf function.
*/
#ifndef SdkLog
#define SdkLog( message ) vLoggingPrintf message
#endif
/**
* Disable definition of logging interface macros when generating doxygen output,
* to avoid conflict with documentation of macros at the end of the file.
*/
/* Check that LIBRARY_LOG_LEVEL is defined and has a valid value. */
#if !defined( LIBRARY_LOG_LEVEL ) || \
( ( LIBRARY_LOG_LEVEL != LOG_NONE ) && \
( LIBRARY_LOG_LEVEL != LOG_ERROR ) && \
( LIBRARY_LOG_LEVEL != LOG_WARN ) && \
( LIBRARY_LOG_LEVEL != LOG_INFO ) && \
( LIBRARY_LOG_LEVEL != LOG_DEBUG ) )
#error "Please define LIBRARY_LOG_LEVEL as either LOG_NONE, LOG_ERROR, LOG_WARN, LOG_INFO, or LOG_DEBUG."
#else
#if LIBRARY_LOG_LEVEL == LOG_DEBUG
/* All log level messages will logged. */
#define LogError( message ) SdkLog( ( "[ERROR] [%s] "LOG_METADATA_FORMAT, LIBRARY_LOG_NAME, LOG_METADATA_ARGS ) ); SdkLog( message ); SdkLog( ( "\r\n" ) )
#define LogWarn( message ) SdkLog( ( "[WARN] [%s] "LOG_METADATA_FORMAT, LIBRARY_LOG_NAME, LOG_METADATA_ARGS ) ); SdkLog( message ); SdkLog( ( "\r\n" ) )
#define LogInfo( message ) SdkLog( ( "[INFO] [%s] "LOG_METADATA_FORMAT, LIBRARY_LOG_NAME, LOG_METADATA_ARGS ) ); SdkLog( message ); SdkLog( ( "\r\n" ) )
#define LogDebug( message ) SdkLog( ( "[DEBUG] [%s] "LOG_METADATA_FORMAT, LIBRARY_LOG_NAME, LOG_METADATA_ARGS ) ); SdkLog( message ); SdkLog( ( "\r\n" ) )
#elif LIBRARY_LOG_LEVEL == LOG_INFO
/* Only INFO, WARNING and ERROR messages will be logged. */
#define LogError( message ) SdkLog( ( "[ERROR] [%s] "LOG_METADATA_FORMAT, LIBRARY_LOG_NAME, LOG_METADATA_ARGS ) ); SdkLog( message ); SdkLog( ( "\r\n" ) )
#define LogWarn( message ) SdkLog( ( "[WARN] [%s] "LOG_METADATA_FORMAT, LIBRARY_LOG_NAME, LOG_METADATA_ARGS ) ); SdkLog( message ); SdkLog( ( "\r\n" ) )
#define LogInfo( message ) SdkLog( ( "[INFO] [%s] "LOG_METADATA_FORMAT, LIBRARY_LOG_NAME, LOG_METADATA_ARGS ) ); SdkLog( message ); SdkLog( ( "\r\n" ) )
#define LogDebug( message )
#elif LIBRARY_LOG_LEVEL == LOG_WARN
/* Only WARNING and ERROR messages will be logged.*/
#define LogError( message ) SdkLog( ( "[ERROR] [%s] "LOG_METADATA_FORMAT, LIBRARY_LOG_NAME, LOG_METADATA_ARGS ) ); SdkLog( message ); SdkLog( ( "\r\n" ) )
#define LogWarn( message ) SdkLog( ( "[WARN] [%s] "LOG_METADATA_FORMAT, LIBRARY_LOG_NAME, LOG_METADATA_ARGS ) ); SdkLog( message ); SdkLog( ( "\r\n" ) )
#define LogInfo( message )
#define LogDebug( message )
#elif LIBRARY_LOG_LEVEL == LOG_ERROR
/* Only ERROR messages will be logged. */
#define LogError( message ) SdkLog( ( "[ERROR] [%s] "LOG_METADATA_FORMAT, LIBRARY_LOG_NAME, LOG_METADATA_ARGS ) ); SdkLog( message ); SdkLog( ( "\r\n" ) )
#define LogWarn( message )
#define LogInfo( message )
#define LogDebug( message )
#else /* if LIBRARY_LOG_LEVEL == LOG_ERROR */
#define LogError( message )
#define LogWarn( message )
#define LogInfo( message )
#define LogDebug( message )
#endif /* if LIBRARY_LOG_LEVEL == LOG_ERROR */
#endif /* if !defined( LIBRARY_LOG_LEVEL ) || ( ( LIBRARY_LOG_LEVEL != LOG_NONE ) && ( LIBRARY_LOG_LEVEL != LOG_ERROR ) && ( LIBRARY_LOG_LEVEL != LOG_WARN ) && ( LIBRARY_LOG_LEVEL != LOG_INFO ) && ( LIBRARY_LOG_LEVEL != LOG_DEBUG ) ) */
#endif /* ifndef LOGGING_STACK_H */

View File

@ -0,0 +1,14 @@
Directories:
+ Utilities/backoff_algorithm contains a utility that calculates an
exponential back off time, with some jitter. It is used to ensure fleets of
IoT devices that become disconnected don't all try and reconnect at the same
time.
+ Utilities/logging contains header files for use with the core libraries logging
macros. See https://www.FreeRTOS.org/logging.html.
+ Utililties/mbedtls_freertos contains a few FreeRTOS specifics required by
mbedTLS.