Squashed 'features/nanostack/FEATURE_NANOSTACK/sal-stack-nanostack/' content from commit 8f75e39

git-subtree-dir: features/nanostack/FEATURE_NANOSTACK/sal-stack-nanostack
git-subtree-split: 8f75e39541f1d2c7fe47406cceeb187b6bc5d6cc
pull/5511/head
Arto Kinnunen 2017-11-16 15:45:42 +02:00
commit 0c2a41eb55
1161 changed files with 203929 additions and 0 deletions

3
.gitattributes vendored Normal file
View File

@ -0,0 +1,3 @@
* text=auto
*.uvproj eol=lf
*.uvmpw eol=lf

73
.gitignore vendored Normal file
View File

@ -0,0 +1,73 @@
.settings/
.yotta.json
*.dep
*.htm
*.crf
*.ewd
*.ewt
bin/
*Debug/
*DEBUG/
*_debug/
gcov/
*Release/
*RELEASE/
*_release/
riliisi/
/output/
Output/
objs/
path.txt
jlink.config
settings/
*.bin
*.hex
*.elf
*.srec
*.eep
*.o
*.d
*.a
*.zip
*.tmp
Backup *
*.__i
*.pbi
*.cout
*.pbd.*
*.pbd
*.lst
*.Scr
*.uvgui.*
*.uvgui_*
*.log
*.lss
*.map
*.lib
*.uvopt
*.sim
*.out
*.atsuo
*.s37
*.S37
*.r43
*.r90
.tags_sorted_by_file
cscope.files
.tags
*~
*.c.orig
*.h.orig
*.axf
*.iex
*.sct
*.lnp
*.ini
!debugger.ini
*Log.txt
*.mpw
yotta_modules
yotta_targets
build
html
site

0
.gitmodules vendored Normal file
View File

5
.mbedignore Normal file
View File

@ -0,0 +1,5 @@
test/*
unittest/*
release/*
source/Service_Libs/CCM_lib/mbedOS/aes_mbedtls.c
output/*

11
DOXYGEN_FRONTPAGE.md Normal file
View File

@ -0,0 +1,11 @@
ARM mbed Networking Stack
=========================
## Introduction
This is Doxygen generated documentation of Nanostack.
It should be used in conjunction with [ARM mbed Networking Stack](https://docs.mbed.com/docs/arm-ipv66lowpan-stack/en/latest/) manual
hosted in http://docs.mbed.com
# API documentation
See [Files](files.html) section to find a documentation about specific api.

2332
Doxyfile Normal file

File diff suppressed because it is too large Load Diff

290
Jenkinsfile vendored Normal file
View File

@ -0,0 +1,290 @@
// Compiler:target pairs for assigning yotta builds to correct slave labels
def yottaTargets = [
armcc : "frdm-k64f-armcc",
gcc : "frdm-k64f-gcc"
]
def morpheusTargets = [
armcc: "K64F",
gcc : "K64F"
]
// Compilers for makefile based build steps
def makeCompilers = [
"armcc",
"gcc",
"arm-none-eabi-gcc"
]
// Nanostack configurations for makefile based build steps
def makeConfigs = [
"generic",
"lowpan_border_router",
"lowpan_border_router_rf_tunnel",
"lowpan_host",
"lowpan_router",
"nanostack_full",
"rf_interface",
"thread_border_router",
"thread_router",
"thread_end_device",
"thread_full_end_device",
"thread_thci"
]
/*****************************************************
* *
* Check out sources only once and use stash/unstash *
* to distribute source to actual builds *
* *
****************************************************/
node ("linux") {
stage "checkout"
// deleteDir deletes recursively current directory
deleteDir()
// Recursively clone ARMmbed/nanomesh-applications repository
checkoutApplications()
// After cloning nanomesh-applications we need to clean and
// re-clone nanostack with the changes under test
dir ("applications") {
sh "rm -rf nanostack && mkdir nanostack"
dir("nanostack") {
// Check out current branch with changes under test
checkout scm
}
}
// Check if these variables are available
echo "source branch: ${env.BRANCH_NAME}\n"
echo "target branch: ${env.CHANGE_TARGET}\n"
echo "change id: ${env.CHANGE_ID}\n"
echo "change title: ${env.CHANGE_TITLE}\n"
echo "change url: ${env.CHANGE_URL}\n"
echo "git revision: ${env.GIT_REVISION}\n"
// Stash stores a set of files for use later in the same build
stash includes: '**', useDefaultExcludes: false, name: 'workarea'
}
/**********************************************
* *
* Create step definitions for parallel *
* build execution *
* *
*********************************************/
def stepsForParallel = [:]
// Add yotta build steps to parallel execution
for (int i = 0; i < yottaTargets.size(); i++) {
def compiler = yottaTargets.keySet().asList().get(i)
def target = yottaTargets.get(compiler)
def stepName = "yotta ${target}"
stepsForParallel[stepName] = yottaBuildStep(compiler, target)
}
// Add morpheus build steps to parallel execution
/* Not yet
for (int i = 0; i < morpheusTargets.size(); i++) {
def compiler = morpheusTargets.keySet().asList().get(i)
def target = morpheusTargets.get(compiler)
def stepName = "morpheus ${target}"
stepsForParallel[stepName] = morpheusBuildStep(compiler, target)
}
*/
// Add makefile build steps to parallel execution
for (int i = 0; i < makeCompilers.size(); i++) {
for (int j = 0; j < makeConfigs.size(); j++) {
def compiler = makeCompilers.get(i)
def config = makeConfigs.get(j)
def stepName = "${compiler} ${config}"
stepsForParallel[stepName] = makeBuildStep(compiler, config)
}
}
// Add smoketest step to parallel execution
stepsForParallel["smokeTest"] = smokeTestStep()
/**********************************************
* *
* Actually run the steps in parallel *
* *
*********************************************/
stage "build"
parallel stepsForParallel
/**********************************************
* *
* End of execution, internal functions below *
* *
*********************************************/
// Create build step for morpheus
def morpheusBuildStep(compiler, target) {
return {
node ("${compiler}") {
deleteDir()
unstash 'workarea'
dir ("applications/nanostack") {
if("${compiler}" == "armcc") {
sh "mbed compile -m ${target} -t ARM -c"
}
if("${compiler}" == "gcc") {
sh "mbed compile -m ${target} -t GCC_ARM -c"
}
}
}
}
}
// Create build step definition for yotta build
def yottaBuildStep(compiler, target) {
return {
node ("${compiler}") {
deleteDir()
unstash 'workarea'
dir ("applications/nanostack") {
sh "yotta target ${target}"
sh "yotta build"
}
}
}
}
// Create build step definition for makefile build
def makeBuildStep(compiler, config) {
return {
node ("${compiler}") {
deleteDir()
unstash 'workarea'
dir ("applications") {
sh "make -C libService CC=${compiler} CONFIG=${config} export-headers"
sh "make -C nanostack CC=${compiler} CONFIG=${config}"
}
}
}
}
// Create build step definition for smoke test
def smokeTestStep() {
return {
node ("linux_test") {
deleteDir()
unstash 'workarea'
executeSmokeTest()
executeSmokePostbuild()
}
}
}
// Recursively clone ARMmbed/nanomesh-applications repository
def checkoutApplications() {
// Check out nanomesh-applications master branch and update all submodules
checkout([$class: 'GitSCM',
branches: [[name: '*/master']],
doGenerateSubmoduleConfigurations: false,
extensions: [
[$class: 'RelativeTargetDirectory', relativeTargetDir: 'applications'],
[$class: 'ScmName', name: 'nanomesh-applications'],
[$class: 'SubmoduleOption', disableSubmodules: false, recursiveSubmodules: true, reference: '', trackingSubmodules: true],
[$class: 'LocalBranch', localBranch: '**']
],
submoduleCfg: [],
userRemoteConfigs: [[url: 'git@github.com:ARMmbed/nanomesh-applications.git']]
])
}
def executeSmokeTest() {
dir ("applications") {
sh "make -f Makefile.simulator test-all-builds"
sh "make -f Makefile.simulator"
dir ("mbed-clitest") {
sh "python clitest.py --tcdir testcases/6lowpan --testtype smoke --type simulate --use_sniffer -w --valgrind --valgrind_tool memcheck -v"
dir ("log") {
sh "find . -name \\result.html -execdir mv {} result_6lp_smoke.html \\;"
sh "find . -name \\result_6lp_smoke.html -exec cp {} . \\;"
sh "find . -name \\*valgrind* -exec cp {} . \\;"
sh "find . -name \\result.junit.xml -execdir mv {} result.junit_6lp_smoke.xml \\;"
sh "find . -name \\result.junit_6lp_smoke.xml -exec cp {} . \\;"
}
sh "python clitest.py --group thread --testtype smoke --status released --type simulate -w --valgrind --valgrind_tool memcheck -v"
dir ("log") {
sh "find . -name \\result.html -execdir mv {} result_thread_smoke.html \\;"
sh "find . -name \\result_thread_smoke.html -exec cp {} . \\;"
sh "find . -name \\*valgrind* -exec cp {} . \\;"
sh "find . -name \\result.junit.xml -execdir mv {} result.junit_thread_smoke.xml \\;"
sh "find . -name \\result.junit_thread_smoke.xml -exec cp {} . \\;"
}
}
dir ("nanostack") {
sh "make CC=cppcheck CPPCHECK_OPTS=\"--xml --xml-version=2 2> cppcheck.xml\""
sh "sed -i 's%\\(<location file=\"\\)%\\1nanomesh-applications/nanostack/%' cppcheck.xml"
}
}
}
def executeSmokePostbuild() {
// Archive artifacts
archive 'applications/nanostack/cppcheck.xml, applications/mbed-clitest/log/**/*'
// Publish HTML reports
publishHTML(target: [allowMissing: false, alwaysLinkToLastBuild: false, keepAll: false,
reportDir: 'applications/mbed-clitest/log/',
reportFiles: 'result_6lp_smoke.html, result_thread_smoke.html',
reportName: 'Test Results'])
// Publish JUnit test result report
step([$class: 'JUnitResultArchiver', testResults: 'applications/mbed-clitest/log/result.junit*.xml'])
// This version of plugin currently only on AWS test Jenkins
/*
step([$class: 'TextFinderPublisher',
fileSet: 'applications/mbed-clitest/log/result*.html',
regexp: 'fail<',
alsoCheckConsoleOutput: false,
succeedIfFound: false,
unstableIfFound: true
])
*/
// This version of plugin currently only on AWS test Jenkins
/*
step([$class: 'CppcheckPublisher',
pattern: 'applications/nanostack/cppcheck.xml',
allowNoReport: true, ignoreBlankFiles: false,
threshold: "", newThreshold: "",
failureThreshold: "", newFailureThreshold: "",
healthy: "", unHealthy: "",
severityError: true, severityWarning: true,
severityStyle: true, severityPerformance: true,
severityInformation: true, severityNoCategory: true,
severityPortability: true,
xSize: 500, ySize: 200, numBuildsInGraph: 10,
displayAllErrors: true,
displayErrorSeverity: false, displayWarningSeverity: false,
displayStyleSeverity: false, displayPerformanceSeverity: false,
displayInformationSeverity: false, displayNoCategorySeverity: false,
displayPortabilitySeverity: false
])
*/
// This version of plugin currently only on AWS test Jenkins
/*
step([$class: 'ValgrindPublisher',
pattern: "applications/mbed-clitest/log/*valgrind*.xml",
failThresholdInvalidReadWrite: "",
failThresholdDefinitelyLost: "",
failThresholdTotal: "",
unstableThresholdInvalidReadWrite: "",
unstableThresholdDefinitelyLost: "8",
unstableThresholdTotal: "",
publishResultsForAbortedBuilds: true,
publishResultsForFailedBuilds: true,
failBuildOnMissingReports: false,
failBuildOnInvalidReports: false
])
*/
}

67
LICENSE-Apache-2.0 Normal file
View File

@ -0,0 +1,67 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
2. Grant of Copyright License.
Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
3. Grant of Patent License.
Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
4. Redistribution.
You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
You must give any other recipients of the Work or Derivative Works a copy of this License; and
You must cause any modified files to carry prominent notices stating that You changed the files; and
You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
5. Submission of Contributions.
Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
6. Trademarks.
This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty.
Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
8. Limitation of Liability.
In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability.
While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS

25
LICENSE-BSD-3-Clause Normal file
View File

@ -0,0 +1,25 @@
Copyright 2017 Arm Limited and affiliates.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

196
Makefile Normal file
View File

@ -0,0 +1,196 @@
#
# Makefile for NanoStack
#
# Define compiler toolchain with CC variable
# Example (GCC toolchains, default $CC and $AR are used)
# make
#
# OR (armcc/Keil)
# make CC=armcc AR=ArmAR
#
# OR (IAR-ARM)
# make CC=iccarm
LIB = libnanostack.a
# If configuration is not specified, use generic
ifeq (,$(CONFIG))
CONFIG=generic
endif
include sources.mk
include include_dirs.mk
override CFLAGS += -DNSCONFIG=$(CONFIG)
COAP_SERVICE_LIB := ../coap-service
SERVLIB_DIR := ../libService
EVENTLOOP_DIR := ../event-loop
NSDL_DIR := ../nsdl-c
COAP_DIR := ../mbed-coap
MDNS_DIR := source/Service_Libs/mdns
MDNS_SRV_DIR := source/Service_Libs/mdns/fnet/fnet_stack/services
MBEDTLS_DIR := ../mbedtls
override CFLAGS += -I$(MDNS_DIR) -I$(MDNS_DIR)/fnet -I$(MDNS_DIR)/fnet/fnet_stack -I$(MDNS_DIR)/fnet/fnet_stack/stack
override CFLAGS += -I$(MDNS_SRV_DIR) -I$(MDNS_SRV_DIR)/poll -I$(MDNS_SRV_DIR)/mdns -I$(MDNS_SRV_DIR)/serial
override CFLAGS += -I$(SERVLIB_DIR)/libService
override CFLAGS += -I$(EVENTLOOP_DIR)/nanostack-event-loop
override CFLAGS += -I$(NSDL_DIR)/nsdl-c
override CFLAGS += -I$(COAP_DIR)
override CFLAGS += -I$(COAP_SERVICE_LIB)/coap-service
override CFLAGS += -I$(MBEDTLS_DIR)/include
override CFLAGS += $(addprefix -I,$(INCLUDE_DIRS))
override CFLAGS += $(addprefix -D,$(FLAGS))
#
# Define compiler toolchain
#
include ../libService/toolchain_rules.mk
$(eval $(call generate_rules,$(LIB),$(SRCS)))
.PHONY: $(LIB)
# Extend default clean rule
clean: clean-extra
TEST_FOLDER := ./test/
UNITTESTS := $(sort $(dir $(wildcard $(TEST_FOLDER)*/unittest/*)))
TESTDIRS := $(UNITTESTS:%=build-%)
CLEANTESTDIRS := $(UNITTESTS:%=clean-%)
COVERAGEFILE := ./lcov/coverage.info
$(TESTDIRS):
@make -C $(@:build-%=%)
$(CLEANTESTDIRS):
@make -C $(@:clean-%=%) clean
.PHONY: release
release:
7z a nanostack_$(VERSION).zip *.a *.lib include
.PHONY: deploy_to
deploy_to: all
tar --transform 's,^,nanostack/,' --append -f $(TO) *.a
.PHONY: test
test: $(TESTDIRS)
@rm -rf lcov
@rm -rf results
@mkdir -p lcov
@mkdir -p results
@./xsl_script.sh
@cp junit_xsl.xslt results/.
@xsltproc -o results/index.html results/junit_xsl.xslt results/index.xml
@lcov -d test/. -c -o $(COVERAGEFILE)
@lcov -q -r $(COVERAGEFILE) "/usr*" -o $(COVERAGEFILE)
@lcov -q -r $(COVERAGEFILE) "/test*" -o $(COVERAGEFILE)
@lcov -q -r $(COVERAGEFILE) "/libService*" -o $(COVERAGEFILE)
@genhtml -q $(COVERAGEFILE) --show-details --prefix $(CURDIR:%/applications/nanostack=%) --output-directory lcov
@echo Nanostack unit tests built, see results/index.html and lcov/index.html
@sed -n 's/.*\(failures: [0-9]\+\).*/\1/p' results/index.html
clean-extra: $(CLEANTESTDIRS)
@rm -rf lcov/
#
# Releasing the binary for mbed module
#
# This must be runned from fully cloned Nanomesh application repository
# with all submodules.
#
# 1. `make mbed-release-build`
# You can also separate this step per toolchain:
# `make mbed-release-build-GCC`
# `make mbed-release-build-ARM`
# `make mbed-release-build-IAR`
# 2. `make mbed-release`
# 3. TBD: importing to mbed OS
TARGET_DIR:=release
CONFIGURATIONS_TO_BUILD:=lowpan_border_router lowpan_host lowpan_router nanostack_full thread_border_router thread_router thread_end_device ethernet_host
TOOLCHAINS_TO_BUILD:=GCC ARM ARMC6 IAR
CORES_TO_BUILD:=Cortex-M0 Cortex-M3
CC_GCC:=arm-none-eabi-gcc
CC_ARM:=armcc
CC_ARMC6=armclang
CC_IAR:=iccarm
LIB_SUFFIX_GCC:=a
LIB_SUFFIX_ARM:=ar
LIB_SUFFIX_ARMC6:=ar
LIB_SUFFIX_IAR:=a
.PHONY: mbed-release
mbed-release: mbed-release-copy
cd release; git add -A
(TAG=$$(git describe --tag); cd release; git commit -m "$$TAG")
git add release; git commit -m "Update release pointer"
.PHONY: mbed-release-copy
mbed-release-copy: mbed-release-pre-clean
cp mbed_lib.json $(TARGET_DIR)
cp -r nanostack $(TARGET_DIR)
cp -r docs README.md $(TARGET_DIR)
cp -r Doxyfile DOXYGEN_FRONTPAGE.md doxygen $(TARGET_DIR)
cp mkdocs.yml $(TARGET_DIR)
cp binary_release_template_lisense $(TARGET_DIR)/LICENSE
cp binary_release_template_lisense_txt $(TARGET_DIR)/LICENSE-permissive-binary-license-1.0.txt
for header in `find release/nanostack -name \*.h`;do awk 'BEGIN{found=0;}{if(!found){print >"tmp-head";}else{print >"tmp-tail"}}/Copyright/{found=1;}' $$header; cat tmp-head binary_release_template_header tmp-tail > tmp && mv tmp $$header; rm tmp-head tmp-tail; done
# Template for generating rules for all configuration options
# $(1) is Toolchain, GCC, ARM or IAR
# $(2) is Configuration
# $(3) is CPU variant
#
# Here be dragons... This is dangerous territory. Touch only if you have a beard.
#
define mbed-rel-build-template
mbed-release-build: $(1)-$(2)-$(3)-build
mbed-release-build-$(1): $(1)-$(2)-$(3)-build
.PHONY: $(1)-$(2)-build
$(1)-$(2)-$(3)-build: export-headers
@echo Build $(2) on $(1) for $(3)
make CC=$(CC_$(1)) CONFIG=$(2) CPU=$(3) APPEND_LIB_NAME=1 CFLAGS="-DNS_USE_EXTERNAL_MBED_TLS -I../mbedtls/include/"
# Generate target directory name
# Like: FEATURE_NANOSTACK/FEATURE_LOWPAN_ROUTER/TOOLCHAIN_ARM/TARGET_CORTEX_M0P
$(1)-$(2)-$(3)-target-dir:=$(TARGET_DIR)/FEATURE_$(shell echo $(2) | tr '[:lower:]' '[:upper:]')/TOOLCHAIN_$(1)/TARGET_$(shell echo $(3) | tr '[:lower:]' '[:upper:]' | tr - _ | sed 's/CORTEX_//')
# Cortex-M3 is also used for M4...M7, there is alias for them
ifeq (Cortex-M3,$(3))
$(1)-$(2)-$(3)-alt-target-dir:=$(TARGET_DIR)/FEATURE_$(shell echo $(2) | tr '[:lower:]' '[:upper:]')/TOOLCHAIN_$(1)/TARGET_RTOS_M4_M7
endif
# M0 is used as M0 and M0+. There is alias for them
ifeq (Cortex-M0,$(3))
$(1)-$(2)-$(3)-target-dir:=$(TARGET_DIR)/FEATURE_$(shell echo $(2) | tr '[:lower:]' '[:upper:]')/TOOLCHAIN_$(1)/TARGET_LIKE_CORTEX_M0
endif
mbed-release-copy: $(1)-$(2)-$(3)-copy
$(1)-$(2)-$(3)-copy: mbed-release-pre-clean
mkdir -p $$($(1)-$(2)-$(3)-target-dir)
cp libnanostack_$(CC_$(1))_$(3)_$(2).* $$($(1)-$(2)-$(3)-target-dir)/libnanostack.$(LIB_SUFFIX_$(1))
ifneq (,$$($(1)-$(2)-$(3)-alt-target-dir))
mkdir -p $$($(1)-$(2)-$(3)-alt-target-dir)
cp libnanostack_$(CC_$(1))_$(3)_$(2).* $$($(1)-$(2)-$(3)-alt-target-dir)/libnanostack.$(LIB_SUFFIX_$(1))
endif
endef
# Now generate rules
$(foreach tool,$(TOOLCHAINS_TO_BUILD),$(foreach cpu,$(CORES_TO_BUILD),$(foreach cfg,$(CONFIGURATIONS_TO_BUILD),$(eval $(call mbed-rel-build-template,$(tool),$(cfg),$(cpu))))))
#
# End of dangerous territory
#
# Run export-headers before build
.PHONY: export-headers
export-headers:
make -C ../ -f build_external_libs.mk export-headers
.PHONY: mbed-release-pre-clean
mbed-release-pre-clean:
rm -rf $(TARGET_DIR)/*
.PHONY: mbed-release-build
mbed-release-build:
@echo Done

20
NOTICE Normal file
View File

@ -0,0 +1,20 @@
Nanostack contains an open source implementation of the Thread 1.1.1 Final Specification.
The Thread 1.1.1 Final Specification is promulgated by the Thread Group. The Thread
Group is a non-profit organization formed for the purposes of defining one or
more specifications, best practices, reference architectures, implementation
guidelines and certification programs to promote the availability of compliant
implementations of the Thread protocol. Information on becoming a Member, including
information about the benefits thereof, can be found at http://threadgroup.org.
Nanostack is not affiliated with or endorsed by the Thread Group. Implementation
of this Nanostack code does not assure compliance with the Thread 1.1.1 Final
Specification and does not convey the right to identify any final product as Thread
certified. Members of the Thread Group may hold patents and other intellectual
property rights relating to the Thread 1.1.1 Final Specification, ownership and
licenses of which are subject to the Thread Groups IP Policies, and not this license.
The included copyright to the Nanostack code is subject to the license defined in the
README.md file, and all other rights and licenses are expressly reserved.
No warranty or assurance is made with respect to additional rights that may be
required to implement this code.

25
README.md Normal file
View File

@ -0,0 +1,25 @@
ARM IPV6/6LoWPAN stack.
=======================
This repository contains the ARM IPv6/6LoWPAN/Thread Stack for mbed OS.
![](docs/img/thread_certified.png)
mbed OS is now a Thread Certified Component. Using IPv6 with 6LoWPAN as the foundation, Thread technology provides a low-power, self-healing mesh network designed for the home.
The documentation is hosted in http://docs.mbed.com/projects/arm-ipv66lowpan-stack/
On mbed OS, usage is through [mbed Mesh API](https://docs.mbed.com/docs/mbed-os-api-reference/en/latest/APIs/communication/mesh/) and [Socket API](https://docs.mbed.com/docs/mbed-os-api-reference/en/latest/APIs/communication/network_sockets/).
To see, how the 6LoWPAN Stack works, check the example application [mbed-os-example-mesh-minimal](https://github.com/ARMmbed/mbed-os-example-mesh-minimal).
## License
The software is partially provided under a Apache 2.0 license and partially BSD-3-Clause as described below.
This project also contains code from other projects as listed below. The original license text is included in those source files.
* Public header files are provided under Apache 2.0 license.
* Source code excluding Thread protocol, is provided under Apache 2.0
* Source code implementing Thread protocol is provided under BSD-3-Clause
* mDNS library is from FNET project and provided under Apache 2.0 license.

15
doxygen/mainpage.dox Normal file
View File

@ -0,0 +1,15 @@
/** \mainpage ARM mbed Networking Stack
\section intro Introduction
This is Doxygen generated documentation of Nanostack.
It should be used in conjunction with <b>ARM mbed Networking Stack</b> manual
hosted in http://docs.mbed.com
\section apis API documentation
See <b>Files</b> section to find a documentation about specific api.
The <b>Data Structures</b> section should contain documentation for specific
data structures used with stack.
*/

4
include_dirs.mk Normal file
View File

@ -0,0 +1,4 @@
INCLUDE_DIRS := \
nanostack \
source

102
junit_xsl.xslt Normal file
View File

@ -0,0 +1,102 @@
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output encoding="UTF-8" indent="yes" method="html"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="list"
select="document('index.xml')/list" />
<xsl:template match="/">
<h1>
Unittest report
</h1>
<p>
<b>
Total tests run <xsl:value-of select="sum(document($list/entry/@name)/testsuite/@tests)"/>, failures: <xsl:value-of select="sum(document($list/entry/@name)/testsuite/@failures) + sum(document($list/entry/@name)/testsuite/@errors)"/>
</b>
<xsl:for-each select="document($list/entry/@name)" >
<xsl:apply-templates select="testsuite"/>
</xsl:for-each>
</p>
</xsl:template>
<xsl:template match="testsuite">
<h2>
<xsl:value-of select="@name" />
</h2>
<table border="1" cellSpacing="0" cellPadding="10" >
<tr>
<th>Tests run</th>
<th>Tests fail</th>
<th>Other errors</th>
</tr>
<tr>
<td><xsl:value-of select="@tests"/></td>
<td><xsl:value-of select="@failures"/></td>
<td><xsl:value-of select="@errors"/></td>
</tr>
</table>
<br/>
<table border="1" cellSpacing="0" cellPadding="10" >
<tr>
<th>Tests name</th>
<th>PASS/FAIL</th>
<th>Failing case</th>
<th>Reason</th>
</tr>
<xsl:apply-templates select="testcase"/>
</table>
</xsl:template>
<xsl:template match="testcase">
<xsl:choose>
<xsl:when test="failure">
<tr><td><font color="#FF0000"><xsl:value-of select="@name" /></font></td><xsl:apply-templates select="failure"/></tr>
</xsl:when>
<xsl:when test="error">
<tr><td><font color="#FF0000"><xsl:value-of select="@name" /></font></td><xsl:apply-templates select="error"/></tr>
</xsl:when>
<xsl:otherwise>
<tr><td><xsl:value-of select="@name" /></td><td><font color="#00FF00">PASS</font></td><td></td><td></td></tr>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="failure">
<td>
<b><font color="#FF0000">FAILED</font></b>
</td>
<td>
<font color="#ff0000">
<xsl:value-of select="@message" />
</font>
</td>
<td>
<font color="#ff0000">
<xsl:value-of select="@type" />
</font>
</td>
</xsl:template>
<xsl:template match="error">
<td>
<b><font color="#FF0000">FAILED</font></b>
</td>
<td>
<font color="#ff0000">
<xsl:value-of select="@message" />
</font>
</td>
<td>
<font color="#ff0000">
<xsl:value-of select="@type" />
</font>
</td>
</xsl:template>
</xsl:stylesheet>

7
mbed_lib.json Normal file
View File

@ -0,0 +1,7 @@
{
"name": "nanostack",
"config": {
"configuration": "nanostack_full"
},
"macros": ["NS_USE_EXTERNAL_MBED_TLS"]
}

19
nanostack/cca_api.h Normal file
View File

@ -0,0 +1,19 @@
/*
* Copyright (c) 2014-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/** \file cca_api.h \brief Obsolete */
#warning "cca_api.h is obsoleted"

116
nanostack/ccmLIB.h Normal file
View File

@ -0,0 +1,116 @@
/*
* Copyright (c) 2014-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef CCMLIB_H_
#define CCMLIB_H_
#include "ns_types.h"
/**
*
* \file ccmLIB.h
* \brief CCM Library API.
*
* \section ccm-api CCM Library API:
* - ccm_sec_init(), A function to init CCM library.
* - ccm_process_run(), A function to run configured CCM process.
*
* \section ccm-instruction CCM process sequence:
* 1. Init CCM library by, ccm key, ccm_sec_init()
* - security level
* - 128-bit CCM key
* - mode: AES_CCM_ENCRYPT or AES_CCM_DECRYPT
* - CCM L parameter: 2 or 3 depending on the nonce length (802.15.4 use 2 and TLS security use 3)
* 2. Define ADATA pointer and length, if returned global structure mic_len field is > 0
* 3. Set data pointer and length
* 4. Do configured CCM process ccm_process_run()
* 5. Check return value:
* -If 0 Process ok
* -< 0 MIC fail or parameter fail
*
* \section ccm-mutex CCM Mutex for Multi Thread System
* If you are running a multi thread system and the CCM library will be used for multiple thread, do the following:
* 1. Add compiler flag to library build process CCM_USE_MUTEX.
* 2. Define OS-specific mutex at the application.
* 3. Implement arm_ccm_mutex_lock() arm_ccm_mutex_unlock() function for using the generated and initialized mutex.
*/
#ifdef __cplusplus
extern "C" {
#endif
#define AES_NO_SECURITY 0x00 /**< No security */
#define AES_SECURITY_LEVEL_MIC32 0x01 /**< MIC32 */
#define AES_SECURITY_LEVEL_MIC64 0x02 /**< MIC64 */
#define AES_SECURITY_LEVEL_MIC128 0x03 /**< MIC128 */
#define AES_SECURITY_LEVEL_ENC 0x04 /**< ENC */
#define AES_SECURITY_LEVEL_ENC_MIC32 0x05 /**< ENC_MIC32 */
#define AES_SECURITY_LEVEL_ENC_MIC64 0x06 /**< ENC_MIC64 */
#define AES_SECURITY_LEVEL_ENC_MIC128 0x07 /**< ENC_MIC128 */
#define AES_CCM_ENCRYPT 0x00 /**< Encryption mode */
#define AES_CCM_DECRYPT 0x01 /**< Decryption mode */
/**
* \brief A function for locking CCM mutex if the OS is multi thread. If you are using single thread create an empty function.
*/
extern void arm_ccm_mutex_lock(void);
/**
* \brief A function for unlocking CCM mutex if the OS is multi thread. If you are using single thread create an empty function
*/
extern void arm_ccm_mutex_unlock(void);
/*!
* \struct ccm_globals_t
* \brief CCM global structure.
* The structure is used for configuring NONCE, adata and data before calling ccm_process_run().
*/
typedef struct {
uint8_t exp_nonce[15]; /**< CCM NONCE buffer Nonce. */
uint8_t *data_ptr; /**< Pointer to data IN. */
uint16_t data_len; /**< Length of data IN. */
const uint8_t *adata_ptr; /**< Pointer to authentication data. */
uint16_t adata_len; /**< Length of authentication data. */
uint8_t mic_len; /**< ccm_sec_init() sets here the length of MIC. */
uint8_t *mic; /**< Encrypt process writes MIC. Decrypt reads it and compares it with the MIC obtained from data. */
} ccm_globals_t;
/**
* \brief A function to initialize the CCM library.
* \param sec_level Used CCM security level (0-7).
* \param ccm_key Pointer to 128-key.
* \param mode AES_CCM_ENCRYPT or AES_CCM_DECRYPT.
* \param ccm_l Can be 2 or 3. 2 when NONCE length is 13 and 3 when 12. (NONCE length = (15-ccm_l))
*
* \return Pointer to Global CCM parameter buffer.
* \return 0 When parameter fails or CCM is busy.
*/
extern ccm_globals_t *ccm_sec_init(uint8_t sec_level, const uint8_t *ccm_key, uint8_t mode, uint8_t ccm_l);
/**
* \brief A function to run the configured CCM process.
* When AES_CCM_ENCRYPT mode is selected and MIC is needed, the library saves MIC right after the encrypted data.
* \param ccm_params CCM parameters
*
* \return 0 CCM process OK and when AES_CCM_DECRYPT mode was selected also MIC was correct.
* \return -1 Init not called or data or adata pointers or lengths are zero.
* \return -2 Null pointer given to function.
*/
extern int8_t ccm_process_run(ccm_globals_t *ccm_params);
#ifdef __cplusplus
}
#endif
#endif /* CCMLIB_H_ */

View File

@ -0,0 +1,200 @@
/*
* Copyright (c) 2013-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef DHCP_SERVICE_API_H_
#define DHCP_SERVICE_API_H_
#include <ns_types.h>
/**
* \file dhcp_service_api.h
* \brief DHCP server connection interfaces
*
* \section dhcp-service DHCP Service Instance
* - dhcp_service_init(), Initializes a DHCP service.
* - dhcp_service_delete(), Removes the DHCP service.
*
* \section dhcp-msg DHCP Service Messages
* - dhcp_service_send_req(), Sends out DHCP request messages.
* - dhcp_service_send_resp(), Sends out DHCP response messages.
*
* \section dhcp-tim DHCP Service Timers (retry timers)
* - dhcp_service_send_req(), Sends out DHCP request messages.
* - dhcp_service_set_retry_timers(), Sets the retransmission parameters.
* - dhcp_service_req_remove(), Stops retrying and retransmissions.
* - dhcp_service_timer_tick(), Indicates if a timeout occurred.
*
*/
/** Defines Debug Trace String for DHCP service */
#define DHCP_SERVICE_API_TRACE_STR "DHcS"
/*
* Return values for callbacks
*/
/** Message belongs to someone else. */
#define RET_MSG_NOT_MINE 0
/** Message is handled. */
#define RET_MSG_ACCEPTED 1
/** Message is not the final one and needs to hold on a bit. */
#define RET_MSG_WAIT_ANOTHER -1
/** Message is unexpected or corrupted. */
#define RET_MSG_CORRUPTED -2
/** \name DHCP options */
///@{
#define TX_OPT_NONE 0x00 /**< No options. */
#define TX_OPT_USE_SHORT_ADDR 0x01 /**< Use short addresses. */
#define TX_OPT_MULTICAST_HOP_LIMIT_64 0x02 /**< Use multicast hop limit of 64. */
///@}
/**
* /enum dhcp_instance_type
* /brief DHCP instance types.
*/
typedef enum dhcp_instance_type
{
DHCP_INSTANCE_CLIENT,
DHCP_INSTANCE_SERVER
} dhcp_instance_type_e;
/**
* \brief DHCP Service receive callback.
*
* When the DHCP service receives a DHCP message it will go through a list of registered DHCP services instances
* until some instance acknowledges that the message belongs to it.
* \param instance_id An instance of registered server.
* \param msg_tr_id The message transaction ID.
* \param msg_name Message type.
* \param msg_ptr An allocated message pointer. Should not deallocate unless RET_MSG_ACCEPTED returned (then responsibility of client).
* \param msg_len The length of the message.
*
* Return values
* \return RET_MSG_ACCEPTED - Message is handled.
* \return RET_MSG_CORRUPTED - Message is corrupted.
* \return RET_MSG_NOT_MINE - Message belongs to someone else.
*/
typedef int (dhcp_service_receive_req_cb)(uint16_t instance_id, uint32_t msg_tr_id, uint8_t msg_name, uint8_t *msg_ptr, uint16_t msg_len);
/**
* \brief DHCP Service Message Response callback.
*
* When the DHCP service receives a response to a DHCP message, this callback receives it.
*
* \param instance_id An instance of a registered server.
* \param ptr A pointer for the client object.
* \param msg_name Message type.
* \param msg_ptr An allocated message pointer. Should not deallocate unless RET_MSG_ACCEPTED returned (then responsibility of client).
* \param msg_len The length of the message.
*
* Return values
* \return RET_MSG_ACCEPTED - Message is handled
* \return RET_MSG_WAIT_ANOTHER - This message was not the last one for this transaction and a new reply is expected.
*/
typedef int (dhcp_service_receive_resp_cb)(uint16_t instance_id, void *ptr, uint8_t msg_name, uint8_t *msg_ptr, uint16_t msg_len);
/**
* \brief Initialize a new DHCP service instance.
*
* Creates and shares the socket for other DHCP services.
*
* \param interface_id Interface for the new DHCP instance.
* \param instance_type The type of the new DHCP instance.
* \param receive_req_cb A callback function to receive DHCP messages.
*
* \return Instance ID that is used to identify the service.
*/
uint16_t dhcp_service_init(int8_t interface_id, dhcp_instance_type_e instance_type, dhcp_service_receive_req_cb *receive_req_cb);
/**
* \brief Deletes a server instance.
*
* Removes all data related to this instance.
*
* \param instance The instance ID of the registered server.
*/
void dhcp_service_delete(uint16_t instance);
/**
* \brief Sends a DHCP response message.
*
* \param msg_tr_id The message transaction ID.
* \param options Options for this request.
* \param msg_ptr An allocated message pointer. Should not deallocate unless RET_MSG_ACCEPTED returned (then responsibility of client).
* \param msg_len The length of the message.
*
* \return 0, if everything went fine.
* \return -1, if error occurred.
*/
int dhcp_service_send_resp(uint32_t msg_tr_id, uint8_t options, uint8_t *msg_ptr, uint16_t msg_len);
/**
* \brief Sends DHCP request message.
*
* Service takes care of retransmissions.
*
* \param instance_id The instance ID of the registered server.
* \param options Options for this request.
* \param ptr A void pointer to the client object.
* \param addr The address of the server.
* \param msg_ptr An allocated message pointer. This pointer is the responsibility of the service after this call.
* \param msg_len The length of the message.
* \param receive_resp_cb Callback pointer
*
* \return Transaction ID of the DHCP transaction
* \return 0, if error occurred.
*/
uint32_t dhcp_service_send_req(uint16_t instance_id, uint8_t options, void *ptr, const uint8_t addr[static 16], uint8_t *msg_ptr, uint16_t msg_len, dhcp_service_receive_resp_cb *receive_resp_cb);
/**
* \brief Setting retransmission parameters.
*
* Sets the retransmission parameters for this transaction.
*
* \param msg_tr_id The message transaction ID.
* \param timeout_init An initial timeout value.
* \param timeout_max The maximum timeout value when initial timeout is doubled with every retry.
* \param retrans_max The maximum number of retries after which an error is received.
*
*/
void dhcp_service_set_retry_timers(uint32_t msg_tr_id, uint16_t timeout_init, uint16_t timeout_max, uint8_t retrans_max);
/**
* \brief Stops transactions for a message (retransmissions).
*
* Clears off sending retransmissions for a particular message transaction by finding it via its message transaction ID.
*
* \param msg_tr_id The message transaction ID.
*
*/
void dhcp_service_req_remove(uint32_t msg_tr_id);
/**
* \brief Timer tick function for retransmissions.
*
* Retransmission timer ticks should be increased with 100ms interval, if necessary. One tick is one millisecond.
*
*/
bool dhcp_service_timer_tick(uint16_t ticks);
#endif //DHCP_SERVICE_API_H_

View File

@ -0,0 +1,159 @@
/*
* Copyright (c) 2016-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/** \file ethernet_mac_api.h
* \brief Ethernet MAC API
*/
#ifndef ETHERNET_MAC_API_H
#define ETHERNET_MAC_API_H
#include <inttypes.h>
#include "platform/arm_hal_phy.h"
#ifdef __cplusplus
extern "C" {
#endif
#define ETHERTYPE_IPV4 0x0800 /**< ethernet type for IPv4 */
#define ETHERTYPE_ARP 0x0806 /**< ethernet type for ARP */
#define ETHERTYPE_802_1Q_TAG 0x8100 /**< ethernet type for 802_1Q */
#define ETHERTYPE_IPV6 0x86dd /**< ethernet type for IPv6 */
typedef struct eth_mac_api_s eth_mac_api_t;
/**
* \brief Struct eth_data_conf_s defines arguments for data confirm message
*/
typedef struct eth_data_conf_s {
uint8_t msduHandle; /**< Handle associated with MSDU */
uint8_t status; /**< Status of the last transaction */
}eth_data_conf_t;
/**
* \brief Struct eth_data_req_s defines arguments for data request message
*/
typedef struct eth_data_req_s {
uint16_t msduLength; /**< Service data unit length */
uint8_t *msdu; /**< Service data unit */
uint8_t *srcAddress; /**< Source address */
uint8_t *dstAddress; /**< Destination address */
uint16_t etehernet_type; /**< Ethernet type */
uint8_t msduHandle; /**< Handle associated with MSDU */
} eth_data_req_t;
/**
* \brief Struct eth_data_ind_s defines arguments for data indication message
*/
typedef struct eth_data_ind_s {
uint16_t msduLength; /**< Service data unit length */
uint8_t *msdu; /**< Service data unit */
uint8_t srcAddress[6]; /**< Source address */
uint8_t dstAddress[6]; /**< Destination address */
uint16_t etehernet_type; /**< Ethernet type */
uint8_t link_quality; /**< Link quality */
int8_t dbm; /**< measured dBm */
}eth_data_ind_t;
/**
* @brief Creates ethernet MAC API instance which will use driver given
* @param driver_id Ethernet driver id. Must be valid
* @return New MAC instance if successful, NULL otherwise
*/
extern eth_mac_api_t *ethernet_mac_create(int8_t driver_id);
/**
* @brief Destroy ethernet MAC API instance
* Call this only for freeing all allocated memory and when mac is total unused
*
* @param mac_api Removed mac class pointer
* @return -1 Unknow MAC
* @return 0 Mac class is removed
*/
extern int8_t ethernet_mac_destroy(eth_mac_api_t *mac_api);
/**
* @brief data_request data request call
* @param api API to handle the request
* @param data Data containing request parameters
*/
typedef void eth_mac_data_request(const eth_mac_api_t* api, const eth_data_req_t *data);
/**
* @brief data_confirm confirm is called as a response to data_request
* @param api The API which handled the request
* @param data Data containing confirm parameters
*/
typedef void eth_mac_data_confirm(const eth_mac_api_t* api, const eth_data_conf_t *data );
/**
* @brief data_indication Data indication is called when MAC layer has received data
* @param api The API which handled the response
* @param data Data containing indication parameters
*/
typedef void eth_mac_data_indication(const eth_mac_api_t* api, const eth_data_ind_t *data );
/**
* @brief Set 48 bit address from MAC
* @param api API to handle the request
* @param mac48 Pointer having mac address to be set
* @return 0 if successful, -1 otherwise
*/
typedef int8_t eth_mac_mac48_address_set(const eth_mac_api_t* api, const uint8_t *mac48);
/**
* @brief Read 48 bit address from MAC
* @param api API to handle the request
* @param mac48_buf Pointer where mac address can be written
* @return 0 if successful, -1 otherwise
*/
typedef int8_t eth_mac_mac48_address_get(const eth_mac_api_t* api, uint8_t *mac48_buf);
/**
* @brief Upper layer will call this function, when MAC is taken into use
* @param api API to initialize
* @param conf_cb Callback for confirm type of messages
* @param ind_cb Callback for indication type of messages
* @param parent_id Upper layer identifier
* @return 0 if success; -1 if api is NULL or not found
*/
typedef int8_t eth_mac_api_initialize(eth_mac_api_t *api, eth_mac_data_confirm *conf_cb,
eth_mac_data_indication *ind_cb, uint8_t parent_id);
/**
* \brief Struct eth_mac_api_s defines functions for two-way communications between ethernet MAC and Upper layer.
*/
struct eth_mac_api_s {
eth_mac_api_initialize *mac_initialize; /**< Callback function for MAC initialization */
eth_mac_data_request *data_req; /**< Callback function for data request */
eth_mac_data_confirm *data_conf_cb; /**< Callback function for data confirmation */
eth_mac_data_indication *data_ind_cb; /**< Callback function for data indication */
eth_mac_mac48_address_set *mac48_set; /**< Setter for MAC address */
eth_mac_mac48_address_get *mac48_get; /**< Getter for MAC address */
uint8_t parent_id; /**< Upper layer ID */
bool address_resolution_needed; /**< Normal ethernet should set this true for tunnel or false for slip */
};
#ifdef __cplusplus
}
#endif
#endif // ETHERNET_MAC_API_H

279
nanostack/fhss_api.h Normal file
View File

@ -0,0 +1,279 @@
/*
* Copyright (c) 2016-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* \file fhss_api.h
* \brief
*/
#ifndef FHSS_API_H
#define FHSS_API_H
#ifdef __cplusplus
extern "C" {
#endif
typedef struct fhss_api fhss_api_t;
typedef struct fhss_callback fhss_callback_t;
/**
* @brief FHSS frame types.
*/
#define FHSS_SYNCH_FRAME 0 /**< FHSS synchronization frame */
#define FHSS_SYNCH_REQUEST_FRAME 1 /**< FHSS synchronization request frame */
#define FHSS_DATA_FRAME 2 /**< FHSS data frame */
/**
* @brief FHSS synchronization info length.
*/
#define FHSS_SYNCH_INFO_LENGTH 21
/**
* @brief FHSS states.
*/
typedef enum
{
FHSS_UNSYNCHRONIZED,
FHSS_SYNCHRONIZED,
} fhss_states;
/**
* @brief FHSS is broadcast channel. Checks if current channel is broadcast channel.
* @param api FHSS instance.
* @return false if unicast channel, true if broadcast channel.
*/
typedef bool fhss_is_broadcast_channel(const fhss_api_t *api);
/**
* @brief FHSS queue check. Checks if broadcast queue must be used instead of unicast queue.
* @param api FHSS instance.
* @param is_broadcast_addr Destination address type of packet (true if broadcast address).
* @param frame_type Frame type of packet (Frames types are defined by FHSS api).
* @return false if unicast queue, true if broadcast queue.
*/
typedef bool fhss_use_broadcast_queue(const fhss_api_t *api, bool is_broadcast_addr, int frame_type);
/**
* @brief FHSS TX handle. Set destination channel and write synchronization info.
* @param api FHSS instance.
* @param is_broadcast_addr Destination address type of packet (true if broadcast address).
* @param destination_address Destination MAC address.
* @param frame_type Frame type of packet (Frames types are defined by FHSS api).
* @param synch_info Pointer to where FHSS synchronization info is written (if synch frame).
* @param frame_length MSDU length of the frame.
* @param phy_header_length PHY header length.
* @param phy_tail_length PHY tail length.
* @return 0 Success.
* @return -1 Transmission of the packet is currently not allowed, try again.
* @return -2 Invalid api.
* @return -3 Broadcast packet on Unicast channel (not allowed), push packet back to queue.
* @return -4 Synchronization info missing.
*/
typedef int fhss_tx_handle(const fhss_api_t *api, bool is_broadcast_addr, uint8_t *destination_address, int frame_type, uint8_t *synch_info, uint16_t frame_length, uint8_t phy_header_length, uint8_t phy_tail_length);
/**
* @brief Check TX permission.
* @param api FHSS instance.
* @param is_broadcast_addr Destination address type of packet (true if broadcast address).
* @param handle Handle of the data request.
* @param frame_type Frame type of packet (Frames types are defined by FHSS api).
* @param frame_length MSDU length of the frame.
* @param phy_header_length PHY header length.
* @param phy_tail_length PHY tail length.
* @return false if transmission is denied, true if transmission is allowed.
*/
typedef bool fhss_check_tx_conditions(const fhss_api_t *api, bool is_broadcast_addr, uint8_t handle, int frame_type, uint16_t frame_length, uint8_t phy_header_length, uint8_t phy_tail_length);
/**
* @brief Notification of received FHSS synch or synch request frame.
* @param api FHSS instance.
* @param pan_id Source PAN id of the received frame (FHSS_SYNCH_FRAME only).
* @param source_address Source address of the received frame (FHSS_SYNCH_FRAME only).
* @param timestamp Timestamp of reception (FHSS_SYNCH_FRAME only).
* @param synch_info Pointer to synchronization info (FHSS_SYNCH_FRAME only).
* @param frame_type Frame type of packet (Frames types are defined by FHSS api).
*/
typedef void fhss_receive_frame(const fhss_api_t *api, uint16_t pan_id, uint8_t *source_address, uint32_t timestamp, uint8_t *synch_info, int frame_type);
/**
* @brief Data TX done callback.
* @param api FHSS instance.
* @param waiting_ack MAC is waiting Acknowledgement for this frame.
* @param tx_completed TX completed (Ack received or no more retries left (if unicast frame)).
* @param handle Handle of the data request.
*/
typedef void fhss_data_tx_done(const fhss_api_t *api, bool waiting_ack, bool tx_completed, uint8_t handle);
/**
* @brief Data TX or CCA failed callback.
* @param api FHSS instance.
* @param handle Handle of the data request.
* @param frame_type Frame type of packet (Frames types are defined by FHSS api).
* @return true if frame has to be queued for retransmission, false otherwise.
*/
typedef bool fhss_data_tx_fail(const fhss_api_t *api, uint8_t handle, int frame_type);
/**
* @brief Change synchronization state.
* @param api FHSS instance.
* @param fhss_state FHSS state (FHSS states are defined by FHSS api).
* @param pan_id PAN id of the network FHSS synchronizes with.
*/
typedef void fhss_synch_state_set(const fhss_api_t *api, fhss_states fhss_state, uint16_t pan_id);
/**
* @brief Read timestamp.
* @param api FHSS instance.
* @return Timestamp to be written in received frame.
*/
typedef uint32_t fhss_read_timestamp(const fhss_api_t *api);
/**
* @brief Get retransmission period. FHSS uses different retry periods for different destinations.
* @param api FHSS instance.
* @param destination_address Destination MAC address.
* @param phy_mtu PHY MTU size.
* @return Retransmission period.
*/
typedef uint16_t fhss_get_retry_period(const fhss_api_t *api, uint8_t *destination_address, uint16_t phy_mtu);
/**
* @brief Initialize MAC functions.
* @param api FHSS instance.
* @param callbacks MAC functions to be called from FHSS.
* @return 0 Success.
* @return -1 Invalid parameters.
*/
typedef int fhss_init_callbacks(const fhss_api_t *api, fhss_callback_t *callbacks);
/**
* \brief Struct fhss_api defines interface between software MAC and FHSS.
* Application creates fhss_api_s object by calling FHSS creator function.
* Then object is passed to software MAC which then initialises it's own callback functions.
*/
struct fhss_api {
fhss_is_broadcast_channel *is_broadcast_channel; /**< FHSS is broadcast channel. */
fhss_use_broadcast_queue *use_broadcast_queue; /**< FHSS queue check. */
fhss_tx_handle *tx_handle; /**< FHSS TX handle. */
fhss_check_tx_conditions *check_tx_conditions; /**< Check TX permission. */
fhss_receive_frame *receive_frame; /**< Notification of received FHSS synch or synch request frame. */
fhss_data_tx_done *data_tx_done; /**< Data TX done callback. */
fhss_data_tx_fail *data_tx_fail; /**< Data TX or CCA failed callback. */
fhss_synch_state_set *synch_state_set; /**< Change synchronization state. */
fhss_read_timestamp *read_timestamp; /**< Read timestamp. */
fhss_get_retry_period *get_retry_period; /**< Get retransmission period. */
fhss_init_callbacks *init_callbacks; /**< Initialize MAC functions. */
};
/**
* @brief Read MAC TX queue size.
* @param fhss_api FHSS instance.
* @param broadcast_queue Queue type to be read (true if broadcast queue).
* @return Queue size (number of frames queued).
*/
typedef uint16_t mac_read_tx_queue_size(const fhss_api_t *fhss_api, bool broadcast_queue);
/**
* @brief Read MAC address.
* @param fhss_api FHSS instance.
* @param mac_address MAC address pointer.
* @return 0 Success.
* @return -1 Invalid parameters.
*/
typedef int mac_read_mac_address(const fhss_api_t *fhss_api, uint8_t *mac_address);
/**
* @brief Read PHY datarate.
* @param fhss_api FHSS instance.
* @return PHY datarate.
*/
typedef uint32_t mac_read_datarate(const fhss_api_t *fhss_api);
/**
* @brief Change channel.
* @param fhss_api FHSS instance.
* @param channel_number Channel number.
* @return 0 Success.
* @return -1 Invalid parameters.
*/
typedef int mac_change_channel(const fhss_api_t *fhss_api, uint8_t channel_number);
/**
* @brief Send FHSS frame.
* @param fhss_api FHSS instance.
* @param frame_type Frame type of packet (Frames types are defined by FHSS api).
* @return 0 Success.
* @return -1 Invalid parameters.
*/
typedef int mac_send_fhss_frame(const fhss_api_t *fhss_api, int frame_type);
/**
* @brief Send notification when FHSS synchronization is lost.
* @param fhss_api FHSS instance.
* @return 0 Success.
* @return -1 Invalid parameters.
*/
typedef int mac_synch_lost_notification(const fhss_api_t *fhss_api);
/**
* @brief Poll TX queue.
* @param fhss_api FHSS instance.
* @return 0 Success.
* @return -1 Invalid parameters.
*/
typedef int mac_tx_poll(const fhss_api_t *fhss_api);
/**
* @brief Broadcast channel notification from FHSS.
* @param fhss_api FHSS instance.
* @param broadcast_time Remaining broadcast time.
* @return 0 Success.
* @return -1 Invalid parameters.
*/
typedef int mac_broadcast_notify(const fhss_api_t *fhss_api, uint32_t broadcast_time);
/**
* @brief Read coordinator MAC address.
* @param fhss_api FHSS instance.
* @param mac_address MAC address pointer.
* @return 0 Success.
* @return -1 Invalid parameters.
*/
typedef int mac_read_coordinator_mac_address(const fhss_api_t *fhss_api, uint8_t *mac_address);
/**
* \brief Struct fhss_callback defines functions that software MAC needs to implement.
* Function pointers are passed to FHSS using fhss_init_callbacks function.
*/
struct fhss_callback {
mac_read_tx_queue_size *read_tx_queue_size; /**< Read MAC TX queue size. */
mac_read_mac_address *read_mac_address; /**< Read MAC address. */
mac_read_datarate *read_datarate; /**< Read PHY datarate. */
mac_change_channel *change_channel; /**< Change channel. */
mac_send_fhss_frame *send_fhss_frame; /**< Send FHSS frame. */
mac_synch_lost_notification *synch_lost_notification; /**< Send notification when FHSS synchronization is lost. */
mac_tx_poll *tx_poll; /**< Poll TX queue. */
mac_broadcast_notify *broadcast_notify; /**< Broadcast channel notification from FHSS. */
mac_read_coordinator_mac_address *read_coord_mac_address; /**< Read coordinator MAC address. */
};
#ifdef __cplusplus
}
#endif
#endif // FHSS_API_H

142
nanostack/fhss_config.h Normal file
View File

@ -0,0 +1,142 @@
/*
* Copyright (c) 2015-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* \file fhss_config.h
* \brief
*/
#ifndef FHSS_CONFIG_H
#define FHSS_CONFIG_H
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief Struct fhss_tuning_parameter defines FHSS tuning parameters.
* All delays are given in microseconds.
*/
typedef struct fhss_tuning_parameter
{
/** Delay between data pushed to PHY TX function and TX started (Contains CSMA-CA maximum random period). */
uint32_t tx_processing_delay;
/** Delay between TX done (by transmitter) and received data pushed to MAC (by receiver). */
uint32_t rx_processing_delay;
/** Delay between TX done (by transmitter) and Ack transmission started (by receiver) */
uint32_t ack_processing_delay;
} fhss_tuning_parameter_t;
/**
* \brief Struct fhss_configuration defines basic configuration of FHSS.
*/
typedef struct fhss_configuration
{
/** Tuning parameters can be used to enhance synchronization accuracy*/
fhss_tuning_parameter_t fhss_tuning_parameters;
/** Maximum used interval for requesting synchronization info from FHSS parent device (seconds). */
uint16_t fhss_max_synch_interval;
/** Number of channel retries. */
uint8_t fhss_number_of_channel_retries;
/** Channel mask */
uint32_t channel_mask[8];
} fhss_configuration_t;
/**
* \brief Struct fhss_timer defines interface between FHSS and FHSS platform timer.
* Application must implement FHSS timer driver which is then used by FHSS with this interface.
*/
typedef struct fhss_timer
{
/** Start timeout (1us) */
int (*fhss_timer_start)(uint32_t, void (*fhss_timer_callback)(const fhss_api_t *fhss_api, uint16_t), const fhss_api_t *fhss_api);
/** Stop timeout */
int (*fhss_timer_stop)(const fhss_api_t *fhss_api);
/** Get remaining time of started timeout*/
uint32_t (*fhss_get_remaining_slots)(const fhss_api_t *fhss_api);
/** Get timestamp since initialization of driver. Overflow of 32-bit counter is allowed (1us) */
uint32_t (*fhss_get_timestamp)(const fhss_api_t *fhss_api);
/** Divide 1 microsecond resolution. E.g. to use 64us resolution, use fhss_resolution_divider = 64*/
uint8_t fhss_resolution_divider;
} fhss_timer_t;
/**
* \brief Struct fhss_synch_configuration defines the synchronization time configurations.
* Border router application must define and set these configuration for FHSS network.
*/
typedef struct fhss_synch_configuration
{
/** Number of broadcast channels. */
uint8_t fhss_number_of_bc_channels;
/** TX slots per channel. */
uint8_t fhss_number_of_tx_slots;
/** Length of superframe(microseconds) * Number of superframes defines the
channel dwell time. E.g. 50000us * 8 -> Channel dwell time 400ms */
uint16_t fhss_superframe_length;
/** Number of superframes. */
uint8_t fhss_number_of_superframes;
} fhss_synch_configuration_t;
/**
* \brief Struct fhss_statistics defines the available FHSS statistics.
*/
typedef struct fhss_statistics
{
/** FHSS synchronization drift compensation (us/channel). */
int16_t fhss_drift_compensation;
/** FHSS hop count. */
uint8_t fhss_hop_count;
/** FHSS synchronization interval (s). */
uint16_t fhss_synch_interval;
/** Average of 5 preceding synchronization fixes (us). Updated after every fifth synch fix. */
int16_t fhss_prev_avg_synch_fix;
/** FHSS synchronization lost counter. */
uint32_t fhss_synch_lost;
} fhss_statistics_t;
/**
* \brief Enumeration fhss_channel_mode_e defines the channel modes.
*/
typedef enum fhss_channel_mode_e {
SINGLE_CHANNEL, //< Single channel
FHSS, //< Frequency hopping mode
} fhss_channel_mode_e;
#ifdef __cplusplus
}
#endif
#endif // FHSS_CONFIG_H

257
nanostack/mac_api.h Normal file
View File

@ -0,0 +1,257 @@
/*
* Copyright (c) 2016-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* \file mac_api.h
* \brief A API class to support different MACs from multiple vendors.
* Vendor must implement a function which fills supported callback functions which Upper layer will use.
*/
#ifndef MAC_API_H
#define MAC_API_H
#include <inttypes.h>
#include "mlme.h"
#include "mac_mcps.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct mac_api_s mac_api_t;
/**
* Every MAC adapting to Upper layer must implement a function which creates mac_api_t pointer, e.g 'mac_api_t* create_mac_api();'
* In the function external Mac needs to fill necessary function pointers so that Upper layer can use it.
* For Nanostack to work, following (mlme/mcps) request functions are mandatory:
* - mcps-data
* - scan
* - start
* - poll
* - get
* - set
* - reset
* - (purge)
* Also indication and confirm callbacks for above are needed plus
* - beacon notify
* - comm status
*
* \return mac_api_t Ownership of newly created object
*/
/*!
* \enum mlme_primitive
* \brief Enum for MLME primitive types.
*/
typedef enum {
MLME_ASSOCIATE,
MLME_DISASSOCIATE,
MLME_BEACON_NOTIFY,
MLME_GET,
MLME_GTS,
MLME_ORPHAN,
MLME_RESET,
MLME_RX_ENABLE,
MLME_SCAN,
MLME_COMM_STATUS,
MLME_SET,
MLME_START,
MLME_SYNC,
MLME_SYNC_LOSS,
MLME_POLL
} mlme_primitive;
/**
* \struct mac_description_storage_size_t
* \brief Container for MAC storage sizes.
*/
typedef struct mac_description_storage_size_s {
uint8_t device_decription_table_size; /**< MAC Device description list size */
uint8_t key_description_table_size; /**< MAC Key description list size */
uint8_t key_lookup_size; /**< Key description key lookup list size */
uint8_t key_usage_size; /**< Key description key usage list size */
} mac_description_storage_size_t;
/*!
* \enum mac_extended_address_type
* \brief Enum for MAC extended address types.
*/
typedef enum mac_extended_address_type {
MAC_EXTENDED_READ_ONLY, /** EUID64 which is unique */
MAC_EXTENDED_DYNAMIC /** Configured MAC 64-bit address to RAM and Radio */
}mac_extended_address_type;
//External MAC functions
/**
* @brief mlme_associate_response
* @param api API to handle the request
* @param data MLME-ASSOCIATE.response specific values
*/
//typedef void mlme_associate_response(const mac_api_t* api, mlme_associate_resp_t *data);
//typedef void mlme_orphan_response(const mac_api_t* api, mlme_orphan_resp_t *data);
/**
* @brief mlme_request
* @param api API to handle the request
* @param id The identifier of the MLME primitive
* @param data Primitive specific data (\see mlme.h)
*/
typedef void mlme_request(const mac_api_t* api, mlme_primitive id, const void *data);
/**
* @brief mcps_request MCPS_DATA request call
* @param api API to handle the request
* @param data MCPS-DATA.request specific values
*/
typedef void mcps_data_request(const mac_api_t* api, const mcps_data_req_t *data);
/**
* @brief mcps_purge_request MCPS_PURGE request call
* @param api API to handle the request
* @param data MCPS-PURGE.request specific values
*/
typedef void mcps_purge_request(const mac_api_t* api, const mcps_purge_t *data);
//Upper layer specific callback functions (will also be set by Upper layer after mac_api_t has been created and given to it)
/**
* @brief mcps_data_confirm MCPS-DATA confirm is called as a response to MCPS-DATA request
* @param api The API which handled the response
* @param data MCPS-DATA.confirm specific values
*/
typedef void mcps_data_confirm(const mac_api_t* api, const mcps_data_conf_t *data);
/**
* @brief mcps_data_indication MCPS-DATA indication is called when MAC layer has received data
* @param api The API which handled the response
* @param data MCPS-DATA.indication specific values
*/
typedef void mcps_data_indication(const mac_api_t* api, const mcps_data_ind_t *data);
/**
* @brief mcps_purge_confirm MCPS-PURGE confirm is called as a response to MCPS-PURGE request
* @param api The API which handled the request
* @param data MCPS-PURGE.confirm specific values
*/
typedef void mcps_purge_confirm( const mac_api_t* api, mcps_purge_conf_t *data );
/**
* @brief mlme_confirm One of the MLME primitive confirm callbacks
* @param api API which handled the response
* @param id The identifier of the MLME primitive
* @param data Primitive specific data (\see mlme.h)
*/
typedef void mlme_confirm(const mac_api_t* api, mlme_primitive id, const void *data);
/**
* @brief mlme_indication One of the
* @param api API which handled the response
* @param id The identifier of the MLME primitive
* @param data Primitive specific data (\see mlme.h)
*/
typedef void mlme_indication(const mac_api_t* api, mlme_primitive id, const void *data);
/**
* @brief Set extended address from MAC
* @param api API to handle the request
* @param mac64 pointer
*/
typedef int8_t mac_ext_mac64_address_set(const mac_api_t* api, const uint8_t *mac64);
/**
* @brief Read extended address from MAC
* @param api API to handle the request
* @param mac64_buf Pointer where mac extended address can be written
*/
typedef int8_t mac_ext_mac64_address_get(const mac_api_t* api, mac_extended_address_type type, uint8_t *mac64_buf);
/**
* @brief Read MAC security description storage sizes from MAC
* @param api API to handle the request
* @param buffer Pointer where supported sizes can be written
*/
typedef int8_t mac_storage_decription_sizes_get(const mac_api_t* api, mac_description_storage_size_t *buffer);
/**
* @brief mac_api_initialize Initialises MAC layer into use, callbacks must be non-NULL.
* @param api mac_api_t pointer, which is created by application.
* @param data_conf_cb Upper layer function to handle MCPS confirmations
* @param data_ind_cb Upper layer function to handle MCPS indications
* @param mlme_conf_cb Upper layer function to handle MLME confirmations
* @param mlme_ind_cb Upper layer function to handle MLME indications
* @param parent_id Upper layer id, which is used in confirmation and indication callbacks
* @return -1 if error, -2 if OOM, 0 otherwise
*/
typedef int8_t mac_api_initialize(mac_api_t *api, mcps_data_confirm *data_conf_cb,
mcps_data_indication *data_ind_cb, mcps_purge_confirm *purge_conf_cb, mlme_confirm *mlme_conf_cb,
mlme_indication *mlme_ind_cb, int8_t parent_id);
/**
* \brief Struct mac_api_s defines functions for two-way communications between external MAC and Upper layer.
* Application creates mac_api_t object by calling external MAC's creator function.
* Then object is passed to Upper layer which then initializes it's own callback functions.
* Then MAC is operated by Upper layer by calling MLME or MCPS primitive functions.
*/
struct mac_api_s {
mac_api_initialize *mac_initialize; /**< MAC initialize function to use */
//External MAC callbacks
mlme_request *mlme_req; /**< MAC MLME request function to use */
mcps_data_request *mcps_data_req; /**< MAC MCPS data request function to use */
mcps_purge_request *mcps_purge_req; /**< MAC MCPS purge request function to use */
//Upper layer callbacksMLME_ASSOCIATE
mcps_data_confirm *data_conf_cb; /**< MAC MCPS data confirm callback function */
mcps_data_indication *data_ind_cb; /**< MAC MCPS data indication callback function */
mcps_purge_confirm *purge_conf_cb; /**< MAC MCPS purge confirm callback function */
mlme_confirm *mlme_conf_cb; /**< MAC MLME confirm callback function */
mlme_indication *mlme_ind_cb; /**< MAC MLME indication callback function */
mac_ext_mac64_address_set *mac64_set; /**< MAC extension function to set mac64 address */
mac_ext_mac64_address_get *mac64_get; /**< MAC extension function to get mac64 address */
mac_storage_decription_sizes_get *mac_storage_sizes_get; /**< Getter function to query data storage sizes from MAC */
int8_t parent_id; /**< Upper layer id */
uint16_t phyMTU; /**< Maximum Transmission Unit(MTU) used by MAC*/
};
/**
* \struct mac_statistics_t
* \brief MAC statistics structure.
*/
typedef struct mac_statistics_s {
uint16_t mac_tx_queue_size; /**< MAC TX queue current size. */
uint16_t mac_tx_queue_peak; /**< MAC TX queue peak size. */
uint32_t mac_rx_count; /**< MAC RX packet count. */
uint32_t mac_tx_count; /**< MAC TX packet count. */
uint32_t mac_bc_rx_count; /**< MAC broadcast RX packet count. */
uint32_t mac_bc_tx_count; /**< MAC broadcast TX packet count. */
uint32_t mac_beacon_rx_count; /**< MAC Beacon RX packet count. */
uint32_t mac_beacon_tx_count; /**< MAC Beacon TX packet count. */
uint32_t mac_rx_drop_count; /**< MAC RX packet drop count. */
uint32_t mac_tx_bytes; /**< MAC TX bytes count. */
uint32_t mac_rx_bytes; /**< MAC RX bytes count. */
uint32_t mac_tx_failed_count; /**< MAC TX failed count. */
uint32_t mac_retry_count; /**< MAC TX retry count. */
uint32_t mac_cca_attempts_count; /**< MAC CCA attempts count. */
uint32_t mac_failed_cca_count; /**< MAC failed CCA count. */
} mac_statistics_t;
#ifdef __cplusplus
}
#endif
#endif // MAC_API_H

View File

@ -0,0 +1,69 @@
/*
* Copyright (c) 2016-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/** \file mac_common_defines.h
* \brief Common definitions for MAC layer.
*/
#ifndef MAC_COMMON_DEFINES_H_
#define MAC_COMMON_DEFINES_H_
#include "ns_types.h"
#define MAC_ADDR_MODE_NONE 0 /**< Address mode for no address defined */
#define MAC_ADDR_MODE_16_BIT 2 /**< Address mode for 16-bit addresses */
#define MAC_ADDR_MODE_64_BIT 3 /**< Address mode for 64-bit addresses */
#define MAC_FRAME_VERSION_2003 0 /**< FCF - IEEE 802.15.4-2003 compatible */
#define MAC_FRAME_VERSION_2006 1 /**< FCF - IEEE 802.15.4-2006 (big payload or new security) */
//See IEEE standard 802.15.4-2006 (table 96) for more details about identifiers
#define MAC_KEY_ID_MODE_IMPLICIT 0 /**< Key identifier mode implicit */
#define MAC_KEY_ID_MODE_IDX 1 /**< Key identifier mode for 1-octet key index */
#define MAC_KEY_ID_MODE_SRC4_IDX 2 /**< Key identifier mode for combined 4-octet key source and 1-octet key index */
#define MAC_KEY_ID_MODE_SRC8_IDX 3 /**< Key identifier mode for combined 8-octet key source and 1-octet key index */
/* IEEE 802.15.4 constants */
#define MAC_IEEE_802_15_4_MAX_MPDU_UNSECURED_OVERHEAD 25 /**< Maximum for MAC protocol data unit unsecured overhead */
#define MAC_IEEE_802_15_4_MIN_MPDU_OVERHEAD 9 /**< Minimum overhead added by MAC to MPDU */
#define MAC_IEEE_802_15_4_MAX_BEACON_OVERHEAD 75 /**< Maximum overhead which is added by the MAC for beacon */
#define MAC_IEEE_802_15_4_MAX_PHY_PACKET_SIZE 127 /**< Maximum number of octets PHY layer is able to receive */
#define MAC_IEEE_802_15_4_MAX_BEACON_PAYLOAD_LENGTH \
(MAC_IEEE_802_15_4_MAX_PHY_PACKET_SIZE - MAC_IEEE_802_15_4_MAX_BEACON_OVERHEAD) /**< Maximum size of beacon payload */
/** Maximum number of bytes which can be transmitted in the MAC payload of an unsecured MAC frame */
#define MAC_IEEE_802_15_4_MAX_MAC_SAFE_PAYLOAD_SIZE \
(MAC_IEEE_802_15_4_MAX_PHY_PACKET_SIZE - MAC_IEEE_802_15_4_MAX_MPDU_UNSECURED_OVERHEAD)
#define mac_unsecured_2003_compatibility false /**< For IEEE 802.15.4-2003 MAC compatibility, force max size to never exceed MAC_IEEE_802_15_4_MAX_MAC_SAFE_PAYLOAD_SIZE */
/**
* @brief struct mlme_security_t MLME/MCPS security structure
* This structure encapsulates security related variables,
* which are always used together if SecurityLevel > 0.
*
* See IEEE standard 802.15.4-2006 (e.g end of table 41) for more details
*/
typedef struct mlme_security_s {
unsigned SecurityLevel:3; /**< Security level */
unsigned KeyIdMode:2; /**< 2-bit value which define key source and ID use case */
uint8_t KeyIndex; /**< Key index */
uint8_t Keysource[8]; /**< Key source */
} mlme_security_t;
#endif /* MAC_COMMON_DEFINES_H_ */

205
nanostack/mac_filter_api.h Normal file
View File

@ -0,0 +1,205 @@
/*
* Copyright (c) 2014-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* \file mac_filter_api.h
* \brief API to allow filtering of packets based upon link quality and received power levels.
*
* \section app-mac-fil Applying a MAC filter
* - mac_filter_start(), Starts a MAC level filter.
* - mac_filter_add_short(), Adds a filter using short MAC address.
* - mac_filter_add_long(), Adds a filter using long MAC address.
*
* \section rem-mac-fil Removing a MAC filter
* - mac_filter_stop(), Stops MAC level filter and clears all defaults.
* - mac_filter_clear(), Stops MAC level filter and leaves the default link configuration.
* - mac_filter_delete_short(), Deletes filter for a device specified by short MAC address.
* - mac_filter_delete_long(), Deletes filter for a device specified by long MAC address.
*
* \section reg-mac-fil Setting up address mapping for filter
* - mac_filter_set_address_mapping(), Registers address mapping functions.
*
* \section macr-help Helper macros
* - mac_filter_start(interface_id, MAC_FILTER_BLOCKED), Black list filter.
* - mac_filter_start(interface_id, MAC_FILTER_ALLOWED), White list filter not modifying the qualities.
* - mac_filter_start(interface_id, MAC_FILTER_FIXED(0x01, -80)), Fixed value for default link quality (poor quality).
* - mac_filter_start(interface_id, MAC_FILTER_FIXED(0xff, -20)), Fixed value for default link quality (good quality).
* - mac_filter_add_short(interface_id, 0x0001, MAC_FILTER_BLOCKED)
* - mac_filter_add_short(interface_id, 0x0001, MAC_FILTER_ALLOWED)
* - mac_filter_add_short(interface_id, 0x0001, MAC_FILTER_FIXED(0xff,-30))
* - mac_filter_add_long(interface_id, mac64, MAC_FILTER_BLOCKED)
* - mac_filter_add_long(interface_id, mac64, MAC_FILTER_ALLOWED)
* - mac_filter_add_long(interface_id, mac64, MAC_FILTER_FIXED(0x7f, -60))
*/
#ifndef MAC_FILTER_API_H_
#define MAC_FILTER_API_H_
#include "ns_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief Start MAC level filter.
* This function can be called again if default values are modified.
*
*
* \param interface_id Network interface ID.
* \param lqi_m LQI multiplier (8.8 Fixed point multiplier).
* \param lqi_add Value added to LQI.
* \param dbm_m DBM multiplier (8.8 Fixed point multiplier).
* \param dbm_add Value added to DBM.
*
* \return 0, OK.
* \return <0 Not OK.
*/
int_fast8_t mac_filter_start(int8_t interface_id, int16_t lqi_m, int16_t lqi_add, int16_t dbm_m, int16_t dbm_add);
/**
* \brief Stop MAC level filter.
*
* Stops the filtering module and clears the default settings and all the filterings made.
*
* \param interface_id Network interface ID.
*
* \return 0, OK.
* \return <0 Not OK.
*/
void mac_filter_stop(int8_t interface_id);
/** White list filter not modifying the qualities.*/
#define MAC_FILTER_ALLOWED 0x100, 0, 0x100, 0
/** Black list filter.*/
#define MAC_FILTER_BLOCKED 0, 0, 0, 0
/** Fixed value for default link quality.*/
#define MAC_FILTER_FIXED(lqi,dbm) 0, lqi, 0, dbm
/**
* \brief Delete all filters.
*
* Leaves the default link configuration.
*
* \param interface_id Network interface ID.
*
* \return 0, OK.
* \return <0 Not OK.
*/
int_fast8_t mac_filter_clear(int8_t interface_id);
/**
* \brief Map the extended address to the short address.
*
* \param interface_id Network Interface.
* \param mac64 Extended address.
* \param mac16 Return the short address.
*
* \return 0, address resolved.
* \return <0 No mapping found.
*/
typedef int_fast8_t (mac_filter_map_extented_to_short_cb)(int8_t interface_id, uint8_t mac64[8], uint16_t *mac16);
/**
* \brief Map short address to extended address.
*
* \param interface_id Network interface ID.
* \param mac64[out] Return buffer for the extended address.
* \param mac16 Short address.
*
* return 0, address resolved.
* return <0 no mapping found.
*/
typedef int_fast8_t (mac_filter_map_short_to_extended_cb)(int8_t interface_id, uint8_t mac64[8], uint16_t mac16);
/**
* \brief Register address mapping functions.
*
* This function should be added for layer in stack that keeps up the list of address mapping functions.
* If filters are enabled these functions are called if no match from filters was found.
*
* When this service is no longer provided call this function with NULL pointers.
*
* \param interface_id Network interface ID.
* \param long_cb Address mapping to resolve long address from short address.
* \param short_cb Address mapping to resolve short address from long address.
*
* \return 0, OK.
* \return <0 Not OK.
*/
int_fast8_t mac_filter_set_address_mapping(int8_t interface_id, mac_filter_map_short_to_extended_cb *long_cb, mac_filter_map_extented_to_short_cb *short_cb);
/**
* \brief Delete filter for device
*
* \param interface_id Network interface ID.
* \param mac16 Short address.
*
* \return 0, OK.
* \return <0 Not OK.
*/
int_fast8_t mac_filter_delete_short(int8_t interface_id, uint16_t mac16);
/**
* \brief Delete filter for device.
*
* \param interface_id Network interface ID.
* \param mac64 Long address.
*
* \return 0, OK
* \return <0 Not OK
*/
int_fast8_t mac_filter_delete_long(int8_t interface_id, uint8_t mac64[8]);
/**
* \brief Add MAC short address filter.
*
* \param interface_id Network interface ID.
* \param mac16 Short address.
* \param lqi_m LQI multiplier (8.8 Fixed point multiplier).
* \param lqi_add Value added to LQI.
* \param dbm_m DBM multiplier (8.8 Fixed point multiplier).
* \param dbm_add Value added to DBM.
*
* \return 0, OK.
* \return <0 Not OK.
*/
int_fast8_t mac_filter_add_short(int8_t interface_id, uint16_t mac16, int16_t lqi_m, int16_t lqi_add, int16_t dbm_m, int16_t dbm_add);
/**
* \brief Add MAC long address filter.
*
* \param interface_id Network interface ID.
* \param mac64 Long address.
* \param lqi_m LQI multiplier (8.8 Fixed point multiplier).
* \param lqi_add Value added to LQI.
* \param dbm_m DBM multiplier (8.8 Fixed point multiplier).
* \param dbm_add Value added to DBM.
*
* \return 0, OK.
* \return <0 Not OK.
*/
int_fast8_t mac_filter_add_long(int8_t interface_id, uint8_t mac64[8], int16_t lqi_m, int16_t lqi_add, int16_t dbm_m, int16_t dbm_add);
#ifdef __cplusplus
}
#endif
#endif /* MAC_FILTER_API_H_ */

102
nanostack/mac_mcps.h Normal file
View File

@ -0,0 +1,102 @@
/*
* Copyright (c) 2016-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/** \file mac_mcps.h
* \brief MAC Common Part Sublayer API
*/
#ifndef MAC_MCPS_H
#define MAC_MCPS_H
#include <inttypes.h>
#include "mac_common_defines.h"
/**
* @brief struct mcps_data_req_t Data request structure
*
* See IEEE standard 802.15.4-2006 (table 41) for more details
*/
typedef struct mcps_data_req_s {
unsigned SrcAddrMode:2; /**< Source address mode */
unsigned DstAddrMode:2; /**< Destination address mode */
uint16_t DstPANId; /**< Destination PAN ID */
uint8_t DstAddr[8]; /**< Destination address */
uint16_t msduLength; /**< Service data unit length */
uint8_t *msdu; /**< Service data unit */
uint8_t msduHandle; /**< Handle associated with MSDU */
bool TxAckReq: 1; /**< Specifies whether ACK is needed or not */
bool InDirectTx:1; /**< Specifies whether indirect or direct transmission is used */
bool PendingBit: 1; /**< Specifies whether more fragments are to be sent or not */
mlme_security_t Key; /**< Security key */
} mcps_data_req_t;
/**
* @brief struct mcps_data_conf_t Data confirm structure
*
* See IEEE standard 802.15.4-2006 (table 42) for more details
*/
typedef struct mcps_data_conf_s {
uint8_t msduHandle; /**< Handle associated with MSDU */
uint8_t status; /**< Status of the last MSDU transmission */
uint32_t timestamp; /**< Time, in symbols, at which the data were transmitted */
//Non-standard extension
uint8_t cca_retries; /**< Number of CCA retries used during sending */
uint8_t tx_retries; /**< Number of retries done during sending, 0 means no retries */
} mcps_data_conf_t;
/**
* @brief struct mcps_data_ind_t Data indication structure
*
* See IEEE standard 802.15.4-2006 (table 43) for more details
*/
typedef struct mcps_data_ind_s {
unsigned SrcAddrMode:2; /**< 0x00 = no address 0x01 = reserved 0x02 = 16-bit short address 0x03 = 64-bit extended address */
uint16_t SrcPANId; /**< Source PAN ID */
uint8_t SrcAddr[8]; /**< Source address */
unsigned DstAddrMode:2; /**< Destination address mode */
uint16_t DstPANId; /**< Destination PAN ID */
uint8_t DstAddr[8]; /**< Destination address */
uint8_t mpduLinkQuality; /**< LQI value measured during reception of the MPDU */
int8_t signal_dbm; /**< This extension for normal IEEE 802.15.4 Data indication */
uint32_t timestamp; /**< The time, in symbols, at which the data were received */
uint8_t DSN; /**< Data sequence number */
mlme_security_t Key; /**< Security key */
uint16_t msduLength; /**< Data unit length */
uint8_t *msdu_ptr; /**< Data unit */
} mcps_data_ind_t;
/**
* @brief struct mcps_purge_t Purge request structure
*
* See IEEE standard 802.15.4-2006 (table 44) for more details
*/
typedef struct mcps_purge_s {
uint8_t msduHandle; /**< Handle associated with MSDU */
} mcps_purge_t;
/**
* @brief struct mcps_purge_conf_t Purge confirm structure
*
* See IEEE standard 802.15.4-2006 (table 45) for more details
*/
typedef struct mcps_purge_conf_s {
uint8_t msduHandle; /**< Handle associated with MSDU */
uint8_t status; /**< Status of the purge performed */
} mcps_purge_conf_t;
#endif // MAC_MCPS_H

500
nanostack/mlme.h Normal file
View File

@ -0,0 +1,500 @@
/*
* Copyright (c) 2013-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/** \file mlme.h
* \brief MLME API
*/
#ifndef MLME_H_
#define MLME_H_
#include <stdbool.h>
#include "mac_common_defines.h"
#include "net_interface.h"
/**
* @brief struct mlme_pan_descriptor_t PAN descriptor
*
* See IEEE standard 802.15.4-2006 (table 55) for more details
*/
typedef struct mlme_pan_descriptor_s {
unsigned CoordAddrMode:2; /**<Coordinator address mode MAC_ADDR_MODE_16_BIT or MAC_ADDR_MODE_64_BIT */
uint16_t CoordPANId; /**<PAN-id */
uint8_t CoordAddress[8]; /**< Coordinator based CoordAddrMode */
uint8_t LogicalChannel; /**< Pan's Logical channel */
uint8_t ChannelPage; /**< Channel Page*/
uint8_t SuperframeSpec[2]; /**< Superframe specification */
bool GTSPermit:1; /**< true = GTS enabled false = disabled */
uint8_t LinkQuality; /**< Link quality based on received packet to Coordinator 0-0xff */
uint32_t Timestamp; /**< Time stamp for received packet */
uint8_t SecurityFailure; /**< Indicates payload security failure */
mlme_security_t Key; /**< PAN beacon used security AUX header */
} mlme_pan_descriptor_t;
/**
* @brief struct mlme_command_type_t Command type enumeration
*
* See IEEE standard 802.15.4-2006 (table 82) for more details
*/
typedef enum {
ASSOCIATION_REQUEST = 1, /**<Assocation request (Not supported)*/
ASSOCIATION_RESPONSE = 2, /**<Assocation response (Not supported)*/
DISASSOCIATION_NOTIFICATION = 3, /**<Disasocation Notification (Not supported)*/
DATA_REQUEST = 4, /**<Data Request */
PAN_ID_CONFLICT_NOTIFICATION = 5, /**<Pan ID conflict notification (Not supported)*/
ORPHAN_NOTIFICATION = 6, /**<Orphan Notification (Not supported)*/
BEACON_REQUEST = 7, /**<Beacon request */
COORDINATOR_REALIGNMENT = 8, /**<Coordinator Realignment (Not supported)*/
GTS_REQUEST = 9 /**<GTS request (Not supported)*/
//Reserved
} mlme_command_type_t;
/**
* @brief enum mlme_loss_reason_t loss reason enumeration
*
* See IEEE standard 802.15.4-2006 (table 75) for more details
*/
typedef enum {
PAN_ID_CONFLICT, /**<Pan id conflict (Not supported)*/
REALIGNMENT, /**<Cordinator Realignment(Not supported)*/
BEACON_LOST /**<FHSS indicate by this when it loose synch to coordinator*/
} mlme_loss_reason_t;
/**
* @brief struct mlme_key_usage_descriptor_t Key usage descriptor
*
* See IEEE standard 802.15.4-2006 (table 90) for more details
*/
typedef struct mlme_key_usage_descriptor_s {
unsigned FrameType:3; /**<0 = Beacon Frame, 1 = Data Frame or 3 Command Frame */
unsigned CommandFrameIdentifier:4; /**< Set this part only when FrameType is 3 */
} mlme_key_usage_descriptor_t;
/**
* @brief struct mlme_key_device_descriptor_t Key usage descriptor
*
* See IEEE standard 802.15.4-2006 (table 91) for more details
*/
typedef struct mlme_key_device_descriptor_s {
uint8_t DeviceDescriptorHandle; /**< User defined unique ID to key User */
bool UniqueDevice:1; /**< true = Key description is for Key Pair Key usage only, False = group key */
bool Blacklisted:1; /**< true = Description is black listed, False = valid to use */
} mlme_key_device_descriptor_t;
/**
* @brief enum mlme_security_type_t Security type enumeration
*
* See IEEE standard 802.15.4-2006 (table 95) for more details
*/
typedef enum {
SEC_NONE = 0, /**< No payload encode and authentication */
SEC_MIC32 = 1, /**< No payload encode with 32-bit MIC authentication */
SEC_MIC64 = 2, /**< No payload encode with 64-bit MIC authentication */
SEC_MIC128 = 3, /**< No payload encode with 128-bit MIC authentication */
SEC_ENC = 4, /**< Payload encode enabled and without authentication */
SEC_ENC_MIC32 = 5, /**< Payload encode enabled with 32-bit MIC authentication */
SEC_ENC_MIC64 = 6, /**< Payload encode enabled with 64-bit MIC authentication */
SEC_ENC_MIC128 = 7 /**< Payload encode enabled with 128-bit MIC authentication */
} mlme_security_type_t;
/**
* @brief struct mlme_security_level_descriptor_t Security level descriptor
*
* See IEEE standard 802.15.4-2006 (table 92) for more details
*/
typedef struct mlme_security_level_descriptor_s {
unsigned FrameType:3; /**<0 = Beacon Frame, 1 = Data Frame or 3 Command Frame */
unsigned CommandFrameIdentifier:4; /**< Set this part only when FrameType is 3 */
unsigned SecurityMinimum:3; /**< Define Minimum acceptable security level for RX */
bool DeviceOverrideSecurityMinimum:1; /**< Set false */
} mlme_security_level_descriptor_t;
/**
* @brief struct mlme_device_descriptor_t Device descriptor
*
* See IEEE standard 802.15.4-2006 (table 93) for more details
*/
typedef struct mlme_device_descriptor_s {
uint16_t PANId; /**< Pan-id */
uint16_t ShortAddress; /**< Device 16-bit short address 0xffff means not defined */
uint8_t ExtAddress[8]; /**< Device Extended 64-bit address */
uint32_t FrameCounter; /**< Security Frame counter */
bool Exempt:1; /**< Set false */
} mlme_device_descriptor_t;
/**
* @brief struct mlme_key_id_lookup_descriptor_t Key id lookup descriptor
*
* See IEEE standard 802.15.4-2006 (table 94) for more details
*/
typedef struct mlme_key_id_lookup_descriptor_s {
uint8_t LookupData[9]; /**< Key Lookup data */
unsigned LookupDataSize:1; /**< Key Lookup data size 0= 5 1 is 9 bytes */
} mlme_key_id_lookup_descriptor_t;
/**
* @brief struct mlme_key_descriptor_entry_t Key descriptor entry
*
* See IEEE standard 802.15.4-2006 (table 89) for more details
*/
typedef struct mlme_key_descriptor_entry_s {
mlme_key_id_lookup_descriptor_t *KeyIdLookupList; /**< List of Key lookup data for this descriptor*/
uint8_t KeyIdLookupListEntries; /**< Number of entries in KeyIdLookupList*/
mlme_key_device_descriptor_t *KeyDeviceList; /**< List of descriptor user entries indicating which devices are valid or blacklisted */
uint8_t KeyDeviceListEntries; /**< Number of entries in KeyDeviceList*/
mlme_key_usage_descriptor_t *KeyUsageList; /**< List of descriptor entries indicating which frame types this key may be used with*/
uint8_t KeyUsageListEntries; /**< Number of entries in KeyUsageList*/
uint8_t Key[16]; /**< Actual value of Security key*/
}mlme_key_descriptor_entry_t;
/**
* @brief MLME primitive error statuses
*
* See IEEE standard 802.15.4-2006 for more details
*/
#define MLME_SUCCESS 0x00 /**< The requested operation was completed successfully*/
#define MLME_BUSY_CHAN 0xe1 /**< CSMA-CA fail*/
#define MLME_BUSY_RX 0x01 /**< The radio is asked to change its state while receiving */
#define MLME_BUSY_TX 0x02 /**< The radio is asked to change its state while transmitting. */
#define MLME_FORCE_TRX_OFF 0x03 /**< The radio is to be switched off immediately */
#define MLME_IDLE 0x04 /**< The CCA attempt has detected an idle channel */
#define MLME_RX_ON 0x06 /**< The radio is in or is to be configured into the receiver enabled state. */
#define MLME_TRX_OFF 0x08 /**< The radio is in or is to be configured into the receiver enabled state. */
#define MLME_TX_ON 0x09 /**< The radio is in or is to be configured into the receiver enabled state. */
#define MLME_COUNTER_ERROR 0xdb /**< Originated messages security counter is not valid */
#define MLME_IMPROPER_KEY_TYPE 0xdc /**< Received Messages key used is agains't key usage policy */
#define MLME_IMPROPER_SECURITY_LEVEL 0xdd /**< Received Messages security level does not meet minimum security level */
#define MLME_UNSUPPORTED_LEGACY 0xde /**< The received frame was purportedly secured using security based on IEEE Std 802.15.4-2003, and such security is not supported by this standard. */
#define MLME_UNSUPPORTED_SECURITY 0xdf /**< The received frame security is not supported */
#define MLME_SECURITY_FAIL 0xe4 /**< Cryptographic processing of the received secured frame failed. */
#define MLME_FRAME_TOO_LONG 0xe5 /**< Either a frame resulting from processing has a length that is greater than aMaxPHYPacketSize */
#define MLME_INVALID_HANDLE 0xe7 /**< Status for Purge request when Mac not detect proper queued message*/
#define MLME_INVALID_PARAMETER 0xe8 /**< A parameter in the primitive is either not supported or is out of the valid range */
#define MLME_TX_NO_ACK 0xe9 /**< No ack was received after macMaxFrameRetries */
#define MLME_NO_BEACON 0xea /**< A scan operation failed to find any network beacons */
#define MLME_NO_DATA 0xeb /**< No response data were available following a request */
#define MLME_NO_SHORT_ADDRESS 0xec /**< Operation fail because 16-bit address is not allocated */
#define MLME_PAN_ID_CONFLICT 0xee /**< A PAN identifier conflict has been detected and communicated to the PAN coordinator. */
#define MLME_TRANSACTION_EXPIRED 0xf0 /**< The transaction has expired and its information was discarded */
#define MLME_TRANSACTION_OVERFLOW 0xf1 /**< MAC have no capacity to store the transaction */
#define MLME_UNAVAILABLE_KEY 0xf3 /**< Received message use unknown key, or the originating device is unknown or is blacklisted with that particular key */
#define MLME_UNSUPPORTED_ATTRIBUTE 0xf4 /**< A SET/GET request was issued with the unsupported identifier */
#define MLME_INVALID_ADDRESS 0xf5 /**< A request to send data was unsuccessful because neither the source address parameters nor the destination address parameters were present.*/
#define MLME_INVALID_INDEX 0xf9 /**< An attempt to write to a MAC PIB attribute that is in a table failed because the specified table index was out of range. */
#define MLME_LIMIT_REACHED 0xfa /**< A scan operation terminated prematurely because the number of PAN descriptors stored reached an implementation- specified maximum */
#define MLME_READ_ONLY 0xfb /**< A SET request was issued with the identifier of an attribute that is read only.*/
#define MLME_SCAN_IN_PROGRESS 0xfc /**< Request scan request fail when scan is already active */
//NOT-standard
#define MLME_DATA_POLL_NOTIFICATION 0xff /**< Thread requirement feature COMM status status for indicate for successfully data poll event to refresh neighbour data */
/**
* @brief enum mac_scan_type_t MAC scan type
*
* See IEEE standard 802.15.4-2006 (table 67) for more details
*/
typedef enum {
MAC_ED_SCAN_TYPE = 0, /**< Energy detection scan operation */
MAC_ACTIVE_SCAN = 1, /**< Active scan operation */
MAC_PASSIVE_SCAN = 2, /**< Passive scan operation */
MAC_ORPHAN_SCAN = 3 /**< Orphan scan operation (Not supported) */
} mac_scan_type_t;
/**
* @brief enum mlme_attr_t MLME attributes used with GET and SET primitives
*
* See IEEE standard 802.15.4-2006 (table 86) for more details
*/
typedef enum {
phyCurrentChannel = 0x00, /*<Current RF channel*/
macAckWaitDuration = 0x40, /*<Integer, n. of symbols*/
macAssociatedPANCoord = 0x56, /*<Boolean, associated to PAN coordinator*/
macAssociationPermit = 0x41, /*<Boolean, if association is allowed (in coordinator)*/
macAutoRequest = 0x42, /*<Boolean, if device automatically sends data request on beacon*/
macBattLifeExt = 0x43, /*<Boolean, if BLE is enabled*/
macBattLifeExtPeriods = 0x44, /*<Integer 6-41, BLE back off periods */
macBeaconPayload = 0x45, /*<Set of bytes, beacon payload*/
macBeaconPayloadLength = 0x46, /*<Integer 0-MaxPayLoadLen*/
macBeaconOrder = 0x47, /*<Integer 015, Beacon tx period, 15 = no periodic beacon*/
macBeaconTxTime = 0x48, /*<Integer 0x0000000xffffff, symbols, when last beacon was transmitted*/
macBSN = 0x49, /*<Integer 0x000xff, Beacon sequence number*/
macCoordExtendedAddress = 0x4a, /*<64-bit IEEE of coordinator*/
macCoordShortAddress = 0x4b, /*<16-bit addr of coordinator*/
macDSN = 0x4c, /*<Integer 0x000xff, Data frame sequence number*/
macGTSPermit = 0x4d, /*<Boolean, GTS allowed?*/
macMaxBE = 0x57, /*<Integer 38, max value of back off exponent*/
macMaxCSMABackoffs = 0x4e, /*<Integer 05*/
macMaxFrameTotalWaitTime = 0x58,/*<Integer, max of CAP symbols while waiting for data requested by DREQ or PEND*/
macMaxFrameRetries = 0x59, /*<Integer 07*/
macMinBE = 0x4f, /*<Integer 0macMaxBE*/
macPANId = 0x50, /*<PAN ID, 16 bits*/
macPromiscuousMode = 0x51, /*<Boolean*/
macResponseWaitTime = 0x5a, /*<Integer 264 The maximum time in SuperFrameDurations to wait for responses*/
macRxOnWhenIdle = 0x52, /*<Boolean*/
macSecurityEnabled = 0x5d, /*<Boolean*/
macShortAddress = 0x53, /*<Short address, 16 bits*/
macSuperframeOrder = 0x54, /*<Integer 015, The length of the active portion of the outgoing super frame, 15 = none*/
macSyncSymbolOffset = 0x5b, /*<Integer 0x0000x100 (symbols) time stamp offset*/
macTimestampSupported = 0x5c, /*<Boolean*/
macTransactionPersistenceTime = 0x55, /*<Integer 0x00000xffff (unit periods)*/
macKeyTable = 0x71, /*<A table of KeyDescriptor entries, each containing keys and related information required for secured communications.*/
macKeyTableEntries = 0x72, /*<The number of entries in macKeyTable.*/
macDeviceTable = 0x73, /*<List of Descriptor entries, each indicating a remote device*/
macDeviceTableEntries = 0x74, /*<The number of entries in macDeviceTable.*/
macSecurityLevelTable = 0x75, /*<A table of SecurityLevelDescriptor entries*/
macSecurityLevelTableEntries = 0x76, /*<The number of entries in macSecurityLevelTable*/
macFrameCounter = 0x77, /*<The outgoing frame counter*/
macAutoRequestSecurityLevel = 0x78, /*<0x000x07 The security level used for automatic data requests.*/
macAutoRequestKeyIdMode = 0x79, /*< The key identifier mode used for automatic data requests.*/
macAutoRequestKeySource = 0x7a, /*<Key source for automatic data*/
macAutoRequestKeyIndex = 0x7b, /*<The index of the key used for automatic data*/
macDefaultKeySource = 0x7c, /*<Default key source*/
//NON standard extension
macLoadBalancingBeaconTx = 0xfd, /*< Trig Beacon from load balance module periodic */
macLoadBalancingAcceptAnyBeacon = 0xfe, /*<Beacon accept state control from other network. Value size bool, data true=Enable, false=disable .*/
macThreadForceLongAddressForBeacon = 0xff /*<Thread standard force beacon source address for extended 64-bit*/
} mlme_attr_t;
/**
* @brief struct mlme_beacon_pending_address_spec_t Pending address specification field
*
* See IEEE standard 802.15.4-2006 (figure 51) for more details
*/
typedef struct mlme_beacon_pending_address_spec_s{
unsigned short_address_count:3; /**< Number of short address count */
unsigned extended_address_count:3; /**< Number of extended address count */
}mlme_beacon_pending_address_spec_t;
/**
* @brief struct mlme_beacon_gts_spec_t Format of GTS specification field
*
* See IEEE standard 802.15.4-2006 (figure 48) for more details
*/
typedef struct mlme_beacon_gts_spec_s{
unsigned description_count:3; /**< Number of GTS description count */
unsigned gts_permit:1; /**< 1= GTS request accepted 0= not accepted */
}mlme_beacon_gts_spec_t;
/**
* @brief struct mlme_beacon_ind_t Beacon notify structure
*
* See IEEE standard 802.15.4-2006 (table 54) for more details
*/
typedef struct mlme_beacon_ind_s {
uint8_t BSN; /**< Beacon sequence number */
mlme_pan_descriptor_t PANDescriptor; /**< Beacon parsed Pan description */
mlme_beacon_pending_address_spec_t PendAddrSpec; /**< Address pending field */
uint8_t *AddrList; /**< Address pending list */
uint16_t beacon_data_length; /**< Length of beacon payload */
uint8_t *beacon_data; /**< Pointer to beacon payload */
} mlme_beacon_ind_t;
/**
* @brief struct mlme_scan_t Scan request structure
*
* See IEEE standard 802.15.4-2006 (table 67) for more details
*/
typedef struct mlme_scan_s {
mac_scan_type_t ScanType; /**< ED=0, active=1, passive=2, orphan=3*/
channel_list_s ScanChannels; /**<bit field, low 27 bits used*/
uint8_t ScanDuration; /**<0-14, scan duration/channel*/
uint8_t ChannelPage; /**<0-31*/
mlme_security_t Key; /**< Security parameters for active scan process */
} mlme_scan_t;
/**
* @brief struct mlme_set_t Set request structure
*
* See IEEE standard 802.15.4-2006 (table 70) for more details
*/
typedef struct mlme_set_s {
mlme_attr_t attr; /**<PIB attribute for operation*/
uint8_t attr_index; /**< attribute index to to table (use only for PIB attributes which are tables)*/
const void *value_pointer; /**< Pointer to value*/
uint8_t value_size; /**< define data length in bytes behind pointer*/
} mlme_set_t;
/**
* @brief struct mlme_get_t Get request structure
*
* See IEEE standard 802.15.4-2006 (table 56) for more details
*/
typedef struct mlme_get_s {
mlme_attr_t attr; /**<PIB attribute for operation*/
uint8_t attr_index; /**< attribute index to to table (use only for PIB attributes which are tables)*/
} mlme_get_t;
/**
* @brief struct mlme_get_conf_t Get confirm structure
*
* See IEEE standard 802.15.4-2006 (table 57) for more details
*/
typedef struct mlme_get_conf_s {
uint8_t status; /**< status of operation*/
mlme_attr_t attr; /**<PIB attribute for operation*/
uint8_t attr_index; /**< attribute index to to table (valid only for PIB attributes which are tables)*/
void *value_pointer; /**< Pointer to data when status is MLME_SUCCESS */
uint8_t value_size; /**< define data length in bytes behind pointer*/
} mlme_get_conf_t;
/**
* @brief struct mlme_set_conf_t Set confirm structure
*
* See IEEE standard 802.15.4-2006 (table 71) for more details
*/
typedef struct mlme_set_conf_s {
uint8_t status; /**< status of operation*/
mlme_attr_t attr; /**<PIB attribute for operation*/
uint8_t attr_index; /**< attribute index to to table (valid only for PIB attributes which are tables)*/
} mlme_set_conf_t;
#define MLME_MAC_RES_SIZE_MAX 16 /**< Mac scan response max supported list size */
/**
* @brief struct mlme_scan_conf_t Scan confirm structure
*
* See IEEE standard 802.15.4-2006 (table 68) for more details
*/
typedef struct mlme_scan_conf_s {
uint8_t status; /**< status of operation*/
unsigned ScanType:2; /**< Finished Scan type*/
uint8_t ChannelPage; /**< Operated Channel Page*/
channel_list_s UnscannedChannels; /**< Channel mask for unscanned channels*/
uint8_t ResultListSize; /**< Result list size*/
uint8_t *ED_values; /**< Energy scan result types Check only when scan type is 0*/
mlme_pan_descriptor_t *PAN_values[MLME_MAC_RES_SIZE_MAX]; /**< List of scanned Pan description's*/
} mlme_scan_conf_t;
/**
* @brief struct mlme_reset_t Reset request structure
*
* See IEEE standard 802.15.4-2006 (table 63) for more details
*/
typedef struct mlme_reset_s {
bool SetDefaultPIB; /**< true= Set standard default values, false= Mac sub layer will be reset but it retain configured MAC PIB values */
} mlme_reset_t;
/**
* @brief struct mlme_reset_conf_t Reset confirm structure
*
* See IEEE standard 802.15.4-2006 (table 64) for more details
*/
typedef struct mlme_reset_conf_s {
uint8_t status; /**< Status of reset operation */
} mlme_reset_conf_t;
/**
* @brief struct mlme_rx_enable_t Rx enable request structure (Not supported)
*
* See IEEE standard 802.15.4-2006 (table 65) for more details
*/
typedef struct mlme_rx_enable_s {
bool DeferPermit; /**< This will be ignored at nonbeacon-enabled PAN*/
uint32_t RxOnTime; /**< This will be ignored at nonbeacon-enabled PAN*/
uint32_t RxOnDuration; /**< Number of symbols which receiver is enabled, 0 receiver is not disabled*/
} mlme_rx_enable_t;
/**
* @brief struct mlme_rx_enable_conf_t Rx enable confirm structure (Not supported)
*
* See IEEE standard 802.15.4-2006 (table 66) for more details
*/
typedef struct mlme_rx_enable_conf_s {
uint8_t status; /**< Status of operation */
} mlme_rx_enable_conf_t;
/**
* @brief struct mlme_comm_status_t Comm status indication structure
*
* See IEEE standard 802.15.4-2006 (table 69) for more details
*/
typedef struct mlme_comm_status_s {
uint16_t PANId; /**< Messages Pan-id */
unsigned SrcAddrMode:2; /**< source address mode: MAC_ADDR_MODE_NONE,MAC_ADDR_MODE_16_BIT or MAC_ADDR_MODE_64_BIT */
uint8_t SrcAddr[8]; /**< source address when mode is: MAC_ADDR_MODE_16_BIT or MAC_ADDR_MODE_64_BIT */
unsigned DstAddrMode:2; /**< destination address mode: MAC_ADDR_MODE_NONE,MAC_ADDR_MODE_16_BIT or MAC_ADDR_MODE_64_BIT */
uint8_t DstAddr[8]; /**< Destination address when mode is: MAC_ADDR_MODE_16_BIT or MAC_ADDR_MODE_64_BIT */
uint8_t status; /**< Communication status */
mlme_security_t Key; /**< Messages Security parameters */
} mlme_comm_status_t;
/**
* @brief struct mlme_start_t Start request structure
*
* See IEEE standard 802.15.4-2006 (table 72) for more details
*/
typedef struct mlme_start_s {
uint16_t PANId; /**< Pan-id */
uint8_t LogicalChannel; /**< Operated Logical channel */
uint8_t ChannelPage; /**< Operated Logical channel page */
uint32_t StartTime; /**< Start time, set 0 */
unsigned BeaconOrder:4; /**< Beacon order, set 15 */
unsigned SuperframeOrder:4; /**< Super frame order, set 15 */
bool PANCoordinator:1; /**< true= Enable beacon response for beacon request, false = disable beacon request responses */
bool BatteryLifeExtension:1; /**< Set false */
bool CoordRealignment:1; /**< Set false */
mlme_security_t CoordRealignKey; /**< Coordinator Realignment security parameter's (Valid only CoordRealignment = true)*/
mlme_security_t BeaconRealignKey; /**< Beacon realign security parameter's (Valid only CoordRealignment = true)*/
} mlme_start_t;
/**
* @brief struct mlme_start_conf_t Start confirm structure (Currently not triggered yet)
*
* See IEEE standard 802.15.4-2006 (table 73) for more details
*/
typedef struct mlme_start_conf_s {
uint8_t status; /**< Status for start confirmation */
} mlme_start_conf_t;
/**
* @brief struct mlme_sync_loss_s Synch loss indication
*
* Stack will trig this with FHSS enabled mac when synch to parent is lost
* See IEEE standard 802.15.4-2006 (table 73) for more details
*/
typedef struct mlme_sync_loss_s {
mlme_loss_reason_t LossReason; /**< Loss reason, BEACON_LOST with FHSS */
uint16_t PANId; /**< Pan-id */
uint8_t LogicalChannel; /**< Logical channel */
uint8_t ChannelPage; /**< Logical channel page */
mlme_security_t Key; /**< Security parameters */
} mlme_sync_loss_t;
/**
* @brief struct mlme_poll_t Poll request structure
*
* See IEEE standard 802.15.4-2006 (table 76) for more details
*/
typedef struct mlme_poll_s {
unsigned CoordAddrMode:2; /**< coordinator address mode:MAC_ADDR_MODE_16_BIT or MAC_ADDR_MODE_64_BIT */
uint16_t CoordPANId; /**< coordinator Pan-id to coordinator*/
uint8_t CoordAddress[8]; /**< coordinator address */
mlme_security_t Key; /**< Security parameters for Poll request */
} mlme_poll_t;
/**
* @brief struct mlme_poll_conf_t Poll confirm structure
*
* See IEEE standard 802.15.4-2006 (table 77) for more details
*/
typedef struct mlme_poll_conf_s {
uint8_t status; /**< Status of Poll operation */
} mlme_poll_conf_t;
#endif /* MLME_H_ */

355
nanostack/multicast_api.h Normal file
View File

@ -0,0 +1,355 @@
/*
* Copyright (c) 2012-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MULTICAST_API_H_
#define MULTICAST_API_H_
/**
* \file multicast_api.h
* \brief Multicast Trickle Forwarding API.
* \section multi-init Init API:
* - multicast_set_parameters(), Set trickle parameters.
* \section multi-cnf Configure API:
* - multicast_add_address(), Add new address to a multicast group and control trickle forwarding.
* - multicast_free_address(), Remove supported multicast address from list.
*
* \section ZigBeeIP Trickle Setups for Multicast Init
*
* | Parameter | VALUE |
* | :---------------: | :---: |
* | imin | 10 |
* | imax | 0 |
* | k | 20 |
* | timer_expirations | 3 |
* | window_expiration | 75 |
*
*/
#include "ns_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief Set new parameters for trickle multicast.
* \deprecated
*
* \param i_min Minimum trickle timer interval in 50ms resolution: Imin = i_min * 50ms.
* \param i_doublings Maximum trickle timer interval expressed as number of doublings of the minimum interval.
* \param k Redundancy constant.
* \param timer_expirations Number of trickle timer expirations before terminating the trickle process.
* \param window_expiration The time window for keeping the state after the end of trickle process in 50ms resolution.
* NOTE: If window_expiration value is set too small an infinite retransmission loop may occur when using the trickle multicast.
*/
void multicast_set_parameters(uint8_t i_min, uint8_t i_doublings, uint8_t k, uint8_t timer_expirations, uint16_t window_expiration);
/**
* \brief Add new address to multicast group.
*
* \deprecated Use setsockopt(SOCKET_IPV6_JOIN_GROUP) to join a group. Use
* multicast_mpl_subscribe_domain() to control MPL behaviour.
*
* \param address_ptr Pointer to a 16-byte array that includes the address to be added.
* \param use_trickle 0 = no trickle multicast forwarding, all other values = trickle multicast forwarding will be used with this address.
*
* \return 0 General error.
* \return 1 Address updated.
* \return 2 Address added.
* \return 255 Link local not allowed when using multicast.
*
*/
uint8_t multicast_add_address(const uint8_t *address_ptr, uint8_t use_trickle);
/**
* \brief Free address from multicast group.
* \deprecated Use setsockopt(SOCKET_IPV6_LEAVE_GROUP)
*
* \param address_ptr Pointer to a 16-byte array that includes the address to be removed.
*
* \return 0 will be returned on successful execution, other values indicate an error on removing the address.
*/
uint8_t multicast_free_address(const uint8_t *address_ptr);
/**
* \brief Treat all Realm-local Domains as one
*
* If enabled on an interface, then all Realm-local scope multicasts will
* be treated as if belonging to the All-MPL-Forwarders domain, rather than
* the domain indicated by their destination address. This is non-standard
* behaviour, not covered by the real MPL specification, but required by the
* Thread specification.
*
* All devices in a realm should have this setting set the same. With the
* setting on, reactive forwarding and control messages will not work.
*
* With this setting on, Realm-scope domains other than All-MPL-Forwarders
* cannot be joined.
*
* This must be set before bringing up an interface, and then not be modified.
*
* \param interface_id interface id
* \param enable true to enable domain unification
*
* \return 0 for success, negative on failure
*/
int_fast8_t multicast_mpl_treat_realm_domains_as_one(int8_t interface_id, bool enable);
/**
* \brief Set default MPL Domain parameters
*
* Modifies the default parameters for MPL Domains using the specified
* interface.
*
* This must be set before subscribing to any MPL Domains with default
* parameters on that interface.
*
* Initial defaults are as specified by RFC 7731.
*
* \param interface_id interface id
* \param proactive_forwarding true to forward Data Messages when first received (default true)
* \param seed_set_entry_lifetime minimum seed set lifetime (seconds, default 1800 = 30 minutes)
* \param data_message_imin minimum Trickle timer for Data Messages (ms, default ~= 10 * expected link latency)
* \param data_message_imax maximum Trickle timer for Data Messages (ms, default = Imin)
* \param data_message_k Trickle redundancy constant for Data Messages (default = 1)
* \param data_message_timer_expirations controls termination of retransmissions (default = 3)
* \param control_message_imin minimum Trickle timer for Control Messages (ms, default ~= 10 * worst-case link latency)
* \param control_message_imax maximum Trickle timer for Control Messages (ms, default = 5 minutes)
* \param control_message_k Trickle redundancy constant for Control Messages (default = 1)
* \param control_message_timer_expirations controls termination of retransmissions (default = 10); 0 disables control messages
*
* \return 0 for success, negative on failure
*/
int_fast8_t multicast_mpl_set_default_parameters(int8_t interface_id,
bool proactive_forwarding,
uint16_t seed_set_entry_lifetime,
uint32_t data_message_imin,
uint32_t data_message_imax,
uint8_t data_message_k,
uint8_t data_message_timer_expirations,
uint32_t control_message_imin,
uint32_t control_message_imax,
uint8_t control_message_k,
uint8_t control_message_timer_expirations);
/** Control selection of MPL Seed Identifier for packets we originate */
typedef enum {
MULTICAST_MPL_SEED_ID_DEFAULT = -256, /** Default selection (used to make a domain use the interface's default) */
MULTICAST_MPL_SEED_ID_MAC_SHORT = -1, /** Use short MAC address if available (eg IEEE 802.15.4 interface's macShortAddress (16-bit)), else full MAC */
MULTICAST_MPL_SEED_ID_MAC = -2, /** Use MAC padded to 64-bit (eg IEEE 802.15.4 interface's macExtendedAddress, or 48-bit Ethernet MAC followed by 2 zero pad bytes) */
MULTICAST_MPL_SEED_ID_IID_EUI64 = -3, /** Use 64-bit IPv6 IID based on EUI-64 (eg 02:11:22:ff:fe:00:00:00 for an Ethernet interface with MAC 00:11:22:00:00:00) */
MULTICAST_MPL_SEED_ID_IID_SLAAC = -4, /** Use 64-bit IPv6 IID that would be used for SLAAC */
MULTICAST_MPL_SEED_ID_IPV6_SRC_FOR_DOMAIN = 0, /** Use IPv6 source address selection to choose 128-bit Seed ID based on MPL Domain Address as destination */
MULTICAST_MPL_SEED_ID_16_BIT = 2, /** Use a manually-specified 16-bit ID */
MULTICAST_MPL_SEED_ID_64_BIT = 8, /** Use a manually-specified 64-bit ID */
MULTICAST_MPL_SEED_ID_128_BIT = 16, /** Use a manually-specified 128-bit ID */
} multicast_mpl_seed_id_mode_e;
/**
* \brief Set default MPL Seed Identifier
*
* Sets the default MPL Seed Identifier used when acting as an MPL Seed.
*
* \param interface_id interface id
* \param seed_id_mode Seed ID selection mode
* \param seed_id For positive (constant) types, pointer to Seed ID data
*
* \return 0 for success, negative on failure
*/
int_fast8_t multicast_mpl_set_default_seed_id(int8_t interface_id,
multicast_mpl_seed_id_mode_e seed_id_mode,
const void *seed_id);
/**
* \brief Subscribe to an MPL Domain (RFC 7731)
*
* This subscribes to an MPL Domain with default parameters on the
* specified interface. (At present there is no support for subscribing to
* the same Domain on multiple interfaces)
*
* If the ALL_MPL_FORWARDERS Domain ff03::fc has not already been subscribed
* to, this will automatically also subscribe to it with default parameters.
*
* Once 1 or more MPL Domains have been subscribed to on an interface,
* multicast transmissions sent to a group with scope greater than link-local
* on that interface will be sent using MPL.
*
* If the destination corresponds to a subscribed MPL Domain, it will be sent
* to that MPL Domain (and hence forwarded only by other subscribers to that
* domain).
*
* If the destination does not correspond to a subscribed MPL Domain, it will
* be tunnelled, with the outer IP packet sent to the ALL_MPL_FORWARDERS Domain.
*
* Typical behaviour for ZigBee IP and Thread networks would be achieved by
* subscribing to ff03::1, and enabling realm auto-subscription - [this is
* done automatically when calling multicast_add_address?]
*
* \param interface_id interface id
* \param address MPL Domain Address (IPv6 multicast address)
* \param seed_id_mode Seed ID selection mode
* \param seed_id For positive (constant) types, pointer to Seed ID data
*
* \return 0 for success, negative on failure
*/
int8_t multicast_mpl_domain_subscribe(int8_t interface_id,
const uint8_t address[16],
multicast_mpl_seed_id_mode_e seed_id_mode,
const void *seed_id);
/**
* \brief Subscribe to an MPL Domain (RFC 7731)
*
* This subscribes to an MPL Domain with default parameters on the
* specified interface.
*
* If the ALL_MPL_FORWARDERS Domain ff03::fc has not already been subscribed
* to, this will automatically also subscribe to it with default parameters.
*
* See multicast_mpl_subscribe_domain and multicast_set_default_parameters
* for more information on parameters.
*/
int8_t multicast_mpl_domain_subscribe_with_parameters
(int8_t interface_id,
const uint8_t address[16],
multicast_mpl_seed_id_mode_e seed_id_mode,
const void *seed_id,
bool proactive_forwarding,
uint16_t seed_set_entry_lifetime,
uint32_t data_message_imin,
uint32_t data_message_imax,
uint8_t data_message_k,
uint8_t data_message_timer_expirations,
uint32_t control_message_imin,
uint32_t control_message_imax,
uint8_t control_message_k,
uint8_t control_message_timer_expirations);
/**
* \brief Unsubscribe from an MPL Domain
*
* This subscribes from a previously-subscribed MPL Domain
*
* \param interface_id interface id
* \param address MPL Domain Address (IPv6 multicast address)
*
* \return 0 for success, negative on failure
*/
int8_t multicast_mpl_domain_unsubscribe(int8_t interface_id,
const uint8_t address[16]);
/**
* \brief Set interface's master multicast forwarding control
*
* Multicast forwarding can occur between interfaces with multicast forwarding
* enabled, according to forwarding records and scope rules controlled by the
* functions below.
*
* If this call disables forwarding on the current proxying upstream interface,
* proxying is disabled, and would need to be manually re-enabled later.
*
* Multicast forwarding state for an interface - forwarding records and scope level - are
* retained even if its master forwarding switch is disabled, enabling the upkeep of backup
* information.
*
* By default this flag is enabled.
*
* \param interface_id interface id
* \param enable Enable / Disable multicast forwarding
*
* \return 0 for success, negative on failure
*/
int8_t multicast_fwd_set_forwarding(int8_t interface_id, bool enable);
/**
* \brief Add multicast forwarding record to an interface
*
* This adds a group to the forwarding list on the specified interface.
* Received multicast packets for the specified group will be forwarded onto
* the specified interface from other interfaces, if multicast forwarding is enabled on
* both incoming and outgoing interfaces, subject to a Reverse Path Forwarding
* check on the source address, and usual scope rules.
*
* If a finite lifetime is set, the record will be removed after that many seconds.
*
* If an entry for the specified group already exists, its lifetime will
* increased if it is lower than the value passed.
*
* \param interface_id interface id
* \param group IPv6 multicast group address
* \param lifetime The time in seconds to maintain the forwarding entry - 0xFFFFFFFF means infinite
*
* \return 0 for success, negative on failure
*/
int8_t multicast_fwd_add(int8_t interface_id, const uint8_t group[16], uint32_t lifetime);
/**
* \brief Remove multicast forwarding record from an interface
*
* Delete a a group from the forwarding list on the specified interface.
*
* \param interface_id interface id
* \param group IPv6 multicast group address
*
* \return 0 for success, negative on failure
*/
int8_t multicast_fwd_remove(int8_t interface_id, const uint8_t group[16]);
/**
* \brief Set full multicast forwarding
*
* If enabled, all multicast packets of specified scope or greater will be
* forwarded onto the specified interface from other interfaces, if multicast
* forwarding is enabled on both incoming and outgoing interfaces, subject to a
* Reverse Path Forwarding check on the source address.
*
* Setting this is equivalent to "multicast_fwd_add" being called for all
* addresses with scope >= min_scope.
*
* This functionality is disabled by setting min_scope to 0x10 or greater (so
* no packets can match).
*
* By default this is set to 0x5 (site-local) for all interfaces.
*
* \param interface_id interface id
* \param min_scope minimum IPv6 scope value for forwarding (see RFC 4291)
*
* \return 0 for success, negative on failure
*/
int8_t multicast_fwd_full_for_scope(int8_t interface_id, uint_fast8_t min_scope);
/**
* \brief Set upstream interface for MLD proxying
*
* This sets the upstream interface for MLD proxying. If set, the stack will
* report group membership on that interface according to the forwarding lists
* of the other interfaces with multicast forwarding enabled (ie it will send
* MLD reports or equivalent on that upstream interface).
*
* Multicast forwarding must be enabled on the upstream interface.
*
* \param interface_id interface id, or -1 to disable
*
* \return 0 for success, negative on failure
*/
int8_t multicast_fwd_set_proxy_upstream(int8_t interface_id);
#ifdef __cplusplus
}
#endif
#endif /* MULTICAST_API_H_ */

View File

@ -0,0 +1,124 @@
/*
* Copyright (c) 2014-2015, 2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef NET_6LOWPAN_PARAMETER_API_H_
#define NET_6LOWPAN_PARAMETER_API_H_
#include "ns_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* \file net_6lowpan_parameter_api.h
* \brief API for setting up 6LoWPAN network parameters
*
* \section tim-para-def 6LoWPAN Default timer values
* - Timer values are specified in ticks
* - Default 6LoWPAN ND Bootstrap tick is 1 tick = 100ms
*
* - Default Random value 0x1f = [0..3.1] seconds.
* - Default RS retry counter 3.
* - Default RS retry interval is 15 + random --> [1.5..4.6] seconds.
* - Default NS retry counter 5.
* - Default NS retry interval is 100 + random + backoff --> [10.0..13.1+10.0*retry] seconds.
* - Default NS retry linear backoff is 100.
*
* - Default RA transmit interval is 150, exponentially backed off --> 15.0, 30.0, 60.0 seconds.
* - Default RA transmit counter is 5.
*
* - Default NS forward timeout is 300 --> 30.0 seconds.
*
* \section Changing random and interval values
* - Random parameter + NS or RS minimum interval must sum to less than 0xFFFF.
* - Random maximums are manipulated as bit masks, so must be (2^n)-1.
*/
/*!
* \struct nd_parameters_s
* \brief 6LoWPAN Neighbor Discovery parameters
*/
typedef struct nd_parameters_s {
uint8_t rs_retry_max; /**< Define Bootstrap RS max retry count. */
uint8_t ns_retry_max; /**< Define Bootstrap NS max retry count. */
uint16_t timer_random_max; /**< Define Interval random in 6LoWPAN bootstrap timer ticks for RS, NS and starting NS - NA process. */
uint16_t rs_retry_interval_min; /**< Define Retry interval in 6LoWPAN bootstrap timer ticks waiting for RA. */
uint16_t ns_retry_interval_min; /**< Define Retry interval in 6LoWPAN bootstrap timer ticks waiting for NA. */
uint16_t ns_retry_linear_backoff; /**< Define Retry interval linear backoff in bootstrap timer ticks. */
bool multihop_dad; /**< Define whether to perform duplicate address detection with border router or locally. */
bool iids_map_to_mac; /**< Define whether IPv6 IIDs can be assumed to be based on MAC address (so no address resolution by routers). */
bool send_nud_probes; /**< Define whether IPv6 NUD probes are enabled (disabling may limit fault detection). */
uint16_t ra_interval_min; /**< Define initial transmission interval for Router Advertisements in standard timer ticks. */
uint8_t ra_transmits; /**< Define number of RA transmissions. */
uint8_t ra_cur_hop_limit; /**< Define the value of current hop limit in RAs. */
uint32_t ra_link_mtu; /**< Define the value of link MTU in RAs. */
uint32_t ra_reachable_time; /**< Define the value of reachable time in RAs (in milliseconds). */
uint32_t ra_retrans_timer; /**< Define the value of retrans timer in RAs (in milliseconds). */
uint16_t ns_forward_timeout; /**< Define timeout when forwarding NS messages - if reached, our own address discovery process is restarted. */
} nd_parameters_s;
/**
* \brief Function to change 6LoWPAN ND bootstrap parameters.
*
* Note: This function should be called after net_init_core() and definitely
* before creating any 6LoWPAN interface.
*
* For future compatibility, to support extensions to this structure, read
* the current parameters using net_6lowpan_timer_parameter_read(),
* modify known fields, then set.
*
* \param parameter_ptr Pointer for ND parameters.
*
* \return 0, Change OK.
* \return -1, Invalid values.
* \return -2, 6LoWPAN interface already active.
*
*/
extern int8_t net_6lowpan_nd_parameter_set(const nd_parameters_s *parameter_ptr);
/**
* \brief Function to change 6LoWPAN bootstrap base tick 100ms multiplier.
*
* Note: This function MUST be called after net_init_core(). Do not change this
* unless you really want 6LoWPAN bootstrap working slower than normally.
*
* This only affects the bootstrap timers.
*
* \param base_tick_x_100ms Tick resolution in 100ms units.
* Max value 10 --> 10 times slower functionality
*
* \return 0, Change OK.
* \return -1, Invalid value (<1 or >10).
*
*/
extern int8_t net_6lowpan_nd_timer_base_tick_set(uint8_t base_tick_x_100ms);
/**
* \brief Function to read 6LoWPAN ND bootstrap parameters.
*
* \param parameter_ptr Output pointer for ND parameters.
*
*/
extern void net_6lowpan_nd_parameter_read(nd_parameters_s *parameter_ptr);
#ifdef __cplusplus
}
#endif
#endif /* NET_6LOWPAN_DEFAULT_PARAMETER_API_H_ */

View File

@ -0,0 +1,65 @@
/*
* Copyright (c) 2013-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _NET_ADDRESS_EXTENSION_H
#define _NET_ADDRESS_EXTENSION_H
#include "ns_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* \file net_address_extension.h
* \brief API for setting up link layer short address manually.
*
* \section set-addr Setting short address
* - net_ext_set_short_address_from_app(), Sets up a user-specified short address and enables or disables DAD.
*
* NOTE: In case of duplication of address and DAD (duplicate address detection) enabled, i.e., DAD=1, the stack
* generates a short address dynamically.
*
* - \section reset-addr Resetting short address.
* - net_ext_reset_short_address_from_app(), Clears any user-specified static or default short address and enables dynamic generation.
*/
/**
* \brief Function to set short address from application.
*
* \param short_id 16-bit user-specified short address.
* \param generate_dynamical_at_DAD Set 1 if stack is allowed to generate new short address dynamically in case of DAD, otherwise set 0.
*
* \return 0xfffe or 0xffff when the stack does not use any short address.
*/
extern void net_ext_set_short_address_from_app(uint16_t short_id, uint8_t generate_dynamical_at_DAD);
/**
* \brief Clears currently used static or default short address and enables dynamic generation of new short address.
*/
extern void net_ext_reset_short_address_from_app(void);
/**
* \brief Get current short address used in the network for this particular interface.
*
* \return 0xfffe or 0xffff if stack is not using any short address.
*/
extern uint16_t net_ext_get_short_address(void);
#ifdef __cplusplus
}
#endif
#endif

61
nanostack/net_fhss.h Normal file
View File

@ -0,0 +1,61 @@
/*
* Copyright (c) 2015-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* \file net_fhss.h
* \brief FHSS API
*
*/
#ifndef NET_FHSS_H_
#define NET_FHSS_H_
#include "ns_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Creates FHSS API instance which will be registered to software MAC.
* @param fhss_configuration Basic FHSS configuration.
* @param fhss_timer FHSS platform timer interface and configuration.
* @param fhss_statistics FHSS statistics storage.
* @return New FHSS instance if successful, NULL otherwise.
*/
extern fhss_api_t *ns_fhss_create(const fhss_configuration_t *fhss_configuration, const fhss_timer_t *fhss_timer, fhss_statistics_t *fhss_statistics);
/**
* @brief Set synchronization time configuration for FHSS network. Should be only called from Border router.
* @param fhss_api FHSS instance.
* @param fhss_synch_configuration FHSS synchronization time configuration.
* @return 0 on success, -1 on fail.
*/
extern int ns_fhss_configuration_set(fhss_api_t *fhss_api, const fhss_synch_configuration_t *fhss_synch_configuration);
/**
* @brief Deletes a FHSS API instance and removes it from software MAC.
* @param fhss_api FHSS instance.
* @return 0 on success, -1 on fail.
*/
extern int ns_fhss_delete(fhss_api_t *fhss_api);
#ifdef __cplusplus
}
#endif
#endif /* NET_FHSS_H_ */

993
nanostack/net_interface.h Normal file
View File

@ -0,0 +1,993 @@
/*
* Copyright (c) 2014-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef NET_INTERFACE_H_
#define NET_INTERFACE_H_
#include "ns_types.h"
#include "platform/arm_hal_phy.h"
#ifdef __cplusplus
extern "C" {
#endif
struct mac_api_s;
struct eth_mac_api_s;
/**
* \file net_interface.h
* \brief Network API
*/
/** Network Interface Status */
typedef enum arm_nwk_interface_status_type_e {
ARM_NWK_BOOTSTRAP_READY = 0, /**< Interface configured Bootstrap is ready.*/
ARM_NWK_RPL_INSTANCE_FLOODING_READY, /**< RPL instance has been flooded. */
ARM_NWK_SET_DOWN_COMPLETE, /**< Interface DOWN command completed successfully. */
ARM_NWK_NWK_SCAN_FAIL, /**< Interface has not detected any valid network. */
ARM_NWK_IP_ADDRESS_ALLOCATION_FAIL, /**< IP address allocation failure (ND, DHCPv4 or DHCPv6). */
ARM_NWK_DUPLICATE_ADDRESS_DETECTED, /**< User-specific GP16 was not valid. */
ARM_NWK_AUHTENTICATION_START_FAIL, /**< No valid authentication server detected behind the access point. */
ARM_NWK_AUHTENTICATION_FAIL, /**< Network authentication failed by handshake. */
ARM_NWK_NWK_CONNECTION_DOWN, /**< No connection between access point and default router. */
ARM_NWK_NWK_PARENT_POLL_FAIL, /**< Sleepy host poll failed 3 times. Interface is shut down. */
ARM_NWK_PHY_CONNECTION_DOWN, /**< Interface PHY cable off or serial port interface not responding anymore. */
} arm_nwk_interface_status_type_e;
/** Event library type. */
typedef enum arm_library_event_type_e {
ARM_LIB_TASKLET_INIT_EVENT = 0, /**< Tasklet init occurs always when generating a tasklet. */
ARM_LIB_NWK_INTERFACE_EVENT, /**< Interface bootstrap or state update event. */
ARM_LIB_SYSTEM_TIMER_EVENT, /*!*< System timer event. */
APPLICATION_EVENT, /**< Application-specific event. */
} arm_library_event_type_e;
/*
* Socket event description:
*
* 8-bit variable where four MSB bits describes the event type and
* four LSB bits describes the socket that has received the event.
*
* Type Socket ID
* ---- ----
* xxxx xxxx
*
*/
/** \name Socket type exceptions.
* @{
*/
/** Socket event mask. */
#define SOCKET_EVENT_MASK 0xF0
/** Data received. */
#define SOCKET_DATA (0 << 4)
/** TCP connection ready. */
#define SOCKET_CONNECT_DONE (1 << 4)
/** TCP connection failure. */
#define SOCKET_CONNECT_FAIL (2 << 4)
/** TCP connection authentication failed. */
#define SOCKET_CONNECT_AUTH_FAIL (3 << 4)
/** TCP incoming connection on listening socket */
#define SOCKET_INCOMING_CONNECTION (4 << 4)
/** Socket data send failure. */
#define SOCKET_TX_FAIL (5 << 4)
/** TCP connection closed (received their FIN and ACK of our FIN). */
#define SOCKET_CONNECT_CLOSED (6 << 4)
/** TCP connection reset */
#define SOCKET_CONNECTION_RESET (7 << 4)
/** No route available to the destination. */
#define SOCKET_NO_ROUTE (8 << 4)
/** Socket TX done. */
#define SOCKET_TX_DONE (9 << 4)
/** Out of memory failure. */
#define SOCKET_NO_RAM (10 << 4)
/** TCP connection problem indication (RFC 1122 R1) */
#define SOCKET_CONNECTION_PROBLEM (11 << 4)
#define SOCKET_BIND_DONE SOCKET_CONNECT_DONE /**< Backward compatibility */
#define SOCKET_BIND_FAIL SOCKET_CONNECT_FAIL /**< Backward compatibility */
#define SOCKET_BIND_AUTH_FAIL SOCKET_CONNECT_AUTH_FAIL /**< Backward compatibility */
/* @} */
/** Network security levels. */
typedef enum net_security_t {
NW_NO_SECURITY = 0, /**< No Security. */
NW_SECURITY_LEVEL_MIC32 = 1, /**< 32-bit MIC verify, no encoding. */
NW_SECURITY_LEVEL_MIC64 = 2, /**< 64-bit MIC verify, no encoding. */
NW_SECURITY_LEVEL_MIC128 = 3, /**< 128-bit MIC verify, no encoding. */
NW_SECURITY_LEVEL_ENC = 4, /**< AES encoding without MIC. */
NW_SECURITY_LEVEL_ENC_MIC32 = 5, /**< 32-bit MIC verify with encoding. */
NW_SECURITY_LEVEL_ENC_MIC64 = 6, /**< 64-bit MIC verify with encoding. */
NW_SECURITY_LEVEL_ENC_MIC128 = 7 /**< 128-bit MIC verify with encoding. */
} net_security_t;
/** Ipv6 address type.*/
typedef enum net_address_t {
ADDR_IPV6_GP, /**< Node default global address. */
ADDR_IPV6_GP_SEC, /**< Node secondary global address. */
ADDR_IPV6_LL /**< Node default link local address. */
} net_address_t;
/** MAC address type. */
typedef enum net_mac_address_t {
ADDR_MAC_SHORT16, /**< Nodes 16-bit short address. */
ADDR_MAC_LONG64, /**< IP layer EUID64 based on MAC layer 64-bit long address after U/I -bit conversion. */
} net_mac_address_t;
/** TLS cipher type */
typedef enum {
NET_TLS_PSK_CIPHER, /**< Network authentication support, only PSK. */
NET_TLS_ECC_CIPHER, /**< Network authentication support, only ECC. */
NET_TLS_PSK_AND_ECC_CIPHER, /**< Network authentication support, PSK & ECC. */
} net_tls_cipher_e;
/** PANA session type. */
typedef enum {
NET_PANA_SINGLE_SESSION, /**< Client tracks only one PANA session data, default use case. */
NET_PANA_MULTI_SESSION, /**< Client supports many Start network coordinator session data */
} net_pana_session_mode_e;
/** 6LoWPAN network security & authentication modes. */
typedef enum {
NET_SEC_MODE_NO_LINK_SECURITY, /**< Security disabled at link layer, DEFAULT. */
NET_SEC_MODE_PSK_LINK_SECURITY, /**< Link security by PSK key. */
NET_SEC_MODE_PANA_LINK_SECURITY, /**< PANA network authentication defined link KEY. */
} net_6lowpan_link_layer_sec_mode_e;
/** Bootstrap modes */
typedef enum {
NET_6LOWPAN_BORDER_ROUTER, /**< Root device for 6LoWPAN ND. */
NET_6LOWPAN_ROUTER, /**< Router device. */
NET_6LOWPAN_HOST, /**< Host device DEFAULT setting. */
NET_6LOWPAN_SLEEPY_HOST, /**< Sleepy host device. */
NET_6LOWPAN_NETWORK_DRIVER, /**< 6LoWPAN radio host device, no bootstrap. */
NET_6LOWPAN_SNIFFER /**< Sniffer device, no bootstrap. */
} net_6lowpan_mode_e;
/** 6LoWPAN Extension modes. */
typedef enum {
NET_6LOWPAN_ND_WITHOUT_MLE, /**< **UNSUPPORTED** */
NET_6LOWPAN_ND_WITH_MLE, /**< 6LoWPAN ND with MLE. */
NET_6LOWPAN_THREAD, /**< 6LoWPAN Thread with MLE attached. */
NET_6LOWPAN_ZIGBEE_IP /**< **UNSUPPORTED** */
} net_6lowpan_mode_extension_e;
/** IPv6 bootstrap modes */
typedef enum {
NET_IPV6_BOOTSTRAP_STATIC, /**< Application defines the IPv6 prefix. */
NET_IPV6_BOOTSTRAP_AUTONOMOUS /**< Interface gets IPv6 address automatically from network using ICMP and DHCP. */
} net_ipv6_mode_e;
/** IPv6 accept RA behaviour */
typedef enum {
NET_IPV6_RA_ACCEPT_IF_AUTONOMOUS, /**<Accept Router Advertisements when using autonomous IPv6 address allocation. Ignore when using a static address. This is the default value for the setting. */
NET_IPV6_RA_ACCEPT_ALWAYS /**<Accept Router Advertisements always, even when using static IPv6 address allocation. */
} net_ipv6_accept_ra_e;
/** Network coordinator parameter list.
* Structure is used to read network parameter for warm start.
*/
typedef struct link_layer_setups_s {
uint16_t PANId; /**< Network PAN-ID. */
uint8_t LogicalChannel; /**< Network logical channel. */
net_mac_address_t addr_mode; /**< Coordinator address mode. */
uint8_t address[8]; /**< Coordinator address. */
uint8_t sf; /**< Network superframe setup. */
} link_layer_setups_s;
/** Network MAC address info. */
typedef struct link_layer_address_s {
uint16_t PANId; /**< Network PAN-ID. */
uint16_t mac_short; /**< MAC short address, if <0xfffe then is valid. */
uint8_t mac_long[8]; /**< MAC long address (EUI-48 for Ethernet; EUI-64 for IEEE 802.15.4). */
uint8_t iid_eui64[8]; /**< IPv6 interface identifier based on EUI-64. */
} link_layer_address_s;
/** Network layer parent address info. */
typedef struct network_layer_address_s {
uint8_t border_router[16]; /**< ND Border Router Address. */
uint8_t prefix[8]; /**< Long 64-bit network ID. */
} network_layer_address_s;
/** Different addressing modes for a network interface. */
typedef enum {
NET_6LOWPAN_GP64_ADDRESS, /**< Interface registers only GP64 address. */
NET_6LOWPAN_GP16_ADDRESS, /**< Interface registers only GP16 address. */
NET_6LOWPAN_MULTI_GP_ADDRESS, /**< Interface registers GP16 & GP64 addresses. */
} net_6lowpan_gp_address_mode_e;
/** TLS PSK info */
typedef struct net_tls_psk_info_s {
uint32_t key_id; /**< PSK Key ID can be 0x01-0xffff, storage size is intentionally 32 bits. */
uint8_t key[16]; /**< 128-bit PSK Key. */
} net_tls_psk_info_s;
/** NETWORK PSK link key structure. */
typedef struct {
uint8_t key_id; /**< Link layer PSK Key ID, can be 0x01-0xff. */
uint8_t security_key[16]; /**< Link layer 128-bit PSK Key. */
} net_link_layer_psk_security_info_s;
/** Certificate chain structure. */
typedef struct {
uint8_t chain_length; /**< Certificate chain length, indicates the chain length. */
const uint8_t *cert_chain[4]; /**< Certificate chain pointer list. */
uint16_t cert_len[4]; /**< Certificate length. */
const uint8_t *key_chain[4]; /**< Certificate private key. */
} arm_certificate_chain_entry_s;
/** Structure for the network keys used by net_network_key_get */
typedef struct ns_keys_t
{
uint8_t previous_active_network_key[16]; /**< The key that is currently active when a new key is generated and activated. */
uint8_t previous_active_key_index; /**< The index associated to the current_active_network_key. */
uint8_t current_active_network_key[16]; /**< Last generated and activated key. */
uint8_t current_active_key_index; /**< The index associated to the current_active_network_key. */
} ns_keys_t;
/** 6LoWPAN border router information structure. */
typedef struct {
uint16_t mac_panid; /**< Link layer PAN-ID, accepts only < 0xfffe. */
uint16_t mac_short_adr; /**< Defines 802.15.4 short address. If the value is <0xfffe it indicates that GP16 is activated. */
uint8_t beacon_protocol_id; /**< ZigBeeIP uses always 2. */
uint8_t network_id[16]; /**< Network ID 16-bytes, will be used at beacon payload. */
uint8_t lowpan_nd_prefix[8]; /**< Define ND default prefix, ABRO, DODAG ID, GP address. */
uint16_t ra_life_time; /**< Define ND router lifetime in seconds, recommend value 180+. */
uint32_t abro_version_num; /**< ND ABRO version number (0 when starting a new ND setup). */
} border_router_setup_s;
/** Channel list */
typedef struct channel_list_s
{
channel_page_e channel_page; /**< Channel page */
uint32_t channel_mask[8]; /**< Channel mask. Each bit defining one channel */
} channel_list_s;
/** 6LoWPAN radio interface setup. */
typedef struct {
uint16_t mac_panid; /**< Link layer PAN-ID, accepts only < 0xfffe. */
uint16_t mac_short_adr; /**< Defines 802.15.4 short address. If the value is <0xfffe it indicates that GP16 is activated. */
uint8_t beacon_protocol_id; /**< ZigBeeIP uses always 2. */
uint8_t network_id[16]; /**< Network ID 16-bytes, will be used at beacon payload. */
uint8_t beacon_payload_tlv_length; /**< Optional steering parameter length. */
uint8_t *beacon_payload_tlv_ptr; /**< Optional steering parameters. */
} network_driver_setup_s;
/**
* Init 6LoWPAN library
*
* \return 0, Init OK.
*/
extern int8_t net_init_core(void);
/**
* \brief Create network interface base to IDLE state.
* \param api Generates interface with ethernet MAC.
* \param interface_name_ptr String pointer to interface name. Need to end to '\0' character.
* Max length 32 characters including NULL at end. Note: the given name is not copied,
* so it must remain valid as long as the interface is.
*
* \return >=0 Interface ID (0-127). Application needs to save this information.
* \return -1 api was NULL.
* \return -2 Ethernet is not supported at this build.
* \return -3 No memory for the interface.
*/
extern int8_t arm_nwk_interface_ethernet_init(struct eth_mac_api_s *api, const char *interface_name_ptr);
/**
* \brief Create network interface base to IDLE state.
* \param api Generates interface with 802.15.4 MAC.
* \param interface_name_ptr String pointer to interface name. Need to end to '\0' character.
* Max length 32 characters including NULL at end. Note: the given name is not copied,
* so it must remain valid as long as the interface is.
*
* \return >=0 Interface ID (0-127). Application needs to save this information.
* \return -1 api was NULL.
* \return -3 No memory for the interface.
*/
extern int8_t arm_nwk_interface_lowpan_init(struct mac_api_s *api, char *interface_name_ptr);
/**
* \brief Set IPv6 interface setup.
*
* \param interface_id Network interface ID.
* \param bootstrap_mode Selected bootstrap mode:
* * NET_IPV6_BOOTSTRAP_STATIC, Application defines the IPv6 prefix.
* \param ipv6_prefix_pointer Pointer to 64 bit IPv6 prefix. The data is copied, so it can be invalidated after function call.
*
* \return >=0 Bootstrap mode set OK.
* \return -1 Unknown network ID.
*/
extern int8_t arm_nwk_interface_configure_ipv6_bootstrap_set(int8_t interface_id, net_ipv6_mode_e bootstrap_mode, const uint8_t *ipv6_prefix_pointer);
/**
* \brief Accept Router Advertisements setting.
*
* Accept Router Advertisements setting. Setting can be changed after an interface is created.
* If setting is changed it must be done before the bootstrap is started.
*
* \param interface_id The network interface ID.
* \param accept_ra Router Advertisements handling mode.
* \return 0 Setting done.
* \return <0 Failed (for example an invalid interface ID).
*/
extern int8_t arm_nwk_interface_accept_ipv6_ra(int8_t interface_id, net_ipv6_accept_ra_e accept_ra);
/**
* \brief Set network interface bootstrap setup.
*
* \param interface_id Network interface ID.
* \param bootstrap_mode Selected bootstrap mode:
* * NET_6LOWPAN_BORDER_ROUTER, Initialize border router basic setup.
* * NET_6LOWPAN_ROUTER, Enable normal 6LoWPAN ND and RPL to bootstrap.
* * NET_6LOWPAN_HOST, Enable normal 6LoWPAN ND only to bootstrap.
* * NET_6LOWPAN_SLEEPY_HOST, Enable normal 6LoWPAN ND only to bootstrap.
* * NET_6LOWPAN_NETWORK_DRIVER, 6LoWPAN radio host device no bootstrap.
* * NET_6LOWPAN_SNIFFER, 6LoWPAN sniffer device no bootstrap.
*
* \param net_6lowpan_mode_extension Define 6LoWPAN MLE and mode as ZigBeeIP or Thread.
*
* \return >=0 Bootstrap mode set OK.
* \return -1 Unknown network ID.
* \return -2 Unsupported bootstrap type in this library.
* \return -3 No memory for 6LoWPAN stack.
* \return -4 Null pointer parameter.
*/
extern int8_t arm_nwk_interface_configure_6lowpan_bootstrap_set(int8_t interface_id, net_6lowpan_mode_e bootstrap_mode, net_6lowpan_mode_extension_e net_6lowpan_mode_extension);
/**
* \brief Set network interface link layer parameters.
*
* \param interface_id Network interface ID
* \param nwk_channel_list Defines network channel page and channel.
* \param link_setup Link layer parameters for NET_6LOWPAN_NETWORK_DRIVER defines NetworkID, PAN-ID Short Address.
*
* \return >=0 Configuration set OK.
* \return -1 Unknown network ID.
* \return -2 Interface is active, bootsrap mode not selected or is not NET_6LOWPAN_NETWORK_DRIVER or NET_6LOWPAN_SNIFFER.
* \return -3 No memory for 6LoWPAN stack.
* \return -4 Null pointer parameter.
*/
extern int8_t arm_nwk_interface_network_driver_set(int8_t interface_id, const channel_list_s *nwk_channel_list, network_driver_setup_s *link_setup);
/**
* \brief Set configured network interface global address mode (border router bootstrap mode cannot set this).
*
* \param interface_id Network interface ID.
* \param mode Define 6LoWPAN Global Address register mode:
* * NET_6LOWPAN_GP64_ADDRESS, Interface registers only GP64
* * NET_6LOWPAN_GP16_ADDRESS, Interface registers only GP16
* * NET_6LOWPAN_MULTI_GP_ADDRESS, Interface registers GP16 and GP64 addresses. GP16 is primary address and GP64 is secondary.
*
* \param short_address_base Short address base. If the application defines value 0-0xfffd, 6LoWPAN tries to register GP16 address
* using that address. 0xfffe and 0xffff generate random 16-bit short address.
*
* \param define_new_short_address_at_DAD This parameter is only checked when mode is not NET_6LOWPAN_GP64_ADDRESS and
* short_address_base is 0-0xfffd. Recommended value is 1. It enables automatic new address definition at
* Duplicate Address Detection (DAD). Value 0 generates a DAD error for the interface bootstrap.
* Border router device will not check that part.
*
* \return >=0 Bootstrap mode set OK.
* \return -1 Unknown network ID.
* \return -2 Illegal for border router.
* \return -3 No memory for 6LoWPAN stack.
*/
extern int8_t arm_nwk_6lowpan_gp_address_mode(int8_t interface_id, net_6lowpan_gp_address_mode_e mode, uint16_t short_address_base, uint8_t define_new_short_address_at_DAD);
/**
* \brief Set the channel list configuration to be used on the network interface.
*
* \param interface_id Network interface ID.
* \param nwk_channel_list Channel list to be used.
*
* \return >=0 Channel configuration OK.
* \return -1 Unknown network interface ID.
* \return -2 Empty channel list, no channels enabled.
* \return -4 If network interface is already active and cannot be re-configured.
*/
extern int8_t arm_nwk_set_channel_list(int8_t interface_id, const channel_list_s *nwk_channel_list);
/**
* \brief Set the link scan time used on network interface.
*
* \param interface_id Network interface ID.
* \param scan_time Value 0-14, scan duration/channel.
*
* \return >=0 Scan configuration OK.
* \return -1 Unknown network interface ID.
* \return -4 If network interface is already active and cannot be re-configured.
* \return -5 Invalid scan time.
*/
extern int8_t arm_nwk_6lowpan_link_scan_parameter_set(int8_t interface_id, uint8_t scan_time);
/**
* \brief A function to set the PAN ID filter.
*
* \param interface_id Network interface ID.
* \param pan_id_filter Enable filter for specific PAN ID. 0xffff disables the filter.
*
* \return 0 Filter set OK.
* \return -1 Unknown Network interface ID.
* \return -2 Interface is active.
*
*/
extern int8_t arm_nwk_6lowpan_link_panid_filter_for_nwk_scan(int8_t interface_id, uint16_t pan_id_filter);
/**
* \brief Get current used channel.
*
* \param interface_id Network interface ID.
*
* \return Active channel.
* \return -1 = Radio is closed.
*/
extern int16_t arm_net_get_current_channel(int8_t interface_id);
/**
* \brief A function to read the PAN ID filter.
*
* \param interface_id Network interface ID.
*
* \return 16-bit value indicating a PAN ID filter.
*/
extern uint16_t arm_net_get_nwk_pan_id_filter(int8_t interface_id);
/**
* \brief Enable/Disable network ID filter.
*
* \param interface_id Network interface ID.
* \param nwk_id_filter A pointer to a new network ID filter, NULL disable filter.
*
* \return 0 On success.
* \return -1 Unknown network ID.
* \return -2 Interface active.
*/
extern int8_t arm_nwk_6lowpan_link_nwk_id_filter_for_nwk_scan(int8_t interface_id, const uint8_t *nwk_id_filter);
/**
* \brief Enable/Disable network protocol ID filter.
*
* \param interface_id Network interface ID.
* \param protocol_ID A value that filters only supported network protocols (0= Zigbee1.x, 2= ZigBeeIP).
*
* \return 0 On success.
* \return -1 Unknown network ID.
* \return -2 Interface active.
*/
extern int8_t arm_nwk_6lowpan_link_protocol_id_filter_for_nwk_scan(int8_t interface_id, uint8_t protocol_ID);
/**
* \brief Beacon join priority transmit callback.
*
* Callback defines join priority that is transmitted in beacon. Join priority is
* 8 bit field in beacon that can be set e.g. based on RPL protocol rank data.
*
* \param interface_id The network interface ID.
*
* \return Join priority to be transmitted in beacon. 0 to 255.
*/
typedef uint8_t beacon_join_priority_tx_cb(int8_t interface_id);
/**
* \brief Compare received beacon callback.
*
* Callback defines how preferred the node that has sent beacon is for connecting
* to the network.
*
* \param interface_id The network interface ID.
* \param join_priority Join priority that has been received in beacon. 0 to 255.
* \param link_quality Link quality. 0 to 255. 255 is best quality.
*
* \return Connect to preference. 0 to 255. 255 is highest connect to preference.
*/
typedef uint8_t beacon_compare_rx_cb(int8_t interface_id, uint8_t join_priority, uint8_t link_quality);
/**
* \brief Set callback for beacon join priority transmit
*
* Sets callback that defines join priority that is transmitted in beacon.
* If callback is not set default functionality is used. On default functionality
* join priority is combined from RPL DAGRank and RPL DODAG preference.
*
* \param interface_id The network interface ID.
* \param beacon_join_priority_tx_cb_ptr Function pointer.
*
* \return 0 on success.
* \return -1 Unknown network ID.
* \return -2 Other error.
*/
extern int8_t arm_nwk_6lowpan_beacon_join_priority_tx_callback_set(int8_t interface_id, beacon_join_priority_tx_cb *beacon_join_priority_tx_cb_ptr);
/**
* \brief Set callback for comparing received beacon
*
* Sets callback that defines how preferred the node that has sent beacon is for
* connecting to the network. If callback is not set default functionality is used.
* On default functionality connecting priority is defined based on join priority
* received in beacon and link quality.
*
* \param interface_id Network interface ID.
* \param beacon_compare_rx_cb_ptr Function pointer.
*
* \return 0 on success.
* \return -1 Unknown network ID.
* \return -2 Other error.
*/
extern int8_t arm_nwk_6lowpan_beacon_compare_rx_callback_set(int8_t interface_id, beacon_compare_rx_cb *beacon_compare_rx_cb_ptr);
/**
* \brief Initialize and configure the interface security mode.
*
* \param interface_id Network interface ID.
* \param mode Defines link layer security mode.
* NET_SEC_MODE_NO_LINK_SECURITY, No security.
* NET_SEC_MODE_PSK_LINK_SECURITY, Predefined PSK link layer key and ID.
* NET_SEC_MODE_PANA_LINK_SECURITY, PANA bootstrap network authentication.
*
* \param sec_level Defined security level is checked only when the mode is not NET_SEC_MODE_NO_LINK_SECURITY.
* \param psk_key_info Pointer for PSK link layer keys. Checked only when the mode is NET_SEC_MODE_PSK_LINK_SECURITY.
*
* \return 0 on success.
*/
extern int8_t arm_nwk_link_layer_security_mode(int8_t interface_id, net_6lowpan_link_layer_sec_mode_e mode, uint8_t sec_level, const net_link_layer_psk_security_info_s *psk_key_info);
/**
* \brief Initialize and configure interface PANA network client.
*
* \param interface_id Network interface ID.
* \param cipher_mode Defines TLS 1.2 Cipher mode PSK, ECC or both.
* \param psk_key_id PSK KEY id for PSK Setup
*
* \return 0 on success.
* \return -1 Unknown network ID or PANA is not supported at this library.
* \return -2 Interface active.
*/
extern int8_t arm_pana_client_library_init(int8_t interface_id, net_tls_cipher_e cipher_mode, uint32_t psk_key_id);
/**
* \brief Initialize and Configure interface PANA network server.
*
* \param interface_id Network interface ID.
* \param cipher_mode Defines TLS 1.2 Cipher mode PSK, ECC or both.
* \param key_material A pointer to 128-bit key material or NULL when the PANA server generates the random key.
* \param time_period_before_activate_key Guard period after a succesful key delivery phase before the key will be activated by server.
*
* \return 0 On success.
* \return -1 Unknown network ID.
* \return -2 Interface active.
*/
extern int8_t arm_pana_server_library_init(int8_t interface_id, net_tls_cipher_e cipher_mode, const uint8_t *key_material, uint32_t time_period_before_activate_key);
/**
* \brief Manually initiate a PANA client key pull. For test purposes only.
*
* \param interface_id Network interface ID.
*
* \return 0 On success.
* \return -1 Unknown network ID.
*/
extern int8_t arm_pana_client_key_pull(int8_t interface_id);
/**
* \brief Trigger network key update process
*
* This function delivers a new network key to all ZigBee routers that have registered a GP address to server.
* The function call always trig new key-id. Key delivery is started in 300ms interval between nodes.
* This function does not cause any traffic if the server does not have any router device sessions.
*
* \param interface_id Network interface ID.
* \param network_key_material Pointer to new 128-bit key material, NULL generates a random key.
*
* \return 0 Key Update process OK.
* \return -1 PANA server is not initialized yet.
* \return -2 Old key update still active.
* \return -3 Memory allocation fails.
*/
extern int8_t arm_pana_server_key_update(int8_t interface_id, const uint8_t *network_key_material);
/**
* \brief Activate new key material before standard timeout.
*
* This function is only for testing.
*
* \param interface_id Network interface ID.
*
* \return 0 Key activate process OK.
* \return -1 No Pending key update.
* \return -2 PANA server is not initialized or PANA server API is disabled with this library.
*/
extern int8_t arm_pana_activate_new_key(int8_t interface_id);
/**
* \brief Read PANA server security key material.
*
* previous_active_network_key Only valid when current_active_key_index is bigger than 1.
*
* \param interface_id Interface
* \param key Pointer for key material information store.
*
* \return 0 Key read OK.
* \return -1 PANA server key material not available.
*/
extern int8_t arm_network_key_get(int8_t interface_id, ns_keys_t *key);
/**
* \brief Start network interface bootstrap.
*
* \param interface_id Network interface ID.
*
*
* \return >=0 Bootstrap start OK.
* \return -1 Unknown network ID.
* \return -2 Not configured.
* \return -3 Active.
*/
extern int8_t arm_nwk_interface_up(int8_t interface_id);
/**
* \brief Stop and set interface to idle.
*
* \param interface_id Network interface ID
*
* \return >=0 Process OK.
* \return -1 Unknown network ID.
* \return -3 Not Active.
*/
extern int8_t arm_nwk_interface_down(int8_t interface_id);
/**
* \brief Define border router MAC and 6LoWPAN ND setup for selected interface.
*
* \param interface_id Network interface ID.
* \param border_router_setup_ptr Pointer to MAC and 6LoWPAN ND setup.
*
* \return 0 on success, negative value on error case.
*/
extern int8_t arm_nwk_6lowpan_border_router_init(int8_t interface_id, const border_router_setup_s *border_router_setup_ptr);
/**
* \brief Add context at 6LoWPAN interface configure state.
*
* \param interface_id Network interface ID.
* \param c_id_flags Bit 4 indicates compress support and bit 0-3 context ID.
* \param context_len Context length in bits need to be 64-128.
* \param ttl Context time to live, value in minutes.
* \param context_ptr Pointer to full 128-bit memory area.
*
* \return 0 Context update OK.
* \return -1 No memory for new context.
* \return -2 Border router base not allocated.
* \return -3 Given parameter fails (c_id_flags > 0x1f or contex_len < 64).
* \
*/
extern int8_t arm_nwk_6lowpan_border_router_context_update(int8_t interface_id, uint8_t c_id_flags, uint8_t context_len, uint16_t ttl, const uint8_t *context_ptr);
/**
* \brief Update runtime configured context.
*
* This function can change the value of context compress state or time to live.
* It triggers a new ABRO version number, indicating that ND parameters are updated.
*
* \param interface_id Network interface ID.
* \param c_id Context ID stack checks first 4 bits, supported values 0-15.
* \param compress_mode 0 = Compress disabled, otherwise compress enabled.
* \param ttl Context time to live value in minutes.
*
* \return 0 Update OK.
* \return -1 Update fail by router state.
*
*/
extern int8_t arm_nwk_6lowpan_border_router_context_parameter_update(int8_t interface_id, uint8_t c_id, uint8_t compress_mode, uint16_t ttl);
/**
* \brief Delete allocated context by ID.
*
* \param interface_id Network interface ID.
* \param c_id 4-bit Context ID to be deleted.
*
* \return 0 Context delete OK.
* \return -1 Delete process fails.
*/
extern int8_t arm_nwk_6lowpan_border_router_context_remove_by_id(int8_t interface_id, uint8_t c_id);
/**
* \brief Update ND ABRO version number.
*
* \param interface_id Network interface ID
*
* \return 0 ABRO version update OK.
* \return -1 ABRO update fails (Interface is not up yet or the border router base is not allocated).
*/
extern int8_t arm_nwk_6lowpan_border_router_configure_push(int8_t interface_id);
/**
* Set timeout for default prefix on cache.
* Requires arm_nwk_6lowpan_border_router_configure_push() be called to settings be taken into use.
* \param interface_id mesh interface.
* \param time seconds
* \return 0 on success, negative value on failure.
*/
extern int8_t arm_nwk_6lowpan_border_route_nd_default_prefix_timeout_set(int8_t interface_id, uint32_t time);
/**
* \brief A function to read network layer configurations.
* \param interface_id Network interface ID.
* \param network_params A pointer to the structure where the network layer configs are written.
* \return 0 On success.
* \return Negative value if interface is not known.
*/
int8_t arm_nwk_param_read(int8_t interface_id, link_layer_setups_s *network_params);
/**
* \brief A function to read MAC PAN-ID, Short address and EUID64.
* \param interface_id Network interface ID.
* \param mac_params A pointer to the structure where the MAC addresses are written.
* \return 0 On success.
* \return Negative value if interface is not known.
*/
int8_t arm_nwk_mac_address_read(int8_t interface_id, link_layer_address_s *mac_params);
/**
* \brief A function to read 6LoWPAN ND border router address and NWK prefix.
* \param interface_id Network interface ID.
* \param nd_addr_info Pointer to the structure where the address is written.
* \return 0 On success.
* \return Negative value if network interface is not known or if the interface
* is not in active or ready state.
*/
int8_t arm_nwk_nd_address_read(int8_t interface_id, network_layer_address_s *nd_addr_info);
/**
* \brief A function to read the networking address information.
* \param interface_id Network interface ID.
* \param addr_id The address information type to be read.
* \param address A pointer to a structure where the address information is written.
* \return 0 On success, -1 on failure.
*/
extern int8_t arm_net_address_get(int8_t interface_id, net_address_t addr_id, uint8_t *address);
/**
* \brief A function to read networking addresses one by one.
* \param interface_id Network interface ID.
* \param n A pointer that is incremented every call. Start looping with n=0.
* \param address_buffer A pointer to buffer where address is copied.
* \return 0 On success.
* \return -1 No more addresses available.
*/
extern int8_t arm_net_address_list_get_next(int8_t interface_id, int *n, uint8_t address_buffer[16]);
/**
* \brief A function to read network interface address count.
* \param interface_id Network interface ID.
* \param address_count A pointer to the structure where the address count is saved.
*
* \return 0 On success, -1 on errors.
*/
extern int8_t arm_net_interface_address_list_size(int8_t interface_id, uint16_t *address_count);
/**
* \brief A function to set interface metric.
* \param interface_id Network interface ID.
* \param metric Used to rank otherwise-equivalent routes. Lower is preferred and default is 0. The metric value is added to metric provided by the arm_net_route_add() function.
*
* \return 0 On success, -1 on errors.
*/
extern int8_t arm_net_interface_set_metric(int8_t interface_id, uint16_t metric);
/**
* \brief A function to read the interface metric value on an interface.
* \param interface_id Network interface ID.
* \param metric A pointer to the variable where the interface metric value is saved.
*
* \return 0 On success, -1 on errors.
*/
extern int8_t arm_net_interface_get_metric(int8_t interface_id, uint16_t *metric);
/**
* \brief A function to read the network interface.
* \param interface_id Network interface ID.
* \param address_buf_size Buffer size in bytes, minimum 16 bytes.
* \param address_buffer A pointer to a structure where the addresses are saved one by one.
* \param writed_address_count A pointer to the structure where the number of addresses saved is written.
*
* \return 0 on success, -1 on errors.
*/
extern int8_t arm_net_address_list_get(int8_t interface_id, uint8_t address_buf_size, uint8_t *address_buffer, int *writed_address_count);
/**
* \brief A function to add an address to an interface.
* \param interface_id Network interface ID.
* \param address The address to be added to the interface.
* \param prefix_len The length of the address prefix.
* \param valid_lifetime The time in seconds until the address becomes invalid and is removed from the interface. Value 0xffffffff represents infinity.
* \param preferred_lifetime The time in seconds until the address becomes deprecated. Value 0xffffffff represents infinity. The preferred lifetime should not be longer than a valid lifetime.
* \return 0 on success, -1 on errors.
*/
extern int8_t arm_net_address_add_to_interface(int8_t interface_id, const uint8_t address[16], uint8_t prefix_len, uint32_t valid_lifetime, uint32_t preferred_lifetime);
/**
* \brief A function to remove an address from an interface.
* \param interface_id Network interface ID.
* \param address The address to be removed from the interface.
*
* \return 0 on success, -1 on errors.
*/
extern int8_t arm_net_address_delete_from_interface(int8_t interface_id, const uint8_t address[16]);
/**
* \brief A function to add a route to the routing table.
* \param prefix Destination prefix for the route to be added.
* \param prefix_len The length of the prefix.
* \param next_hop Link-local address of the next hop (e.g. router); if NULL the route is marked as on-link.
* \param lifetime The time in seconds until the route is removed from the routing table. Value 0xffffffff means infinite.
* \param metric Used to rank otherwise-equivalent routes. Lower is preferred. Normally 128.
* \param interface_id Network interface ID.
* \return 0 on success, -1 on add failure, -2 on invalid function parameters.
*/
extern int8_t arm_net_route_add(const uint8_t *prefix, uint8_t prefix_len, const uint8_t *next_hop, uint32_t lifetime, uint8_t metric, int8_t interface_id);
/**
* \brief A function to remove a route from the routing table.
* \param prefix The prefix to be removed.
* \param prefix_len The length of the prefix.
* \param next_hop Link-local address of the next hop.
* \param interface_id Network interface ID.
* \return 0 on success, -1 on delete failure, -2 on invalid function parameters.
*/
extern int8_t arm_net_route_delete(const uint8_t *prefix, uint8_t prefix_len, const uint8_t *next_hop, int8_t interface_id);
/** Border Router ND NVM update types. */
/** ND context update, 20 bytes data behind pointer. */
#define ND_PROXY_CONTEXT_NVM_UPDATE 0
/** ND context update flags update. */
#define ND_PROXY_CONTEXT_FLAGS_NVM_UPDATE 1
/** ND context remove. */
#define ND_PROXY_CONTEXT_NVM_REMOVE 2
/** ND prefix update. */
#define ND_PROXY_PREFIX_NVM_UPDATE 3
/** ND ABRO version update. */
#define ND_PROXY_ABRO_VERSION_NVM_UPDATE 4
/**
* \brief Load context from NVM at ZigBeeIP interface configure state.
*
* \param interface_id Network Interface ID
* \param contex_data A pointer to properly built 20 bytes update array.
*
* \return 0 Context reload OK.
* \return <0 Load fail.
*/
extern int8_t arm_nwk_6lowpan_border_router_nd_context_load(int8_t interface_id, uint8_t *contex_data); //NVM
/**
* Set certificate chain for PANA
* \param chain_info Certificate chain.
* \return 0 on success, negative on failure.
*/
extern int8_t arm_network_certificate_chain_set(const arm_certificate_chain_entry_s *chain_info);
/**
* \brief Add PSK key to TLS library.
*
* \param key_ptr A pointer to 16 bytes long key array.
* \param key_id PSK key ID.
*
* \return 0 = success
* \return -1 = failure
*/
extern int8_t arm_tls_add_psk_key(const uint8_t *key_ptr, uint16_t key_id);
/**
* \brief Remove PSK key from TLS library.
*
* \param key_id PSK key ID.
*
* \return 0 = success
* \return -1 = failure
*/
extern int8_t arm_tls_remove_psk_key(uint16_t key_id);
/**
* \brief Check if PSK key ID exists.
*
* \param key_id PSK key ID
*
* \return 0 = success
* \return -1 = failure
*/
extern int8_t arm_tls_check_key(uint16_t key_id);
/**
* \brief Print routing table
*
* Prints the routing table to the command line
*/
void arm_print_routing_table(void);
/**
* \brief Print routing table
*
* Outputs the routing table using the given printf style function
*
* \param print_fn pointer to a printf style output function
*/
void arm_print_routing_table2(void (*print_fn)(const char *fmt, ...));
/**
* \brief Flush neighbor cache
*
* Flushes the neighbor cache
*/
void arm_ncache_flush(void);
/**
* \brief Print neighbor cache
*
* Prints neighbor cache to the command line
*/
void arm_print_neigh_cache(void);
/**
* \brief Print neighbor cache
*
* Outputs the neighbor cache using the given printf style function
*
* \param print_fn pointer to a printf style output function
*/
void arm_print_neigh_cache2(void (*print_fn)(const char *fmt, ...));
/**
* \brief Print PCB list
*
* Prints Protocol Control Block list to the command line
*/
void arm_print_protocols(void);
/**
* \brief Print PCB list
*
* Prints Protocol Control Block list using the given printf style function
*
* \param print_fn pointer to a printf style output function
* \param sep column separator character
*/
void arm_print_protocols2(void (*print_fn)(const char *fmt, ...), char sep);
/**
* \brief Get the library version information.
*
* \param *ptr Pointer to data location. Required size is 20 bytes.
*
*
* The array containing the version information has the following structure.
*
* | Platform type | Version | Build ID |
* | :-----------: | :----------------: |
* | 1 byte | 1 byte | 4 bytes |
*
*/
extern void net_get_version_information(uint8_t *ptr);
#ifdef __cplusplus
}
#endif
#endif /* NET_INTERFACE_H_ */

100
nanostack/net_ipv6_api.h Normal file
View File

@ -0,0 +1,100 @@
/*
* Copyright (c) 2016-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* \file net_ipv6_api.h
* \brief IPv6 configuration API.
*/
#ifndef NET_IPV6_API_H_
#define NET_IPV6_API_H_
#include "ns_types.h"
/**
* \brief Set maximum IPv6 fragmented datagram reception size.
*
* Set the maximum size limit for fragmented datagram reception.
*
* RFC 2460 requires this to be at least 1500. It should also be at least
* as large as the MTU of each attached link.
*
* \param frag_mru The fragmented Maximum Receive Unit in octets.
* \return 0 Change OK - actual MRU is at least the requested value.
* \return <0 Change invalid - unable to set the specified MRU.
*/
int8_t arm_nwk_ipv6_frag_mru(uint16_t frag_mru);
/**
* \brief Set the maximum number of entries for the neighbour cache and
* destination cache. Default value is 64 and minimum allowed value is 4.
*
* Note: This must be called before arm_nwk_interface_lowpan_init()
*
* \param max_entries The absolute maximum entries allowed in cache at any time.
* \return 0 Change OK.
* \return <0 Change invalid - unable to change the maximum for cache.
*/
int8_t arm_nwk_ipv6_max_cache_entries(uint16_t max_entries);
/**
* \brief Configure automatic flow label calculation.
*
* Enable or disable automatic generation of IPv6 flow labels for outgoing
* packets.
*
* \param auto_flow_label True to enable auto-generation.
*/
void arm_nwk_ipv6_auto_flow_label(bool auto_flow_label);
/**
* \brief Set the key for opaque IPv6 interface identifiers
*
* This call sets the secret key used to generate opaque interface identifiers,
* as per RFC 7217. Once this has been set, all interfaces will use opaque
* interface identifiers by default. If secret_key is NULL, opaque interface
* identifiers will be disabled.
*
* Correct implementation of RFC 7217 would require that this key be
* randomly generated at first bootstrap, and thereafter remain constant, which
* would require non-volatile storage. The next closest alternative would be
* to base this on a MAC address.
*
* \param secret_key A pointer to secret key (will be copied by call).
* \param key_len The length of the key.
*
* \return 0 key set okay.
* \return <0 key set failed (for example due to memory allocation).
*/
int8_t arm_nwk_ipv6_opaque_iid_key(const void *secret_key, uint8_t key_len);
/**
* \brief Enable/disable opaque IPv6 interface identifiers by interface
*
* Enable or disable RFC 7217 opaque IIDs generated by SLAAC, per interface.
* By default opaque IIDs are enabled if the opaque key is set. If disabled,
* SLAAC IIDs will be EUI-64-based as per RFC 4291.
*
* \param interface_id Interface ID.
* \param enable True to enable.
* \return 0 enabled/disabled OK.
* \return <0 failed (for example invalid interface ID).
*
*/
int8_t arm_nwk_ipv6_opaque_iid_enable(int8_t interface_id, bool enable);
#endif /* NET_IPV6_API_H_ */

View File

@ -0,0 +1,118 @@
/*
* Copyright (c) 2016-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* \file net_load_balance_api.h
* \brief 6LoWPAN network load balance control API.
*/
#ifndef NET_LOAD_BALANCE_API_H_
#define NET_LOAD_BALANCE_API_H_
#include "ns_types.h"
/**
* \brief load_balance_network_switch_notify This function is called by the load balancer when it has detected a better network to switch to.
*
* \return true The network can be switched immediately.
* \return false The load balancer will ask later a time for network switching if a better network is still available at that time.
*/
typedef bool net_load_balance_network_switch_notify(void);
/**
* \brief Set user callback for accepting the network switch.
* \param interface_id Interface ID.
* \param network_switch_notify User callback.
*
* \return 0 Set OK.
* \return -1 unknown Interface.
*/
int8_t net_load_balance_network_switch_cb_set(int8_t interface_id, net_load_balance_network_switch_notify *network_switch_notify);
/**
* \brief Create and enable load balance to the selected interface.
* \param interface_id Interface ID.
* \param enable_periodic_beacon_interval Set True when you want to activate load balance periodic beacon; false will work only properly with the FHSS system.
*
* \return 0 Enable OK.
* \return -1 unknown Interface or parameter error.
* \return -2 Out of memory.
* \return -3 Load balance already configured to this interface.
*/
int8_t net_load_balance_create(int8_t interface_id, bool enable_periodic_beacon_interval);
/**
* \brief Disable and delete load balancing from the interface.
* \param interface_id Interface ID.
*
* \return 0 Process OK.
* \return -1 Unknown interface.
*/
int8_t net_load_balance_delete(int8_t interface_id);
/**
* \brief Set load balance threshold min and max.
*
* Network switch: diff_priority >= randLIB_get_random_in_range(threshold_min, threshold_max) --> switch network if true.
* For border router: Disable network compare by setting threshold_min and threshold_max to 0.
*
* \param interface_id Interface ID.
* \param threshold_min Min value defines a random minimum value for compare (must be bigger than 0).
* \param threshold_max Max value defines a random maximum value for compare (must be bigger than 0).
*
* \return 0 Process OK, -1 Unknown interface ID.
*/
int8_t net_load_balance_threshold_set(int8_t interface_id, uint8_t threshold_min, uint8_t threshold_max);
/**
* \brief Set the network probability percent when the new network is better than threshold max.
*
* \param interface_id Interface ID.
* \param max_p Probability percent to switch the network. Default is 25%. Accepted values are [1,100], recommend values are 10-25.
*
* \return 0 Process OK, -1 Unknown interface ID or parameter fail.
*/
int8_t net_load_balance_set_max_probability(int8_t interface_id , uint8_t max_p);
/**
* \brief Set load balance expected device count and enable automatic network load level update.
*
* This feature is just for RPL DoDAG root device!
*
* \param interface_id Interface ID.
* \param expected_device_count Device count that sets the max load level.
* - If the count is not divisible by 8, the function rounds the number up to reach that.
* - It is not hard limit it define max DoDAG preference.
* - For hard limit, check whiteboard_api.h.
*
* \return 0 Process OK, -1 Unknown interface ID, -2 Out of memory.
*/
int8_t net_load_balance_load_level_update_enable(int8_t interface_id, uint16_t expected_device_count);
/**
* \brief Disable the automatic network load level update.
*
* \param interface_id Interface ID.
*
* \return 0 Process OK, -1 Unknown interface ID.
*/
int8_t net_load_balance_load_level_update_disable(int8_t interface_id);
#endif /* NET_LOAD_BALANCE_API_H_ */

112
nanostack/net_mle_api.h Normal file
View File

@ -0,0 +1,112 @@
/*
* Copyright (c) 2016-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* \file net_mle_api.h
* \brief 6LoWPAN MLE options control API
*
*/
#ifndef _NET_MLE_API_H
#define _NET_MLE_API_H
#include "ns_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief Set default MLE neighbor lifetime for a router.
*
* \param interface_id Interface ID.
* \param lifetime Lifetime in seconds. 64 to 2560.
*
* \return 0, Lifetime update OK.
* \return < 0, Lifetime update fail.
*
*/
int8_t arm_nwk_6lowpan_mle_router_lifetime_set(int8_t interface_id, uint16_t lifetime);
/**
* \brief Set default MLE neighbor lifetime for a host.
*
* \param interface_id Interface ID.
* \param lifetime Lifetime in seconds. 64 to 2560.
*
* \return 0, Lifetime update OK.
* \return < 0, Lifetime update fail.
*
*/
int8_t arm_nwk_6lowpan_mle_host_lifetime_set(int8_t interface_id, uint16_t lifetime);
/**
* \brief Set MLE neighbor list limits.
*
* The MLE neighbor limits configuration settings limit the number of neighbors
* added to the MLE neighbor list.
*
* If the number of neighbors reaches the lower threshold, MLE starts to limit addition
* of new neighbors. Multicast MLE messages from unknown neighbors are ignored (ignore probability is randomized).
* The value must be smaller than the upper threshold and maximum value.
*
* If the number of neighbors reaches the upper threshold, MLE stops adding new neighbors
* based on the multicast MLE messages. Only nodes that select this node for a
* parent during the bootstrap will be accepted. The value must be smaller than or the same as
* the maximum value.
*
* If the number of neighbors reaches the maximum value, no new neighbors are added.
*
* If the MLE neighbor list limits are not used, all values must be set to 0.
*
* \param interface_id Interface ID.
* \param lower_threshold Lower threshold. 5 to 499. 0 limits not used.
* \param upper_threshold Upper threshold. 5 to 500. 0 limits not used.
* \param max Maximum number of neighbors. 5 to 500. 0 limits not used.
*
* \return 0, Limits update OK.
* \return < 0, Limits update fail.
*
*/
int8_t arm_nwk_6lowpan_mle_neighbor_limits_set(int8_t interface_id, uint16_t lower_threshold, uint16_t upper_threshold, uint16_t max);
/**
* \brief Set MLE message token bucket settings
*
* The MLE message token bucket limits the MLE message sending rate. The token bucket size
* controls the bucket size. The token bucket rate controls the rate in which
* new tokens are added. The count defines how many tokens at a time are added to the bucket.
*
* The rate is entered in multiplies of 0.1 second minimum interval (for example, if rate is 3
* and count is 4 then 4 new tokens are added to bucket every 0.3 seconds).
*
* If the token bucket is not used, all values must be set to 0.
*
* \param interface_id Interface ID.
* \param size Bucket size. 1 to 255. 0 token bucket not used.
* \param rate Token rate. 1 to 255. 0 token bucket not used.
* \param count Token count. 1 to 255. 0 token bucket not used.
*
* \return 0, Token bucket settings update OK.
* \return < 0, Token bucket settings update fail.
*
*/
int8_t arm_nwk_6lowpan_mle_token_bucket_settings_set(int8_t interface_id, uint8_t size, uint8_t rate, uint8_t count);
#ifdef __cplusplus
}
#endif
#endif /* _NET_MLE_API_H */

275
nanostack/net_nvm_api.h Normal file
View File

@ -0,0 +1,275 @@
/*
* Copyright (c) 2013-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* \file net_nvm_api.h
* \brief Library PANA NVM API for Client and Server.
*
* \section server-api Server NVM API
*
* - pana_server_nvm_callback_set(), Initialize PANA server NVM functionality.
* - pana_server_restore_from_nvm(), Load PANA server base and security material from NVM.
* - pana_server_nvm_client_session_load(), Load client session from NVM.
*
* \section client-api Client NVM API
*
* nw_nvm.c use already this API and the application can just use net_nvm_api.h.
*
* - pana_client_nvm_callback_set(), Initialize PANA session NVM.
*
*/
#ifndef PANA_NVM_API_H_
#define PANA_NVM_API_H_
#include "ns_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief Pana client and common data structure for get / Update callback's
*
* Client: [session address 16-bytes] + [session data 70-bytes] , Total 86 bytes
*
* Server: [offset 2-bytes] + [session address 16-bytes] + [session port 2-bytes] + [session id 4-bytes] + [session data 92-bytes], Total 116 bytes
*/
/**
* Size of Pana client session data without session address
*/
#define PANA_CLIENT_NVM_SESSION_BUF_SIZE 70
/**
* Size of Pana client session data with session address
*/
#define PANA_CLIENT_NVM_SESSION_BUF_SIZE_WITH_ADDRESS 86
/**
* Size of data for Server client Uodate and get callback
*
*/
#define PANA_SERVER_CLIENT_NVM_SESSION_BUF_SIZE 116
/**
* Size of data for Server material update and restore operation
*
*/
#define PANA_SERVER_MATERIAL_BUF_SIZE 90
/*!
* \enum pana_nvm_update_process_t
* \brief PANA server NVM update states.
*/
typedef enum pana_nvm_update_process_t {
PANA_SERVER_MATERIAL_UPDATE, /**< PANA server security material update. */
PANA_SERVER_CLIENT_SESSION_UPDATE, /**< PANA client session update. */
PANA_SERVER_CLIENT_SESSION_REMOVE_UPDATE, /**< PANA client session remove. */
} pana_nvm_update_process_t;
/*!
* \enum pana_client_nvm_update_process_t
* \brief PANA client NVM update states.
*/
typedef enum pana_client_nvm_update_process_t {
PANA_CLIENT_SESSION_UPDATE, /**< PANA client session update. */
PANA_CLIENT_SESSION_REMOVE, /**< PANA client session remove. */
} pana_client_nvm_update_process_t;
/*!
* \struct wpan_nvm_params_t
* \brief Network nvm parameters.
*/
typedef struct wpan_nvm_params {
uint16_t pan_id; /**< WPAN Pan-id. */
uint32_t mac_security_frame_counter; /**< Mac security counter. */
uint32_t mle_securit_counter; /**< MLE security counter. */
} wpan_nvm_params_t;
/**
* \brief NVM memory user callback for updated parameters
*
* \param parameters Updated wpan parameters
*/
typedef void wpan_params_updated(wpan_nvm_params_t *parameters);
/**
* \brief NVM memory user for get parameter->pan_id network setup
*
* \param parameters Pointer for request parameters parameter->pan_id is configured for proper setup
*
* \return true when configure is loaded to buffer
* \return false when there is no proper data for current wpan
*/
typedef bool wpan_params_get(wpan_nvm_params_t *parameters);
/**
* \brief Pana client session update callback
*
* \param pan_id define which pan session is
* \param process PANA_CLIENT_SESSION_UPDATE or PANA_CLIENT_SESSION_REMOVE
*/
typedef void pana_client_session_update_cb(uint16_t pan_id, pana_client_nvm_update_process_t process);
/**
* \brief Pana client discover session from NVM user based on pan id
*
* \param pan_id define which pan session is
*
* \return true When Session is stored to behind given session buffer
* \return false NVM can't detect session for given pan id
*/
typedef bool pana_client_session_get_cb(uint16_t pan_id);
/**
* \brief Pana server call this when it create /Update / delete client session or update Server material
*
* \param operation Pana server NVM update
*
* \return session offset . Requirement for operation PANA_SERVER_CLIENT_SESSION_UPDATE
*/
typedef uint16_t pana_server_update_cb(pana_nvm_update_process_t operation);
/**
* \brief Pana server call this when discover client session from NVM for given address
*
* \param linklocal_address Link local address for sesion
*
* \return true When Session is stored to behind given session buffer
* \return false NVM can't detect session for given address
*/
typedef bool pana_server_session_get_cb(uint8_t *linklocal_address);
/**
* \brief Pana server call this when discover client session from NVM for pana session
*
* \param session_id Pana session Id
*
* \return true When Session is stored to behind given session buffer
* \return false NVM can't detect session for given session id
*/
typedef bool pana_server_session_get_by_id_cb(uint32_t session_id);
/* NVM API PART */
/**
* \brief PANA server NVM functionality initialization.
*
* \param update_cb A function pointer to NVM update process.
* \param nvm_get A function pointer for discover session data from NVM by link local address
* \param nvm_session_get A function pointer for discover session data from NVM by pana session id
* \param nvm_static_buffer A pointer to application allocated static memory, minimum size PANA_SERVER_CLIENT_NVM_SESSION_BUF_SIZE (116 bytes).
*
*
* \return 0, Init OK.
* \return -1, Null parameter detect.
*
*/
extern int8_t pana_server_nvm_callback_set(pana_server_update_cb *update_cb, pana_server_session_get_cb *nvm_get, pana_server_session_get_by_id_cb *nvm_session_get, uint8_t *nvm_static_buffer);
/**
* \brief PANA server base restore from NVM.
*
* \param nvm_data A pointer to PANA server base data.
* \param interface_id Interface ID.
*
* \return 0, Restore OK.
* \return -1, Memory allocation fail.
*
*/
extern int8_t pana_server_restore_from_nvm(uint8_t *nvm_data, int8_t interface_id);
/**
* \brief PANA client session load from NVM API.
*
* \param nvm_pointer A pointer PANA client session.
*
* \return 0, Restore OK.
* \return -1, Memory allocation fail.
*
*/
extern int8_t pana_server_nvm_client_session_load(uint8_t *nvm_pointer);
/**
* \brief PANA client NVM functionality init.
*
* \param nvm_update A function pointer to NVM update process.
* \param nvm_get A function pointer for discover session from NVM for given Pan-id
* \param nvm_static_buffer A pointer to application allocated static memory, minimum size for session 86 bytes + 16-bit pan-id.
*
*
* \return 0, Init OK.
* \return -1, Null parameter detect.
*
*/
extern int8_t pana_client_nvm_callback_set(pana_client_session_update_cb *nvm_update, pana_client_session_get_cb *nvm_get,uint8_t *nvm_static_buffer);
/**
* \brief Clean node persistent data and all PANA client sessions from the stack.
*
* This function disables the network ID filter, sets EUID-16 to 0xffff and removes PANA client sessions. It is only for client purposes.
*
*
* \return 0, Clean OK.
* \return -1, Stack is active.
*
*/
extern int8_t net_nvm_data_clean(int8_t interface_id);
/**
* \brief Enable and init network NVM parameter automatic update.
*
* This function enables MAC and MLE protocol critical components update process to NVM memory user.
*
* \param interface_id Interface ID.
* \param nvm_update_cb Function pointer for update NVM
* \param nvm_get_cb Function for stack to request setup from NVM.
*
*
* \return 0, Init OK.
* \return -1, Unknown Interface.
* \return -2, Memory allocation fail.
*
*/
extern int8_t net_nvm_wpan_params_storage_enable(int8_t interface_id, wpan_params_updated *nvm_update_cb, wpan_params_get *nvm_get_cb);
/**
* \brief Reset stored WPAN parameter's at interface .
*
* This function clean state at WPAN params at stack. Force Request from NVM
*
*\param interface_id Interface ID.
*
* \return 0, reset OK.
* \return -1, Unknown Interface.
*
*/
extern int8_t net_nvm_wpan_params_storage_reset(int8_t interface_id);
/**
* \brief Disable stored WPAN parameter's to interface .
*
*
*\param interface_id Interface ID.
*
* \return 0, Disable OK.
* \return -1, Unknown Interface.
*
*/
extern int8_t net_nvm_wpan_params_storage_disable(int8_t interface_id);
#ifdef __cplusplus
}
#endif
#endif /* PANA_NVM_API_H_ */

137
nanostack/net_nwk_scan.h Normal file
View File

@ -0,0 +1,137 @@
/*
* Copyright (c) 2013-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _NS_NWK_SCAN_H
#define _NS_NWK_SCAN_H
#ifdef __cplusplus
extern "C" {
#endif
#include "ns_types.h"
#include "net_interface.h" /* needed for channel_list_s */
#include "mlme.h"
/**
* \file net_nwk_scan.h
* \brief Link layer Scan API for Active and Energy Detection Scan API.
*
* - arm_net_energy_scan(), Energy scan start (Use only with ZIP node library).
* - arm_net_nwk_scan(), Active scan for network (Use only with ZIP node library).
* - arm_net_get_scanned_nwk_list(), Active scan result read.
*
* Scan API works only when stack is in idle state.
*
* The scan operation result is handled at callback function that is defined by scan function call.
* The scan result format is as follows:
*
* | Data pointer | VALUE |
* | :----------: | :---------------------------------------------------: |
* | 1.Byte | Scan Type: NET_NWK_ENERGY_SCAN or NET_NWK_ACTIVE_SCAN |
* | 2.Byte | Result length |
* | 3+n Bytes | Payload :Read Only at Energy Detection type |
*
* The result length indicates the scan response size as follows:
* - NET_NWK_ENERGY_SCAN Payload length is result length *2 bytes after length field.
* * 1.Byte Channel
* * 2.Byte Energy Level
* - NET_NWK_ACTIVE_SCAN result indicates the the number of networks.
* * The network list needs to be read by net_get_scanned_nwk_list().
*
*/
/** Network energy detection scan type */
#define NET_NWK_ENERGY_SCAN 0
/** Network active scan type */
#define NET_NWK_ACTIVE_SCAN 1
/** Network parent address type 16-bit short */
#define NET_PARET_SHORT_16_BIT 2
/** Network parent address type 64-bit long */
#define NET_PARET_LONG_64_BIT 3
/* Active scan level definition */
/** List only PAN networks at channels */
#define NET_ACTIVE_SCAN_ONLY_NWK 0
/** List PAN networks with any beacon payload */
#define NET_ACTIVE_SCAN_ACCEPT_ANY_BEACON_PAYLOAD 1
/** List PAN networks with ZIP-specific payload that accept join */
#define NET_ACTIVE_SCAN_ACCEPT_ONLY_ZIP_SPESIFIC 2
/*!
* \struct nwk_pan_alternative_parent_t
* \brief Network alternative parent structure.
*/
typedef struct nwk_pan_alternative_parent_t {
uint8_t CoordAddrMode; /**< Parent address mode NET_PARET_SHORT_16_BIT or NET_PARET_LONG_64_BIT. */
uint8_t CoordAddress[8]; /**< Parent address based on CoordAddrMode. */
uint8_t LinkQuality; /**< LQI to parent. */
} nwk_pan_alternative_parent_t;
/*!
* \struct nwk_pan_descriptor_t
* \brief Linked network response list.
*/
typedef struct nwk_pan_descriptor_t {
mlme_pan_descriptor_t *pan_descriptor; /**< Pan Description */
uint8_t *beacon_payload; /**< Beacon Payload pointer */
uint8_t beacon_length; /**< Beacon Payload length */
nwk_pan_alternative_parent_t alternative_parent; /**< Alternative Parent information pointer */
struct nwk_pan_descriptor_t *next; /**< Link to next network result */
} nwk_pan_descriptor_t;
/**
* \brief Energy detection scan start for configured channel with application-specific threshold.
*
* \param interface_id Interface id.
* \param scan_list Channel list for scan operation.
* \param passed_fptr A function pointer for scan result notify.
* \param energy_tresshold Scan response lists all channels with smaller or equal level.
*
* \return 0 Scan operation started OK.
* \return -1 Stack is active.
* \return -2 Channel list not valid.
* \return -3 Function not enabled at border router.
*
*/
extern int8_t arm_net_energy_scan(int8_t interface_id, channel_list_s *scan_list, void (*passed_fptr)(int8_t if_id, const mlme_scan_conf_t *conf), uint8_t energy_tresshold);
/**
* \brief Active network scan for configured channels.
*
* \param interface_id Interface id.
* \param scan_list Channel list for scan operation.
* \param passed_fptr A function pointer for scan result notify.
* \param scan_level NET_ACTIVE_SCAN_ONLY_NWK, NET_ACTIVE_SCAN_ACCEPT_ANY_BEACON_PAYLOAD,NET_ACTIVE_SCAN_ACCEPT_ONLY_ZIP_SPESIFIC
*
* \return 0 Scan operation started OK.
* \return -1 Stack is active.
* \return -2 Channel list not valid.
* \return -3 Function not enabled at border router.
*
*/
extern int8_t arm_net_nwk_scan(int8_t interface_id, channel_list_s *scan_list, void (*passed_fptr)(int8_t if_id, const mlme_scan_conf_t *conf), uint8_t scan_level);
/**
* \brief Active scan result read.
*
* Note: The pointer is only valid at callback function call time. The application needs to allocate memory if it wants to save the result.
*
* \return >0 A pointer to scan result.
* \return 0 No network results available.
*
*/
extern nwk_pan_descriptor_t *arm_net_get_scanned_nwk_list(int8_t interface_id);
#ifdef __cplusplus
}
#endif
#endif /*_NS_NWK_SCAN_H*/

View File

@ -0,0 +1,82 @@
/*
* Copyright (c) 2014-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef NET_PANA_PARAMETERS_API_H_
#define NET_PANA_PARAMETERS_API_H_
#include "ns_types.h"
/**
* \file net_pana_parameters_api.h
* \brief An API for setting up or changing PANA library parameters.
*
* \section set-pana-param Setting up PANA parameters.
* - net_pana_parameter_set(), A function to set up PANA library parameters.
* \section check-pana-param Checking existing PANA setup.
* - net_pana_parameter_read(), A function to read current PANA library setup.
*/
/*!
* \struct pana_lib_parameters_s
* \brief PANA library dynamic parameters.
*/
/** The structure defines PANA library parameters.*/
typedef struct pana_lib_parameters_s {
uint16_t PCI_IRT; /**< Initial PCI timeout in seconds, default 10. */
uint16_t PCI_MRT; /**< Max PCI timeout value in seconds, default 60. */
uint8_t PCI_MRC; /**< PCI_MRC Max PCI retransmission attempts, default 5. */
uint16_t REQ_IRT; /**< PCI_MRC Initial request timeout in seconds, default 20. */
uint16_t REQ_MRT; /**< Max request timeout value, default 60. */
uint16_t REQ_MRC; /**< Max request retransmission attempts, default 4. */
uint16_t AUTHENTICATION_TIMEOUT; /**< Max timeout for authencication, default 100 seconds. */
uint16_t KEY_UPDATE_THRESHOLD; /**< Gap in seconds before the server starts to send a new network key, default 10. */
uint8_t KEY_ID_MAX_VALUE; /**< Define resolution for key ID [1-KEY_ID_MAX_VALUE], default 255. MIN accepted value is 3.*/
uint16_t EAP_FRAGMENT_SIZE; /**< Define EAP fragment slot size. Fragmentation is activated when EAP payload is more than 920. Default 296. */
uint8_t AUTH_COUNTER_MAX; /**< Define PANA session re-authentication limit. When the MAX value is reached the server does not respond to the PANA notify request. Default 0xff. */
} pana_lib_parameters_s;
/**
* \brief A function to set PANA library parameters.
*
* Note: This function should be called after net_init_core() and definitely
* before creating any 6LoWPAN interface.
*
* For future compatibility, to support extensions to this structure, read
* the current parameters using net_pana_parameter_read(),
* modify known fields, then set.
*
* \param parameter_ptr A pointer for PANA parameters.
*
* \return 0, Change OK.
* \return -1, Invalid values.
* \return -2, PANA not supported.
*
*/
extern int8_t net_pana_parameter_set(const pana_lib_parameters_s *parameter_ptr);
/**
* \brief A function to read existing PANA library parameters.
*
* \param parameter_ptr An output pointer for PANA parameters.
*
* \return 0, Read OK.
* \return -1, PANA not supported.
*/
extern int8_t net_pana_parameter_read(pana_lib_parameters_s *parameter_ptr);
#endif /* NET_PANA_PARAMETERS_API_H_ */

109
nanostack/net_polling_api.h Normal file
View File

@ -0,0 +1,109 @@
/*
* Copyright (c) 2013-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* \file net_polling_api.h
* \brief ZigBeeIP Sleepy Host Data Poll API.
*
* - arm_nwk_host_mode_set(), Set sleepy host new state.
* - arm_nwk_host_mode_get(), Read current host state.
* - net_host_enter_sleep_state_set(), Enable deep sleep state.
*
* The sleepy host default state is NET_HOST_FAST_POLL_MODE after bootstrap.
* The stack always disables radio automatically between data polls.
* The stack can also enable deep sleep when application net_host_enter_sleep_state_set().
*
* A sleepy host can change the host state to normal, which saves time and resources when the client is waiting for a large amount of data.
* - nwk_host_mode_set(NET_HOST_RX_ON_IDLE,0) A function call to trigger MLE handshake update automatically.
* From NET_HOST_RX_ON_IDLE state back to polling state causes an MLE handshake with parent:
* - nwk_host_mode_set (NET_HOST_FAST_POLL_MODE,0), Enter fast mode.
* - nwk_host_mode_set (NET_HOST_SLOW_POLL_MODE,10), Enter slow poll mode by 10 seconds max data poll period.
*
* The stack will tell max sleepy time to the application by selecting min values from the following cases:
* - Next active system timer trigger
* - ND protocol next state trigger
* - MLE handshake trigger
* - PANA key pull trigger
* - Next data poll period
*
*/
#ifndef NET_POLLING_H_
#define NET_POLLING_H_
#include "ns_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/*!
* \enum net_host_mode_t
* \brief Sleepy host states.
*/
typedef enum net_host_mode {
NET_HOST_FAST_POLL_MODE, /**< Sleepy host fast poll state, max poll period 400ms. */
NET_HOST_SLOW_POLL_MODE, /**< Sleepy host slow poll state, user-defined max period in seconds. */
NET_HOST_RX_ON_IDLE, /**< Disable polling and enable direct data flow from parent to host. */
NET_HOST_MODE_NOT_ACTIVE, /**< Host mode is not active. */
} net_host_mode_t;
/**
* \brief Set new host state.
*
* \param interface_id Network interface ID.
* \param mode New host state.
* \param poll_time Poll time in seconds, only handled when NET_HOST_SLOW_POLL_MODE is enabled.
*
* Valid poll time for NET_HOST_SLOW_POLL_MODE is 0 < poll_time poll_time < 864001 (1 Day)
*
* \return 0, State update OK.
* \return -1, Unknown state.
* \return -2, Invalid time.
* \return -3 MLE handshake trigger failure.
*
*/
extern int8_t arm_nwk_host_mode_set(int8_t interface_id, net_host_mode_t mode, uint32_t poll_time);
/**
* \brief Read current host state.
*
* \param interface_id Network interface ID.
* \param mode A pointer to the location for saving the host state.
* \return 0, State read update OK.
* \return -1, The host role is router or the stack is idle.
*
*/
extern int8_t arm_nwk_host_mode_get(int8_t interface_id, net_host_mode_t *mode);
/**
* \brief Host sleep state control.
*
* \param interface_id Network interface ID.
* \param state >0 enables power saving between data polling. Otherwise, only radio is disabled.
*
* When the application wants to save more power it can call net_host_enter_sleep_state_set(nwk_interface_id, 1).
* When the application wants to disable sleep it just calls net_host_enter_sleep_state_set(nwk_interface_id, 0).
*/
extern void arm_net_host_enter_sleep_state_set(int8_t interface_id, uint8_t state);
#ifdef __cplusplus
}
#endif
#endif /* NET_POLLING_H_ */

329
nanostack/net_rpl.h Normal file
View File

@ -0,0 +1,329 @@
/*
* Copyright (c) 2013-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _NS_RPL_H
#define _NS_RPL_H
#include "ns_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* \file net_rpl.h
* \brief ZigBeeIP Router and Border Router RPL API.
*
* This API is primarily used with a border router. You can also use it with a basic router.
*
* - arm_nwk_6lowpan_rpl_memory_limit_set(), Set RPL global memory limit sizes. Call this only at boot ones.
* - arm_nwk_6lowpan_rpl_dodag_init(), Allocate and init RPL DODAG root.
* - arm_nwk_6lowpan_rpl_dodag_remove(), Remove DDAG root, specifically.
* - arm_nwk_6lowpan_rpl_dodag_start(), Activate RPL DODAG instance.
* - arm_nwk_6lowpan_rpl_dodag_poison(), Trigger some poison advertisements for the current instance, and then become a leaf (so no more adverts are sent). If a DODAG root, this remains allocated so arm_nwk_6lowpan_rpl_dodag_remove() still needs to be called to free it, after delaying some seconds to allow the poison advertisements to be sent().
* - arm_nwk_6lowpan_rpl_dodag_prefix_update(), Update prefix info to the root.
* - arm_nwk_6lowpan_rpl_dodag_route_update(), Update route info to the root.
* - arm_nwk_6lowpan_rpl_dodag_dao_trig(), Increment the DAO Trigger Sequence Number (DTSN), to cause downstream nodes to refresh their Destination Advertisement Objects (DAOs).
* - arm_nwk_6lowpan_rpl_dodag_version_increment(), Increment the DODAG version to trigger a global DODAG repair.
*
* \section rpl-recommend RECOMMEND API for router and border router:
* - rpl_instance_list_read(), Read active RPL instance list.
* - rpl_read_dodag_info(), Read RPL DODAG information to rpl_dodag_info_t structure by selected RPL instance ID.
*
* \section rpl-dodag-init Steps to define a new RPL DODAG instance:
* 1. Allocate RPL root base with arm_nwk_6lowpan_rpl_dodag_init().
* 2. Set prefix 1 to root with arm_nwk_6lowpan_rpl_dodag_prefix_update().
* 3. Set Route(s) to root with arm_nwk_6lowpan_rpl_dodag_route_update().
* 4. Start Activate RPL DODAG:
* * arm_nwk_6lowpan_rpl_dodag_start() if RPL is generated after arm_nwk_interface().
*
*/
/** \name DoDag Root setups
* <B>DODAGPreference (Prf):</B> A 3-bit unsigned integer that defines how
preferable the root of this DODAG is compared to other DODAG
roots within the instance. DAGPreference ranges from 0x00
(least preferred) to 0x07 (most preferred). The default is 0
(least preferred).
*
* @{
*/
#define RPL_DODAG_PREF_MASK 0x07 /**< Preference mask */
#define RPL_DODAG_PREF(n) ((n) & RPL_DODAG_PREF_MASK) /**< DODAG preference */
/** @} */
/** \name Mode of Operation (MOP)
* The Mode of Operation (MOP) field identifies
the mode of operation of the RPL instance as administratively
provisioned at and distributed by the DODAG root. All nodes
joining the DODAG must be able to honor the MOP to
fully participate as a router. Otherwise, they must only join as a leaf.
* @{
*/
#define RPL_MODE_MASK 0x38 /**< MOP mask */
#define RPL_MODE_SHIFT 3 /**< shift count */
#define RPL_MODE_NO_DOWNWARD 0x00 /**< No Downward routes maintained by RPL */
#define RPL_MODE_NON_STORING 0x08 /**< Non-Storing Mode of Operation */
#define RPL_MODE_STORING 0x10 /**< Storing Mode of Operation with no multicast support */
#define RPL_MODE_STORING_MULTICAST 0x18 /**< Storing Mode of Operation with multicast support */
#define RPL_MODE_P2P_DISCOVERY 0x20 /**< RFC 6997 */
/** @} */
/** Grounded (G): The Grounded 'G' flag indicates whether the DODAG
advertised can satisfy the application-defined goal. If the
flag is set, the DODAG is grounded. If the flag is cleared,
the DODAG is floating.
*/
#define RPL_GROUNDED 0x80
/** \name FOR BACKWARDS COMPATIBILITY
* @{
*/
#define BR_DODAG_PREF_0 RPL_DODAG_PREF(0) /**< backward compatibility */
#define BR_DODAG_PREF_1 RPL_DODAG_PREF(1) /**< backward compatibility */
#define BR_DODAG_PREF_2 RPL_DODAG_PREF(2) /**< backward compatibility */
#define BR_DODAG_PREF_3 RPL_DODAG_PREF(3) /**< backward compatibility */
#define BR_DODAG_PREF_4 RPL_DODAG_PREF(4) /**< backward compatibility */
#define BR_DODAG_PREF_5 RPL_DODAG_PREF(5) /**< backward compatibility */
#define BR_DODAG_PREF_6 RPL_DODAG_PREF(6) /**< backward compatibility */
#define BR_DODAG_PREF_7 RPL_DODAG_PREF(7) /**< backward compatibility */
#define BR_DODAG_MOP_NON_STORING RPL_MODE_NON_STORING /**< backward compatibility */
#define BR_DODAG_MOP_STORING RPL_MODE_STORING /**< backward compatibility */
#define BR_DODAG_FLOATING 0 /**< backward compatibility */
#define BR_DODAG_GROUNDED RPL_GROUNDED /**< backward compatibility */
/** @} */
/** \name Compatibility for even older misspellings
* @{
*/
#define BR_DODAG_MOP_NON_STRORING BR_DODAG_MOP_NON_STORING /**< backward compatibility */
#define BR_DODAG_MOP_STRORING BR_DODAG_MOP_STORING /**< backward compatibility */
#define BR_DODAG_FLOATIN BR_DODAG_FLOATING /**< backward compatibility */
/** @} */
/** RPL ROOT parent flag */
#define RPL_ROOT_PARENT 0
/** RPL primary active primary_parent primary_parent_rank information is valid. */
#define RPL_PRIMARY_PARENT_SET 1
/** RPL secondary active secondary_parent secondary_parent_rank information is valid. */
#define RPL_SECONDARY_PARENT_SET 2
/** RPL prefix update flags for A-flag AUTONOMOUS address generation. */
#define RPL_PREFIX_AUTONOMOUS_ADDRESS_FLAG 0x40
/** RPL prefix update flags for R-Flag. */
#define RPL_PREFIX_ROUTER_ADDRESS_FLAG 0x20
/** Flag in RPL instance ID to indicate that it is a local instance. */
#define RPL_INSTANCE_LOCAL 0x80
/*!
* \struct rpl_dodag_info_t
* \brief RPL Instance DODAG info structure for rpl_read_dodag_info. Read RFC 6550 for more information and to make sure you know what you are doing.
*/
typedef struct rpl_dodag_info_t {
uint8_t dodag_id[16]; /**< RPL DODAG ID. */
uint8_t instance_id; /**< RPL instance ID. */
uint8_t flags; /**< RPL DODAG Flags: (MOP,Grounded, Router Pref) */
uint8_t version_num; /**< RPL DODAG version number. */
uint8_t DTSN; /**< RPL DODAG DAO trigger version number. */
uint16_t curent_rank; /**< RPL DODAG node current Rank. */
uint8_t parent_flags; /**< RPL DODAG parent Flags: RPL_ROOT_PARENT or RPL_PRIMARY_PARENT_SET, RPL_SECONDARY_PARENT_SET */
uint8_t primary_parent[16]; /**< Primary Parent GP address if RPL_PRIMARY_PARENT_SET flag is active. */
uint16_t primary_parent_rank; /**< Primary Parent Rank if RPL_PRIMARY_PARENT_SET flag is active. */
uint8_t secondary_parent[16]; /**< Secondary Parent GP address if RPL_SECONDARY_PARENT_SET flag is active. */
uint16_t secondary_parent_rank; /**< Secondary Parent rank if RPL_SECONDARY_PARENT_SET flag is active. */
uint16_t dag_min_hop_rank_inc; /**< RPL DODAG conf DAG minimum rank increase. */
} rpl_dodag_info_t;
/*!
* \struct dodag_config_t
* \brief RPL DODAG config is used when allocating RPL base arm_nwk_6lowpan_rpl_dodag_init().
*/
typedef struct dodag_config_t {
uint8_t DAG_SEC_PCS; /**< Path Control Size limits number of DAO parents. Possible values are 0-7, meaning 1-8 parents.
(This also has an Authentication flag 0x10 the SEC, but we dont support that, and 4 reserved flags, so it is just the 3-bit PCS field). */
uint8_t DAG_DIO_INT_DOUB; /**< RPL Trickle DIOIntervalDoublings, recommended value 12. */
uint8_t DAG_DIO_INT_MIN; /**< RPL Trickle DIOIntervalMin, recommended value 9. */
uint8_t DAG_DIO_REDU; /**< RPL Trickle DIORedundancyConstant, recommended value 3. */
uint16_t DAG_MAX_RANK_INC; /**< RPL MaxRankIncrease, recommended value 2048. */
uint16_t DAG_MIN_HOP_RANK_INC; /**< RPL MinHopRankIncrease, recommended value 128. */
uint16_t DAG_OCP; /**< Objective code point, recommended value 1. */
uint8_t LIFE_IN_SECONDS; /**< Default lifetime for RPL routes, expressed in lifetime units. */
uint16_t LIFETIME_UNIT; /**< Defines the unit used to express route lifetimes, in seconds. */
} dodag_config_t;
/**
* \brief RPL DODAG root base allocate.
*
* \param interface_id Interface ID
* \param dodag_id A pointer to unique DODAGID. This must be the node's GP address in the ZigBeeIP network.
* \param config A pointer to the DODAG configure structure.
* \param instace_id Instance ID for RPL DODAG.
* \param flags Defines RPL MOP and DODAG pref. ZigBeeIP should use (BR_DODAG_MOP_NON_STORING | BR_DODAG_PREF_7).
*
* \return 0, Allocate OK.
* \return -1, Allocate fail (The node is already connected to the same instance or the memory allocate fails).
* \return -2, DODAG configuration parameter failure.
*
*/
extern int8_t arm_nwk_6lowpan_rpl_dodag_init(int8_t interface_id, const uint8_t *dodag_id, const dodag_config_t *config, uint8_t instace_id, uint8_t flags);
/**
* \brief RPL Global memory size limits.
*
* Calling this function you can update default memory limits. Soft default is 1024 and hard limit is 2048.
* \param soft_limit When RPL reach this state at total allocation it start cleaning unused data.
* \param hard_limit Total allocation limit. 0 means no limit and > 0 define hard limit. When hard limit > 0 soft_limit must be smaller than hard.
*
* \return 0, Set OK.
* \return -1, Unsupported parameter
*
*/
extern int8_t arm_nwk_6lowpan_rpl_memory_limit_set(size_t soft_limit, size_t hard_limit);
/**
* \brief RPL DODAG remove by given interface ID.
*
* \param interface_id Interface ID for removed DODAG.
*
* \return 0, Remove OK.
* \return -1, Remove fail.
*
*/
extern int8_t arm_nwk_6lowpan_rpl_dodag_remove(int8_t interface_id);
/**
* \brief Activate RPL DODAG by given Interface ID.
*
* \param interface_id Interface ID for start DODAG root.
*
* \return 0, Start OK.
* \return <0, Start fail.
*
*/
extern int8_t arm_nwk_6lowpan_rpl_dodag_start(int8_t interface_id);
/**
* \brief RPL prefix information update.
*
* \param interface_id Root interface ID
* \param prefix_ptr A pointer to IPv6 prefix (16-bytes).
* \param prefix_len Prefix length (should be 64).
* \param flags Define R-flag (RPL_PREFIX_ROUTER_ADDRESS_FLAG), A-flag (RPL_PREFIX_AUTONOMOUS_ADDRESS_FLAG).
* \param lifetime Prefix lifetime.
*
*
* \return 0, Update OK.
* \return <0, Update fail.
*
*/
extern int8_t arm_nwk_6lowpan_rpl_dodag_prefix_update(int8_t interface_id, uint8_t *prefix_ptr, uint8_t prefix_len, uint8_t flags, uint32_t lifetime);
/**
* \brief RPL route information update.
*
* \param interface_id Root interface ID.
* \param route_ptr A pointer to IPv6 prefix (16-bytes).
* \param prefix_len Prefix length (should be 64).
* \param flags Define R-flag (RPL_PREFIX_ROUTER_ADDRESS_FLAG).
* \param lifetime Route lifetime.
*
*
* \return 0, Update OK.
* \return <0, Update fail.
*
*/
extern int8_t arm_nwk_6lowpan_rpl_dodag_route_update(int8_t interface_id, uint8_t *route_ptr, uint8_t prefix_len, uint8_t flags, uint32_t lifetime);
/**
* \brief RPL DODAG poison.
*
* This function poisons the current RPL instance. After a few seconds arm_nwk_6lowpan_rpl_dodag_remove() can also clean the root.
*
* \param interface_id Interface ID that defines the RPL instance to be poisoned.
*
*
* \return 0, Poison OK.
* \return <0, Poison fail.
*
*/
extern int8_t arm_nwk_6lowpan_rpl_dodag_poison(int8_t interface_id);
/**
* \brief Trigger RPL DODAG DAO by DTSN increment.
*
*
* \param interface_id Network interface ID.
*
*
* \return 0, DAO trig OK
* \return <0, DAO trig Fail
*
*/
extern int8_t arm_nwk_6lowpan_rpl_dodag_dao_trig(int8_t interface_id);
/**
* \brief RPL DODAG version update.
*
* Network devices need to reset the current RPL instance and do unicast DIS/DIO and DAO/DAO ACK handshake.
*
* \param interface_id Root interface ID.
*
*
* \return 0, Version update OK.
* \return <0, Version update fail.
*
*/
extern int8_t arm_nwk_6lowpan_rpl_dodag_version_increment(int8_t interface_id);
/**
* \brief Read RPL instance list of a node.
*
* Global instances are output as a single byte containing the instance ID;
* local instances are output as the instance ID followed by the 16-byte DODAG ID.
*
* \param buffer_ptr A pointer to the location of the instance IDs.
* \param buffer_size Instance list buffer size.
*
* \return RPL instance count (not necessarily number of bytes, if local instances).
*
*/
extern uint8_t rpl_instance_list_read(uint8_t *buffer_ptr, uint8_t buffer_size);
/**
* \brief Read DODAG information by given RPL instance ID.
*
* If it is a local instance ID, dodag_ptr must contain the DODAG ID on entry.
*
* \param dodag_ptr A pointer to DODAG information structure.
* \param instance_id Read instance ID.
*
* \return 1, Read OK.
* \return 0, Read fail.
*
*/
extern uint8_t rpl_read_dodag_info(rpl_dodag_info_t *dodag_ptr, uint8_t instance_id);
/**
* \brief RPL DODAG preference set.
*
* \param interface_id Interface ID in which the RPL instance updates the DODAG preference.
* \param preference DODAG preference. 0 to 7. 0 is least preferred.
*
* \return 0, Update OK
* \return <0, Update Fail
*
*/
extern int8_t arm_nwk_6lowpan_rpl_dodag_pref_set(int8_t interface_id, uint8_t preference);
#ifdef __cplusplus
}
#endif
#endif /*_NS_RPL_H*/

64
nanostack/net_sleep.h Normal file
View File

@ -0,0 +1,64 @@
/*
* Copyright (c) 2014-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef NET_SLEEP_H_
#define NET_SLEEP_H_
#include "ns_types.h"
/**
* \file net_sleep.h
* \brief Checks if there is a sleep possibility for the stack and the max sleep time.
*
* \section check-slp-poss Checking sleep possibility.
* - arm_net_check_enter_deep_sleep_possibility(), Checks whether the stack can enter a sleep cycle.
* - arm_net_enter_sleep(), A function to enter sleep cycle.
* - arm_net_wakeup_and_timer_synch(), Restarts the stack and synchronizes the timer.
*/
/**
*\brief Check sleep possibility.
* \return Time in milliseconds for sleep.
* \return 0, No possibility to enter deep sleep.
*/
uint32_t arm_net_check_enter_deep_sleep_possibility(void);
/**
* \brief Set stack to sleep.
*
* \return 0 Stack stopped.
* \return -1 Not supported action at the moment.
*
*/
int arm_net_enter_sleep(void);
/**
* \brief Restart stack after sleep.
*
* Stack enable and synch timers after sleep.
*
* \param sleeped_time_in_ms The total sleep time in milliseconds. The stack needs to synch with this.
*
* \return 0 Stack restarted.
* \return 1 Stack can continue sleep for the time defined in sleeped_time_in_ms.
* \return -1 Stack already active.
*
*/
int arm_net_wakeup_and_timer_synch(uint32_t sleeped_time_in_ms);
#endif /* NET_SLEEP_H_ */

59
nanostack/net_test_api.h Normal file
View File

@ -0,0 +1,59 @@
/*
* Copyright (c) 2016-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* \file net_ipv6_api.h
* \brief IPv6 configuration API.
*/
#ifndef NET_TEST_API_H_
#define NET_TEST_API_H_
#include "ns_types.h"
/**
* \brief Makes TCP protocol drop given number of packets from a particular state (TX side).
*
* Testing API for TCP retransmission mechanism after a packet is dropped in a particular state.
*
* \param state Particular TCP state - Identified by its number from 1-11. Numbering is from the SNMP MIB - RFC 4022.
* \param count No. of packets to be dropped
* \return 0 OK
* \return <0 If request can't be fulfilled, i.e., Not test environment.
*/
int8_t arm_nwk_test_tcp_drop_tx(int state, uint8_t count);
/**
* \brief Makes TCP protocol drop given number of packets from a particular state (RX side).
*
* Testing API for TCP to drop received packets.
*
* \param state Particular TCP state - Identified by its number from 1-11. Numbering is from the SNMP MIB - RFC 4022.
* \param count No. of packets to be dropped
* \return 0 OK
* \return <0 If request can't be fulfilled, i.e., Not test environment.
*/
int8_t arm_nwk_test_tcp_drop_rx(int state, uint8_t count);
/**
* \brief Resets drop counters.
*
* Testing API for TCP reset any packet drop counters.
*/
void arm_nwk_test_tcp_drop_reset(void);
#endif //NET_TEST_API_H_

525
nanostack/net_thread_test.h Normal file
View File

@ -0,0 +1,525 @@
/*
* Copyright (c) 2014-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef NET_THREAD_TEST_H_
#define NET_THREAD_TEST_H_
/* Prevent this file being inserted in public Doxygen generated file
* this is not part of our external API. */
#ifndef DOXYGEN
/**
* \file net_thread_test.h
* \brief Thread Library Test API.
*
* \warning NOTICE! This is test API must not be used externally.
*
* \warning This file is not part of the version number control and can change any time.
*
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "ns_types.h"
#define thread_test_router_upgrade(iface) thread_test_router_id_request_send(iface, 2) // THREAD_COAP_STATUS_TLV_TOO_FEW_ROUTERS
/**
* \brief Add a static neighbour
*
* Test API: Add a neighbour. Adds, or updates, a non-expiring neighbour to the
* Thread Link Set, and updates the Route Set accordingly. Basically equivalent
* to receiving an MLE advertisement with a Route TLV, except it doesn't expire.
*
* See draft-kelsey-thread-routing-00 for more info on data format.
*
* \param interface_id Interface to modify
* \param neighbour_addr Neighbour short address (must be a router address)
* \param link_margin_db Notional link margin for reception from this neighbour.
* \param id_sequence Sequence number for id_mask
* \param id_mask Bit mask of router IDs
* \param route_data One octet per set bit in id_mask
*
* \return 0 Success
* \return <0 Failure
*/
int_fast8_t arm_nwk_6lowpan_thread_test_add_neighbour(
int8_t interface_id,
uint16_t neighbour_short_addr,
uint_fast8_t link_margin_db,
uint8_t id_sequence,
const uint8_t *id_mask,
const uint8_t *route_data);
/**
* \brief API to set reed advertisement interval
* \param interface_id Interface to modify
* \param advertisement_interval Interval between advertisements to be set
* \param jitter_interval Maximum value of random jitter interval to be added to advertisement_interval
* \return 0 Success
* \return < 0 Other errors
*/
int8_t thread_reed_set_advertisement_interval(int8_t interface_id, uint16_t advertisement_interval, uint16_t jitter_interval);
/**
* \brief Remove a static neighbour
*
* Test API: Remove a neighbour. Remove a neighbour from the Thread Link Set
* (whether added through arm_nwk_6lowpan_thread_test_add_neighbour, or
* automatically through MLE).
*
* \param interface_id Interface to modify
* \param neighbour_addr Neighbour short address (must be a router address)
*
* \return 0 Success
* \return -1 Not an existing neighbour
* \return <-1 Other errors
*/
int_fast8_t arm_nwk_6lowpan_thread_test_remove_neighbour(
int8_t interface_id,
uint16_t neighbour_short_addr);
/**
* \brief Print routing database
*
* Test API: Dump the routing data base (Router ID Set, Link Set and Route
* Set) to the debug channel.
*
* \param interface_id Interface to interrogate
*/
void arm_nwk_6lowpan_thread_test_print_routing_database(int8_t interface_id);
/**
* \brief Thread Leader max router ID limit set
*
* This function should use just for test purpose Thread define this by default to 32
*
* \param interface_id Network Interface
* \param maxRouterLimit Min Accepted value is 1 and max 32
*
* return 0, Set OK
* return <0 Set Fail
*/
int thread_test_max_accepted_router_id_limit_set(
int8_t interface_id,
uint8_t maxRouterLimit);
/**
* \brief Set Thread network ID timeout
*
* \param interface_id Interface to modify
* \param network_id_timeout network timeout as seconds
*
* \return 0 Success
* \return -1 Invalid interface id
* \return -2 Thread not active
* \return -3 invalid timeout value
*/
int8_t thread_routing_set_network_id_timeout(int8_t interface_id, uint16_t network_id_timeout);
/**
* \brief Get Thread network ID timeout
*
* \param interface_id Interface to modify
* \param network_id_timeout pointer, where current network id timeout will be saved as seconds
*
* \return 0 Success
* \return -1 Invalid interface id
* \return -2 Thread not active
* \return -3 invalid pointer
*/
int8_t thread_routing_get_network_id_timeout(int8_t interface_id, uint16_t *network_id_timeout);
/**
* \brief Print Thread network data
*
* \param interface_id Network Interface
*
* \return 0, OK
* \return <0 Not OK
*/
int thread_test_print_network_data(int8_t interface_id);
/**
* \brief Thread Leader Context ID reuse timeout set
*
* This function should be used to change default 48 hours to shorter one
*
* \param interface_id Network Interface
* \param timeout Min Accepted value is 60 seconds and max 48 hours (48*3600)
*
* \return 0, Set OK
* \return <0 Set Fail
*/
int thread_test_set_context_id_reuse_timeout(
int8_t interface_id,
uint32_t timeout);
/**
* \brief Leader of Thread network can kick Router out from Network.
*
* \param interface_id Network Interface
* \param routerId Routter id of router that is kicked
*
* \return 0, Remove OK
* \return <0 Remove fail
*/
int thread_test_remove_router_by_id(int8_t interface_id, uint8_t routerId);
/**
* \brief Start router downgrade process.
*
* \param interface_id Network Interface
*
* \return 0, downgrade started
* \return <0 fail
*/
int thread_test_router_downgrade(int8_t interface_id);
/**
* \brief Set Thread Security Material. Terms are defined in Thread security specification
*
* \param interface_id Network Interface
* \param enableSecurity Boolean for enable security or disable
* \param thrMasterKey Master Key material which will be used for generating new key
* \param thrKeySequenceCounter Periodic counter used to generate new MAC and MLE keys
* \param thrKeyRotation Update period (in seconds) for thrKeySequenceCounter
*
* \return 0, ADD OK
* \return <0 Add Not OK
*/
int thread_test_security_material_set(int8_t interface_id, bool enableSecurity, uint8_t *thrMasterKey, uint32_t thrKeySequenceCounter, uint32_t thrKeyRotation);
/**
* \brief Set Thread version number.
*
* \param interface_id Network Interface
* \param version "1 == Thread version 1.0" or "2 == Thread version 1.1"
*
* \return 0, OK
* \return <0 Error
*/
int thread_test_version_set(int8_t interface_id, uint8_t version);
/**
* \brief Set Thread router selection jitter.
*
* \param interface_id Network Interface
* \param value must be over 1 default is 120
*
* \return 0, OK
* \return <0 Error
*/
int thread_test_router_selection_jitter_set(int8_t interface_id, uint32_t jitter);
/**
* \brief Sets the thread MIN_DELAY_TIMER default value.
*
* \param interface_id Network Interface
* \param delay_timer_value delay timer value in seconds used in leader
*
* \return 0, OK
* \return <0 Error
*/
int thread_test_min_delay_timer_set(int8_t interface_id, uint32_t delay_timer_value);
/**
* \brief Increment Thread key sequence counter
*
* \param interface_id Network Interface
*
* \return 0, OK
* \return <0 Error
*/
int thread_test_increment_key_sequence_counter(int8_t interface_id);
/**
* \brief Set new Thread key sequence counter
*
* Call define new key and next key same time
*
* \param interface_id Network Interface
* \param thrKeySequenceCounter this need to be bigger than current sequence
*
* \return 0, OK
* \return <0 Error
*/
int thread_test_key_sequence_counter_update(int8_t interface_id, uint32_t thrKeySequenceCounter);
/**
* \brief Set new Thread key rotation value
*
* \param interface_id Network interface ID
* \param thrKeyRotation Key rotation value in seconds
*
* \return 0, OK
* \return <0 Error
*/
int thread_test_key_rotation_update(int8_t interface_id, uint32_t thrKeyRotation);
/**
* \brief Thread router select threshold values set
*
* \param interface_id Network Interface
* \param upgradeThreshold Set REED up grade to router threshold
* \param downgradeThreshold Set Router down grade to REED threshold
*
* \return 0, Set OK
* \return <0 Set Fail
*/
int thread_test_router_select_threshold_values_set(
int8_t interface_id,
uint8_t upgradeThreshold,
uint8_t downgradeThreshold);
/**
* \brief Send PAN ID query message to destination
*
* \param interface_id Network Interface
*
* \return 0, Set OK
* \return <0 Set Fail
*/
int thread_test_panid_query_send(int8_t interface_id, uint8_t *address_ptr, uint16_t session_id, uint16_t panid, uint8_t channel_page, uint8_t *mask_ptr);
/**
* \brief Send energy scan message to destination
*
* \param interface_id Network Interface
*
* \return 0, Set OK
* \return <0 Set Fail
*/
int thread_test_energy_scan_send(int8_t interface_id, uint8_t *address_ptr, uint16_t session_id, uint8_t channel_page, uint8_t *mask_ptr, uint16_t period, uint8_t count, uint16_t duration);
/**
* \brief Send announcement message
*
* \param interface_id Network Interface
* \param channel high uint16 is the channel page, lower part is the channel number on that page
*
* \return 0, Set OK
* \return <0 Set Fail
*/
int thread_test_announce_ntf_send(int8_t interface_id, uint8_t *address_ptr, uint32_t channel, uint16_t panid, uint64_t timestamp);
/**
* \brief Send energy scan message to destination
*
* \param interface_id Network Interface
*
* \return 0, Set OK
* \return <0 Set Fail
*/
int thread_test_announce_begin_send(int8_t interface_id, uint8_t *address_ptr, uint16_t session_id, uint8_t channel_page, uint8_t *mask_ptr, uint16_t period, uint8_t count);
/**
* \brief Get partition info
*
* \param interface_id Network Interface
* \param partition_id Current partition id can be NULL if not needed.
* \param weighting Current weighting can be NULL if not needed.
* \param data_version Current data version can be NULL if not needed.
* \param stable_data_version Current stable data version can be NULL if not needed.
* \param leader_id Current leader id can be NULL if not needed.
*
* \return 0, Set OK
* \return <0 Set Fail
*/
int thread_test_partition_info_get(int8_t interface_id, uint32_t *partition_id, uint8_t *weighting, uint8_t *data_version, uint8_t *stable_data_version, uint8_t *leader_id);
/**
* \brief Set next partition ID when we next time partition. This is used to control specific behaviour in tests.
*
* \param interface_id Network Interface
*
* \return 0, Set OK
* \return <0 Set Fail
*/
int thread_test_partition_info_set(int8_t interface_id, uint32_t partition_id);
/**
* \brief Get thread information.
*
* \param interface_id Network Interface
* \param short_addr own short address
* \param router_count amount of active routers in network
* \param network_stable stable network achieved no upgrade or downgrade pending
*
* \return 0, Set OK
* \return <0 Set Fail
*/
int8_t thread_test_thread_information_get(int8_t interface_id, uint16_t *short_addr, uint8_t *router_count, bool *network_stable);
/**
* \brief Get child count
*
* \param interface_id Network Interface
*
* \return 0, Set OK
* \return <0 Set Fail
*/
int8_t thread_test_child_count_get(int8_t interface_id);
/**
* \brief Get child information
*
* get information for index child. if found returns 0 with correct information.
*
* \param interface_id Network Interface
*
* \return 0, OK
* \return <0 Fail no child with this index found
*/
int8_t thread_test_child_info_get(int8_t interface_id, uint8_t index, uint16_t *short_addr, bool *sleepy, uint8_t *mac64, uint8_t *margin);
/**
* \brief Get neighbour information
*
* \param interface_id Network Interface
*
* \return 0, Set OK
* \return <0 Set Fail
*/
int8_t thread_test_neighbour_info_get(int8_t interface_id, uint8_t index, uint16_t *short_addr, uint8_t *mac64, uint8_t *margin);
typedef int (response_cb)(int8_t interface_id, uint8_t *response_ptr, uint16_t response_len);
/**
* \brief Send diagnostic command DEPRECATED
*
* \param interface_id Network Interface
* \param address_ptr Address to which the command is sent
* \param uri_ptr Uri for the command
* \param request_length The length of the request
* \param request_ptr Pointer to the beginning of the request contents
* \param resp_cb Pointer to callback function that is called after the reply for the command is obtained
* \return 0, Command send OK
* \return <0 Command send Fail
*/
int thread_test_diagnostic_command_send(int8_t interface_id, uint8_t *address_ptr,const char *uri_ptr, uint8_t request_length, uint8_t *request_ptr, response_cb *resp_cb);
typedef int (coap_response_cb)(int8_t interface_id, uint8_t message_code, uint8_t message_type, uint8_t *response_ptr, uint16_t response_len);
/**
* \brief Send diagnostic request
*
* \param interface_id Network Interface
* \param address_ptr Address to which the command is sent
* \param msg_type Uri for the command
* \param msg_code Uri for the command
* \param uri_ptr Uri for the command
* \param request_length The length of the request
* \param request_ptr Pointer to the beginning of the request contents
* \param resp_cb Pointer to callback function that is called after the reply for the command is obtained
*
* \return 0, Command send OK
* \return <0 Command send Fail
*/
int thread_test_coap_request_send(int8_t interface_id, uint8_t *address_ptr, uint16_t port, uint8_t msg_type, uint8_t msg_code, uint16_t content_format, const char *uri_ptr, uint8_t *request_ptr, uint8_t request_length, coap_response_cb *resp_cb);
/**
* \brief Set initial SLAAC iid.
*
* \param interface_id Network Interface
* \param iid Interface identifier pointer must be 8 bytes long buffer. can be NULL to disable.
* \return 0, Command OK
* \return <0 Command Fail
*/
int8_t thread_test_initial_slaac_iid_set(int8_t interface_id, uint8_t *iid);
/**
* \brief Send router ID request.
*
* \param interface_id Network Interface
* \param status Value of router ID request status TLV
* \return 0, Command OK
* \return <0 Command Fail
*/
int8_t thread_test_router_id_request_send(int8_t interface_id, uint8_t status);
/**
* \brief Set joiner port to joiner router device.
* If port == 0, then default port is used.
*
* \param iid Joiner port.
* \return 0, Command OK
* \return <0 Command Fail
*/
int8_t thread_test_joiner_router_joiner_port_set(uint16_t port);
/**
*\brief set a router address to be requested. For a router, this address is sent
*\in address solicit request to leader and for leader this is the router address
*
* \param interface_id Network Interface
* \param router_addr Address requested
* \return 0, Command OK
* \return <0 Command Fail
*/
int8_t thread_test_router_address_set(int8_t interface_id, uint16_t router_addr);
/**
*\brief sends any MLE message to any destination.
*
* \param interface_id Network Interface
* \param dst_address destination address
* \param msg_id MLE message id
* \param write_src_addr write short address of the device
* \param write_leader_data write leader data
* \param write_network_data write network data
* \param write_timestamp write current timestamps*
* \param write_operational_set write current operational datasets *
* \param write_challenge add challenge to the message
* \param msg_ptr additional buffer addded to message
* \param msg_len length of the additional message
* \return 0, Command OK
* \return <0 Command Fail
*/
int thread_test_mle_message_send(int8_t interface_id, uint8_t *dst_address, uint8_t msg_id, bool write_src_addr, bool write_leader_data, bool write_network_data, bool write_timestamp, bool write_operational_set, bool write_challenge, uint8_t *msg_ptr, uint8_t msg_len);
/**
* \brief Set extension name.
*
* \param interface_id Network Interface
* \param extension_name Extension name string
*
* \return 0 OK
* \return <0 Failure
*/
int thread_test_extension_name_set(int8_t interface_id, char extension_name[16]);
#ifdef __cplusplus
}
#endif
#endif /* DOXYGEN */
#endif /* NET_THREAD_TEST_H_ */

47
nanostack/ns_address.h Normal file
View File

@ -0,0 +1,47 @@
/*
* Copyright (c) 2010-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _NS_LIB_ADDRESS_H
#define _NS_LIB_ADDRESS_H
/**
* \file ns_address.h
* \brief 6LowPAN library address format description.
*
*/
#include "ns_types.h"
/**
* /enum address_type_t
* /brief Address types.
*/
typedef enum address_type_t {
ADDRESS_IPV6, /**< IPv6 Address type. Must be used always at socket interface. */
ADDRESS_IPV4, /**< IPv4 Address type. Must be used always at socket interface. */
ADDRESS_TUN_DRIVER_ID /**< Local socket address type. The length is 1 byte (driver ID for packet source). */
} address_type_t;
/**
* /struct ns_address_t
* /brief Struct for the addresses used by the socket interface functions and net_address_get().
*/
typedef struct ns_address {
address_type_t type; /**< Address type. */
uint8_t address[16]; /**< Address. */
uint16_t identifier; /**< TCP/UDP port number. */
} ns_address_t;
#endif /* _NS_ADDRESS_H */

View File

@ -0,0 +1,54 @@
/*
* Copyright (c) 2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _NS_FILE_SYSTEM_H_
#define _NS_FILE_SYSTEM_H_
/**
* \file ns_file_system.h
* \brief Nanostack file system API.
*/
/**
* \brief Set file system root path.
*
* Allow stack to store information to the location provided.
* Setting root path to NULL will prevent file system usage.
*
* \param root_path Path to location where networking files can be stored. Path must exists in the file system
* and path must end to "/" character. Path can be NULL to disable file system usage.
*
* \return 0 in success, negative value in case of error.
*
*/
#ifdef __cplusplus
extern "C" {
#endif
int ns_file_system_set_root_path(const char *root_path);
/**
* \brief Get file system root path.
*
* \return Root path to stack storage location.
*
*/
char *ns_file_system_get_root_path(void);
#ifdef __cplusplus
}
#endif
#endif /* _NS_FILE_SYSTEM_H_ */

103
nanostack/ns_mdns_api.h Normal file
View File

@ -0,0 +1,103 @@
/*
* Copyright (c) 2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _NS_MDNS_API_H_
#define _NS_MDNS_API_H_
/**
* \file ns_mdns_api.h
* \brief Nanostack mDNS-SD API.
*/
/*!
* \struct ns_mdns_t
* \brief Structure for Nanostack mDNS instance
*/
typedef struct ns_mdns *ns_mdns_t; /**< Instance */
/*!
* \struct ns_mdns_service_t
* \brief Structure for Nanostack mDNS service instance
*/
typedef struct ns_mdns_service *ns_mdns_service_t; /**< Service instance */
/*!
* \struct ns_mdns_service_param_t
* \brief Structure for mDNS service parameters
*/
typedef struct ns_mdns_service_param
{
const char *service_type; /**< Null-terminated string owned by the caller */
uint16_t service_port; /**< Service Port number */
const uint8_t *(*service_get_txt)(void); /**< Call-back function, which returns a pointer to the service TXT record (null-terminated).
If the service does not provide any TXT record, this parameter must be set to NULL. */
} ns_mdns_service_param_t;
/**
* \brief Start mDNS server
*
* \param server_name NULL terminated string, max length 63 characters
*
* \param ttl time-to-live value in seconds, if set to 0 default value is used
*
* \param ttl_ip time-to-live in hop count, if set to 0 default value is used
*
* \param interface_id ID of the network interface where mDNS will operate
*
* \return mDNS server instace or NULL in case of failure..
*/
ns_mdns_t ns_mdns_server_start(const char *server_name, uint32_t ttl, uint32_t ttl_ip, int8_t interface_id);
/**
* \brief Stop mDNS server
*
* \param ns_mdns_instance Server instance received from ns_mdns_server_start
*
*/
void ns_mdns_server_stop(ns_mdns_t ns_mdns_instance);
/**
* \brief Register service to mDNS server
*
* \param ns_mdns_instance Server instance received from ns_mdns_server_start
*
* \param service Parameters for service
*
* \return mDNS Service descriptor or NULL in case of failure.
*
*/
ns_mdns_service_t ns_mdns_service_register(ns_mdns_t ns_mdns_instance, ns_mdns_service_param_t *service);
/**
* \brief Unregister service from mDNS server
*
* \param service_desc mDNS Service descriptor received from call to ns_mdns_service_register.
*/
void ns_mdns_service_unregister(ns_mdns_service_t service_desc);
/**
* \brief Send mDNS announcement. Application should call this method once application
* advertised parameters has changed.
*
* \param ns_mdns_instance Server instance received from ns_mdns_server_start
*/
void ns_mdns_announcement_send(ns_mdns_t ns_mdns_instance);
#endif /* _NS_MDNS_API_H_ */

205
nanostack/ns_sha256.h Normal file
View File

@ -0,0 +1,205 @@
/*
* Copyright (c) 2006-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* \file ns_sha256.h
*
* \brief SHA-256 cryptographic hash function
*
* This file is derived from sha256.h in mbed TLS 2.3.0.
*
* This file provides an API very similar to mbed TLS, either implemented
* locally, or by calling mbed TLS, depending on NS_USE_EXTERNAL_MBED_TLS.
*
* Differences from mbed TLS:
*
* a) ns_ prefix instead of mbedtls_;
* b) Pointers are void * instead of unsigned char * to avoid type clashes;
* c) SHA-224 not supported;
* d) Ability to output truncated hashes.
*/
#ifndef NS_SHA256_H_
#define NS_SHA256_H_
#ifdef NS_USE_EXTERNAL_MBED_TLS
#include <string.h>
#include "mbedtls/sha256.h"
typedef mbedtls_sha256_context ns_sha256_context;
static inline void ns_sha256_init(ns_sha256_context *ctx)
{
mbedtls_sha256_init(ctx);
}
static inline void ns_sha256_free(ns_sha256_context *ctx)
{
mbedtls_sha256_free(ctx);
}
static inline void ns_sha256_clone(ns_sha256_context *dst,
const ns_sha256_context *src)
{
mbedtls_sha256_clone(dst, src);
}
static inline void ns_sha256_starts(ns_sha256_context *ctx)
{
mbedtls_sha256_starts(ctx, 0);
}
static inline void ns_sha256_update(ns_sha256_context *ctx, const void *input,
size_t ilen)
{
mbedtls_sha256_update(ctx, input, ilen);
}
static inline void ns_sha256_finish(ns_sha256_context *ctx, void *output)
{
mbedtls_sha256_finish(ctx, output);
}
static inline void ns_sha256(const void *input, size_t ilen, void *output)
{
mbedtls_sha256(input, ilen, output, 0);
}
/* Extensions to standard mbed TLS - output the first bits of a hash only */
/* Number of bits must be a multiple of 32, and <=256 */
static inline void ns_sha256_finish_nbits(ns_sha256_context *ctx, void *output, unsigned obits)
{
if (obits == 256) {
mbedtls_sha256_finish(ctx, output);
} else {
uint8_t sha256[32];
mbedtls_sha256_finish(ctx, sha256);
memcpy(output, sha256, obits / 8);
}
}
static inline void ns_sha256_nbits(const void *input, size_t ilen, void *output, unsigned obits)
{
if (obits == 256) {
mbedtls_sha256(input, ilen, output, 0);
} else {
uint8_t sha256[32];
mbedtls_sha256(input, ilen, sha256, 0);
memcpy(output, sha256, obits / 8);
}
}
#else /* NS_USE_EXTERNAL_MBED_TLS */
#include <stddef.h>
#include <stdint.h>
/**
* \brief SHA-256 context structure
*/
typedef struct
{
uint32_t total[2]; /*!< number of bytes processed */
uint32_t state[8]; /*!< intermediate digest state */
unsigned char buffer[64]; /*!< data block being processed */
}
ns_sha256_context;
/**
* \brief Initialize SHA-256 context
*
* \param ctx SHA-256 context to be initialized
*/
void ns_sha256_init( ns_sha256_context *ctx );
/**
* \brief Clear SHA-256 context
*
* \param ctx SHA-256 context to be cleared
*/
void ns_sha256_free( ns_sha256_context *ctx );
/**
* \brief Clone (the state of) a SHA-256 context
*
* \param dst The destination context
* \param src The context to be cloned
*/
void ns_sha256_clone( ns_sha256_context *dst,
const ns_sha256_context *src );
/**
* \brief SHA-256 context setup
*
* \param ctx context to be initialized
*/
void ns_sha256_starts( ns_sha256_context *ctx );
/**
* \brief SHA-256 process buffer
*
* \param ctx SHA-256 context
* \param input buffer holding the data
* \param ilen length of the input data
*/
void ns_sha256_update( ns_sha256_context *ctx, const void *input,
size_t ilen );
/**
* \brief SHA-256 final digest
*
* \param ctx SHA-256 context
* \param output SHA-256 checksum result
*/
void ns_sha256_finish( ns_sha256_context *ctx, void *output );
/**
* \brief SHA-256 final digest
*
* \param ctx SHA-256 context
* \param output SHA-256 checksum result
* \param obits Number of bits of to output - must be multiple of 32
*/
void ns_sha256_finish_nbits( ns_sha256_context *ctx,
void *output, unsigned obits );
/**
* \brief Output = SHA-256( input buffer )
*
* \param input buffer holding the data
* \param ilen length of the input data
* \param output SHA-256 checksum result
*/
void ns_sha256( const void *input, size_t ilen,
void *output );
/**
* \brief Output = SHA-256( input buffer )
*
* \param input buffer holding the data
* \param ilen length of the input data
* \param output SHA-256 checksum result
* \param obits Number of bits of to output - must be multiple of 32
*/
void ns_sha256_nbits( const void *input, size_t ilen,
void *output, unsigned obits );
#endif /* NS_USE_EXTERNAL_MBED_TLS */
#endif /* NS_SHA256_H_ */

View File

@ -0,0 +1,53 @@
/*
* Copyright (c) 2016-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/** \file ns_virtual_rf_api.h
* \brief Virtual RF interface API.
*/
#ifndef NS_VIRTUAL_RF_API_H_
#define NS_VIRTUAL_RF_API_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "platform/arm_hal_phy.h"
/**
* @brief virtual_rf_device_register Creates virtual RF device
* Emulates "radio" link like the real RF driver would do it. MAC does not know the difference.
* Sends and listens data to/from serial MAC.
* @param link_type Link type behind virtual device
* @param mtu_size Maximum transmission unit size
* @return Rf driver id
*/
int8_t virtual_rf_device_register(phy_link_type_e link_type, uint16_t mtu_size);
/**
* @brief virtual_rf_client_register Creates virtual RF client
* "Acts" in a role of upper layer for MAC (802.15.4 or ethernet) and in a role of RF driver for serial MAC.
* Forwards data between serial MAC and either 802.15.4 or ethernet MAC.
* @return Rf driver id
*/
int8_t virtual_rf_client_register(void);
#ifdef __cplusplus
}
#endif
#endif /* NS_VIRTUAL_RF_API_H_ */

96
nanostack/nwk_stats_api.h Normal file
View File

@ -0,0 +1,96 @@
/*
* Copyright (c) 2013-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef NWK_STATS_API_H
#define NWK_STATS_API_H
/**
* \file nwk_stats_api.h
* \brief 6LowPAN library network stats API
*
* - protocol_stats_start(), Enable stats update.
* - protocol_stats_stop(), Stop stack stats update.
* - protocol_stats_reset(), Reset all stats information to null.
*
*
*/
#include "ns_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* /struct nwk_stats_t
* /brief Struct for network stats buffer structure.
*/
typedef struct nwk_stats_t {
/* 6Lowpan */
uint32_t ip_rx_count; /**< IP RX packet count. */
uint32_t ip_tx_count; /**< IP TX packet count. */
uint32_t ip_rx_drop; /**< IP RX packet drops count. */
uint32_t ip_cksum_error; /**< IP checksum error count. */
/* IP Payload Flow */
uint32_t ip_tx_bytes; /**< IP TX bytes count. */
uint32_t ip_rx_bytes; /**< IP RX bytes count. */
uint32_t ip_routed_up; /**< IP routed UP bytes count. */
uint32_t ip_no_route; /**< IP no route count. */
/* Fragments */
uint32_t frag_rx_errors; /**< Fragmentation RX error count. */
uint32_t frag_tx_errors; /**< Fragmentation TX error count. */
/*RPL stats*/
uint32_t rpl_route_routecost_better_change; /**< RPL parent change count. */
uint32_t ip_routeloop_detect; /**< RPL route loop detection count. */
uint32_t rpl_memory_overflow; /**< RPL memory overflow count. */
uint32_t rpl_parent_tx_fail; /**< RPL transmit errors to DODAG parents. */
uint32_t rpl_unknown_instance; /**< RPL unknown instance ID count. */
uint32_t rpl_local_repair; /**< RPL local repair count. */
uint32_t rpl_global_repair; /**< RPL global repair count. */
uint32_t rpl_malformed_message; /**< RPL malformed message count. */
uint32_t rpl_time_no_next_hop; /**< RPL seconds without a next hop. */
uint32_t rpl_total_memory; /**< RPL current memory usage total. */
/* Buffers */
uint32_t buf_alloc; /**< Buffer allocation count. */
uint32_t buf_headroom_realloc; /**< Buffer headroom realloc count. */
uint32_t buf_headroom_shuffle; /**< Buffer headroom shuffle count. */
uint32_t buf_headroom_fail; /**< Buffer headroom failure count. */
/* ETX */
uint16_t etx_1st_parent; /**< Primary parent ETX. */
uint16_t etx_2nd_parent; /**< Secondary parent ETX. */
} nwk_stats_t;
/**
* \brief Enable stats collection.
*
* \param stats_ptr A static pointer to stack update.
*
*/
extern void protocol_stats_start(nwk_stats_t *stats_ptr);
/**
* \brief Disable stats collection.
*
*/
extern void protocol_stats_stop(void);
/**
* \brief Reset stats info fiels.
*
*/
extern void protocol_stats_reset(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,79 @@
/*
* Copyright (c) 2014-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* \file arm_hal_aes.h
* \brief AES Platform API
*/
#ifndef ARM_HAL_AES_H_
#define ARM_HAL_AES_H_
/* The network library requires a simple AES implementation for its
* IEEE 802.15.4 security. The expectation is that 802.15.4 devices will have
* some hardware acceleration, which should be made available through this API.
*
* If no hardware acceleration is available, the API can be easily hooked up to
* an external software library such as mbed TLS.
*
* To simplify porting, the API is used single-threaded, so that no special care
* is needed to maintain global context or state in the hardware accelerator.
*/
#include "ns_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief Set the AES key
*
* This function sets the 128-bit AES key that will be used for future
* calls to arm_aes_encrypt(). The key must be copied by the function.
*
* \param key pointer to 128-bit AES key
*/
void arm_aes_start(const uint8_t key[__static 16]);
/**
* \brief This function performs dst=E[preset key,src] (Simple ECB block).
*
* This function performs a single-block AES encryption, using the preset key.
* It is called between arm_aes_start() and arm_aes_finish().
* Note that src and dst pointers may be equal.
*
* \param src pointer to 128-bit plaintext in
* \param dst pointer for 128-bit ciphertext out
*/
extern void arm_aes_encrypt(
const uint8_t src[__static 16],
uint8_t dst[__static 16]);
/**
* \brief Finish AES operations
*
* This function is called to terminate a series of AES operations.
* It may be a no-op, or it may disable AES hardware. Use of the preset key is
* no longer valid after this call.
*/
void arm_aes_finish(void);
#ifdef __cplusplus
}
#endif
#endif /* ARM_HAL_AES_H_ */

View File

@ -0,0 +1,323 @@
/*
* Copyright (c) 2014-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* \file arm_hal_phy.h
* \brief PHY device driver API.
*/
#ifndef ARM_HAL_PHY_H_
#define ARM_HAL_PHY_H_
#include "ns_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/** Interface states */
typedef enum {
PHY_INTERFACE_RESET, /**< Reset PHY driver and set to idle. */
PHY_INTERFACE_DOWN, /**< Disable PHY interface driver (RF radio disable). */
PHY_INTERFACE_UP, /**< Enable PHY interface driver (RF radio receiver ON). */
PHY_INTERFACE_RX_ENERGY_STATE, /**< Enable wireless interface ED scan mode. */
PHY_INTERFACE_SNIFFER_STATE /**< Enable sniffer mode. */
} phy_interface_state_e;
/** TX process return codes */
typedef enum {
PHY_LINK_TX_DONE, /**< TX process ready and ACK RX. */
PHY_LINK_TX_DONE_PENDING, /**< TX process OK with ACK pending flag. */
PHY_LINK_TX_SUCCESS, /**< MAC TX complete. MAC will a make decision to enter wait ACK or TX done state. */
PHY_LINK_TX_FAIL, /**< Link TX process fail. */
PHY_LINK_CCA_FAIL, /**< RF link CCA process fail. */
} phy_link_tx_status_e;
/** Extension types */
typedef enum {
PHY_EXTENSION_CTRL_PENDING_BIT, /**< Control MAC pending bit for indirect data. */
PHY_EXTENSION_READ_LAST_ACK_PENDING_STATUS, /**< Read status if the last ACK is still pending. */
PHY_EXTENSION_SET_CHANNEL, /**< Net library channel set. */
PHY_EXTENSION_READ_CHANNEL_ENERGY, /**< RF interface ED scan energy read. */
PHY_EXTENSION_READ_LINK_STATUS, /**< Net library could read link status. */
PHY_EXTENSION_CONVERT_SIGNAL_INFO, /**< Convert signal info. */
PHY_EXTENSION_ACCEPT_ANY_BEACON, /**< Set boolean true or false for accept beacon from other Pan-ID than configured. Default value should be false */
} phy_extension_type_e;
/** Address types */
typedef enum {
PHY_MAC_48BIT, /**< IPv4/IPv6/BLE link layer address for Ethernet. This is optional. */
PHY_MAC_64BIT, /**< RF/PLC link layer address. */
PHY_MAC_16BIT, /**< RF interface short address. */
PHY_MAC_PANID, /**< RF interface 16-Bit PAN-ID. */
} phy_address_type_e;
/** PHY types */
typedef enum phy_link_type_e {
PHY_LINK_ETHERNET_TYPE, /**< Standard IEEE 802 Ethernet. */
PHY_LINK_15_4_2_4GHZ_TYPE, /**< Standard 802.15.4 2.4GHz radio. */
PHY_LINK_15_4_SUBGHZ_TYPE, /**< Standard 802.15.4 subGHz radio 868 /915MHz. */
PHY_LINK_TUN, /**< Tunnel interface for Linux TUN, RF network driver over serial bus or just basic application to application data flow. */
PHY_LINK_SLIP, /**< Generic SLIP driver which just forward SLIP payload */
} phy_link_type_e;
/** Data layers */
typedef enum data_protocol_e {
LOCAL_SOCKET_DATA = 0, /**< 6LoWPAN library local socket data. */
INTERFACE_DATA = 1, /**< 6LoWPAN library interface internal used protocol. */
PHY_LAYER_PAYLOAD = 2, /**< PHY layer data selection or handler. */
IPV6_DATAGRAM = 3, /**< IP layer data or TUN driver request data. */
UNKNOWN_PROTOCOL = 4 /**< Non-supported protocol ID. */
} data_protocol_e;
/** Requested data layer */
typedef enum driver_data_request_e {
PHY_LAYER_PAYLOAD_DATA_FLOW, /**< PHY layer data. */
IPV6_DATAGRAMS_DATA_FLOW, /**< IP layer data or TUN driver request data. */
} driver_data_request_e;
/** \brief Signal info types.
*
* Types of signal quality indication desired by various link protocols. Some are
* really statistical, but a driver should ideally be able to create an estimate
* based on its LQI/DBM numbers, for example to bootstrap a statistic calculation.
*/
typedef enum phy_signal_info_type_e {
PHY_SIGNAL_INFO_ETX, /**< Expected transmissions, unsigned 16-bit fixed-point ETX*128 [1..512], for example Zigbee IP + RFC 6719. */
PHY_SIGNAL_INFO_IDR, /**< Inverse Delivery Ratio, unsigned 16-bit fixed-point IDR*32*256 [1..8], for example MLE draft 06. */
PHY_SIGNAL_INFO_LINK_MARGIN, /**< Link margin, unsigned 16-bit fixed-point dB*256, [0..255], for example Thread routing draft. */
} phy_signal_info_type_e;
/** Signal level info */
typedef struct phy_signal_info_s {
phy_signal_info_type_e type; /**< Signal info type desired. */
uint8_t lqi; /**< Quality passed to arm_net_phy_rx. */
int8_t dbm; /**< Strength passed to arm_net_phy_rx. */
uint16_t result; /**< Resulting signal information. */
} phy_signal_info_s;
/** PHY modulation scheme */
typedef enum phy_modulation_e
{
M_OFDM, ///< QFDM
M_OQPSK, ///< OQPSK
M_BPSK, ///< BPSK
M_GFSK, ///< GFSK
M_UNDEFINED ///< UNDEFINED
} phy_modulation_e;
/** Channel page numbers */
typedef enum
{
CHANNEL_PAGE_0 = 0, ///< Page 0
CHANNEL_PAGE_1 = 1, ///< Page 1
CHANNEL_PAGE_2 = 2, ///< Page 2
CHANNEL_PAGE_3 = 3, ///< Page 3
CHANNEL_PAGE_4 = 4, ///< Page 4
CHANNEL_PAGE_5 = 5, ///< Page 5
CHANNEL_PAGE_6 = 6, ///< Page 6
CHANNEL_PAGE_9 = 9, ///< Page 9
CHANNEL_PAGE_10 = 10 ///< Page 10
} channel_page_e;
/** Channel configuration */
typedef struct phy_rf_channel_configuration_s
{
uint32_t channel_0_center_frequency; ///< Center frequency
uint32_t channel_spacing; ///< Channel spacing
uint32_t datarate; ///< Data rate
uint16_t number_of_channels; ///< Number of channels
phy_modulation_e modulation; ///< Modulation scheme
} phy_rf_channel_configuration_s;
/** Channel page configuration */
typedef struct phy_device_channel_page_s
{
channel_page_e channel_page; ///< Channel page
const phy_rf_channel_configuration_s *rf_channel_configuration; ///< Pointer to channel configuration
} phy_device_channel_page_s;
/** Virtual data request */
typedef struct virtual_data_req_s {
uint16_t parameter_length; /**< Length of user specified header. Can be zero. */
uint8_t *parameters; /**< Pointer to user specified header. Optional */
uint16_t msduLength; /**< MSDU Length */
const uint8_t *msdu; /**< MSDU */
} virtual_data_req_t;
/**
* @brief arm_net_phy_rx RX callback set by upper layer. Called when data is received
* @param data_ptr Data received
* @param data_len Length of the data received
* @param link_quality Link quality
* @param dbm Power ratio in decibels
* @param driver_id ID of driver which received data
* @return 0 if success, error otherwise
*/
typedef int8_t arm_net_phy_rx_fn(const uint8_t *data_ptr, uint16_t data_len, uint8_t link_quality, int8_t dbm, int8_t driver_id);
/**
* @brief arm_net_phy_tx_done TX done callback set by upper layer. Called when tx sent by upper layer has been handled
* @param driver_id Id of the driver which handled TX request
* @param tx_handle Handle of the TX
* @param status Status code of the TX handling result
* @param cca_retry Number of CCA retries done during handling
* @param tx_retry Number of TX retries done during handling
* @return 0 if success, error otherwise
*/
typedef int8_t arm_net_phy_tx_done_fn(int8_t driver_id, uint8_t tx_handle, phy_link_tx_status_e status, uint8_t cca_retry, uint8_t tx_retry);
/**
* @brief arm_net_virtual_rx RX callback set by user of serial MAC. Called when virtual RF has received data.
* @param data_ptr Data received
* @param data_len Length of the data received
* @param driver_id ID of driver which received data
* @return 0 if success, error otherwise
*/
typedef int8_t arm_net_virtual_rx_fn(const uint8_t *data_ptr, uint16_t data_len,int8_t driver_id);
/**
* @brief arm_net_virtual_tx TX callback set by serial MAC. Used to send data.
* @param data_req Data to be sent
* @param driver_id Id of the driver to be used.
* @return 0 if success, error otherwise
*/
typedef int8_t arm_net_virtual_tx_fn(const virtual_data_req_t *data_req,int8_t driver_id);
/**
* @brief arm_net_virtual_config Configuration receive callback set by upper layer. Used to receive internal configuration parameters.
* @param driver_id Id of the driver to be used.
* @param data Pointer to received configuration data.
* @param length Length of the configuration data.
* @return 0 if success, error otherwise
*/
typedef int8_t arm_net_virtual_config_rx_fn(int8_t driver_id, const uint8_t *data, uint16_t length);
/**
* @brief arm_net_virtual_config Configuration send callback set by upper layer. Used to send internal configuration parameters.
* @param driver_id Id of the driver to be used.
* @param data Pointer to sent configuration data.
* @param length Length of the configuration data.
* @return 0 if success, error otherwise
*/
typedef int8_t arm_net_virtual_config_tx_fn(int8_t driver_id, const uint8_t *data, uint16_t length);
/**
* @brief arm_net_virtual_confirmation Confirmation receive callback set by upper layer. Used to receive MLME confirmation data.
* @param driver_id Id of the driver to be used.
* @param data Pointer to received confirmation data.
* @param length Length of the confirmation data.
* @return 0 if success, error otherwise
*/
typedef int8_t arm_net_virtual_confirmation_rx_fn(int8_t driver_id, const uint8_t *data, uint16_t length);
/** Device driver structure */
typedef struct phy_device_driver_s
{
phy_link_type_e link_type; /**< Define driver types. */
driver_data_request_e data_request_layer; /**< Define interface data OUT protocol. */
uint8_t *PHY_MAC; /**< Pointer to 64-bit or 48-bit MAC address. */
uint16_t phy_MTU; /**< Define MAX PHY layer MTU size. */
char *driver_description; /**< Short driver platform description. Needs to end with zero. */
uint8_t phy_tail_length; /**< Define PHY driver needed TAIL Length. */
uint8_t phy_header_length; /**< Define PHY driver needed header length before PDU. */
int8_t (*state_control)(phy_interface_state_e, uint8_t); /**< Function pointer for control PHY driver state. */
int8_t (*tx)(uint8_t *, uint16_t, uint8_t, data_protocol_e); /**< Function pointer for PHY driver write operation. */
int8_t (*address_write)(phy_address_type_e , uint8_t *); /**< Function pointer for PHY driver address write. */
int8_t (*extension)(phy_extension_type_e, uint8_t *); /**< Function pointer for PHY driver extension control. */
const phy_device_channel_page_s *phy_channel_pages; /**< Pointer to channel page list */
//Upper layer callbacks, set with arm_net_phy_register();
arm_net_phy_rx_fn *phy_rx_cb; /**< PHY RX callback. Initialized by \ref arm_net_phy_register(). */
arm_net_phy_tx_done_fn *phy_tx_done_cb; /**< Transmission done callback. Initialized by \ref arm_net_phy_register(). */
//Virtual upper data rx
arm_net_virtual_rx_fn *arm_net_virtual_rx_cb; /**< Virtual RX callback. Initialized by \ref arm_net_phy_register(). */
arm_net_virtual_tx_fn *arm_net_virtual_tx_cb; /**< Virtual TX callback. Initialized by \ref arm_net_phy_register(). */
arm_net_virtual_config_rx_fn *virtual_config_rx_cb; /**< Virtual config receive callback. Initialized by \ref arm_net_phy_register(). */
arm_net_virtual_config_tx_fn *virtual_config_tx_cb; /**< Virtual config send callback. Initialized by \ref arm_net_phy_register(). */
arm_net_virtual_confirmation_rx_fn *virtual_confirmation_rx_cb; /**< Virtual confirmation receive callback. Initialized by \ref arm_net_phy_register(). */
uint16_t tunnel_type; /**< Tun driver type. */
} phy_device_driver_s;
/**
* \brief This function registers the device driver to stack.
*
* \param phy_driver A pointer to device driver structure.
*
* \return >= 0 Device driver ID.
* \return < 0 Means register fail.
*
*/
extern int8_t arm_net_phy_register(phy_device_driver_s *phy_driver);
/**
* \brief Set driver mac64 address.
*
* \param MAC A pointer to new mac64 address which is copied to old one.
* \param id driver id
*
* \return >= 0 SET OK.
* \return < 0 Means register fail.
*
*/
extern int8_t arm_net_phy_mac64_set(uint8_t *MAC, int8_t id);
/**
* \brief Get driver mac64 address.
*
* \param id driver id
*
* \return > 0 Return pointer to MAC.
* \return NULL.
*
*/
extern uint8_t *arm_net_phy_mac64_get(int8_t id);
/**
* \brief Get driver link type.
*
* \param id driver id
*
* \return driver link type.
*
*/
extern int arm_net_phy_rf_type(int8_t id);
/**
* \brief Get driver link type MTU size.
*
* \param id driver id
*
* \return size of MTU.
*
*/
extern uint16_t arm_net_phy_mtu_size(int8_t id);
/**
* \brief Unregister the driver from storage.
*
* \param driver_id driver id
*
*/
extern void arm_net_phy_unregister(int8_t driver_id);
#ifdef __cplusplus
}
#endif
#endif /* ARM_HAL_PHY_H_ */

View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 2014-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OS_WHITEBOARD_H
#define OS_WHITEBOARD_H
#include "ns_types.h"
/**
* \file os_whiteboard.h
* \brief Platform API to modify the operating system routing table.
* API to modify the operating system routing table and neighbor cache.
* Required on Linux. Not needed on embedded systems.
*/
/** Mode selection */
enum add_or_remove {ADD = 1, REMOVE = 0};
#ifndef __linux__
/* Use DUMMY functions on non-Linux platforms. */
/** \cond DOXYGEN_IGNORE */
#define whiteboard_os_modify(x,y) ((void)(x),(void)(y))
/** \endcond */
#else /* LINUX */
/** Modify the operating system whiteboard.
* Add entries to or remove from the OS routing table.
* \param address IPv6 address.
* \param add_or_remove select whether to add or remove address.
*/
void whiteboard_os_modify(const uint8_t address[static 16], enum add_or_remove mode);
#endif
#endif /* OS_WHITEBOARD_H */

View File

@ -0,0 +1,67 @@
/*
* Copyright (c) 2014-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef TOPO_TRACE_H
#define TOPO_TRACE_H
#include "ns_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* \file topo_trace.h
* \brief test API to trace the network topology
*/
#ifndef HAVE_TOPO_TRACE
/* Use DUMMY functions if not required. */
/** \cond DOXYGEN_IGNORE */
#define topo_trace(type, address, update_type) ((void) 0)
/** \endcond */
#else /* HAVE_TOPO_TRACE */
enum topo_type {
TOPOLOGY_RPL,
TOPOLOGY_MLE,
TOPOLOGY_THREAD,
};
enum topo_update {
TOPO_CLEAR = 2, // Clear all links of specified type to any address.
TOPO_ADD = 1, // Add a link of specified type to specified address.
TOPO_REMOVE = 0 // Remove a link of specified type to specified address.
};
/** Modify topology tables.
*
* Add or remove entries to external topology tracer.
*
* \param topo_type Topology link type.
* \param address EUI-64 address.
* \param update_type Add or remove address.
*/
void topo_trace(enum topo_type type, const uint8_t address[static 8], enum topo_update update_type);
#endif
#ifdef __cplusplus
}
#endif
#endif /* TOPO_TRACE_H */

View File

@ -0,0 +1,90 @@
/*
* Copyright (c) 2016-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/** \file serial_mac_api.h
* \brief Serial MAC API.
*/
#ifndef SERIAL_MAC_API_H_
#define SERIAL_MAC_API_H_
#include <inttypes.h>
#ifdef __cplusplus
extern "C" {
#endif
struct virtual_data_req_s;
typedef struct serial_mac_api_s serial_mac_api_t;
/**
* Create serial MAC
* @param serial_driver_id PHY driver ID.
* @return Serial MAC callback structure on success.
* @return NULL on failure.
*/
extern serial_mac_api_t *serial_mac_create(int8_t serial_driver_id);
/**
* @brief data_request data request call
* @param api API to handle the request
* @param data Data to be sent
* @param data_length Length of the data
*/
typedef int8_t data_request(const serial_mac_api_t* api, const uint8_t *data_ptr, uint16_t data_length);
/**
* @brief data_indication Data indication is called when MAC layer has received data
* @param api The API which handled the response
* @param data Data to be sent
* @param data_length Length of the data
*/
typedef void data_indication(const serial_mac_api_t *api, const uint8_t *data_ptr, uint16_t data_length);
/**
* * @brief serial_mac_api_initialize Initialises Serial MAC layer into use
* @param api API to initialize
* @param ind_cb Callback to call when data is received.
* @return 0 if success, -1 if api is invalid
*/
typedef int8_t serial_mac_api_initialize(serial_mac_api_t *api, data_indication *ind_cb);
/**
* @brief serial_mac_virtual_initialize Initialises MAC to use virtual driver
* @param api API to start using virtual driver
* @param driver_id Virtual driver ID. Must be valid.
* @return 0 if success, -1 if api or driver is invalid
*/
typedef int8_t serial_mac_virtual_initialize(const serial_mac_api_t *api, int8_t driver_id);
/**
* Serial MAC callback structure.
*/
struct serial_mac_api_s {
serial_mac_api_initialize *mac_initialize; /**< Inititilize data callback */
serial_mac_virtual_initialize * virtual_initilize; /**< Enable bridge to virtual driver */
data_request *data_request_cb; /**< Data request callback */
data_indication *data_ind_cb; /**< Data indication callback */
};
#ifdef __cplusplus
}
#endif
#endif /* SERIAL_MAC_API_H_ */

104
nanostack/shalib.h Normal file
View File

@ -0,0 +1,104 @@
/*
* Copyright (c) 2014-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* \file shalib.h
* \brief SHA256 Library API.
*
* \section hmac256-inctuction HMAC256 process sequence:
* 1. SHALIB_init_HMAC(), Init HMAC IN process by given security signature material
* 2. SHALIB_push_data_HMAC(), Give data sectors(s) one by one
* 3. SHALIB_finish_HMAC(), Finish HMAC and save SHA256 hash to given buffer
*
* \section prf256-inctuction PRF256 process sequence:
* 1. shalib_prf_param_get(), Init PRF and get configure structure
* 2. Set the following parameters to configure structure:
* - HMAC security signature pointer and length
* - Label text
* - Seed data and length
* 3. shalib_prf_calc(), Calc PRF256 HASH
*
*/
#ifndef SHALIB_H_
#define SHALIB_H_
#include "ns_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/*!
* \struct prf_sec_param_t
* \brief PRF 256 stucture
* This structure is used to configure PRF calc operation: secret, label, seed and buffer before call shalib_prf_calc().
*/
typedef struct {
const uint8_t *secret; /**< HMAC security signature pointer. */
uint8_t sec_len; /**< HMAC security signature length. */
const char *label; /**< PRF label text. */
const uint8_t *seed; /**< PRF Seed data. */
uint8_t seedlen; /**< PRF Seed data length. */
} prf_sec_param_t;
// Use these for cumulative HMAC
/**
* \brief Init HMAC256 operation by given security material.
*
* \param secret A pointer to security material.
* \param sec_len Length of security material.
*/
void SHALIB_init_HMAC(const uint8_t *secret, uint8_t sec_len); // Call this first...
/**
* \brief Push data for HMAC
*
* \param data A pointer to data.
* \param len Length of data.
*/
void SHALIB_push_data_HMAC(const void *data, uint16_t len); // ... add data ...
/**
* \brief Finish HMAC256 operation and save result in given buffer.
*
* \param buffer A pointer to result buffer.
* \param nwords Length of 32-bit register to save to buffer (8= 256 bit and 4= 128-bit).
*/
void SHALIB_finish_HMAC(void *buffer, uint8_t nwords); // ... get the HMAC digest.
/** PRF API */
/**
* \brief Init PRF library and SHA registers.
* This function returns configure structure where the user needs to set the following items:
* -Security material and length
* -Label text and length
* -Seed data and length
*
* \return A pointer to PRF configure structure.
*/
prf_sec_param_t *shalib_prf_param_get(void); // GET PRF structure
/* SET secret, label, seed & buffer to 256 PRF */
/**
* \brief Finish PRF256 operation and save result in given buffer.
*/
void shalib_prf_calc(void *output, uint_fast16_t nwords);// GET 256 PRF
#ifdef __cplusplus
}
#endif
#endif /* SHALIB_H_ */

813
nanostack/socket_api.h Normal file
View File

@ -0,0 +1,813 @@
/*
* Copyright (c) 2010-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _NS_SOCKET_API_H
#define _NS_SOCKET_API_H
#ifdef __cplusplus
extern "C" {
#endif
/**
* \file socket_api.h
* \brief 6LoWPAN Library Socket API
*
* \section socket-com Common socket API
* - socket_open(), A function to open a socket.
* - socket_close(), A function to close a socket.
* - socket_connect(), A function to connect to a remote peer.
* - socket_bind(), A function to bind a local address or port or both.
* - socket_getpeername(), A function to get remote address and port of a connected socket.
* - socket_getsockname(), A function to get local address and port of a bound socket.
*
* \section socket-read Socket read API at callback
* - socket_read(), A function to read received data buffer from a socket.
* - socket_recvmsg(), A function to read received data buffer from a socket to Posix defined message structure
*
* \section socket-tx Socket TX API
* - socket_send(), A function to write data buffer to a socket.
* - socket_sendto(), A function to write data to a specific destination in the socket.
* - socket_sendmsg(), A function which support socket_send and socket_sendto functionality which supports ancillary data
*
* \section sock-connect TCP socket connection handle
* - socket_listen(), A function to set the socket to listening mode.
* - socket_accept(), A function to accept an incoming connection.
* - socket_shutdown(), A function to shut down a connection.
*
* Sockets are a common abstraction model for network communication and are used in most operating systems.
* 6LoWPAN Library API follows BSD socket API conventions closely with some extensions necessitated
* by the event-based scheduling model.
*
* Library supports the following socket types:
* | Socket name | Socket description |
* | :------------: | :----------------------------: |
* | SOCKET_UDP | UDP socket type |
* | SOCKET_TCP | TCP socket type |
* | SOCKET_ICMP | ICMP raw socket type |
*
* \section socket-raw ICMP RAW socket instruction
* An ICMP raw socket can be created with the function socket_open() and the
* identifier 0xffff. When using ICMP sockets, the minimum packet length is 4
* bytes which is the 4 bytes of ICMP header. The first byte is for type, second
* for code and last two are for the checksum that must always be set to zero.
* The stack will calculate the checksum automatically before transmitting the packet.
* THe header is followed by the payload if there is any.
* NOTE: While it is perfectly legal to send an ICMP packet without payload,
* some packet sniffing softwares might regard such packets as malformed.
* In such a case, a dummy payload can be attached by providing a socket_sendto()
* function with a pointer to your desired data buffer.
* Moreover, the current implementation of the stack allows only certain ICMP types, for example
* ICMP echo, reply, destination unreachable, router advertisement, router solicitation.
* It will drop any other unimplemented types. For example, Private experimentation type (200) will
* be dropped by default.
* | ICMP Type | ICMP Code | Checksum | Payload | Notes |
* | :-------: | :----------: | :-------: | :--------: | :--------------:|
* | 1 | 1 | 2 | n bytes | Length in bytes |
* | 0xXX | 0xXX | 0x00 0x00 | n bytes | Transmit |
* | 0xXX | 0xXX | 0xXX 0xXX | n bytes | Receive |
*
* ICMP echo request with 4 bytes of payload (ping6).
*
* | ICMP Type | ICMP Code | Checksum | Payload |
* | :-------: | :----------: | :-------: | :-----------------: |
* | 0x80 | 0x00 | 0x00 0x00 | 0x00 0x01 0x02 0x03 |
*
* ICMP echo response for the message above.
*
* | ICMP Type | ICMP Code | Checksum | Payload |
* | :-------: | :----------: | :-------: | :-----------------: |
* | 0x81 | 0x00 | 0xXX 0xXX | 0x00 0x01 0x02 0x03 |
*
* \section socket-receive Socket receiving
* When there is data to read from the socket, a receive callback function is called with the event type parameter set to SOCKET_DATA.
* The application must read the received data with socket_read() or socket_recvmsg() during the callback because the stack will release the data
* when returning from the receive callback.
*
* Socket event has event_type and socket_id fields. The receive callback function must be defined when socket is opened using socket_open() API.
*
* All supported socket event types are listed here:
*
* | Event Type | Value | Description |
* | :------------------------: | :---: | :-----------------------------------------------------------------: |
* | SOCKET_EVENT_MASK | 0xF0 | NC Socket event mask. |
* | SOCKET_DATA | 0x00 | Data received, read data length available in d_len field. |
* | SOCKET_CONNECT_DONE | 0x10 | TCP connection ready. |
* | SOCKET_CONNECT_FAIL | 0x20 | TCP connection failed. |
* | SOCKET_INCOMING_CONNECTION | 0x40 | TCP incoming connection on listening socket. |
* | SOCKET_TX_FAIL | 0x50 | Socket data send failed. |
* | SOCKET_CONNECT_CLOSED | 0x60 | TCP connection closed. |
* | SOCKET_CONNECTION_RESET | 0x70 | TCP connection reset. |
* | SOCKET_NO_ROUTE | 0x80 | No route available to destination. |
* | SOCKET_TX_DONE | 0x90 | UDP: link layer TX ready (d_len = length of datagram). |
* | | | TCP: some data acknowledged (d_len = data remaining in send queue) |
* | SOCKET_NO_RAM | 0xA0 | No RAM available. |
* | SOCKET_CONNECTION_PROBLEM | 0xB0 | TCP connection is retrying. |
*
*
* \section socket-tcp How to use TCP sockets:
*
* | API | Socket Type | Description |
* | :---------------------------: | :-----------: | :------------------------------------------------------------: |
* | socket_open() | Server/Client | Open socket to specific or dynamic port number. |
* | socket_shutdown() | Server/Client | Shut down opened TCP connection. |
* | socket_listen() | Server | Set server port to listen state. |
* | socket_accept() | Server | Accept a connection to a listening socket as a new socket. |
* | socket_connect() | Client | Connect client socket to specific destination. |
* | socket_close() | Server/Client | Closes the TCP Socket. |
* | socket_send() | Server/Client | Send data to peer. |
* | socket_recv() | Server/Client | Receive data from peer. |
*
* When the TCP socket is opened it is in closed state. It must be set either to listen or to connect state before it can be used to receive or transmit data.
*
* A socket can be set to listen mode with the socket_listen() function. After the call, the socket can accept an incoming connection from a remote host.
*
* A TCP socket can be connected to a remote host with socket_connect() with correct arguments. After the function call, a (non-blocking) application must wait for the socket event to confirm the successful state change of the socket.
* After the successful state change, data can be sent using socket_send().
* The connection can be shut down in either direction with socket_shutdown() function - shutting down write signals end-of-data to the peer.
*
* \section socket-udpicmp How to use UDP and RAW socket:
*
* A UDP socket is ready to receive and send data immediately after a successful call of socket_open() and a NET_READY event is received.
* Data can be transmitted with the socket_sendto() function. An ICMP socket works with same function call.
*/
#include "ns_address.h"
/** \name Protocol IDs used with sockets. */
///@{
/** UDP socket type. */
#define SOCKET_UDP 17
/** Normal TCP socket type. */
#define SOCKET_TCP 6
/** ICMPv6 raw socket type */
#define SOCKET_ICMP 32
/** Raw IPv6 socket type (socket_open identifier is IPv6 protocol number) */
#define SOCKET_RAW 2
/** REMOVED Feature in this release socket open return error Local Sockets for Tun interface functionality to APP-APP trough any BUS */
#define SOCKET_LOCAL 1
///@}
/** ICMP socket instruction
*
* ICMP header is comprised of 4 bytes. The first byte is for type, second for code and
* the last two are for checksum that must always be zero.
* The stack will calculate the checksum automatically when sending the packet.
* The payload comes after the header and it can be of any length. It can also be set to 0.
*
* This applies for reading and sending.
*
* ICMP TYPE ICMP Code ICMP Checksum (2 bytes) Payload n bytes
* -------- -------- -------- -------- -------- -------- ....... -------
* 0xXX 0xXX 0x00 0x00 0xXX 0xXX ...... 0xXX
*
* Example data flow for ping:
*
* ICMP echo request with 4-bytes payload (Ping6).
* 0x80, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03
*
* ICMP echo response for the message above.
* 0x81, 0x00, 0xXX, 0xXX, 0x00, 0x01, 0x02, 0x03
*/
/*!
* \struct socket_callback_t
* \brief Socket Callback function structure type.
*/
typedef struct socket_callback_t {
uint8_t event_type; /**< Socket Callback Event check list below */
int8_t socket_id; /**< Socket id queue which socket cause call back */
int8_t interface_id; /**< Network Interface ID where Packet came */
uint16_t d_len; /**< Data length if event type is SOCKET_DATA */
uint8_t LINK_LQI; /**< LINK LQI info if interface cuold give */
} socket_callback_t;
/*!
* \struct ns_msghdr_t
* \brief Normal IP socket message structure for socket_recvmsg() and socket_sendmsg().
*/
typedef struct ns_msghdr {
void *msg_name; /**< Optional address send use for destination and receive it will be source. MUST be ns_address_t */
uint_fast16_t msg_namelen; /**< Length of optional address use sizeof(ns_address_t) when msg_name is defined */
ns_iovec_t *msg_iov; /**< Message data vector list */
uint_fast16_t msg_iovlen; /**< Data vector count in msg_iov */
void *msg_control; /**< Ancillary data list of ns_cmsghdr_t pointer */
uint_fast16_t msg_controllen; /**< Ancillary data length */
int msg_flags; /**< Flags for received messages */
} ns_msghdr_t;
/*!
* \struct ns_cmsghdr_t
* \brief Control messages.
*/
typedef struct ns_cmsghdr {
uint16_t cmsg_len; /**< Ancillary data control messages length including cmsghdr */
uint8_t cmsg_level; /**< Originating protocol level should be SOCKET_IPPROTO_IPV6 */
uint8_t cmsg_type; /**< Protocol Specific types for example SOCKET_IPV6_PKTINFO, */
} ns_cmsghdr_t;
/** \name Error values
* \anchor ERROR_CODES
*/
///@{
/** No data currently available to read, or insufficient queue space for write */
#define NS_EWOULDBLOCK (-100)
///@}
/** \name socket_recvfrom() or socket_recvmsg() flags.
* \anchor MSG_HEADER_FLAGS
*/
///@{
/** In msg_flags, indicates that given data buffer was smaller than received datagram. Can also be passed as an flag parameter to recvmsg. */
#define NS_MSG_TRUNC 1
/** Indicates that given ancillary data buffer was smaller than enabled at socket msg->msg_controllen define proper writed data lengths. */
#define NS_MSG_CTRUNC 2
/** Can be passed as an input flag to socket_recvfrom() to not consume data */
#define NS_MSG_PEEK 4
/** \deprecated Can be passed as an input flag to get legacy returns of zero - used by socket_read() and socket_sendto() */
#define NS_MSG_LEGACY0 0x4000
///@}
/*!
* \struct ns_in6_pktinfo_t
* \brief IPv6 packet info which is used for socket_recvmsg() socket_sendmsg().
*/
typedef struct ns_in6_pktinfo {
uint8_t ipi6_addr[16]; /**< src/dst IPv6 address */
int8_t ipi6_ifindex; /**< send/recv interface index */
} ns_in6_pktinfo_t;
/** \name Alignment macros for control message headers
* \anchor CMSG_ALIGN_FLAGS
*/
///@{
/** Base header alignment size */
#define CMSG_HEADER_ALIGN sizeof(long)
/** Base data alignment size */
#define CMSG_DATA_ALIGN CMSG_HEADER_ALIGN
/** Returns control message alignment size for data or header based upon alignment base */
#ifndef NS_ALIGN_SIZE
#define NS_ALIGN_SIZE(length, aligment_base) \
((length + (aligment_base -1 )) & ~(aligment_base -1))
#endif
///@}
/**
* \brief Parse first control message header from message ancillary data.
*
* \param msgh Pointer for socket message.
*
* \return Pointer to first control message header , Could be NULL when control_message is undefined.
*/
#define NS_CMSG_FIRSTHDR(msgh) \
((msgh)->msg_controllen >= sizeof(struct ns_cmsghdr) ? \
(struct ns_cmsghdr *)(msgh)->msg_control : \
(struct ns_cmsghdr *)NULL )
/**
* \brief Parse next control message from message by current control message header.
*
* \param msgh Pointer for socket message.
* \param cmsg Pointer for last parsed control message
*
* \return Pointer to Next control message header , Could be NULL when no more control messages data.
*/
ns_cmsghdr_t *NS_CMSG_NXTHDR(const ns_msghdr_t *msgh, const ns_cmsghdr_t *cmsg);
/**
* \brief Get Data pointer from control message header.
*
* \param cmsg Pointer (ns_cmsghdr_t) for last parsed control message
*
* \return Data pointer.
*/
#define NS_CMSG_DATA(cmsg) \
((uint8_t *)(cmsg) + NS_ALIGN_SIZE(sizeof(ns_cmsghdr_t), CMSG_DATA_ALIGN))
/**
* \brief Returns the total space required for a cmsg header plus the specified data, allowing for all padding
*
* \param length size of the ancillary data
*
* For example, the space required for a SOCKET_IPV6_PKTINFO is NS_CMSG_SPACE(sizeof(ns_in6_pktinfo))
*
* \return Total size of CMSG header, data and trailing padding.
*/
#define NS_CMSG_SPACE(length) \
(NS_ALIGN_SIZE(sizeof(ns_cmsghdr_t), CMSG_DATA_ALIGN) + NS_ALIGN_SIZE(length, CMSG_HEADER_ALIGN))
/**
* \brief Calculate length to store in cmsg_len with taking into account any necessary alignment.
*
* \param length size of the ancillary data
*
* For example, cmsg_len for a SOCKET_IPV6_PKTINFO is NS_CMSG_LEN(sizeof(ns_in6_pktinfo))
*
* \return Size of CMSG header plus data, without trailing padding.
*/
#define NS_CMSG_LEN(length) \
(NS_ALIGN_SIZE(sizeof(ns_cmsghdr_t), CMSG_DATA_ALIGN) + length)
/** IPv6 wildcard address IN_ANY */
extern const uint8_t ns_in6addr_any[16];
/**
* \brief Create and initialize a socket for communication.
*
* \param protocol Defines the protocol to use.
* \param identifier The socket port. 0 indicates that port is not specified and it will be selected automatically when using the socket.
* \param passed_fptr A function pointer to a function that is called whenever a data frame is received to this socket.
*
* \return 0 or greater on success; Return value is the socket ID.
* \return -1 on failure.
* \return -2 on port reserved.
*/
int8_t socket_open(uint8_t protocol, uint16_t identifier, void (*passed_fptr)(void *));
/**
* \brief A function to close a socket.
*
* \param socket ID of the socket to be closed.
*
* \return 0 socket closed.
* \return -1 socket not closed.
*/
int8_t socket_close(int8_t socket);
/**
* \brief A function to set a socket to listening mode.
*
* \param socket The socket ID.
* \param backlog The pending connections queue size.
* \return 0 on success.
* \return -1 on failure.
*/
int8_t socket_listen(int8_t socket, uint8_t backlog);
/**
* \brief A function to accept a new connection on an socket.
*
* \param socket_id The socket ID of the listening socket.
* \param addr Either NULL pointer or pointer to structure where the remote address of the connecting host is copied.
* \param passed_fptr A function pointer to a function that is called whenever a data frame is received to the new socket.
* \return 0 or greater on success; return value is the new socket ID.
* \return -1 on failure.
* \return NS_EWOULDBLOCK if no pending connections.
*/
int8_t socket_accept(int8_t socket_id, ns_address_t *addr, void (*passed_fptr)(void *));
/**
* \brief A function to connect to remote peer (TCP).
*
* \param socket The socket ID.
* \param address The address of a remote peer.
* \deprecated \param randomly_take_src_number Ignored - random local port is always chosen if not yet bound
*
* \return 0 on success.
* \return -1 in case of an invalid socket ID or parameter.
* \return -2 if memory allocation fails.
* \return -3 if the socket is in listening state.
* \return -4 if the socket is already connected.
* \return -5 connect is not supported on this type of socket.
* \return -6 if the TCP session state is wrong.
* \return -7 if the source address selection fails.
*/
int8_t socket_connect(int8_t socket, ns_address_t *address, uint8_t randomly_take_src_number);
/**
* \brief Bind socket to address.
*
* Used by the application to bind a socket to a port and/or an address. Binding of each
* of address and port can only be done once.
*
* If address is ns_in6addr_any, the address binding is not changed. If port is 0,
* the port binding is not changed.
*
* \param socket Socket ID of the socket to bind.
* \param address Address structure containing the port and/or address to bind.
*
* \return 0 on success.
* \return -1 if the given address is NULL.
* \return -2 if the port is already bound to another socket.
* \return -3 if address is not us.
* \return -4 if the socket is already bound.
* \return -5 bind is not supported on this type of socket.
*
*/
int8_t socket_bind(int8_t socket, const ns_address_t *address);
/**
* \brief Bind a local address to a socket based on the destination address and
* the address selection preferences.
*
* Binding happens to the same address that socket_connect() would bind to.
* Reference: RFC5014 IPv6 Socket API for Source Address Selection.
*
* \param socket The socket ID.
* \param dst_address The destination address to which the socket wants to communicate.
*
* \return 0 on success.
* \return -1 if the given address is NULL or socket ID is invalid.
* \return -2 if the memory allocation failed.
* \return -3 if the socket is already bound to address.
* \return -4 if the interface cannot be found.
* \return -5 if the source address selection fails.
* \return -6 bind2addrsel is not supported on this type of socket.
*/
int8_t socket_bind2addrsel(int8_t socket, const ns_address_t *dst_address);
/**
* Options for the socket_shutdown() parameter 'how'.
*/
#define SOCKET_SHUT_RD 0 ///< Disables further receive operations.
#define SOCKET_SHUT_WR 1 ///< Disables further send operations.
#define SOCKET_SHUT_RDWR 2 ///< Disables further send and receive operations.
/**
* \brief A function to shut down a connection.
*
* \param socket The ID of the socket to be shut down.
* \param how How socket is to be shut down, one of SOCKET_SHUT_XX.
*
* \return 0 on success.
* \return -1 if the given socket ID is not found, if the socket type is wrong or TCP layer returns a failure.
* \return -2 if socket is not connected.
*/
int8_t socket_shutdown(int8_t socket, uint8_t how);
/**
* \brief Send data via a connected socket by client.
*
* Note: The socket connection must be ready before using this function.
* The stack uses automatically the address of the remote connected host as the destination address for the packet.
*
* This call is equivalent to socket_sendto() with address set to NULL - see
* that call for more details.
*
* \param socket The socket ID.
* \param buffer A pointer to data.
* \param length Data length.
*/
int16_t socket_send(int8_t socket, const void *buffer, uint16_t length);
/**
* \brief A function to read received data buffer from a socket.
* \deprecated
*
* Used by the application to get data from a socket. See socket_recvfrom()
* for more details.
*
* This is equivalent to socket_recvfrom, except that it passes the
* flag NS_MSG_LEGACY0, which modifies the return behaviour for zero data.
*
* \param socket The socket ID.
* \param src_addr A pointer to a structure where the sender's address is stored.
* May be NULL if not required.
* \param buffer A pointer to an array where the read data is written to.
* \param length The maximum length of the allocated buffer.
*
* \return >0 indicates the length of the data copied to buffer.
* \return 0 if no data was read (includes zero-length datagram,
* end of stream and no data currently available)
* \return -1 invalid input parameters.
*/
int16_t socket_read(int8_t socket, ns_address_t *src_addr, uint8_t *buffer, uint16_t length);
/**
* \brief A function to read received data buffer from a socket,
*
* Equivalent to socket_recvfrom with src_address set to NULL.
*
* \param socket The socket ID.
* \param buffer A pointer to an array where the read data is written to.
* \param length The maximum length of the allocated buffer.
* \param flags Flags for read call
*
* \return as for socket_recvfrom
*/
int16_t socket_recv(int8_t socket, void *buffer, uint16_t length, int flags);
/**
* \brief A function to read received data buffer from a socket
*
* Used by the application to get data from a socket.
*
* This has two modes of operation.
*
* 1) For non-stream sockets, if the receive queue is disabled (set to 0 via
* SOCKET_SO_RCVBUF), which is the non-stream default and original Nanostack
* behaviour, then applications receive exactly one SOCKET_DATA callback per
* datagram, indicating that datagram's length. They must make 1 read call
* in that callback, and they will be given the data. If not read, the
* datagram is discarded on return from the callback.
*
* 2) Otherwise - stream sockets or SOCKET_SO_RCVBUF non-zero - behaviour is
* akin to traditional BSD. SOCKET_DATA callbacks occur when new data arrives,
* and read calls can be made any time. Data will be queued to an extent
* determined by the receive buffer size. The length in the data callback
* is the total amount of data in the receive queue - possibly multiple
* datagrams.
*
* \param socket The socket ID.
* \param buffer A pointer to an array where the read data is written to.
* \param length The maximum length of the allocated buffer.
* \param flags Flags for read call
* \param src_addr A pointer to a structure where the sender's address is stored.
* May be NULL if not required.
*
* The returned length is normally the length of data actually written to the buffer; if
* NS_MSG_TRUNC is set in flags, then for non-stream sockets, the actual datagram length is
* returned instead, which may be larger than the buffer size.
*
* Return values assume flag NS_MSG_LEGACY0 is not set - if it is set, they are
* as per socket_read().
*
* \return >0 indicates the length of the data copied to buffer (or original datagram size)
* \return 0 if end of stream or zero-length datagram
* \return -1 invalid input parameters.
* \return NS_EWOULDBLOCK if no data is currently available
*/
int16_t socket_recvfrom(int8_t socket, void *buffer, uint16_t length, int flags, ns_address_t *src_addr);
/**
* \brief A function to read received message with ancillary data from a socket.
*
* Used by the application to get data from a socket. See socket_recvfrom for
* details of the two delivery mechanisms.
*
* Ancillary data must request by socket_setsockopt().
*
* msg->msg_controllen is updated to indicate actual length of ancillary data output
*
* \param socket The socket ID.
* \param msg A pointer to a structure where messages is stored with or without ancillary data
* \param flags A flags for message read.
*
* \return as for socket_recvfrom
*/
int16_t socket_recvmsg(int8_t socket, ns_msghdr_t *msg, int flags);
/**
* \brief A function to send UDP, TCP or raw ICMP data via the socket.
*
* Used by the application to send data.
*
* The return of 0 on success is unconventional, and obtained by passing
* NS_MSG_LEGACY0 to socket_sendmsg internally - to get conventional
* return values, you can use socket_sendmsg() instead.
*
* \param socket The socket ID.
* \param address A pointer to the destination address information.
* \param buffer A pointer to data to be sent.
* \param length Length of the data to be sent.
*
* \return 0 On success (whole packet queued)
* \return NS_EWOULDBLOCK if nothing written due to lack of queue space.
*
* Error returns:
*
* \return -1 Invalid socket ID.
* \return -2 Socket memory allocation fail.
* \return -3 TCP state not established or address scope not defined .
* \return -4 Unknown interface.
* \return -5 Socket not connected
* \return -6 Packet too short (ICMP raw socket error).
*/
int16_t socket_sendto(int8_t socket, const ns_address_t *address, const void *buffer, uint16_t length);
/**
* \brief A function to send UDP, TCP or raw ICMP data via the socket with or without ancillary data or destination address.
*
* Used by the application to send data message header support also vector list socket_send() and socket_sendto() use this functionality internally.
*
* \param socket The socket ID.
* \param msg A pointer to the Message header which include address, payload and ancillary data.
* \param flags A flags for message send (eg NS_MSG_LEGACY0)
*
* Messages destination address is defined by msg->msg_name which must be ns_address_t. If msg->msg_nme is NULL socket select connected address
*
* Messages payload and length is defined msg->msg_iov and msg->msg_iovlen. API support to send multiple data vector.
*
* Supported ancillary data for send defined by msg->msg_control and msg->msg_controllen.
*
* msg->msg_flags is unused, and need not be initialised.
*
* The following main return values assume flag NS_MSG_LEGACY0 is not set -
* if it is set, they are as per socket_sendto().
*
* \return length if entire amount written (which could be 0)
* \return value >0 and <length if partial amount written (stream only)
* \return NS_EWOULDBLOCK if nothing written due to lack of queue space.
* Error returns:
*
* \return -1 Invalid socket ID.
* \return -2 Socket memory allocation fail.
* \return -3 TCP state not established or address scope not defined .
* \return -4 Unknown interface.
* \return -5 Socket not connected
* \return -6 Packet too short (ICMP raw socket error).
*/
int16_t socket_sendmsg(int8_t socket, const ns_msghdr_t *msg, int flags);
/**
* \brief A function to read local address and port for a bound socket.
*
* This call writes ns_in6addr_any if address is not bound and 0 if the port is not bound.
*
* \param socket The socket ID.
* \param address A pointer to the address structure where the local address information is written to.
*
* \return 0 on success.
* \return -1 if no socket is found.
*/
int8_t socket_getsockname(int8_t socket, ns_address_t *address);
/**
* \brief A function to read remote address and port for a connected socket.
*
* \param socket The socket ID.
* \param address A pointer to the address structure where the remote address information is written to.
*
* \return 0 on success.
* \return -1 if no socket is found.
* \return -2 if no socket is not connected.
*/
int8_t socket_getpeername(int8_t socket, ns_address_t *address);
/* Backwards compatibility */
static inline int8_t socket_read_session_address(int8_t socket, ns_address_t *address)
{
return socket_getpeername(socket, address);
}
/** \name Flags for SOCKET_IPV6_ADDR_PREFERENCES - opposites 16 bits apart. */
///@{
#define SOCKET_IPV6_PREFER_SRC_TMP 0x00000001 /**< Prefer temporary address (RFC 4941); default. */
#define SOCKET_IPV6_PREFER_SRC_PUBLIC 0x00010000 /**< Prefer public address (RFC 4941). */
#define SOCKET_IPV6_PREFER_SRC_6LOWPAN_SHORT 0x00000100 /**< Prefer 6LoWPAN short address. */
#define SOCKET_IPV6_PREFER_SRC_6LOWPAN_LONG 0x01000000 /**< Prefer 6LoWPAN long address. */
///@}
/** \name Options for SOCKET_IPV6_ADDRESS_SELECT. */
///@{
#define SOCKET_SRC_ADDRESS_MODE_PRIMARY 0 /**< Default value always. */
#define SOCKET_SRC_ADDRESS_MODE_SECONDARY 1 /**< This mode typically selects the secondary address. */
///@}
/** \name Protocol levels used for socket_setsockopt. */
///@{
#define SOCKET_SOL_SOCKET 0 /**< Socket level */
#define SOCKET_IPPROTO_IPV6 41 /**< IPv6. */
///@}
/** \name Option names for protocol level SOCKET_SOL_SOCKET.
* \anchor OPTNAMES_SOCKET
*/
///@{
/** Specify receive buffer size in payload bytes, as int32_t. 0 means traditional Nanostack behaviour - unread data dropped unless read in data callback */
#define SOCKET_SO_RCVBUF 1
/** Specify send buffer size in payload bytes, as int32_t. Only currently used for stream sockets. */
#define SOCKET_SO_SNDBUF 2
/** Specify receive low water mark in payload bytes, as int32_t. Not yet implemented. */
#define SOCKET_SO_RCVLOWAT 3
/** Specify send low water mark in payload bytes, as int32_t. Queued sends will only be accepted if this many bytes of send queue space are available, else NS_EWOULDBLOCK is returned. */
#define SOCKET_SO_SNDLOWAT 4
///@}
/** \name IPv6 socket options
* \anchor OPTNAMES_IPV6
*
* IPv6 socket options summary
*
* | opt_name / cmsg_type | Data type | set/getsockopt | sendmsg | recvmsg |
* | :--------------------------: | :--------------: | :-------------: | :-----: | :-------------------------------: |
* | SOCKET_IPV6_TCLASS | int16_t | Yes | Yes | If enabled with RECVTCLASS |
* | SOCKET_IPV6_UNICAST_HOPS | int16_t | Yes | No | No |
* | SOCKET_IPV6_MULTICAST_HOPS | int16_t | Yes | No | No |
* | SOCKET_IPV6_ADDR_PREFERENCES | int | Yes | No | No |
* | SOCKET_IPV6_USE_MIN_MTU | int8_t | Yes | Yes | No |
* | SOCKET_IPV6_DONTFRAG | int8_t | Yes | Yes | No |
* | SOCKET_IPV6_FLOW_LABEL | int32_t | Yes | No | No |
* | SOCKET_IPV6_HOPLIMIT | int16_t | No | Yes | If enabled with RECVHOPLIMIT |
* | SOCKET_IPV6_PKTINFO | ns_in6_pktinfo_t | No | Yes | If enabled with RECVPKTINFO |
* | SOCKET_IPV6_RECVPKTINFO | bool | Yes | No | No |
* | SOCKET_IPV6_RECVHOPLIMIT | bool | Yes | No | No |
* | SOCKET_IPV6_RECVTCLASS | bool | Yes | No | No |
* | SOCKET_IPV6_MULTICAST_IF | int8_t | Yes | No | No |
* | SOCKET_IPV6_MULTICAST_LOOP | bool | Yes | Yes | No |
* | SOCKET_IPV6_JOIN_GROUP | ns_ipv6_mreq_t | Set only | No | No |
* | SOCKET_IPV6_LEAVE_GROUP | ns_ipv6_mreq_t | Set only | No | No |
* | SOCKET_BROADCAST_PAN | int8_t | Yes | No | No |
* | SOCKET_LINK_LAYER_SECURITY | int8_t | Yes | No | No |
* | SOCKET_INTERFACE_SELECT | int8_t | Yes | No | No |
*
*/
///@{
/** Specify traffic class for outgoing packets, as int16_t (RFC 3542 S6.5 says int); valid values 0-255, or -1 for system default. */
#define SOCKET_IPV6_TCLASS 1
/** Specify hop limit for outgoing unicast packets, as int16_t (RFC 3493 S5.1 says int); valid values 0-255, or -1 for system default. */
#define SOCKET_IPV6_UNICAST_HOPS 2
/** Specify hop limit for outgoing multicast packets, as int16_t (RFC 3493 S5.2 says int); valid values 0-255, or -1 for system default. */
#define SOCKET_IPV6_MULTICAST_HOPS 3
/** Specify source address preferences, as uint32_t - see RFC 5014; valid values combinations of SOCKET_IPV6_PREFER_xxx flags. */
#define SOCKET_IPV6_ADDR_PREFERENCES 4
/** Specify PMTU preference, as int8_t (RFC 3542 S11.1 says int); valid values -1 (PMTUD for unicast, default), 0 (PMTUD always), 1 (PMTUD off). */
#define SOCKET_IPV6_USE_MIN_MTU 5
/** Specify not to fragment datagrams, as int8_t (RFC 3542 S11.2 says int); valid values 0 (fragment to path MTU, default), 1 (no fragmentation, TX fails if bigger than outgoing interface MTU). */
#define SOCKET_IPV6_DONTFRAG 6
/** Specify flow label for outgoing packets, as int32_t; valid values 0-0xfffff, or -1 for system default, or -2 to always autogenerate */
#define SOCKET_IPV6_FLOW_LABEL 7
/** Hop limit control for socket_sendmsg() and indicate for hop limit socket_recmsg(), as int16_t; valid values 0-255, -1 for default for outgoing packet */
#define SOCKET_IPV6_HOPLIMIT 8
/** Specify control messages packet info for send and receive as ns_in6_pktinfo_t socket_sendmsg() it define source address and outgoing interface. socket_recvmsg() it define messages destination address and arrival interface. Reference at RFC3542*/
#define SOCKET_IPV6_PKTINFO 9
/** Specify socket_recvmsg() ancillary data request state for Packet info (destination address and interface id), as bool; valid values true write enabled, false write disabled */
#define SOCKET_IPV6_RECVPKTINFO 10
/** Specify socket_recvmsg() ancillary data request state for receive messages hop-limit, as bool; valid values true write enabled, false information write disabled */
#define SOCKET_IPV6_RECVHOPLIMIT 11
/** Specify socket_recvmsg() ancillary data request state for receive messages traffic class, as bool; valid values true write enabled, false information write disabled */
#define SOCKET_IPV6_RECVTCLASS 12
/** Set the interface to use for outgoing multicast packets, as int8_t (RFC3493 S5.2 says unsigned int); 0 means unspecified (use routing table) */
#define SOCKET_IPV6_MULTICAST_IF 13
/** Specify whether outgoing multicast packets are looped back, as bool (RFC3493 S5.2 says unsigned int) */
#define SOCKET_IPV6_MULTICAST_LOOP 14
/** Join a multicast group, using ns_ipv6_mreq_t */
#define SOCKET_IPV6_JOIN_GROUP 15
/** Leave a multicast group, using ns_ipv6_mreq_t */
#define SOCKET_IPV6_LEAVE_GROUP 16
#define SOCKET_BROADCAST_PAN 0xfc /**< Internal use - transmit with IEEE 802.15.4 broadcast PAN ID */
#define SOCKET_LINK_LAYER_SECURITY 0xfd /**< Not standard enable or disable socket security at link layer (For 802.15.4). */
#define SOCKET_INTERFACE_SELECT 0xfe /**< Not standard socket interface ID. */
#define SOCKET_IPV6_ADDRESS_SELECT 0xff /**< Deprecated - use SOCKET_IPV6_ADDR_PREFERENCES instead. */
/** Multicast group request used for setsockopt() */
typedef struct ns_ipv6_mreq {
uint8_t ipv6mr_multiaddr[16]; /**< IPv6 multicast address */
int8_t ipv6mr_interface; /**< interface id */
} ns_ipv6_mreq_t;
/**
* \brief Set an option for a socket
*
* Used to specify miscellaneous options for a socket. Supported levels and
* names defined above.
*
* \param socket The socket ID.
* \param level The protocol level.
* \param opt_name The option name (interpretation depends on level).
* See \ref OPTNAMES_SOCKET and \ref OPTNAMES_IPV6.
* \param opt_value A pointer to value for the specified option.
* \param opt_len Size of the data pointed to by the value.
*
* \return 0 on success.
* \return -1 invalid socket ID.
* \return -2 invalid/unsupported option.
* \return -3 invalid option value.
*/
int8_t socket_setsockopt(int8_t socket, uint8_t level, uint8_t opt_name, const void *opt_value, uint16_t opt_len);
///@}
/**
* \brief Get an option for a socket.
*
* Used to read miscellaneous options for a socket. Supported levels and
* names defined above. If the buffer is smaller than the option, the output
* is silently truncated; otherwise opt_len is modified to indicate the actual
* length.
*
* \param socket The socket ID.
* \param level The protocol level.
* \param opt_name The option name (interpretation depends on level). See \ref OPTNAMES_IPV6.
* \param opt_value A pointer to output buffer.
* \param opt_len A pointer to length of output buffer; updated on exit.
*
* \return 0 on success.
* \return -1 invalid socket ID.
* \return -2 invalid/unsupported option.
*/
int8_t socket_getsockopt(int8_t socket, uint8_t level, uint8_t opt_name, void *opt_value, uint16_t *opt_len);
#ifdef __cplusplus
}
#endif
#endif /*_NS_SOCKET_H*/

81
nanostack/sw_mac.h Normal file
View File

@ -0,0 +1,81 @@
/*
* Copyright (c) 2016-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/** \file sw_mac.h
* \brief Software MAC API.
*/
#ifndef NS_SW_MAC_H
#define NS_SW_MAC_H
#include "ns_types.h"
#ifdef __cplusplus
extern "C" {
#endif
struct protocol_interface_rf_mac_setup;
struct mac_api_s;
struct mac_description_storage_size_s;
struct fhss_api;
struct mac_statistics_s;
/**
* @brief Creates 802.15.4 MAC API instance which will use RF driver given
* @param rf_driver_id RF driver id. Must be valid
* @param storage_sizes dynamic mac storage sizes DO NOT set any values to zero !!
* @return New MAC instance if successful, NULL otherwise
*/
extern struct mac_api_s *ns_sw_mac_create(int8_t rf_driver_id, struct mac_description_storage_size_s *storage_sizes);
/**
* @brief ns_sw_mac_virtual_client_register registers virtual driver to be used with 802.15.4 MAC.
* This is always used with serial_mac_api
* @param api API to start using virtual driver
* @param virtual_driver_id
* @return 0 if success, -1 if api or driver is invalid
*/
extern int8_t ns_sw_mac_virtual_client_register(struct mac_api_s *api, int8_t virtual_driver_id);
/**
* @brief ns_sw_mac_virtual_client_unregister Unregisters virtual driver from 802.15.4 MAC
* @param api API from which to unregister virtual driver
* @return 0 if success, -1 if api is invalid
*/
extern int8_t ns_sw_mac_virtual_client_unregister(struct mac_api_s *api);
/**
* @brief Registers created FHSS API instance to given software MAC instance.
* @param mac_api MAC instance.
* @param fhss_api FHSS instance.
* @return 0 on success, -1 on fail.
*/
extern int ns_sw_mac_fhss_register(struct mac_api_s *mac_api, struct fhss_api *fhss_api);
/**
* @brief Start collecting statistics from software MAC.
* @param mac_api MAC instance.
* @param mac_statistics Statistics storage.
* @return 0 on success, -1 on fail.
*/
extern int ns_sw_mac_statistics_start(struct mac_api_s *mac_api, struct mac_statistics_s *mac_statistics);
#ifdef __cplusplus
}
#endif
#endif // NS_SW_MAC_H

104
nanostack/thread_bbr_api.h Normal file
View File

@ -0,0 +1,104 @@
/*
* Copyright (c) 2017, Arm Limited and affiliates.
* SPDX-License-Identifier: BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \file thread_bbr_api.h
* \brief Thread backbone border router (BBR) application interface.
*
* This is Thread backbone Border router service.
* When started the module takes care of starting the
* components that enables default border router functionality in Thread mesh network.
*
*/
#ifndef THREAD_BBR_API_H_
#define THREAD_BBR_API_H_
#include "ns_types.h"
/**
* Start backbone border router service.
*
* Enables the mDNS responder with default service name. \<rand\>-ARM-\<Network name\>
* if backbone interface is enabled and allows routing.
* Publishes Default route with DHCP addressing
* Enables ND proxy
*
* \param interface_id Thread network interface id.
* \param backbone_interface_id backbone interface id.
*
* \return 0 on success
* \return <0 in case of errors
*
*/
int thread_bbr_start(int8_t interface_id, int8_t backbone_interface_id);
/**
* Set the bbr timeout values. Default timeout values are used if not called.
*
* If this function is called it will trigger the modification to thread network causing'
* refreshing of registrations.
*
* \param interface_id interface ID of the Thread network.
* \param timeout_a timeout a set. 0 = do not change.
* \param timeout_b timeout_b set. 0 = do not change
* \param delay Jitter delay value. 0 do not change
*
* \return 0 on success
* \return <0 in case of errors
*
*/
int thread_bbr_timeout_set(int8_t interface_id, uint32_t timeout_a, uint32_t timeout_b, uint32_t delay);
/**
* Set the Thread validation interface destination address.
*
* \param interface_id interface ID of the Thread network.
* \param addr_ptr IPv6 address.
* \param port UDP port.
*
* \return 0 on success
* \return <0 in case of errors
*
*/
int thread_bbr_validation_interface_address_set(int8_t interface_id, const uint8_t *addr_ptr, uint16_t port);
/**
* Stop backbone Border router.
*
* \param interface_id interface ID of the Thread network
*
* \return 0 on success
* \return <0 in case of errors
*
*/
void thread_bbr_stop(int8_t interface_id);
#endif /* THREAD_BBR_API_H_ */

View File

@ -0,0 +1,322 @@
/*
* Copyright (c) 2014-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \file thread_border_router_api.h
* \brief Thread border router application interface.
*
* This file contains functions for managing Thread border router features.
* Border routers can set up services in the Thread network including routes,
* DHCPv6 servers, on-mesh prefixes and services.
*
*/
#ifndef THREAD_BORDER_ROUTER_API_H_
#define THREAD_BORDER_ROUTER_API_H_
#include "ns_types.h"
/**
* \brief Border router network data structure.
*/
typedef struct thread_border_router_info_t {
unsigned Prf: 2; /**< Prefix preference, 01 = High, 00 = Default, 11 = Low, 10 = Reserved. */
bool P_preferred: 1; /**< Address is considered preferred address. */
bool P_slaac: 1; /**< Allowed to configure a new address */
bool P_dhcp: 1; /**< DHCPv6 server is available in the network. */
bool P_configure: 1; /**< DHCPv6 agent provides other configuration. */
bool P_default_route: 1; /**< This device provides the default route. */
bool P_on_mesh: 1; /**< This prefix is considered to be on-mesh */
bool P_nd_dns: 1; /**< this border router is able to provide DNS information */
bool stableData: 1; /**< This data is stable and expected to be available at least 48h. */
} thread_border_router_info_t;
/**
* \brief Create local service that is provided to the Thread network.
* If a prefix exists it is updated. For example, when removing SLAAC (Stateless Address Autoconfiguration) you should modify the prefix
* first to remove the creation of new addresses and after a while, remove the prefix.
*
* When you have configured the services locally, you need to call
* thread_border_router_publish to make the services available in the network.
*
* \param interface_id Network interface ID.
* \param prefix_ptr Pointer prefix.
* \param prefix_len Length of prefix.
* \param prefix_info_ptr Prefix service structure configuring the published service.
*
* \return 0, Set OK.
* \return <0 Set not OK.
*/
int thread_border_router_prefix_add(int8_t interface_id, uint8_t *prefix_ptr, uint8_t prefix_len, thread_border_router_info_t *prefix_info_ptr);
/**
* \brief Delete local service.
*
* \param interface_id Network interface ID.
* \param prefix_ptr Pointer prefix.
* \param prefix_len Length of prefix.
*
* \return 0, Set OK.
* \return <0 Set not OK.
*/
int thread_border_router_prefix_delete(int8_t interface_id, uint8_t *prefix_ptr, uint8_t prefix_len);
/**
* \brief Add a new route to the Thread network. Other devices can use the route.
* For example, 0::0/0 means that this device provides the default route.
* For example, 2001::0/64 means that this device provides a more specific route.
*
* If a prefix exists it is updated.
*
* \param interface_id Network interface ID.
* \param prefix_ptr Pointer prefix. Can be NULL for the default route.
* \param prefix_len Length of prefix.
* \param stable This data is stable and expected to be available at least 48h.
* \param prf Route preference, 01 = High, 00 = Default, 11 = Low, 10 = Reserved.
*
* \return 0, Set OK.
* \return <0 Set not OK.
*/
int thread_border_router_route_add(int8_t interface_id, uint8_t *prefix_ptr, uint8_t prefix_len, bool stable, int8_t prf);
/**
* \brief Delete locally served route.
*
* \param interface_id Network interface ID.
* \param prefix_ptr Pointer prefix.
* \param prefix_len Length of prefix.
*
* \return 0, Set OK.
* \return <0 Set not OK.
*/
int thread_border_router_route_delete(int8_t interface_id, uint8_t *prefix_ptr, uint8_t prefix_len);
/**
* \brief Add or modify a local service.
*
* \param interface_id Network interface ID.
* \param service_data Pointer to a byte string specifying the type of service.
* \param service_len Length of service data.
* \param sid Service Type ID, a value between 0 and 15, inclusive, assigned to this service data.
* \param enterprise_number Enterprise number of the vendor that defined the type of the server.
* \param server_data Pointer to a byte string containing server-specific information.
* \param server_data_len Length of server data.
* \param stable This data is stable and expected to be available at least 48h.
*
* \return 0, Addition OK.
* \return <0 Addition not OK.
*/
int thread_border_router_service_add(int8_t interface_id, uint8_t *service_data, uint8_t service_len, uint8_t sid, uint32_t enterprise_number, uint8_t *server_data, uint8_t server_data_len, bool stable);
/**
* \brief Delete local service by service data and enterprise number.
*
* \param interface_id Network interface ID.
* \param service_data Pointer to a byte string specifying the type of service.
* \param service_len Length of service.
* \param enterprise_number Enterprise number of the vendor that defined the type of the server.
*
* \return 0, Delete OK.
* \return <0 Delete not OK.
*/
int thread_border_router_service_delete(int8_t interface_id, uint8_t *service_data, uint8_t service_len, uint32_t enterprise_number);
/**
* \brief Publish local services to Thread network.
*
* If local services are deleted before calling this, all services are deregistered from the network.
*
* \param interface_id Network interface ID.
*
* \return 0, Push OK.
* \return <0 Push not OK.
*/
int thread_border_router_publish(int8_t interface_id);
/**
* \brief Clear the local service list.
*
* \param interface_id Network interface ID.
*
* \return 0, Push OK.
* \return <0 Push not OK.
*/
int thread_border_router_delete_all(int8_t interface_id);
/**
* \brief Set Recursive DNS server (RDNSS) option that is encoded according to RFC6106.
* Setting a new RDNSS will overwrite previous RDNSS option. Set RNDDS will be used
* until it is cleared.
*
* \param interface_id Network interface ID.
* \param recursive_dns_server_option Recursive DNS server option encoded according to rfc6106, can be NULL to clear existing RDNSS.
* \param recursive_dns_server_option_len Length of the recursive_dns_server_option in bytes.
*
* \return 0, Option saved OK.
* \return <0 when error occurs during option processing.
*/
int thread_border_router_recursive_dns_server_option_set(int8_t interface_id, uint8_t *recursive_dns_server_option, uint16_t recursive_dns_server_option_len);
/**
* \brief Set DNS server search list (DNSSL) option that is encoded according to RFC6106.
* Setting a new DNSSL will overwrite previous DNSSL option. Set DNSSL will be used
* until it is cleared.
*
* \param interface_id Network interface ID.
* \param dns_search_list_option DNS search list option encoded according to rfc6106, can be NULL to clear existing DNSSL.
* \param search_list_option_len Length of the dns_search_list_option in bytes.
*
* \return 0, Option saved OK.
* \return <0 when error occurs during option processing.
*/
int thread_border_router_dns_search_list_option_set(int8_t interface_id, uint8_t *dns_search_list_option, uint16_t search_list_option_len);
/**
* \brief Callback type for Thread network data TLV registration
*
* \param interface_id Network interface ID.
* \param network_data_tlv Thread Network data TLV as specified in Thread specification.
* \param network_data_tlv_length length of the network data TLV.
*/
typedef void (thread_network_data_tlv_cb)(int8_t interface_id, uint8_t *network_data_tlv, uint16_t network_data_tlv_length);
/**
* \brief Register callback function to receive thread network data TLV in byte array. For the first time the callback
* will be called before returning from the function. Afterwards the callback will be called when there is a change
* to the network data or when the network data is advertised. Application is not allowed to block the callback execution
* and must make a copy of the network data if it is needed afterwards.
*
* Setting nwk_data_cb to NULL will prevent further calls to the callback function.
*
* \param interface_id Network interface ID.
* \param nwk_data_cb callback function to receive network data TLV in byte array as specified in the Thread specification.
*
* \return 0, Callback function registered successfully.
* \return <0 when error occurs during registering the callback function.
*/
int thread_border_router_network_data_callback_register(int8_t interface_id, thread_network_data_tlv_cb* nwk_data_cb);
/**
* Find Prefix TLV from the Network Data TLV byte array.
*
* \param network_data_tlv [IN] Network data TLV in byte array.
* \param network_data_tlv_length [IN] Length of the network data TLV byte array in bytes.
* \param prefix_tlv [IN] pointer to the previous prefix_tlv, NULL if previous TLV not known.
* [OUT] Pointer to the prefix TLV found.
* \param stable [OUT] value set to true if found TLV is stable, false otherwise.
*
* \return Length of the found Prefix TLV
* \return 0 if TLV is empty or no Prefix TLV found.
* \return negative value indicates error in input parameters.
*/
int thread_border_router_prefix_tlv_find(uint8_t* network_data_tlv, uint16_t network_data_tlv_length, uint8_t** prefix_tlv, bool* stable);
/**
* Find Border router TLV from the Network Data TLV (under Prefix TLV) byte array.
*
* \param prefix_tlv [IN] Network data TLV in byte array.
* \param prefix_tlv_length [IN] Length of the Network data TLV byte array in bytes.
* \param border_router_tlv [IN] pointer to the previous Border Router TLV, NULL if not known.
* [OUT] Pointer to the Border Router TLV found.
* \param stable [OUT] value set to true if found TLV is stable, false otherwise
*
* \return Length of the Prefix found
* \return 0 if TLV is empty or no TLV found.
* \return negative value indicates error in input parameters.
*/
int thread_border_router_tlv_find(uint8_t* prefix_tlv, uint16_t prefix_tlv_length, uint8_t** border_router_tlv, bool* stable);
/**
* Find Service TLV from the Network Data TLV byte array.
*
* \param network_data_tlv [IN] Network data TLV in byte array.
* \param network_data_tlv_length [IN] Length of the network data TLV byte array in bytes.
* \param service_tlv [IN] pointer to the previous Service TLV, NULL if previous TLV not known.
* [OUT] Pointer to the Service TLV found.
* \param stable [OUT] value set to true if found TLV is stable, false otherwise.
*
* \return Length of the found Service TLV
* \return 0 if TLV is empty or no Service TLV found.
* \return negative value indicates error in input parameters.
*/
int thread_border_router_service_tlv_find(uint8_t* network_data_tlv, uint16_t network_data_tlv_length, uint8_t** service_tlv, bool* stable);
/**
* Find Server TLV from the Network Data TLV (under Service TLV) byte array.
*
* \param service_tlv [IN] Network data TLV in byte array.
* \param service_tlv_length [IN] Length of the Network data TLV byte array in bytes.
* \param server_tlv [IN] pointer to the previous Server TLV, NULL if not known.
* [OUT] Pointer to the Server TLV found.
* \param stable [OUT] value set to true if found TLV is stable, false otherwise
*
* \return Length of the Prefix found
* \return 0 if TLV is empty or no TLV found.
* \return negative value indicates error in input parameters.
*/
int thread_border_router_server_tlv_find(uint8_t* service_tlv, uint16_t service_tlv_length, uint8_t** server_tlv, bool* stable);
/**
* Determine context ID from the Network Data TLV (under Prefix TLV) byte array.
*
* \param prefix_tlv [IN] Prefix TLV in byte array.
* \param prefix_tlv_length [IN] Length of the Prefix TLV byte array in bytes.
*
* \return The context ID value found
* \return -1 if error in input parameters.
* \return -2 if no context ID value found.
*/
int thread_border_router_prefix_context_id(uint8_t *prefix_tlv, uint16_t prefix_tlv_length);
/**
* Start mDNS responder service. The responder will respond to DNS-SD queries and send announcement when
* Thread network data is updated.
*
* The mDNS responder can be closed by calling thread_border_router_mdns_responder_stop(). Closing the Thread
* network interface will stop the mDNS responder automatically.
*
* \param interface_id interface ID of the Thread network
* \param interface_id_mdns interface where mDNS messaging occurs
* \param service_name mDNS instance name
*
* \return 0 on success
* \return <0 in case of errors
*
*/
int thread_border_router_mdns_responder_start(int8_t interface_id, int8_t interface_id_mdns, const char *service_name);
/**
* Stop mDNS responder service
*
* \return 0 on success
* \return <0 in case of errors
*
*/
int thread_border_router_mdns_responder_stop(void);
#endif /* THREAD_BORDER_ROUTER_API_H_ */

View File

@ -0,0 +1,278 @@
/*
* Copyright (c) 2015-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \file thread_commissioning_api.h
* \brief Thread commissioning API.
*
* This is a public API used for creating a commissioning device. You can create an on-mesh commissioner
* and a native commissioner.
*/
#ifndef THREAD_COMMISSIONING_API_H_
#define THREAD_COMMISSIONING_API_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "ns_types.h"
#define TRACE_GROUP_THREAD_COMMISSIONING_API "TCoA" /**< trace group definition */
/**
* /enum commissioning_state_e
* /brief Commissioning states.
*/
typedef enum {
COMMISSIONING_STATE_ACCEPT,
COMMISSIONING_STATE_PENDING,
COMMISSIONING_STATE_REJECT,
COMMISSIONING_STATE_NO_NETWORK
} commissioning_state_e;
/** \brief Commissioning petition response callback.
*
* \param interface_id Network interface ID. The request comes from this ID.
* \param commissioner_session_id Commissioner session ID.
* \param state State of the commissioning.
*
* \return 0 success, other values failure.
*/
typedef int (thread_commissioning_status_cb)(int8_t interface_id, uint16_t commissioner_session_id, commissioning_state_e state);
/** \brief Register the commissioner interface.
*
* If the network interface is up, the commissioner functionality is started within the Thread network.
* If there is no interface, the network needs to be scanned first. When the network is found you can add an insecure commissioner,
* attach to it and start using a different communication method with the border router.
*
* \param interface_id Interface ID where the request was made.
* \param PSKc Pre-shared key between the commissioner and the Thread network.
*
* \return 0 success, other values failure.
*/
int thread_commissioning_register(int8_t interface_id, uint8_t PSKc[16]);
/** \brief Unregister the commissioner interface.
*
* This cleans up all the commissioner data from the device and disconnects it from the Thread network if an insecure commissioner was used.
*
* \param interface_id Network interface ID. The request comes from this ID.
*
* \return 0 success, other values failure.
*/
int thread_commissioning_unregister(int8_t interface_id);
/** \brief Start the commissioning petition.
*
* If the commissioner is insecure, you need to scan the networks and select the Thread network where you want to be a commissioner.
*
* \param interface_id Network interface ID. The request comes from this ID.
* \param commissioner_id_ptr NUL terminated commissioner ID string.
* \param status_cb_ptr A callback function indicating the result of the operation. Can be NULL if no result code needed.
* \return 0 Indicates success.
*
* \return -1 The client needs to scan the network to become an insecure commissioner.
* \return Any other value indicates other failures.
*/
int thread_commissioning_petition_start(int8_t interface_id, char *commissioner_id_ptr, thread_commissioning_status_cb *status_cb_ptr);
/** \brief Send petition keep alive.
*
* This function must be called in 40 second intervals. TODO rethink if this should be automatic.
*
* \param interface_id Network interface ID. The request comes from this ID.
* \param state Commissioning state.
*
* \return 0 success, other values failure.
*/
int thread_commissioning_petition_keep_alive(int8_t interface_id, commissioning_state_e state);
/** \brief Callback received when a new device is completing the joining process.
*
* The message may include the following meshcop TLV fields:
* * State TLV
* * Vendor Name TLV
* * Vendor Model TLV
* * Vendor SW Version TLV
* * Vendor Data TLV
* * Vendor Stack
* * Version TLV
* * Provisioning URL TLV
*
* \param interface_id Network interface ID. The request comes from this ID.
* \param EUI64 The client identifier.
* \param message_ptr A message including the meshcop TLV set. This message can be parsed using thread_meshcop_lib.h.
* \param message_len The length of the message.
*
* \return 0 Device accepted.
* \return Any other value, device rejected.
*/
typedef int (thread_commissioning_joiner_finalisation_cb)(int8_t interface_id, uint8_t EUI64[8], uint8_t *message_ptr, uint16_t message_len);
/** \brief Add a device to commission to the Thread network.
*
* \param interface_id Network interface ID. The request comes from this ID.
* \param short_eui64 A boolean value indicating that short EUI version is used for bloom filter generation.
* \param EUI64 A pointer to EUI64 buffer.
* \param PSKd_ptr A pointer to PSKd buffer.
* \param PSKd_len PSKd string length, current validity check is 1-32 bytes.
* \param joining_device_cb_ptr A callback function indicating the result of the operation. Can be NULL if no result code needed.
*
* \return 0 success, other values failure
*/
int thread_commissioning_device_add(int8_t interface_id, bool short_eui64, uint8_t EUI64[8], uint8_t *PSKd_ptr, uint8_t PSKd_len, thread_commissioning_joiner_finalisation_cb *joining_device_cb_ptr);
/** \brief Delete a device to commission to the Thread network.
*
* \param interface_id Network interface ID. The request comes from this ID.
* \param EUI64 A pointer to EUI64 buffer.
*
* \return 0 success, other values failure.
*/
int thread_commissioning_device_delete(int8_t interface_id, uint8_t EUI64[8]);
/** \brief Get next added device details.
*
* \param ptr A pointer for internal looping. First, use NULL pointer, after that use return pointer.
* \param interface_id Network interface ID. The request comes from this ID.
* \param short_eui64 A boolean value indicating that short EUI version is used for bloom filter generation. Can be NULL when no result wanted.
* \param EUI64 A pointer to EUI64 buffer. Can be NULL when no result wanted.
* \param PSKd A pointer to PSKd buffer. Can be NULL when no result wanted.
* \param PSKd_len Length of data in PSKd.
*
* \return >NULL for next iteration.
* \return NULL when end of list.
*/
void *thread_commission_device_get_next(void *ptr, int8_t interface_id, bool *short_eui64, uint8_t EUI64[8], uint8_t PSKd[32], uint8_t *PSKd_len);
/** Interfaces needed for native commissioner.
* current design:
* - The application configures the interface to scan available Thread networks to join
* - Time passes and the user wants to start scanning for native commissioner networks.
* - The application configures the interface to begin native commissioner interface scans.
* - The application selects a network to connect to.
* - The stack connects to that network -> interface UP event sent.
* - The application starts using Commissioning API to send COMM_PET.req message triggering a DTLS handshake.
* - Commission API queries the leader address and native info and uses the one that works.
*
*
*/
typedef struct thread_commissioning_link_configuration {
uint8_t name[16]; /**< Name of the Thread network. utf8 string nul terminated if shorter than 16. */
uint8_t extented_pan_id[8]; /**< Extended PAN ID. */
uint16_t panId; /**< Network ID. */
uint8_t Protocol_id; /**< Current protocol ID. */
uint8_t version; /**< Current protocol version. */
uint8_t rfChannel; /**< Current RF channel. */
} thread_commissioning_link_configuration_s;
/** \brief Native commissioner network scan result callback.
*
* This callback is called when networks that allow native commissioner to join are found.
* Pointers are valid during this call.
*
* \param interface_id Interface ID of this Thread instance.
* \param count Count of link configurations
* \param link_ptr Poiner to Commissioning link configuration
*
*/
typedef void thread_commissioning_native_select_cb(int8_t interface_id, uint8_t count, thread_commissioning_link_configuration_s *link_ptr );
/** \brief Native commissioner network scan start.
*
* Starts the network scan mode to find networks where the device can become a native commissioner.
* This stops the normal Thread joining process and informs the application of available networks.
*
* \param interface_id Interface ID of this Thread instance.
* \param cb_ptr Callback function
*
* \return 0 success, other values failure.
*/
int thread_commissioning_native_commissioner_start(int8_t interface_id, thread_commissioning_native_select_cb *cb_ptr);
/** \brief Native commissioner network scan stop.
*
* Stops the network scan mode and continues the normal joining process.
*
* \param interface_id Interface ID of this Thread instance.
*
* \return 0 success, other values failure.
*/
int thread_commissioning_native_commissioner_stop(int8_t interface_id);
/** \brief Native commissioner connect.
*
* Connects to a specific Thread network to become an active native commissioner.
*
* This function can be called in any time. When the network scan is completed, the available native commissioner networks are listed
* using the callback.
*
* If the connection fails, network scan keeps looking for a new network. After a successful connection, the interface up event is sent.
* TODO do we need backup timers or blacklist if PSKc fails. who is responsible for triggering new scans?
*
* Matching of thread network is made using Network name, Xpanid, panid, TODO channel?? or not? gives channel flexibility
*
* \param interface_id Interface ID of this Thread instance.
* \param link_ptr Pointer to Commissioning link configuration.
*
* \return 0 success, other values failure.
*/
int thread_commissioning_native_commissioner_connect(int8_t interface_id, thread_commissioning_link_configuration_s *link_ptr);
/**
*\brief Get the address of the native commissioner parent and the commissioning port for the connection.
*
* \param interface_id Network interface ID.
* \param address_ptr A pointer to address buffer (16 bytes) for the commission messages.
* \param port Return the port for the commissioner.
*
* \return 0, address OK.
* \return <0 fail.
*/
int thread_commissioning_native_commissioner_get_connection_info(int8_t interface_id, uint8_t *address_ptr, uint16_t *port);
/**
* \brief Get the management instance ID from the commissioner interface.
*
* \param interface_id Network interface ID.
*
* \return > 0 Instance ID.
* \return <= 0 fail.
*/
int8_t thread_commissioning_get_management_id(int8_t interface_id);
#ifdef __cplusplus
}
#endif
#endif /* THREAD_COMMISSIONING_API_H_ */

View File

@ -0,0 +1,102 @@
/*
* Copyright (c) 2014-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \file thread_dhcpv6_server.h
* \brief Thread specific DHCP server.
*
* \warning This api will be removed as there is no Thread specific modifications anymore.
*/
#ifndef THREAD_DHCPV6_SERVER_H_
#define THREAD_DHCPV6_SERVER_H_
#include "ns_types.h"
/**
* Set DHCPV6 server for Thread GP data purpose
*
* \param interface_id Network Interface
* \param prefix_ptr pointer DHCPv6 Server Given Prefix
* \param max_client_cnt Max number of clients
* \param stableData True if data is stable
*
* \return 0, Set OK
* \return <0 Set Not OK
*/
int thread_dhcpv6_server_add(int8_t interface_id, uint8_t *prefix_ptr, uint16_t max_client_cnt, bool stableData);
/**
* Modify dhcp address valid lifetime values default value is 1 day (86400)
*
* \param interface_id Network Interface
* \param prefix_ptr pointer DHCPv6 Server Given Prefix (size must be 16 bytes)
* \param valid_lifetime New valid life value given to new address valid values are (120 - 0xffffffff)
*
* \return 0, ADD OK
* \return <0 Add Not OK
*/
int thread_dhcpv6_server_set_lifetime(int8_t interface_id, uint8_t *prefix_ptr, uint32_t valid_lifetime);
/**
* Modify dhcp maximum client count.
*
* \param interface_id Network Interface
* \param prefix_ptr pointer DHCPv6 Server Given Prefix (size must be 16 bytes)
* \param max_client_count maximum amount of clients valid values (1 - 0xffffffff)
*
* \return 0, ADD OK
* \return <0 Add Not OK
*/
int thread_dhcpv6_server_set_max_client(int8_t interface_id, uint8_t *prefix_ptr, uint32_t max_client_count);
/**
* Modify dhcp anonymous mode.
*
* \param interface_id Network Interface
* \param prefix_ptr pointer DHCPv6 Server Given Prefix (size must be 16 bytes)
* \param anonymous true == addressing mode is anonymous, false == addressing mode uses mac address after prefix.
*
* \return 0, ADD OK
* \return <0 Add Not OK
*/
int thread_dhcpv6_server_set_anonymous_addressing(int8_t interface_id, uint8_t *prefix_ptr, bool anonymous);
/**
* Stop DHCPV6 server for Thread GP data purpose
*
* \param interface_id Network Interface
* \param prefix_ptr pointer DHCPv6 Server Given Prefix
*
* \return 0, Stop OK
* \return <0 Stop Not OK
*/
int thread_dhcpv6_server_delete(int8_t interface_id, uint8_t *prefix_ptr);
#endif /* THREAD_DHCPV6_SERVER_H_ */

View File

@ -0,0 +1,173 @@
/*
* Copyright (c) 2015-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef NANOSTACK_SOURCE_6LOWPAN_THREAD_THREAD_DIAGCOP_LIB_H_
#define NANOSTACK_SOURCE_6LOWPAN_THREAD_THREAD_DIAGCOP_LIB_H_
#include "ns_types.h"
#include "thread_meshcop_lib.h" // this uses the same parser functions than meshcop but different message types
/**
* \file thread_diagcop_lib.h
* \brief CoAP diagnostic TLV.
* Note that these TLV types overlap with meshcop
* and must not be used in same messages.
*/
#define DIAGCOP_TLV_EXTENDED_MAC_ADDRESS 0 /**< Can not reset*/
#define DIAGCOP_TLV_ADDRESS16 1 /**< Can not reset*/
#define DIAGCOP_TLV_MODE 2 /**< Can not reset*/
#define DIAGCOP_TLV_TIMEOUT 3 /**< Can not reset*/
#define DIAGCOP_TLV_CONNECTIVITY 4 /**< Can not reset*/
#define DIAGCOP_TLV_ROUTE64 5 /**< Can not reset*/
#define DIAGCOP_TLV_LEADER_DATA 6 /**< Can not reset*/
#define DIAGCOP_TLV_NETWORK_DATA 7 /**< Can not reset*/
#define DIAGCOP_TLV_IPV6_ADDRESS_LIST 8 /**< Can not reset*/
#define DIAGCOP_TLV_MAC_COUNTERS 9 /**< Can reset*/
#define DIAGCOP_TLV_BATTERY_LEVEL 14 /**< Can reset*/
#define DIAGCOP_TLV_SUPPLY_VOLTAGE 15 /**< Can not reset*/
#define DIAGCOP_TLV_CHILD_TABLE 16 /**< Can not reset*/
#define DIAGCOP_TLV_CHANNEL_PAGES 17 /**< Can not reset*/
#define DIAGCOP_TLV_TYPE_LIST 18 /**< List type*/
/**
* \brief Write array TLV.
*
* \param ptr A pointer to array in which to write the TLV.
* \param type The type of TLV.
* \param length The length of the data that is written in TLV.
* \param data The array for TLV value.
* \return pointer The value for writing the next TLV.
*/
#define thread_diagcop_tlv_data_write(ptr,type,length,data) thread_meshcop_tlv_data_write(ptr,type,length,data)
/**
* \brief Write 1 byte length TLV.
*
* \param ptr A pointer to array in which to write the TLV.
* \param type The type of TLV.
* \param data value.
* \return pointer value for writing the next TLV.
*/
#define thread_diagcop_tlv_data_write_uint8(ptr,type,data) thread_meshcop_tlv_data_write_uint8(ptr,type,data)
/**
* \brief Write 2 byte length TLV.
*
* \param ptr pointer for array where to write the TLV.
* \param type Type of TLV.
* \param data value.
* \return pointer value for writing the next TLV.
*/
#define thread_diagcop_tlv_data_write_uint16(ptr,type,data) thread_meshcop_tlv_data_write_uint16(ptr,type,data)
/**
* \brief Write 4 byte length TLV.
*
* \param ptr pointer for array where to write the TLV.
* \param type Type of TLV.
* \param data value.
* \return pointer value for writing the next TLV.
*/
#define thread_diagcop_tlv_data_write_uint32(ptr,type,data) thread_meshcop_tlv_data_write_uint32(ptr,type,data)
/**
* \brief Write 8 byte length TLV.
*
* \param ptr pointer for array where to write the TLV.
* \param type Type of TLV.
* \param data value.
* \return pointer value for writing the next TLV.
*/
#define thread_diagcop_tlv_data_write_uint64(ptr,type,data) thread_meshcop_tlv_data_write_uint64(ptr,type,data)
/**
* \brief Find TLV from message.
*
* \param ptr Message buffer.
* \param length Length of the message buffer to validate message.
* \param type Type of TLV searched.
* \param result Pointer value is given as result if length is positive. Can be NULL which only searches for the length.
* \return The length of the TLV data found
* \return 0 if TLV is empty or no TLV found.
* \return negative value indicates corrupted message.
*/
#define thread_diagcop_tlv_find(ptr,length,type,result) thread_meshcop_tlv_find(ptr,length,type,result)
/**
* \brief Read 1 byte length TLV.
*
* \param ptr pointer TLV message array.
* \param length length of TLV message array.
* \param type Type of TLV.
* \param data pointer to variable where the value is read.
* \return pointer length of TLV 1 if success. 0 means TLV not found or does not have any data.
* Any other value indicates that TLV is not as expected.
*/
#define thread_diagcop_tlv_data_get_uint8(ptr,length,type,data) thread_meshcop_tlv_data_get_uint8(ptr,length,type,data)
/**
* \brief Read 2 byte length TLV.
*
* \param ptr pointer TLV message array.
* \param length length of TLV message array.
* \param type Type of TLV.
* \param data pointer to variable where the value is read.
* \return pointer length of TLV 2 if success. 0 means TLV not found or does not have any data.
* Any other value indicates that TLV is not as expected.
*/
#define thread_diagcop_tlv_data_get_uint16(ptr,length,type,data) thread_meshcop_tlv_data_get_uint16(ptr,length,type,data)
/**
* \brief Read 4 byte length TLV.
*
* \param ptr pointer TLV message array.
* \param length length of TLV message array.
* \param type Type of TLV.
* \param data pointer to variable where the value is read.
* \return pointer length of TLV 4 if success. 0 means TLV not found or does not have any data.
* Any other value indicates that TLV is not as expected.
*/
#define thread_diagcop_tlv_data_get_uint32(ptr,length,type,data) thread_meshcop_tlv_data_get_uint32(ptr,length,type,data)
/**
* \brief Read 8 byte length TLV.
*
* \param ptr pointer TLV message array.
* \param length length of TLV message array.
* \param type Type of TLV.
* \param data pointer to variable where the value is read.
* \return pointer length of TLV 4 if success. 0 means TLV not found or does not have any data.
* Any other value indicates that TLV is not as expected.
*/
#define thread_diagcop_tlv_data_get_uint64(ptr,length,type,data) thread_meshcop_tlv_data_get_uint64(ptr,length,type,data)
#endif /* NANOSTACK_SOURCE_6LOWPAN_THREAD_THREAD_DIAGCOP_LIB_H_ */

View File

@ -0,0 +1,84 @@
/*
* Copyright (c) 2017, Arm Limited and affiliates.
* SPDX-License-Identifier: BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \file thread_lowpower_api.h
* \brief Nanostack Thread lowpower probe implementation. Responsible for tasks like
* request link metrics by sending data requests.
*/
#ifndef THREAD_LOWPOWER_API_H_
#define THREAD_LOWPOWER_API_H_
#include <ns_types.h>
/** \brief callback function that returns the received metrics
*
* \param destination_address address to which the lowpower query is sent
* \param interface_id interface_id of destination
* \param metrics_ptr Pointer to metrics
* \param metrics_len Length of metrics_ptr
*
* \return metrics_ptr if response received, NULL if no response is received
* \return metrics_len length of the response received, 0 if NULL response is received
*
*/
typedef int (thread_lowpower_resp_cb)(uint8_t *destination_address, int8_t interface_id, uint8_t *metrics_ptr, uint16_t metrics_len);
/** \brief Send lowpower data request for requesting low power metrics
*
* \param interface_id Interface ID of the Thread network.
* \param address destination ll64 address
* \param series_id id of the query or series id
* \param series_flags query type 0 for single probe
* \param timeout Timeout for the query 0 for single probe
* \param metrics_ptr array of metrics to be measured
* \param metrics_len length of the metrics array
* \param response_cb callback function called to return values after execution
*
* \return 0 if data request successfully initiated.
*
*/
int thread_lowpower_metrics_management_request_send(int8_t interface_id, uint8_t *address, uint8_t series_id, uint8_t series_flags, uint16_t timeout, uint8_t *metrics_ptr, uint8_t metrics_len, thread_lowpower_resp_cb response_cb);
/** \brief DEPRECATED Send lowpower data request for requesting low power metrics
*
* use thread_lowpower_metrics_management_request_send instead
* \param interface_id Interface ID of the Thread network.
* \param destination_address destination ll64 address
* \param metrics_ptr array of metrics to be measured
* \param metrics_len length of the metrics array
* \param response_cb callback function called to return values after execution
*
* \return 0 if data request successfully initiated.
*
*/
int thread_lowpower_test_probe_send(int8_t interface_id, uint8_t *destination_address, uint8_t *metrics_ptr, uint8_t metrics_len, thread_lowpower_resp_cb response_cb);
#endif /*THREAD_LOWPOWER_API_H_ */

View File

@ -0,0 +1,195 @@
/*
* Copyright (c) 2015-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \file thread_management_api.h
* \brief Public API for managing Thread network configuration.
*
* This interface enables modification and reading the Thread network parameters.
*
* Thread management can modify the following values in the Thread network:
* * [Network Name] (Read/write)
* * [Security Policy] (Read/write)
* * [Steering Data] (Read/write)
* * [Commissioning Data Timestamp] (Read/write)
* * [Commissioning Credential] PSKc (Write only)
* * [Network Master Key] (Read only when policy allows)
* * [Network Key Sequence] (Read only when policy allows)
* * [Network Mesh-Local ULA] (Read only)
* * [Border Router Locator] (Read only)
* * [Commissioner Session ID] (Read only)
* * [XPANID] (Read only)
* * [PANID] (Read only)
* * [Channel] (Read only)
*/
#ifndef THREAD_MANAGEMENT_API_H_
#define THREAD_MANAGEMENT_API_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "ns_types.h"
#define TRACE_GROUP_THREAD_MANAGEMENT_API "TMaA" /**< trace group definition */
/** Thread management state
*/
typedef enum {
MANAGEMENT_STATE_REJECT,
MANAGEMENT_STATE_PENDING,
MANAGEMENT_STATE_ACCEPT
} management_state_e;
/** \brief Register Thread management interface
*
* \param interface_id Interface ID of the Thread network.
*
* \return A handle for the management interface.
*
*/
int thread_management_register(int8_t interface_id);
/** \brief Unregister Thread management interface
*
* \param instance_id ID of the management session.
*
*/
int thread_management_unregister(int8_t instance_id);
/** \brief Callback to display the result of management set command.
*
* This callback is called when the server responds to the management set command.
* This can fail if the leader rejects the request or the request times out.
*
* \param interface_id The interface ID of the Thread network.
* \param status Result of the request.
*
*/
typedef int (management_set_response_cb)(int8_t interface_id, management_state_e status);
/** \brief Set the Thread security policy
*
* \param instance_id The ID of the management session.
* \param options Security policy options:
* bit 8 Out-of-band commissioning restricted.
* bit 7 Native commissioner restricted.
* \param rotation_time Thread key rotation time in hours.
* \param cb_ptr A callback function indicating the result of the operation. Can be NULL if no result code needed.
*
* \return 0 Success.
* \return <0 Fail.
*/
int thread_management_set_security_policy(int8_t instance_id, uint8_t options, uint16_t rotation_time, management_set_response_cb *cb_ptr);
/** \brief Set the steering data
*
* Steering data can be either:
* - Empty to decline joining.
* - Any length with all bits set to 0 to decline joining.
* - Any length with all bits 1 to allow anyone to join.
* - Bloom filter to guide which device can join.
*
* If a Bloom filter is present it can be any length between 1-16 bytes. The first bit of the Bloom
* filter indicates whether to use 0 == EUI-64 or 1 == bottom 24 bits of EUI-64.
*
* \param instance_id The ID of the management session.
* \param session_id The commissioning session ID that needs to be added.
* \param steering_data_ptr A pointer to new steering data.
* \param steering_data_len The length of the new steering data.
* \param cb_ptr A callback function indicating the result of the operation. Can be NULL if no result code needed.
*
* \return 0 Success.
* \return <0 Fail.
*/
int thread_management_set_steering_data(int8_t instance_id, uint16_t session_id, uint8_t *steering_data_ptr, uint8_t steering_data_len, management_set_response_cb *cb_ptr);
/** \brief Set the Thread commissioning data timestamp
*
* \param instance_id The ID of the management session.
* \param time Upper 48 bits is the timestamp in seconds since the start of unix time, lower 16 bits are fractional portion of time. If the last bit is set to 1, the commissioner has accurate time.
* \param cb_ptr A callback function indicating the result of the operation. Can be NULL if no result code needed.
*
* \return 0 Success.
* \return <0 Fail.
*/
int thread_management_set_commissioning_data_timestamp(int8_t instance_id, uint64_t time, management_set_response_cb *cb_ptr);
/** \brief Callback for reading Thread management information
*
* Result message containing the Thread management TLV message.
* This message can be parsed with thread_meshcop_lib.h.
*
* \param instance_id The ID of the management session.
* \param status Result of the request.
* \param response_message_ptr A meshcop TLV structure pointer containing the requested TLVs.
* \param response_message_len The length of the message.
*
* \return 0 Success.
* \return <0 Fail.
*/
typedef int (management_get_response_cb)(int8_t instance_id, management_state_e status, uint8_t *response_message_ptr, uint16_t response_message_len);
/** \brief Get Thread management fields.
* Fetching Thread management field values from any device in the Thread network.
*
* \param instance_id Instance ID of the management session.
* \param dst_addr Destination address; the address of a remote device from whome it is desirable to fetch management information. If however, the address is not provided, a request is sent to the leader of the network for this purpose. If a native commissioner is used, the request for management information is sent to the border router.
* \param uri_ptr The ASCII string for the URI. This string identifies the CoAP URI for the desired resource. For example, /c/mg identifies the management get information resource.
* \param fields_ptr A pointer that points to an array of desirable MESHCOP TLVs. A list of such TLVs can be found in thread_meshcop_lib.h
* \param fields_count Number of fields in the field pointer array (set of TLVs).
* \param cb_ptr A callback function carrying the result of the operation.
*
* \return 0, Success.
* \return <0 Fail.
*/
int thread_management_get(int8_t instance_id, uint8_t dst_addr[static 16], char *uri_ptr, uint8_t *fields_ptr, uint8_t fields_count, management_get_response_cb *cb_ptr);
/** \brief Set Thread management fields
*
* Set Thread management field values to a device in Thread network.
*
* \param instance_id Instance ID of the management session.
* \param dst_addr Destination address, the address of a remote device where it is desired to setup management information. If however, the address is not provided, a request is sent to leader of the network for this purpose. If a native commissioner is being used, the rquest for setting up management information is sent to the Border router.
* \param uri_ptr The ASCII string for the URI. This string identifies the CoAP URI for the desired resource, for example, /c/ms identifies the the management set information resource.
* \param data_ptr A pointer to the desired set of TLVs.
* \param data_len count of the members (no. of TLVs) in the TLV set.
* \param cb_ptr A callback function carrying the result of the operation.
*
* \return 0, Success
* \return <0 Fail.
*
*/
int thread_management_set(int8_t instance_id, uint8_t dst_addr[static 16], char *uri_ptr, uint8_t *data_ptr, uint8_t data_len, management_set_response_cb *cb_ptr);
#ifdef __cplusplus
}
#endif
#endif /* THREAD_MANAGEMENT_API_H_ */

View File

@ -0,0 +1,406 @@
/*
* Copyright (c) 2014-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \file thread_management_if.h
* \brief Thread management interface.
*
* This interface is used for configuring Thread devices.
* After creating the Thread interface, you can use this interface to configure the Thread device
* behaviour. When you are done with the configurations, you need to call interface up to enable a Thread node.
*
*/
#ifndef THREAD_MANAGEMENT_IF_H_
#define THREAD_MANAGEMENT_IF_H_
#include "ns_types.h"
#include "net_interface.h" /* Declaration for channel_list_s. */
#ifdef __cplusplus
extern "C" {
#endif
/*
* Current protocol version of the Thread implementation.
*/
#define THREAD_BEACON_PROTOCOL_ID 3 /**< Beacon Protocol ID */
#define THREAD_BEACON_PROTOCOL_VERSION 1 /**< Beacon Protocol version */
/**
* Thread network configuration.
*
* You can use this structure in start-up in case of a static configuration.
* This data can also be read after joining the Thread network.
* If this data is not provided to the stack, the device starts the commissioning process to join the Thread network.
*
* If the data is provided, all fields must be initialised to 0.
*
* If XPANID and MASTER KEY are provided, the device starts out-of-band commissioning. The values must be initialised to other than 0.
* If mesh_local_eid is initialised to 0 it is randomized at start-up.
* If extended_random_mac is initialised to 0 it is randomized at start-up.
*
* If timestamp values are set to 0 it triggers a network configuration update when joining the network.
*
* */
typedef struct link_configuration {
uint8_t name[16]; /**< Name of the Thread network*/
uint8_t master_key[16]; /**< Master key of the thread network*/
uint8_t PSKc[16]; /**< PSKc value that is calculated from commissioning credentials credentials,XPANID and network name*/
uint8_t mesh_local_ula_prefix[8]; /**< Mesh local ula prefix*/
uint8_t mesh_local_eid[8]; /**< Mesh local extented id*/
uint8_t extented_pan_id[8]; /**< Extended pan id*/
uint8_t extended_random_mac[8]; /**< Extended random mac which is generated during commissioning*/
uint8_t channel_mask[8]; /**< channel page and mask only supported is page 0*/
uint8_t channel_page;/**< channel page supported pages 0*/
char *PSKc_ptr; /**< Commissioning credentials. TODO! think if we need the actual credentials*/
uint8_t PSKc_len; /**< Length of PSKc */
uint16_t key_rotation; /**< Key rotation time in hours*/
uint32_t key_sequence; /**< Key sequence counter */
uint16_t panId; /**< network id*/
uint8_t Protocol_id; /**< current protocol id*/
uint8_t version; /**< current protocol version*/
uint16_t rfChannel; /**< current rf channel*/
uint8_t securityPolicy; /**< Commission Security Policy*/
uint64_t timestamp;/**< commissioning data set timestamp. [48 bit timestamp seconds]-[15 bit timestamp ticks]-[U bit] */
} link_configuration_s;
/**
* Security policy options. Default for all is '1';
*/
#define SECURITY_POLICY_ALL_SECURITY 0xff
#define SECURITY_POLICY_OUT_OF_BAND_COMMISSIONING_ALLOWED 0x80 /**< Obtaining the Master Key for out-of-band commissioning is enabled when this is set. */
#define SECURITY_POLICY_NATIVE_COMMISSIONING_ALLOWED 0x40 /**< Native Commissioning using PSKc is allowed when this is set. */
#define SECURITY_POLICY_ALL_ROUTERS_JOIN_ALLOWED 0x20 /**< Thread 1.x Routers are enabled when this is set. */
#define SECURITY_POLICY_EXTERNAL_COMMISSIONER_ALLOWED 0x10 /**< This indicates that external Commissioner authentication is allowed using PSKc. */
#define SECURITY_POLICY_BEACON_PAYLOAD_ENABLED 0x08 /**< Thread 1.x Beacons are enabled when this is set. */
/*
* Mandatory device information
*
* This information is required if commissioning is enabled for this device.
*/
typedef struct {
uint8_t eui64[8];/**< eui64 of the device. This field is used to identify device when joining to network Mandatory*/
uint8_t *PSKd_ptr;/**< Device credentials used to authenticate device to commissioner Mandatory length 6-32*/
uint8_t PSKd_len;/**< Length of PSKd_ptr*/
char *provisioning_uri_ptr;/**< Provisioning url max 64 bytes*/
char *vendor_name_ptr;/**< Vendor name optional max 32 bytes*/
char *vendor_model_ptr;/**< Vendor model optional max 32 bytes*/
char *vendor_sw_version_ptr;/**< Vendor SW version optional max 16 bytes*/
uint8_t vendor_stack_version[6];/**< Vendor stack version optional all 0 indicates not set*/
uint8_t *vendor_data_ptr;/**< optional Array max 64 bytes*/
uint8_t vendor_data_len;/**< optional Array length max 64 bytes*/
} device_configuration_s;
/**
* Initialize Thread stack to node mode.
*
* If static configuration is given and new one is updated by commissioner
* it will override current setup. it is safe to always give this as
* default configuration.
*
* \param interface_id Network interface ID.
* \param channel_list A pointer to channel list. Can be NULL if all channels accepted.
* \param device_configuration A pointer to device configuration.
* \param static_configuration A pointer to static configuration. Can be NULL.
*
* \return 0, Init OK.
* \return <0 Init fail.
*/
int thread_management_node_init(
int8_t interface_id,
channel_list_s *channel_list,
device_configuration_s *device_configuration,
link_configuration_s *static_configuration);
/**
* Thread device type.
*
* REED - Router enabled End device. Device can become router or end device depending on network conditions.
* FED - Full End Device. Device creates links and makes address queries but does not become router.
* MED - Minimal End Device. Device communicates through parent. With radio on
* SED - Sleepy End Device. Device communicates through parent. Uses data poll to sleep.
*/
typedef enum {
THREAD_DEVICE_REED = 1,
THREAD_DEVICE_FED,
THREAD_DEVICE_MED,
THREAD_DEVICE_SED,
} thread_device_type_e;
/**
* Change thread device type.
*
* This function modifies the thread device mode. Default values are given in
* function arm_nwk_interface_configure_6lowpan_bootstrap_set().
*
* If this function is called when interface is up re-attach is made.
*
* \param interface_id Network interface ID.
* \param device_type Device type of current bootstrap.
*
* \return 0, Set OK.
* \return <0 Set fail.
*/
int thread_management_device_type_set(int8_t interface_id, thread_device_type_e device_type);
/**
* Get Thread network settings.
*
* Configuration is a pointer to the static configuration and only valid in current context.
*
* \param interface_id Network interface ID.
*
* \return Pointer to link configuration.
* \return NULL Failure.
*/
link_configuration_s *thread_management_configuration_get(int8_t interface_id);
/** Store Thread network link configuration settings to NVM.
*
* Storing is asynchronous operation and this method makes a request to store link
* configuration settings. Operation will be completed in the background.
* Once settings has been stored the Thread network will be restarted with new
* configuration settings.
*
* /param interface Id of network interface. -1 if interface_id is not available.
* /param link_config Pointer to a structure containing link configuration parameters
*
* /return 0 if store request has been delivered successfully to lower layer.
* /return -1 if storing failed (request not delivered to lower layer)
* /return -2 if store request delivered to lower layer but given interface_id was not valid.
*/
int thread_management_link_configuration_store(int8_t interface_id, link_configuration_s *link_config);
/** Delete Thread network link configuration settings.
*
* Deletion is asynchronous operation and this method makes a request to delete link
* configuration settings. Operation will be completed in the background.
* Once settings has been deleted the Thread network will be restarted with default settings.
*
* /param interface Id of network interface. -1 can be used if interface_id is not available.
*
* /return 0 if delete request has been delivered successfully to lower layer.
* /return -1 if delete failed (request not delivered to lower layer)
* /return -2 if delete request delivered to lower layer but given interface_id was not valid.
*/
int thread_management_link_configuration_delete(int8_t interface_id);
/**
* Get Thread device settings.
*
* Configuration is a pointer to the static device configuration and only valid in current context.
*
* \param interface_id Network interface ID.
*
* \return Pointer to Device configuration.
* \return NULL Failure.
*/
device_configuration_s *thread_management_device_configuration_get(int8_t interface_id);
/**
* Thread router max child count set.
*
* This function is used to limit the number of children allowed for parent.
*
* \param interface_id Network interface ID.
* \param maxChildCount Min accepted value is 0 and max 32.
*
* \return 0, Set OK.
* \return <0 Set Fail.
*/
int thread_management_max_child_count(
int8_t interface_id,
uint8_t maxChildCount);
/**
* Set Thread device link timeout.
*
* \param interface_id Network interface ID.
* \param link_timeout New timeout value in seconds.
*
* \return 0, Set OK.
* \return <0 Set Fail.
*/
int8_t thread_management_set_link_timeout(int8_t interface_id, uint32_t link_timeout);
/**
* Get link timeout from Thread device.
*
* \param interface_id Network interface ID.
* \param link_timeout [out] A pointer to the location for writing the timeout.
*
* \return 0, Get OK
* \return <0 Get Fail
*/
int8_t thread_management_get_link_timeout(int8_t interface_id, uint32_t *link_timeout);
/**
* Set Thread request full network data.
*
* \param interface_id Network interface ID.
* \param full_nwk_data Whether or not to request full network data.
*
* \return 0, Set OK.
* \return <0 Set Fail.
*/
int8_t thread_management_set_request_full_nwk_data(int8_t interface_id, bool full_nwk_data);
/**
* Get Thread request full network data.
*
* \param interface_id Network interface ID.
* \param full_nwk_data [out] Request full network data
*
* \return 0, Get OK.
* \return <0 Get Fail.
*/
int8_t thread_management_get_request_full_nwk_data(int8_t interface_id, bool *full_nwk_data);
/**
* Additional Thread device settings. Changing these can cause non-compliance with Thread.
*
*/
/**
* Diagnostics functions.
*/
/**
* Get leader mesh local 16 address.
*
* \param interface_id Network interface ID.
* \param address_ptr A pointer to the location of address after copying.
*
* \return 0, Read OK.
* \return <0 Read fail.
*/
int thread_management_get_leader_address(int8_t interface_id, uint8_t *address_ptr);
/**
* Get leader anycast address.
*
* Address should be used when contacting Leader without need to know the actual routing details.
* This address will remain valid even after leader changes.
*
* \param interface_id Network interface ID.
* \param address_ptr A pointer to the location of address after copying.
*
* \return 0, Read OK.
* \return <0 Read fail. Not connected to Thread network.
*/
int thread_management_get_leader_aloc(int8_t interface_id, uint8_t *address_ptr);
/**
* Get parent link local 16 address.
*
* \param interface_id Network interface ID.
* \param address_ptr A pointer to the location of address after copying.
*
* \return 0, Read OK.
* \return <0 Read fail.
*/
int thread_management_get_parent_address(int8_t interface_id, uint8_t *address_ptr);
/**
* Get own mesh local 64 address.
*
* \param interface_id Network interface ID.
* \param address_ptr A pointer to the location of address after copying.
*
* \return 0, Read OK.
* \return <0 Read fail.
*/
int thread_management_get_ml64_address(int8_t interface_id, uint8_t *address_ptr);
/**
* Get own mesh local 16 address.
*
* \param interface_id Network interface ID.
* \param address_ptr A pointer to the location of address after copying.
*
* \return 0, Read OK.
* \return <0 Read fail.
*/
int thread_management_get_ml16_address(int8_t interface_id, uint8_t *address_ptr);
/**
* Get commissioner address.
*
* This function returns the commissioner address where you can continue provisioning traffic.
* If the commissioner is not present this function returns a failure.
*
* \param interface_id Network interface ID.
* \param address_ptr A pointer to the location of address after copying.
* \param port_ptr A pointer to the location of port after copying.
*
* \return 0, Read OK.
* \return <0 Read fail.
*/
int thread_management_get_commissioner_address(int8_t interface_id, uint8_t *address_ptr, uint16_t *port_ptr);
/**
* Set device certificate.
*
* This function sets device certificate
*
* \param interface_id Network interface ID.
* \param device_certificate_ptr A pointer to the device certificate.
* \param device_certificate_len Length of device certificate.
* \param priv_key_ptr A private key
* \param priv_key_len Length of a private key
*
* \return 0, OK.
* \return <0 fail.
*/
int thread_management_device_certificate_set(int8_t interface_id, const unsigned char *device_certificate_ptr, uint16_t device_certificate_len, const unsigned char *priv_key_ptr, uint16_t priv_key_len);
/**
* Set network certificate.
*
* This function sets network certificate
*
* \param interface_id Network interface ID.
* \param network_certificate_ptr A pointer array to the network certificate chain.
* \param network_certificate_len An array of lengths of network certificates in chain.
* \param priv_key_ptr A private key
* \param priv_key_len Length of a private key
*
* \return 0, OK.
* \return <0 fail.
*/
int thread_management_network_certificate_set(int8_t interface_id, const unsigned char *network_certificate_ptr, uint16_t network_certificate_len, const unsigned char *priv_key_ptr, uint16_t priv_key_len);
#ifdef __cplusplus
}
#endif
#endif /* THREAD_MANAGEMENT_IF_H_ */

View File

@ -0,0 +1,395 @@
/*
* Copyright (c) 2015-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \file thread_meshcop_lib.h
* \brief Public API to handle the Thread management framework message parsing and building.
*
*/
#ifndef THREAD_MESHCOP_LIB_H_
#define THREAD_MESHCOP_LIB_H_
#include "ns_types.h"
/**
* TLV Types used in thread network
*/
/**
* Network configuration TLV
*/
/** Channel TLV. */
#define MESHCOP_TLV_CHANNEL 0
/** PANID TLV. */
#define MESHCOP_TLV_PANID 1
/** Extended PANID TLV. */
#define MESHCOP_TLV_XPANID 2
/** Network Name TLV. */
#define MESHCOP_TLV_NETWORK_NAME 3
/** PSKc TLV. */
#define MESHCOP_TLV_PSKC 4
/** Network Master key TLV. */
#define MESHCOP_TLV_NETWORK_MASTER_KEY 5
/** Network Key Sequence TLV. */
#define MESHCOP_TLV_NETWORK_KEY_SEQUENCE 6
/** Mesh Local Ula prefix TLV. */
#define MESHCOP_TLV_NETWORK_MESH_LOCAL_ULA 7
/**
* Network management TLV
*/
/** Steering data TLV. */
#define MESHCOP_TLV_STEERING_DATA 8
/** Border router locator TLV. */
#define MESHCOP_TLV_BORDER_ROUTER_LOCATOR 9
/** Commissioner ID TLV. */
#define MESHCOP_TLV_COMMISSIONER_ID 10
/** Commissioner session ID TLV. */
#define MESHCOP_TLV_COMMISSIONER_SESSION_ID 11
/** Security Policy TLV. */
#define MESHCOP_TLV_SECURITY_POLICY 12
/** GET TLV. */
#define MESHCOP_TLV_GET 13
/** Active Timestamp TLV. */
#define MESHCOP_TLV_ACTIVE_TIME_STAMP 14
/** Commissioner UDP port TLV. */
#define MESHCOP_TLV_COMMISSIONER_UDP_PORT 15
/** state TLV. */
#define MESHCOP_TLV_STATE 16
/** Joiner UDP port TLV. */
#define MESHCOP_TLV_JOINER_UDP_PORT 18
/**
* Network management TLV specific bit defines
*/
#define MESHCOP_TLV_ACTIVE_TIME_STAMP_U_BIT 0x01
/**
* Relay message TLV
*/
/** Joiner Encapsulation TLV. */
#define MESHCOP_TLV_JOINER_ENCAPSULATION 17
/** Joiner UDP port TLV. */
#define MESHCOP_TLV_JOINER_UDP_PORT 18
/** Joiner IID TLV. */
#define MESHCOP_TLV_JOINER_IID 19
/** Joiner Router locator TLV. */
#define MESHCOP_TLV_JOINER_ROUTER_LOCATOR 20
/** Key Exchange Key TLV. */
#define MESHCOP_TLV_JOINER_ROUTER_KEK 21
/**
* Application provisioning TLVs
*/
/** Provisioning URL TLV. */
#define MESHCOP_TLV_PROVISIONING_URL 32
/** Vendr Name TLV. */
#define MESHCOP_TLV_VENDOR_NAME 33
/** Vendor Model TLV. */
#define MESHCOP_TLV_VENDOR_MODEL 34
/** Vendor SW version TLV. */
#define MESHCOP_TLV_VENDOR_SW_VERSION 35
/** Vendor Data TLV. */
#define MESHCOP_TLV_VENDOR_DATA 36
/** Vendor Stack Version TLV. */
#define MESHCOP_TLV_VENDOR_STACK_VERSION 37
/**
* Tunneling
*/
/** UDP encapsulation TLV. */
#define MESHCOP_TLV_UDP_ENCAPSULATION 48
/** IPv6 address TLV. */
#define MESHCOP_TLV_IPV6_ADDRESS 49
/** TMF Forwarding Port TLV. */
#define MESHCOP_TLV_TMF_FORWARDING_PORT 50
/**
* Thread management interface TLVs
*/
/** Pending Timestamp TLV. */
#define MESHCOP_TLV_PENDING_TIMESTAMP 51
/** Delay timer for pending configuration TLV. */
#define MESHCOP_TLV_DELAY_TIMER 52
/** Channel mask TLV. */
#define MESHCOP_TLV_CHANNEL_MASK 53
/** Count TLV. */
#define MESHCOP_TLV_COUNT 54
/** Period TLV. */
#define MESHCOP_TLV_PERIOD 55
/** Duration TLV. */
#define MESHCOP_TLV_DURATION 56
/** Energy List TLV. */
#define MESHCOP_TLV_ENERGY_LIST 57
/** Discovery Request TLV. */
#define MESHCOP_TLV_DISCOVERY_REQUEST 128
/** Discovery response TLV. */
#define MESHCOP_TLV_DISCOVERY_RESPONSE 129
/**
* Write array TLV.
*
* \param ptr pointer for array where to write the TLV.
* \param type Type of TLV.
* \param length length of the data that is written in TLV.
* \param data array for TLV value.
*
* \return pointer value for writing the next TLV.
*/
uint8_t *thread_meshcop_tlv_data_write(uint8_t *ptr, const uint8_t type, const uint16_t length, const uint8_t *data);
/**
* Write header.
*
* \param ptr pointer for array where to write the TLV.
* \param type Type of TLV.
* \param length length of the data that is written in TLV.
*
* \return pointer value for writing the remaining bytes of network data.
*/
uint8_t *thread_meshcop_tlv_data_write_header(uint8_t *ptr, uint8_t type, uint16_t length);
/**
* Write 1 byte length TLV.
*
* \param ptr pointer for array where to write the TLV.
* \param type Type of TLV.
* \param data value.
*
* \return pointer value for writing the next TLV.
*/
uint8_t *thread_meshcop_tlv_data_write_uint8(uint8_t *ptr, const uint8_t type, const uint8_t data);
/**
* Write 2 byte length TLV.
*
* \param ptr pointer for array where to write the TLV.
* \param type Type of TLV.
* \param data value.
*
* \return pointer value for writing the next TLV.
*/
uint8_t *thread_meshcop_tlv_data_write_uint16(uint8_t *ptr, const uint8_t type, const uint16_t data);
/**
* Write 4 byte length TLV.
*
* \param ptr pointer for array where to write the TLV.
* \param type Type of TLV.
* \param data value.
*
* \return pointer value for writing the next TLV.
*/
uint8_t *thread_meshcop_tlv_data_write_uint32(uint8_t *ptr, const uint8_t type, const uint32_t data);
/**
* Write 8 byte length TLV.
*
* \param ptr pointer for array where to write the TLV.
* \param type Type of TLV.
* \param data value.
*
* \return pointer value for writing the next TLV.
*/
uint8_t *thread_meshcop_tlv_data_write_uint64(uint8_t *ptr, const uint8_t type, const uint64_t data);
/**
* Check if TLV exists in the message.
*
* \param ptr Message buffer.
* \param length Length of the message buffer to validate message.
* \param type Type of TLV searched.
*
* \return true if TLV is found.
* \return false if TLV does not exist.
*/
bool thread_meshcop_tlv_exist(const uint8_t *ptr, const uint16_t length, const uint8_t type);
/**
* Find TLV from message.
*
* \param ptr Message buffer.
* \param length Length of the message buffer to validate message.
* \param type Type of TLV searched.
* \param result_ptr Pointer value is given as result if length is positive. Can be NULL which only searches for the length.
*
* \return The length of the TLV data found
* \return 0 if TLV is empty or no TLV found.
* \return negative value indicates corrupted message.
*/
uint16_t thread_meshcop_tlv_find(const uint8_t *ptr, const uint16_t length, const uint8_t type, uint8_t **result_ptr);
/**
* Get length of the TLV.
*
* \param ptr Message buffer.
* \param length Length of the message buffer to validate message.
*
* \return The length of the TLV data found
* \return 0 if TLV is empty.
* \return negative value indicates corrupted message or no TLV present.
*/
int16_t thread_meshcop_tlv_length(const uint8_t *ptr, uint16_t length);
/**
* Get length of the TLV including the type and length field.
*
* \param ptr Message buffer.
* \param length Length of the message buffer to validate message.
*
* \return The length of the TLV data found
* \return 0 if TLV is empty.
* \return negative value indicates corrupted message or no TLV present.
*/
int16_t thread_meshcop_tlv_length_required(const uint8_t *ptr, uint16_t length);
/**
* Go through TLV list in order.
*
* \param ptr Message buffer.
* \param length Length of the message buffer to validate message. Length value modified to remaining value or 0 when no more TLVs present
*
* \return ptr to the next TLV
* \return NULL if no TLV found.
*/
const uint8_t *thread_meshcop_tlv_get_next(const uint8_t *ptr, uint16_t *length);
/**
* Validate that required TLVs are present in the buffer.
*
* \param ptr TLV message buffer.
* \param length Length of the TLV message buffer.
* \param required_tlv_ptr buffer where the IDs of TLVs that are must be present
* \param required_tlv_len Amount of TLVs
*
* \return amount of TLVs present in the buffer.
*/
bool thread_meshcop_tlv_list_present(const uint8_t *ptr, uint16_t length, const uint8_t *required_tlv_ptr, uint8_t required_tlv_len);
/**
* Get list of TLVS included in the buffer.
*
* \param ptr TLV message buffer.
* \param length Length of the TLV message buffer.
* \param result_ptr [OUT] buffer where the IDs of TLVs are written. can be NULL when counting amount of TLVs
* \param result_len [OUT] Amount of TLVs written in buffer
*
* \return amount of TLVs present in the buffer.
*/
uint16_t thread_meshcop_tlv_list_generate(const uint8_t *ptr, uint16_t length,uint8_t *result_ptr, uint16_t *result_len);
/**
* Remove TLV from list of TLVs.
*
* \param tlv_ptr pointer to TLV List buffer.
* \param tlv_len Length of the TLV list buffer.
* \param tlv_type TLV that is removed from the List
*
* \return amount of TLVs present in the buffer.
*/
uint16_t thread_meshcop_tlv_list_remove(uint8_t *tlv_ptr, uint16_t tlv_len, uint8_t tlv_type);
/**
* Check if specific type is available in list of TLVs.
*
* \param list_ptr Pointer to TLV list buffer.
* \param list_len Length of the TLV list buffer.
* \param tlv_type TLV type to be find from the list
*
* \return true if type exists, false if type does not exist.
*/
bool thread_meshcop_tlv_list_type_available(const uint8_t *list_ptr, uint16_t list_len, uint8_t tlv_type);
/**
* Find next TLV from message.
*
* \param tlv_ba TLV message buffer.
* \param tlv_ba_length Length of the TLV message buffer.
* \param tlv_id ID of the TLV to be searched.
* \param found_tlv [IN] Pointer value is given as result if length is > 0. Can be NULL which only searches for the length.
* \ [OUT] Pointer to previous TLV found
*
* \return The length of the TLV data found and found_tlv updated to point beginning of value field. 0 if TLV is not found.
*/
uint16_t thread_meshcop_tlv_find_next(uint8_t* tlv_ba, uint16_t tlv_ba_length, uint8_t tlv_id, uint8_t** found_tlv);
/**
* Read 1 byte length TLV.
*
* \param ptr pointer TLV message array.
* \param length length of TLV message array.
* \param type Type of TLV.
* \param data_ptr pointer to variable where the value is read.
*
* \return pointer length of TLV 1 if success. 0 means TLV not found or does not have any data.
* \return Any other value indicates that TLV is not as expected.
*/
uint8_t thread_meshcop_tlv_data_get_uint8(const uint8_t *ptr, const uint16_t length, const uint8_t type, uint8_t *data_ptr);
/**
* Read 2 byte length TLV.
*
* \param ptr pointer TLV message array.
* \param length length of TLV message array.
* \param type Type of TLV.
* \param data_ptr pointer to variable where the value is read.
*
* \return pointer length of TLV 2 if success. 0 means TLV not found or does not have any data.
* \return Any other value indicates that TLV is not as expected.
*/
uint8_t thread_meshcop_tlv_data_get_uint16(const uint8_t *ptr, const uint16_t length, const uint8_t type, uint16_t *data_ptr);
/**
* Read 4 byte length TLV.
*
* \param ptr pointer TLV message array.
* \param length length of TLV message array.
* \param type Type of TLV.
* \param data_ptr pointer to variable where the value is read.
*
* \return pointer length of TLV 4 if success. 0 means TLV not found or does not have any data.
* \return Any other value indicates that TLV is not as expected.
*/
uint8_t thread_meshcop_tlv_data_get_uint32(const uint8_t *ptr, const uint16_t length, const uint8_t type, uint32_t *data_ptr);
/**
* Read 8 byte length TLV.
*
* \param ptr pointer TLV message array.
* \param length length of TLV message array.
* \param type Type of TLV.
* \param data_ptr pointer to variable where the value is read.
*
* \return pointer length of TLV 4 if success. 0 means TLV not found or does not have any data.
* \return Any other value indicates that TLV is not as expected.
*/
uint8_t thread_meshcop_tlv_data_get_uint64(const uint8_t *ptr, const uint16_t length, const uint8_t type, uint64_t *data_ptr);
#endif /* THREAD_MESHCOP_LIB_H_ */

View File

@ -0,0 +1,72 @@
/*
* Copyright (c) 2016-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \file thread_net_config_api.h
* \brief Public API to handle the Thread network services and configuration.
*/
#ifndef _THREAD_NET_CONFIG_API_H_
#define _THREAD_NET_CONFIG_API_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "ns_types.h"
/**
* \brief function callback type for nd_data_request.
*
* \param inteface_id Network interface ID where request was made.
* \param status 0 when response is received from destination, -1 otherwise.
* \param data_ptr ND_data options encoded according to RFC6106. Is NULL if destination was unreachable or didn't have the requested data.
* \param data_len Length of data in bytes.
*/
typedef void thread_net_config_nd_data_req_cb(int8_t interface_id, int8_t status, uint8_t *data_ptr, uint16_t data_len);
/**
* \brief Request ND options (as in RFC6106) from given destination.
* Response data will be provided in callback function.
*
* \param interface_id network interface ID.
* \param destination IPv6 address where request is sent.
* \param options requested option type identifiers according to RFC6106.
* \param options_len number of options requested.
* \param callback Function that will be called once information is available.
*
* \return 0 on success. A callback will be called with/without response data.
* \return <0 in error cases. Callback will not be called.
*/
int thread_net_config_nd_data_request(int8_t interface_id, const uint8_t destination[16], const uint8_t *options, uint8_t options_len, thread_net_config_nd_data_req_cb *callback);
#ifdef __cplusplus
}
#endif
#endif /* _THREAD_NET_CONFIG_API_H_ */

View File

@ -0,0 +1,61 @@
/*
* Copyright (c) 2011-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef WHITEBOARD_API_H_
#define WHITEBOARD_API_H_
#include "net_interface.h"
/**
* \file whiteboard_api.h
* \brief An API for DAD, intercepting messages from backhaul network and keeping track of routes inside the PAN.
*/
#ifdef __cplusplus
extern "C" {
#endif
/**
* \struct whiteboard_entry_t
* \brief A structure describing a whiteboarding entry.
*/
typedef struct whiteboard_entry_t {
uint8_t address[16]; /**< Registered IP address. */
uint_least24_t ttl; /**< Whiteboard entry TTL (seconds). */
uint8_t eui64[8]; /**< EUI-64 of node that IP address is registered to. */
int8_t interface_index; /**< Interface id */
} whiteboard_entry_t;
/**
* \brief Read whiteboard entries
* \param cur NULL to read first entry, or get next entry after cur.
* \return A pointer to whiteboard_entry_t structure.
*/
extern whiteboard_entry_t *whiteboard_get(whiteboard_entry_t *cur);
/**
* @brief Whiteboard_set_device_hard_limit Sets the absolut limit of child devices this device can handle.
* This is very useful in situations, where 1 GW drops from network and causes it's children
* to join other GW networks. This might cause other GWs to run out of memory.
* @param limit Absolute maximum amount of devices allowed to join. Default value=0 means unlimited (as long as there is memory)
*/
extern void whiteboard_set_device_hard_limit(uint16_t limit);
#ifdef __cplusplus
}
#endif
#endif /* WHITEBOARD_API_H_ */

16
run_unit_tests.sh Executable file
View File

@ -0,0 +1,16 @@
#!/bin/bash
# Copyright (c) 2015 ARM Limited. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
# Licensed under the Apache License, Version 2.0 (the License); you may
# not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# * http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an AS IS BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
make test

View File

@ -0,0 +1,148 @@
/*
* Copyright (c) 2013-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "nsconfig.h"
#include "ns_types.h"
#include <string.h>
#include "Core/include/socket.h"
#include "nsdynmemLIB.h"
#include "ns_trace.h"
#include "NWK_INTERFACE/Include/protocol.h"
#include "Common_Protocols/icmpv6.h"
#include "Common_Protocols/udp.h"
#include "6LoWPAN/Bootstraps/network_lib.h"
#include "MLE/mle.h"
#include "shalib.h"
#include "Common_Protocols/ipv6_constants.h"
#ifdef PANA
#ifdef ECC
#include "libX509_V3.h"
#include "ecc.h"
#endif
#include "Security/TLS/tls_lib.h"
#include "Security/Common/sec_lib.h"
#include "net_nvm_api.h"
#include "Security/PANA/pana.h"
#include "ccmLIB.h"
#endif
#include "6LoWPAN/ND/nd_router_object.h"
#include "6LoWPAN/IPHC_Decode/cipv6.h"
#include "net_nwk_scan.h"
#include "nwk_stats_api.h"
#include "NWK_INTERFACE/Include/protocol_stats.h"
#ifdef HAVE_RPL
#include "RPL/rpl_data.h"
#endif
#include "platform/arm_hal_interrupt.h"
#include "common_functions.h"
#include "6LoWPAN/Thread/thread_common.h"
#include "6LoWPAN/Thread/thread_bootstrap.h"
#define MAC_MLME_SACN_PERIO_PARAM 5
#define TRACE_GROUP "nw"
/**
* \brief Check That Network Have IPv6 Address Ready.
*
* \return 1 when IPv6 address is valid and 0 when it is not valid
*/
uint8_t nwk_ready(nwk_interface_id id)
{
uint8_t ret_val = 0;
protocol_interface_info_entry_t *cur = 0;
cur = protocol_stack_interface_info_get(id);
if (cur) {
if (thread_info(cur)) {
if (thread_attach_ready(cur) == 0) {
ret_val = 1;
}
} else {
if ((cur->lowpan_info & INTERFACE_NWK_BOOTSRAP_ADDRESS_REGISTER_READY)) {
ret_val = 1;
}
}
}
return ret_val;
}
void nwk_parent_poll_fail_cb(int8_t id)
{
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(id);
if (!cur) {
tr_error("Data Poll Fail Event: No interface");
return;
}
if (thread_info(cur)) {
//Initialize Bootsrap
thread_bootstrap_connection_error(cur->id, CON_ERROR_POLL, NULL);
} else {
nwk_bootsrap_state_update(ARM_NWK_NWK_PARENT_POLL_FAIL, cur);
}
}
void network_library_init(void)
{
socket_init();
address_module_init();
//SET MAC_MLME Handler
protocol_init();
}
buffer_t *nwk_udp_rx_security_check(buffer_t *buf)
{
protocol_interface_info_entry_t *cur = buf->interface;
uint8_t drop_unsecured = 0;
// Hack for PANA and MLE. PANA socket is not unsecured, need to allow unsecured link local traffic.
// MLE need to allow joiner request, that is not secured.
// TODO: Check if there is better fix for these.
if (buf->src_sa.port == UDP_PORT_PANA || buf->dst_sa.port == UDP_PORT_PANA) {
if ((buf->dst_sa.address[0] != 0xfe) && (buf->options.ll_security_bypass_rx)) {
drop_unsecured = 1;
}
} else if (buf->dst_sa.port == UDP_PORT_MLE) {
// OK
} else if (buf->options.ll_security_bypass_rx) {
if (addr_ipv6_scope(buf->src_sa.address, cur) > IPV6_SCOPE_LINK_LOCAL) {
drop_unsecured = 1;
} else {
if (!buf->socket) {
buffer_socket_set(buf, socket_lookup_ipv6(IPV6_NH_UDP, &buf->dst_sa, &buf->src_sa, true));
}
if (buf->socket && buf->socket->inet_pcb->link_layer_security == 0) {
// non-secure okay if it's for a socket whose security flag is clear.
}
else {
drop_unsecured = 1;
}
}
}
if (drop_unsecured) {
tr_warn("Drop UDP Unsecured");
buf = buffer_free(buf);
}
return buf;
}

View File

@ -0,0 +1,771 @@
/*
* Copyright (c) 2013-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "nsconfig.h"
#include "string.h"
#include "ns_types.h"
#include "eventOS_event.h"
#include "eventOS_scheduler.h"
#include "ns_trace.h"
#include "nsdynmemLIB.h"
#include "Core/include/socket.h"
#include "NWK_INTERFACE/Include/protocol.h"
#include "Common_Protocols/udp.h"
#include "Common_Protocols/ipv6.h"
#include "Common_Protocols/icmpv6.h"
#include "6LoWPAN/Bootstraps/protocol_6lowpan.h"
#include "6LoWPAN/Bootstraps/protocol_6lowpan_bootstrap.h"
#include "6LoWPAN/ND/nd_router_object.h"
#ifdef HAVE_RPL
#include "RPL/rpl_control.h"
#include "RPL/rpl_data.h"
#include "RPL/rpl_protocol.h"
#endif
#include "6LoWPAN/IPHC_Decode/cipv6.h"
#include "6LoWPAN/ND/nd_router_object.h"
#ifndef NO_MLE
#include "MLE/mle.h"
#endif
#include "6LoWPAN/Mesh/mesh.h"
#include "6LoWPAN/Thread/thread_common.h"
#include "6LoWPAN/Thread/thread_nd.h"
#include "6LoWPAN/MAC/mac_helper.h"
#ifdef ECC
#include "libX509_V3.h"
#include "ecc.h"
#endif
#include "ccmLIB.h"
#include "shalib.h"
#include "Security/TLS/tls_lib.h"
#include "Security/Common/sec_lib.h"
#include "net_nvm_api.h"
#include "Security/PANA/pana.h"
#include "Security/PANA/pana_internal_api.h"
#include "Common_Protocols/tcp.h"
#include "randLIB.h"
#include "6LoWPAN/ND/nd_router_object.h"
#include "common_functions.h"
#include "BorderRouter/border_router.h"
#include "net_rpl.h"
#ifdef HAVE_RPL
#ifndef NO_MLE
#include "NWK_INTERFACE/Include/protocol_stats.h"
#endif
#endif
#include "sw_mac.h"
#include "6LoWPAN/MAC/mac_data_poll.h"
#include "6LoWPAN/lowpan_adaptation_interface.h"
#include "6LoWPAN/Fragmentation/cipv6_fragmenter.h"
#define TRACE_GROUP_LOWPAN "6lo"
#define TRACE_GROUP "6lo"
#ifdef HAVE_RPL
rpl_domain_t *protocol_6lowpan_rpl_domain;
/* Having to sidestep old rpl_dodag_t type for the moment */
struct rpl_dodag *protocol_6lowpan_rpl_root_dodag;
#endif
static uint8_t protocol_buffer_valid(buffer_t *b, protocol_interface_info_entry_t *cur)
{
uint8_t valid = 1;
if (cur) {
if ((b->info & B_TO_MAC_MLME_MASK) != B_TO_MAC_FROM_MAC) {
if (cur->lowpan_info & INTERFACE_NWK_ACTIVE) {
//if((power_save_state & (SLEEP_MODE_REQ | ICMP_ACTIVE)) == SLEEP_MODE_REQ)
if (check_power_state(SLEEP_MODE_REQ | ICMP_ACTIVE) == SLEEP_MODE_REQ) {
/* STill active but Sleep Req and ICMP is not ACTIVE */
valid = 0;
}
} else {
/* Set Clean Core Becauce Protocol Is not Active */
valid = 0;
}
}
} else {
valid = 0;
}
return valid;
}
void protocol_init(void)
{
tr_debug("P.Init\n");
#ifdef PANA
sec_libray_init();
#endif
#ifdef HAVE_RPL
protocol_6lowpan_rpl_domain = rpl_control_create_domain();
#endif
}
void protocol_6lowpan_stack(buffer_t *b)
{
protocol_interface_info_entry_t *cur = b->interface;
if (protocol_buffer_valid(b, cur) == 0) {
tr_debug("Drop Packets\n");
buffer_free(b);
return;
}
/* Protocol Buffer Handle until Buffer Go out from Stack */
while (b) {
/* Buffer Direction Select Switch */
if ((b->info & B_DIR_MASK) == B_DIR_DOWN) {
/* Direction DOWN */
switch (b->info & B_TO_MASK) {
case B_TO_ICMP:
/* Build ICMP Header */
b = icmpv6_down(b);
break;
case B_TO_UDP:
/* Build UDP Header */
b = udp_down(b);
break;
case B_TO_IPV6:
/* Build IP header */
b = ipv6_down(b);
break;
case B_TO_IPV6_FWD:
/* IPv6 forwarding */
b = ipv6_forwarding_down(b);
break;
case B_TO_IPV6_TXRX:
/* Resolution, Compress IP header */
b = lowpan_down(b);
break;
#ifdef HAVE_MESH
case B_TO_MESH_ROUTING:
/* Add mesh header */
b = mesh_down(b);
break;
#endif
case B_TO_MAC:
/* no break */
case B_TO_PHY:
b = lowpan_adaptation_data_process_tx_preprocess(cur, b);
if (lowpan_adaptation_interface_tx(cur, b) != 0) {
tr_error("Adaptaion Layer Data req fail");
}
b = NULL;
break;
default:
b = buffer_free(b);
break;
}
} else {
/* Direction UP */
switch (b->info & B_TO_MASK) {
case B_TO_APP:
/* Push Socket Interface */
socket_up(b);
b = NULL;
break;
case B_TO_ICMP:
/* Parse ICMP Message */
b = icmpv6_up(b);
break;
case B_TO_FRAGMENTATION:
/* Packet Reasemley */
b = cipv6_frag_reassembly(cur->id, b);
break;
case B_TO_UDP:
/* Parse UDP Message */
b = udp_up(b);
break;
case B_TO_IPV6_FWD:
/* Handle IP Payload */
b = ipv6_forwarding_up(b);
break;
case B_TO_IPV6_TXRX:
/* Handle MAC Payload */
b = lowpan_up(b);
break;
#ifdef HAVE_MESH
case B_TO_MESH_ROUTING:
/* Handle Mesh header */
b = mesh_up(b);
break;
#endif
case B_TO_TCP:
b = tcp_up(b);
break;
default:
tr_debug("LLL\n");
b = buffer_free(b);
break;
}
}
if (b) {
//Check If Stack forward packet to different interface
if (b->interface != cur) {
protocol_push(b);
b = 0;
}
}
}
}
/* Return length of option always, and write option if opt_out != NULL */
static uint8_t protocol_6lowpan_llao_write(protocol_interface_info_entry_t *cur, uint8_t *opt_out, uint8_t opt_type, bool must, const uint8_t *ip_addr)
{
/* Don't bother including optional LLAO if it's a link-local address -
* they should be mapping anyway.
*/
if (!must && addr_is_ipv6_link_local(ip_addr)) {
return 0;
}
uint16_t mac16 = mac_helper_mac16_address_get(cur);
/* Even if we have a short address, use long address if the IP address's IID matches it */
if (mac16 >= 0xfffe || addr_iid_matches_eui64(ip_addr + 8, cur->mac)) {
if (opt_out) {
opt_out[0] = opt_type;
opt_out[1] = 2;
memcpy(opt_out + 2, cur->mac, 8);
memset(opt_out + 10, 0, 6);
}
return 16;
} else {
if (opt_out) {
opt_out[0] = opt_type;
opt_out[1] = 1;
common_write_16_bit(mac16, opt_out + 2);
memset(opt_out + 4, 0, 4);
}
return 8;
}
}
/* Parse, and return actual size, or 0 if error */
static uint8_t protocol_6lowpan_llao_parse(protocol_interface_info_entry_t *cur, const uint8_t *opt_in, sockaddr_t *ll_addr_out)
{
common_write_16_bit(cur->mac_parameters->pan_id, ll_addr_out->address + 0);
switch (opt_in[1]) {
case 1:
ll_addr_out->addr_type = ADDR_802_15_4_SHORT;
memcpy(ll_addr_out->address + 2, opt_in + 2, 2);
return 2 + 2;
case 2:
ll_addr_out->addr_type = ADDR_802_15_4_LONG;
memcpy(ll_addr_out->address + 2, opt_in + 2, 8);
return 2 + 8;
default:
return 0;
}
}
static bool protocol_6lowpan_map_ip_to_link_addr(protocol_interface_info_entry_t *cur, const uint8_t *ip_addr, addrtype_t *ll_type, const uint8_t **ll_addr_out)
{
static uint8_t ll_addr[10];
*ll_type = ADDR_NONE;
/* RFC 6775 says link-local addresses are based on extended MAC (LL64) */
/* ZigBee IP and Thread both also have link-local addresses based on short MAC (LL16) */
/* Our old IP stack assumed all addresses were based on MAC; this is available as an option */
if (cur->iids_map_to_mac || addr_is_ipv6_link_local(ip_addr)) {
if (memcmp(&ip_addr[8], ADDR_SHORT_ADR_SUFFIC, 6) == 0) {
*ll_type = ADDR_802_15_4_SHORT;
memcpy(&ll_addr[2], &ip_addr[14], 2);
} else {
*ll_type = ADDR_802_15_4_LONG;
memcpy(&ll_addr[2], &ip_addr[8], 8);
ll_addr[2] ^= 2;
}
} else if (thread_addr_is_mesh_local(ip_addr, cur)) {
if (memcmp(&ip_addr[8], ADDR_SHORT_ADR_SUFFIC, 6) == 0) {
/* Thread ML16s map directly to MAC (mesh) short */
*ll_type = ADDR_802_15_4_SHORT;
memcpy(&ll_addr[2], &ip_addr[14], 2);
}
}
if (*ll_type != ADDR_NONE) {
common_write_16_bit(cur->mac_parameters->pan_id, &ll_addr[0]);
*ll_addr_out = ll_addr;
return true;
} else {
return false;
}
}
static bool protocol_6lowpan_map_link_addr_to_ip(protocol_interface_info_entry_t *cur, addrtype_t ll_type, const uint8_t *ll_addr, uint8_t *ip_addr_out)
{
(void)cur;
switch (ll_type) {
case ADDR_802_15_4_LONG:
memcpy(ip_addr_out, ADDR_LINK_LOCAL_PREFIX, 8);
memcpy(ip_addr_out + 8, ll_addr + 2, 8);
ip_addr_out[8] ^= 0x02;
return true;
case ADDR_802_15_4_SHORT:
if (common_read_16_bit(ll_addr + 2) > 0xfffd) {
return false;
}
memcpy(ip_addr_out, ADDR_LINK_LOCAL_PREFIX, 8);
memcpy(ip_addr_out + 8, ADDR_SHORT_ADR_SUFFIC, 6);
memcpy(ip_addr_out + 14, ll_addr + 2, 2);
return true;
default:
return false;
}
}
void protocol_6lowpan_host_init(protocol_interface_info_entry_t *cur, bool sleepy_host)
{
if (sleepy_host) {
cur->bootsrap_mode = ARM_NWK_BOOTSRAP_MODE_6LoWPAN_SLEEPY_HOST;
} else {
cur->bootsrap_mode = ARM_NWK_BOOTSRAP_MODE_6LoWPAN_HOST;
}
//Clear always INTERFACE_NWK_ROUTER_DEVICE, INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE
cur->lowpan_info &= ~(INTERFACE_NWK_ROUTER_DEVICE | INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE);
mle_class_mode_set(cur->id, MLE_CLASS_END_DEVICE);
mac_helper_pib_boolean_set(cur, macRxOnWhenIdle, true);
mac_data_poll_init(cur);
arm_nwk_6lowpan_borderrouter_data_free(cur);
}
void protocol_6lowpan_router_init(protocol_interface_info_entry_t *cur)
{
cur->bootsrap_mode = ARM_NWK_BOOTSRAP_MODE_6LoWPAN_ROUTER;
cur->lowpan_info |= INTERFACE_NWK_ROUTER_DEVICE;
cur->lowpan_info &= ~INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE;
mle_class_mode_set(cur->id, MLE_CLASS_ROUTER);
mac_data_poll_init(cur);
arm_nwk_6lowpan_borderrouter_data_free(cur);
}
void protocol_6lowpan_configure_core(protocol_interface_info_entry_t *cur) {
cur->dup_addr_detect_transmits = 0;
cur->ipv6_neighbour_cache.max_ll_len = 2 + 8;
cur->ipv6_neighbour_cache.link_mtu = LOWPAN_MTU;
#ifdef HAVE_6LOWPAN_ND
cur->ipv6_neighbour_cache.send_nud_probes = nd_params.send_nud_probes;
cur->iids_map_to_mac = nd_params.iids_map_to_mac;
#endif
cur->ip_multicast_as_mac_unicast_to_parent = false;
cur->max_link_mtu = LOWPAN_MAX_MTU;
cur->send_mld = false;
#ifdef HAVE_6LOWPAN_ND
nd_6lowpan_set_radv_params(cur);
#endif
}
void protocol_6lowpan_register_handlers(protocol_interface_info_entry_t *cur)
{
cur->if_stack_buffer_handler = protocol_6lowpan_stack;
cur->if_llao_parse = protocol_6lowpan_llao_parse;
cur->if_llao_write = protocol_6lowpan_llao_write;
cur->if_map_ip_to_link_addr = protocol_6lowpan_map_ip_to_link_addr;
cur->if_map_link_addr_to_ip = protocol_6lowpan_map_link_addr_to_ip;
if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER ||
cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_ROUTER) {
cur->ipv6_neighbour_cache.recv_addr_reg = true;
cur->ipv6_neighbour_cache.recv_ns_aro = true;
}
/* Always send AROs, (compulsory for hosts, and "SHOULD" in RFC 6557 6.5.5
* for routers, as RPL doesn't deal with it) */
cur->ipv6_neighbour_cache.send_addr_reg = true;
cur->ipv6_neighbour_cache.recv_na_aro = true;
}
void protocol_6lowpan_release_short_link_address_from_neighcache(protocol_interface_info_entry_t *cur, uint16_t shortAddress)
{
uint8_t temp_ll[4];
uint8_t *ptr = temp_ll;
ptr = common_write_16_bit(cur->mac_parameters->pan_id, ptr);
ptr = common_write_16_bit(shortAddress, ptr);
ipv6_neighbour_invalidate_ll_addr(&cur->ipv6_neighbour_cache,
ADDR_802_15_4_SHORT, temp_ll);
if (thread_info(cur)) {
thread_nd_address_remove(cur, ADDR_802_15_4_SHORT, temp_ll);
} else {
nd_remove_registration(cur, ADDR_802_15_4_SHORT, temp_ll);
}
}
void protocol_6lowpan_release_long_link_address_from_neighcache(protocol_interface_info_entry_t *cur, uint8_t *mac64)
{
uint8_t temp_ll[10];
uint8_t *ptr = temp_ll;
ptr = common_write_16_bit(cur->mac_parameters->pan_id, ptr);
memcpy(ptr, mac64, 8);
ipv6_neighbour_invalidate_ll_addr(&cur->ipv6_neighbour_cache,
ADDR_802_15_4_LONG, temp_ll);
if (thread_info(cur)) {
thread_nd_address_remove(cur, ADDR_802_15_4_LONG, temp_ll);
} else {
nd_remove_registration(cur, ADDR_802_15_4_LONG, temp_ll);
}
}
#ifdef HAVE_6LOWPAN_ND
static int8_t mle_set_link_priority(int8_t interface_id, const uint8_t *address, bool priority)
{
uint8_t mac64[8];
mle_neigh_table_entry_t *mle_entry;
if (!memcmp(address, ADDR_SHORT_ADR_SUFFIC, 6)) {
mle_entry = mle_class_get_by_link_address(interface_id, address + 6, ADDR_802_15_4_SHORT);
} else {
memcpy(mac64, address, 8);
mac64[0] ^= 2;
mle_entry = mle_class_get_by_link_address(interface_id, mac64, ADDR_802_15_4_LONG);
}
if (!mle_entry) {
return -1;
}
if (priority) {
mle_entry->priorityFlag = 1;
} else {
mle_entry->priorityFlag = 0;
}
return 0;
}
void protocol_6lowpan_neighbor_priority_update(protocol_interface_info_entry_t *cur, uint8_t *removed_priority, uint8_t *updated_priority)
{
if (cur->lowpan_info & INTERFACE_NWK_BOOTSRAP_MLE) {
#ifndef NO_MLE
if (removed_priority) {
mle_set_link_priority(cur->id,removed_priority, false);
}
if (updated_priority) {
mle_set_link_priority(cur->id, updated_priority, true);
}
#endif
}
}
#ifdef HAVE_RPL
#ifndef NO_MLE
uint16_t protocol_6lowpan_neighbor_priority_set(int8_t interface_id, addrtype_t addr_type, const uint8_t *addr_ptr)
{
mle_neigh_table_entry_t *neigh_table_ptr;
if (!addr_ptr) {
return 0;
}
neigh_table_ptr = mle_class_get_by_link_address(interface_id, addr_ptr + PAN_ID_LEN, addr_type);
if (neigh_table_ptr) {
// If primary parent has changed clears priority from previous parent
if (!neigh_table_ptr->priorityFlag) {
protocol_6lowpan_neighbor_priority_clear_all(interface_id, PRIORITY_1ST);
}
neigh_table_ptr->priorityFlag = 1;
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
if (cur) {
uint8_t temp[2];
common_write_16_bit(neigh_table_ptr->short_adr, temp);
mac_helper_coordinator_address_set(cur, ADDR_802_15_4_SHORT, temp);
mac_helper_coordinator_address_set(cur, ADDR_802_15_4_LONG, neigh_table_ptr->mac64);
}
protocol_stats_update(STATS_ETX_1ST_PARENT, neigh_table_ptr->etx >> 4);
return 1;
} else {
return 0;
}
}
uint16_t protocol_6lowpan_neighbor_second_priority_set(int8_t interface_id, addrtype_t addr_type, const uint8_t *addr_ptr)
{
mle_neigh_table_entry_t *neigh_table_ptr;
if (!addr_ptr) {
return 0;
}
neigh_table_ptr = mle_class_get_by_link_address(interface_id, addr_ptr + PAN_ID_LEN, addr_type);
if (neigh_table_ptr) {
// If secondary parent has changed clears priority from previous parent
if (neigh_table_ptr->second_priority_flag == 0) {
protocol_6lowpan_neighbor_priority_clear_all(interface_id, PRIORITY_2ND);
}
neigh_table_ptr->second_priority_flag = 1;
protocol_stats_update(STATS_ETX_2ND_PARENT, neigh_table_ptr->etx >> 4);
return 1;
} else {
return 0;
}
}
void protocol_6lowpan_neighbor_priority_clear_all(int8_t interface_id, neighbor_priority priority)
{
mle_neigh_table_list_t *mle_neigh_table;
mle_neigh_table = mle_class_active_list_get(interface_id);
if (!mle_neigh_table) {
return;
}
ns_list_foreach(mle_neigh_table_entry_t, entry, mle_neigh_table) {
if (priority == PRIORITY_1ST) {
entry->priorityFlag = 0;
} else {
if (entry->second_priority_flag) {
protocol_stats_update(STATS_ETX_2ND_PARENT, 0);
}
entry->second_priority_flag = 0;
}
}
}
#endif
#endif
#endif
int8_t protocol_6lowpan_neighbor_address_state_synch(protocol_interface_info_entry_t *cur, const uint8_t eui64[8], const uint8_t iid[8])
{
int8_t ret_val = -1;
if (cur->lowpan_info & INTERFACE_NWK_BOOTSRAP_MLE) {
#ifndef NO_MLE
mle_neigh_table_entry_t *mle_entry = 0;
mle_entry = mle_class_get_by_link_address(cur->id, eui64, ADDR_802_15_4_LONG);
if (mle_entry && !mle_entry->threadNeighbor) {
if (memcmp(iid, ADDR_SHORT_ADR_SUFFIC, 6) == 0) {
iid += 6;
//Set Short Address to MLE
mle_entry->short_adr = common_read_16_bit(iid);
}
if ((mle_entry->mode & MLE_DEV_MASK) == MLE_RFD_DEV) {
if (mle_entry->handshakeReady) {
mle_entry_timeout_refresh(mle_entry);
}
ret_val = 1;
} else {
ret_val = 0;
}
}
#endif
} else {
ret_val = 0;
}
return ret_val;
}
int8_t protocol_6lowpan_neighbor_remove(protocol_interface_info_entry_t *cur, uint8_t *address_ptr, addrtype_t type)
{
int8_t ret_val = 0;
if (cur->lowpan_info & INTERFACE_NWK_BOOTSRAP_MLE) {
#ifndef NO_MLE
mle_class_remove_neighbour(cur->id, address_ptr, type);
#endif
} else {
//REMOVE Something else
}
return ret_val;
}
void protocol_6lowpan_allocate_mac16(protocol_interface_info_entry_t *cur)
{
if (cur) {
cur->lowpan_desired_short_address = (randLIB_get_16bit() & 0x7fff);
}
}
void protocol_6lowpan_interface_common_init(protocol_interface_info_entry_t *cur)
{
cur->lowpan_info |= INTERFACE_NWK_ACTIVE;
protocol_6lowpan_register_handlers(cur);
ipv6_route_add(ADDR_LINK_LOCAL_PREFIX, 64, cur->id, NULL, ROUTE_STATIC, 0xFFFFFFFF, 0);
// Putting a multicast route to ff00::/8 makes sure we can always transmit multicast.
// Interface metric will determine which interface is actually used, if we have multiple.
ipv6_route_add(ADDR_LINK_LOCAL_ALL_NODES, 8, cur->id, NULL, ROUTE_STATIC, 0xFFFFFFFF, -1);
}
int8_t protocol_6lowpan_interface_compare_cordinator_netid(protocol_interface_info_entry_t *cur, uint8_t *adr_ptr)
{
int8_t ret_val = -1;
if (cur) {
addrtype_t addrType;
uint8_t tempAddress[8];
addrType = mac_helper_coordinator_address_get(cur, tempAddress);
if (addrType == ADDR_802_15_4_LONG) {
tempAddress[0] ^= 2;
if (memcmp(adr_ptr, tempAddress, 8) == 0) {
ret_val = 0;
}
} else if (addrType == ADDR_802_15_4_SHORT) {
if (adr_ptr[6] == tempAddress[0] && adr_ptr[7] == tempAddress[1]) {
ret_val = 0;
}
}
}
return ret_val;
}
int8_t protocol_6lowpan_interface_get_link_local_cordinator_address(protocol_interface_info_entry_t *cur, uint8_t *adr_ptr)
{
addrtype_t addrType;
uint8_t tempAddress[8];
addrType = mac_helper_coordinator_address_get(cur, tempAddress);
if (addrType == ADDR_NONE) {
return -1;
}
memcpy(adr_ptr, ADDR_LINK_LOCAL_PREFIX, 8);
adr_ptr += 8;
if (addrType == ADDR_802_15_4_LONG) {
tempAddress[0] ^= 2;
memcpy(adr_ptr, tempAddress, 8);
} else {
memcpy(adr_ptr, ADDR_SHORT_ADR_SUFFIC, 6);
adr_ptr += 6;
*adr_ptr++ = tempAddress[0];
*adr_ptr = tempAddress[1];
}
return 0;
}
int8_t protocol_6lowpan_interface_get_mac_coordinator_address(protocol_interface_info_entry_t *cur, sockaddr_t *adr_ptr)
{
common_write_16_bit(cur->mac_parameters->pan_id, adr_ptr->address + 0);
adr_ptr->addr_type = mac_helper_coordinator_address_get(cur, adr_ptr->address + 2);
if (adr_ptr->addr_type == ADDR_NONE) {
return -1;
}
return 0;
}
int16_t protocol_6lowpan_rpl_global_priority_get(void)
{
#ifdef HAVE_RPL
uint8_t instance_id_list[10];
uint8_t rpl_instance_count;
uint8_t instance_id = RPL_INSTANCE_LOCAL;
uint8_t instance_id_new;
uint8_t instance_index;
rpl_instance_count = rpl_instance_list_read(&instance_id_list[0], sizeof(instance_id_list));
/* Find lowest global instance ID (assumption: RPL instance with lowest instance ID has
most generic routing rule and its rank should be indicated in beacon) */
for (instance_index = 0; instance_index < rpl_instance_count; instance_index++) {
instance_id_new = instance_id_list[instance_index];
if ((instance_id_new & RPL_INSTANCE_LOCAL) == RPL_INSTANCE_LOCAL) {
break;
} else {
if (instance_id_new < instance_id) {
instance_id = instance_id_new;
}
}
}
// Get DAG rank
if (instance_id == RPL_INSTANCE_LOCAL) {
return 255;
}
rpl_dodag_info_t rpl_dodag_info;
if (!rpl_read_dodag_info(&rpl_dodag_info, instance_id)) {
return 255;
}
if (rpl_dodag_info.curent_rank == RPL_RANK_INFINITE) {
return 255;
}
// Default implementation is
// 32 * (7 - DODAGPreference) + 3 * (DAGRank - 1)
int16_t priority;
priority = 32 * (7 - RPL_DODAG_PREF(rpl_dodag_info.flags));
priority += 3 * (rpl_dodag_info.curent_rank / rpl_dodag_info.dag_min_hop_rank_inc - 1);
return priority;
#else
return 255;
#endif
}
uint8_t protocol_6lowpan_beacon_join_priority_tx(int8_t interface_id)
{
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
if (!cur) {
return 255;
}
int16_t priority = 0;
#ifdef HAVE_RPL
if (cur->rpl_domain) {
priority = protocol_6lowpan_rpl_global_priority_get();
}
#endif
#ifndef NO_MLE
mle_6lowpan_data_t *mle_6lowpan_data = protocol_6lowpan_mle_data_get();
if (mle_6lowpan_data && mle_6lowpan_data->nbr_of_neigh_max != 0) {
uint16_t mle_neigh_cnt = mle_class_active_neigh_counter(interface_id);
if (mle_neigh_cnt > mle_6lowpan_data->nbr_of_neigh_lower_threshold) {
uint16_t mle_neigh_limit;
mle_neigh_cnt -= mle_6lowpan_data->nbr_of_neigh_lower_threshold;
mle_neigh_limit = 32 * mle_neigh_cnt / (mle_6lowpan_data->nbr_of_neigh_max - mle_6lowpan_data->nbr_of_neigh_lower_threshold);
priority += mle_neigh_limit;
}
}
#endif
if (priority < 0) {
priority = 0;
} else if (priority > 255) {
priority = 255;
}
return priority;
}
uint8_t protocol_6lowpan_beacon_compare_rx(int8_t interface_id, uint8_t join_priority, uint8_t link_quality)
{
(void)interface_id; // not used, perhaps should be removed completely
uint16_t conn_to_pref;
conn_to_pref = ((256 - join_priority) * (uint16_t) link_quality) >> 8;
return conn_to_pref;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,175 @@
/*
* Copyright (c) 2015-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* \file protocol_6lowpan_interface.c
* \brief Add short description about this file!!!
*
*/
#include "nsconfig.h"
#include "string.h"
#include "ns_types.h"
#include "eventOS_event.h"
#include "eventOS_scheduler.h"
#include "ns_trace.h"
#include "nsdynmemLIB.h"
#include "NWK_INTERFACE/Include/protocol.h"
#include "Common_Protocols/udp.h"
#include "Common_Protocols/ipv6_constants.h"
#include "Common_Protocols/icmpv6.h"
#include "Common_Protocols/icmpv6_radv.h"
#include "6LoWPAN/Bootstraps/network_lib.h"
#include "6LoWPAN/Bootstraps/protocol_6lowpan.h"
#include "6LoWPAN/Bootstraps/protocol_6lowpan_bootstrap.h"
#include "Service_Libs/blacklist/blacklist.h"
#include "6LoWPAN/MAC/mac_helper.h"
#include "mac_api.h"
#ifdef HAVE_RPL
#include "RPL/rpl_control.h"
#endif
#include "6LoWPAN/IPHC_Decode/cipv6.h"
#ifndef NO_MLE
#include "MLE/mle.h"
#endif
#include "6LoWPAN/Mesh/mesh.h"
#include "6LoWPAN/Thread/thread_common.h"
#ifdef ECC
#include "libX509_V3.h"
#include "ecc.h"
#endif
#include "ccmLIB.h"
#include "shalib.h"
#include "Security/TLS/tls_lib.h"
#include "Security/Common/sec_lib.h"
#include "net_nvm_api.h"
#include "Security/PANA/pana.h"
#include "Security/PANA/pana_internal_api.h"
#include "Common_Protocols/tcp.h"
#include "6LoWPAN/ND/nd_router_object.h"
#include "platform/arm_hal_interrupt.h"
#include "common_functions.h"
#include "mac_api.h"
#include "6LoWPAN/lowpan_adaptation_interface.h"
#include "6LoWPAN/Fragmentation/cipv6_fragmenter.h"
#include "libNET/src/net_load_balance_internal.h"
static int8_t set_6lowpan_nwk_down(protocol_interface_info_entry_t *cur)
{
int8_t ret_val = -1;
// Check first current state
if (cur->lowpan_info & INTERFACE_NWK_ACTIVE) {
/* Change Active -> Idle */
/* Disable Protocols Timers */
if (!thread_info(cur)) {
if (cur->lowpan_info & INTERFACE_NWK_BOOTSRAP_MLE) {
#ifndef NO_MLE
mle_class_list_clean(cur->id);
blacklist_clear();
#endif
}
}
uint16_t pan_id = cur->mac_parameters->pan_id;
if (cur->interface_mode == INTERFACE_UP) {
if (cur->mac_api) {
mlme_reset_t reset;
reset.SetDefaultPIB = true;
cur->mac_parameters->pan_id = 0xffff;
cur->mac_parameters->SecurityEnabled = false;
cur->mac_parameters->security_frame_counter = 0;
cur->mac_parameters->mac_security_level = 0;
cur->mac_api->mlme_req(cur->mac_api, MLME_RESET, &reset);
}
cur->interface_mode = INTERFACE_IDLE;
net_load_balance_internal_state_activate(cur, false);
}
lowpan_adaptation_interface_reset(cur->id);
reassembly_interface_reset(cur->id);
icmp_nd_routers_init();
if (cur->lowpan_info & INTERFACE_NWK_BOOTSRAP_PANA_AUTHENTICATION) {
pana_reset_values(pan_id);
}
if (cur->pana_sec_info_temp) {
ns_dyn_mem_free(cur->pana_sec_info_temp);
cur->pana_sec_info_temp = 0;
}
/* Init RPL Timers */
cur->bootsrap_state_machine_cnt = 0;
mac_helper_free_scan_confirm(&cur->mac_parameters->nwk_scan_params);
cur->lowpan_info &= ~INTERFACE_NWK_ROUTER_DEVICE;
cur->lowpan_info &= ~(INTERFACE_NWK_BOOTSRAP_ACTIVE | INTERFACE_NWK_ACTIVE);
cur->interface_mode = INTERFACE_IDLE;
ret_val = 0;
}
return ret_val;
}
static int8_t set_6lowpan_nwk_up(protocol_interface_info_entry_t *cur)
{
int8_t ret_val = 1;
if ((cur->lowpan_info & INTERFACE_NWK_ACTIVE) == 0) {
/* Change Idle-> Active */
icmp_nd_routers_init();
cur->nwk_bootstrap_state = ER_ACTIVE_SCAN;
cur->lowpan_info |= INTERFACE_NWK_BOOTSRAP_ACTIVE | INTERFACE_NWK_ACTIVE; //Set Active Bootsrap
cur->lowpan_info &= ~INTERFACE_NWK_BOOTSRAP_ADDRESS_REGISTER_READY; //Clear Bind
cur->bootsrap_state_machine_cnt = 2;
//Possible mac_mlme_start_req(call)
mac_helper_panid_set(cur, 0xffff);
mac_helper_mac16_address_set(cur, 0xffff);
if (cur->lowpan_info & INTERFACE_NWK_BOOTSRAP_PANA_AUTHENTICATION) {
mac_helper_default_security_level_set(cur, SEC_NONE);
}
cur->interface_mode = INTERFACE_UP;
ret_val = 0;
}
return ret_val;
}
int8_t nwk_6lowpan_up(protocol_interface_info_entry_t *cur)
{
int8_t ret_val;
ret_val = set_6lowpan_nwk_up(cur);
if (ret_val == 0) {
protocol_6lowpan_interface_common_init(cur);
cur->nwk_mode = ARM_NWK_GP_IP_MODE;
nwk_filter_params_s *filter = &(cur->mac_parameters->nwk_filter_params);
filter->nwk_active_scan_level = 2;
}
return ret_val;
}
int8_t nwk_6lowpan_down(protocol_interface_info_entry_t *cur)
{
int8_t ret_val;
neighbor_cache_flush(&cur->neigh_cache);
ret_val = set_6lowpan_nwk_down(cur);
protocol_core_interface_info_reset(cur);
return ret_val;
}

View File

@ -0,0 +1,27 @@
/*
* Copyright (c) 2013-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef NETWORK_LIB_H_
#define NETWORK_LIB_H_
extern uint8_t nwk_ready(nwk_interface_id id);
extern void nwk_parent_poll_fail_cb(int8_t id);
extern void network_library_init(void);
extern buffer_t *nwk_udp_rx_security_check(buffer_t *buf);
#endif /* NETWORK_LIB_H_ */

View File

@ -0,0 +1,83 @@
/*
* Copyright (c) 2015-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* \file protocol_6lowpan.h
*
*/
#ifndef PROTOCOL_6LOWPAN_H_
#define PROTOCOL_6LOWPAN_H_
struct protocol_interface_info_entry;
struct route_info_entry_t;
struct ns_sockaddr;
struct rpl_domain;
struct rpl_dodag;
struct mlme_pan_descriptor_s;
extern struct rpl_domain *protocol_6lowpan_rpl_domain;
extern struct rpl_dodag *protocol_6lowpan_rpl_root_dodag;
#ifdef HAVE_RPL
#ifndef NO_MLE
typedef enum {
PRIORITY_1ST,
PRIORITY_2ND,
} neighbor_priority;
#endif
#endif
void protocol_6lowpan_interface_common_init(struct protocol_interface_info_entry *cur);
void protocol_6lowpan_host_init(struct protocol_interface_info_entry *cur, bool sleepy_host);
void protocol_6lowpan_router_init(struct protocol_interface_info_entry *cur);
void protocol_6lowpan_configure_core(struct protocol_interface_info_entry *cur);
#ifdef HAVE_6LOWPAN_ND
int protocol_6lowpan_child_update(struct protocol_interface_info_entry *cur);
void protocol_6lowpan_neighbor_priority_update(struct protocol_interface_info_entry *cur, uint8_t *removed_priority, uint8_t *updated_priority);
#ifdef HAVE_RPL
#ifndef NO_MLE
uint16_t protocol_6lowpan_neighbor_priority_set(int8_t interface_id, addrtype_t addr_type, const uint8_t *addr_ptr);
uint16_t protocol_6lowpan_neighbor_second_priority_set(int8_t interface_id, addrtype_t addr_type, const uint8_t *addr_ptr);
void protocol_6lowpan_neighbor_priority_clear_all(int8_t interface_id, neighbor_priority priority);
#endif
#endif
#else
#define protocol_6lowpan_child_update(cur) (-1)
#define protocol_6lowpan_neighbor_priority_update(cur, removed_priority, updated_priority) ((void)0)
#endif
int8_t protocol_6lowpan_neighbor_address_state_synch(struct protocol_interface_info_entry *cur, const uint8_t eui64[8], const uint8_t iid[8]);
int8_t protocol_6lowpan_neighbor_remove(struct protocol_interface_info_entry *cur, uint8_t *address_ptr, addrtype_t type);
void protocol_6lowpan_allocate_mac16(protocol_interface_info_entry_t *cur);
int8_t protocol_6lowpan_interface_compare_cordinator_netid(struct protocol_interface_info_entry *cur, uint8_t *adr_ptr);
int8_t protocol_6lowpan_interface_get_link_local_cordinator_address(protocol_interface_info_entry_t *cur, uint8_t *adr_ptr);
int8_t protocol_6lowpan_interface_get_mac_coordinator_address(protocol_interface_info_entry_t *cur, struct ns_sockaddr *adr_ptr);
int16_t protocol_6lowpan_rpl_global_priority_get(void);
uint8_t protocol_6lowpan_beacon_join_priority_tx(int8_t interface_id);
uint8_t protocol_6lowpan_beacon_compare_rx(int8_t interface_id, uint8_t join_priority, uint8_t link_quality);
bool protocol_6lowpan_bootsrap_start(struct protocol_interface_info_entry *interface);
bool protocol_6lowpan_bootsrap_link_set(struct protocol_interface_info_entry *interface, struct mlme_pan_descriptor_s *pan_descriptor, const uint8_t *beacon_payload, uint8_t beacon_length);
#endif /* PROTOCOL_6LOWPAN_H_ */

View File

@ -0,0 +1,104 @@
/*
* Copyright (c) 2015-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* \file protocol_6lowpan_bootstrap.h
*
*/
#ifndef PROTOCOL_6LOWPAN_BOOTSTRAP_H_
#define PROTOCOL_6LOWPAN_BOOTSTRAP_H_
#include "net_interface.h"
#include "Service_Libs/mle_service/mle_service_api.h"
struct protocol_interface_info_entry;
struct nd_router;
struct mle_neigh_table_entry_t;
#define MLE_NEIGHBOR_PURGE_NBR 3
#define MLE_NEIGHBOR_PURGE_TIMER_TIMEOUT 4 // Times advertisement timeout
#define MLE_ROUTER_DEFAULT_LIFETIME 128
#define MLE_ROUTER_HOST_LIFETIME 400
#define MLE_NBR_OF_NEIGHBOR_MAX_LIMIT 0
#define MLE_NBR_OF_NEIGHBOR_LOWER_THRESHOLD 0
#define MLE_NBR_OF_NEIGHBOR_UPPER_THRESHOLD 0
#define MLE_TOKEN_BUCKET_SIZE 0
#define MLE_TOKEN_BUCKET_RATE 0
#define MLE_TOKEN_BUCKET_COUNT 0
#define MLE_LINK_REQ_TOKEN_BUCKET_SIZE 3
#define LOWPAN_MAX_FRAME_RETRIES 4
// Waiting Scan confirm from MAC (ms)
#define BOOTSTRAP_SCAN_TIMEOUT 30000
// Waiting Start confirm from MAC (ms)
#define BOOTSTRAP_START_TIMEOUT 10000
typedef struct mle_6lowpan_data {
uint16_t router_lifetime; // default lifetime for router neighbor
uint16_t host_lifetime; // default lifetime for host neighbor
uint16_t nbr_of_neigh_lower_threshold; // start to limit addition of neighbors to neighbor list
uint16_t nbr_of_neigh_upper_threshold; // only priority neighbors are added to neighbor list
uint16_t nbr_of_neigh_max; // maximum number of neighbors in neighbor list
uint8_t token_bucket_size; // MLE token bucket size
uint8_t token_bucket_rate; // Rate in which tokens are added to bucket (0.1 seconds * rate)
uint8_t token_bucket_count; // Count of tokens added to bucket at a time
uint8_t link_req_token_bucket; // Token bucket for MLE link request with non-valid security counter
} mle_6lowpan_data_t;
#ifdef PANA
extern void nwk_6lowpan_bootsrap_pana_authentication_cb(bool processSuccesfully, struct protocol_interface_info_entry *cur);
#endif
#ifdef HAVE_6LOWPAN_ND
uint8_t *protocol_6lowpan_mle_service_security_notify_cb(int8_t interface_id, mle_security_event_t event, uint8_t keyId);
void arm_6lowpan_bootstrap_init(struct protocol_interface_info_entry *cur);
uint8_t *protocol_6lowpan_nd_border_router_address_get(nwk_interface_id nwk_id);
uint8_t protocol_6lowpan_rf_link_scalability_from_lqi(uint8_t lqi);
void protocol_6lowpan_bootstrap_re_start(struct protocol_interface_info_entry *interface);
void protocol_6lowpan_link_advertise_handle(struct nd_router *cur, struct protocol_interface_info_entry *cur_interface, uint16_t tick);
void protocol_6lowpan_bootstrap_nd_ready(struct protocol_interface_info_entry *cur_interface);
void protocol_6lowpan_nd_borderrouter_connection_down(struct protocol_interface_info_entry *interface);
int8_t arm_6lowpan_mle_service_ready_for_security_init(protocol_interface_info_entry_t *cur);
int protocol_6lowpan_router_synch_to_new_router(struct protocol_interface_info_entry *cur, uint8_t *ll64, uint8_t incoming_idr, bool retrans);
void protocol_6lowpan_bootstrap(struct protocol_interface_info_entry *cur);
int protocol_6lowpan_del_ll16(struct protocol_interface_info_entry *cur, uint16_t mac_short_address);
int protocol_6lowpan_set_ll16(struct protocol_interface_info_entry *cur, uint16_t mac_short_address);
int8_t arm_6lowpan_bootstarp_bootstrap_set(int8_t interface_id, net_6lowpan_mode_e bootstrap_mode, net_6lowpan_mode_extension_e net_6lowpan_mode_extension);
struct mle_6lowpan_data *protocol_6lowpan_mle_data_get(void);
bool lowpan_neighbour_data_clean(int8_t interface_id, const uint8_t *link_local_address);
void arm_6lowpan_security_init_ifup(protocol_interface_info_entry_t *cur);
void protocol_6lowpan_mle_timer(uint16_t ticks_update);
#else
#define protocol_6lowpan_nd_border_router_address_get(nwk_id) NULL
#define arm_6lowpan_mle_service_ready_for_security_init(cur) -1
#define protocol_6lowpan_bootstrap(cur) ((void)0)
#define protocol_6lowpan_del_ll16(cur, mac_short_address) -1
#define protocol_6lowpan_set_ll16(cur, mac_short_address) -1
#define arm_6lowpan_bootstarp_bootstrap_set(interface_id, bootstrap_mode, net_6lowpan_mode_extension) -1
#define protocol_6lowpan_mle_data_get() NULL
#define arm_6lowpan_security_init_ifup(cur) ((void)0)
#define protocol_6lowpan_mle_timer(ticks_update) ((void)0)
#endif
void bootstrap_timer_handle(uint16_t ticks);
#endif /* PROTOCOL_6LOWPAN_BOOTSTRAP_H_ */

View File

@ -0,0 +1,35 @@
/*
* Copyright (c) 2015, 2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* \file protocol_6lowpan_interface.h
*
*/
#ifndef PROTOCOL_6LOWPAN_INTERFACE_H_
#define PROTOCOL_6LOWPAN_INTERFACE_H_
/**
* 6LoWPAN interface activate
*/
extern int8_t nwk_6lowpan_up(struct protocol_interface_info_entry *cur);
/**
* 6LoWPAN interface deactivate
*/
extern int8_t nwk_6lowpan_down(struct protocol_interface_info_entry *cur);
#endif /* PROTOCOL_6LOWPAN_INTERFACE_H_ */

View File

@ -0,0 +1,541 @@
/*
* Copyright (c) 2013-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
*
* \file cipv6_fragmenter.c
* \brief Packet Fragmentation and Reassembly.
*
*/
#include "nsconfig.h"
#include "ns_types.h"
#include "string.h"
#include "ns_trace.h"
#include "randLIB.h"
#include "Core/include/socket.h"
#include "6LoWPAN/IPHC_Decode/cipv6.h"
#include "6LoWPAN/Fragmentation/cipv6_fragmenter.h"
#include "NWK_INTERFACE/Include/protocol.h"
#include "nsdynmemLIB.h"
#include "6LoWPAN/Mesh/mesh.h"
#include "6LoWPAN/IPHC_Decode/iphc_decompress.h"
#include "nwk_stats_api.h"
#include "NWK_INTERFACE/Include/protocol_stats.h"
#include "common_functions.h"
#include "6LoWPAN/MAC/mac_helper.h"
#define TRACE_GROUP "6frg"
typedef struct {
uint16_t ttl; /*!< Reassembly timer (seconds) */
uint16_t tag; /*!< Fragmentation datagram TAG ID */
uint16_t size; /*!< Datagram Total Size (uncompressed) */
uint16_t orig_size; /*!< Datagram Original Size (compressed) */
uint16_t frag_max; /*!< Maximum fragment size (MAC payload) */
uint16_t offset; /*!< Data offset from datagram start */
int16_t pattern; /*!< Size of compressed LoWPAN headers */
buffer_t *buf;
ns_list_link_t link; /*!< List link entry */
} reassembly_entry_t;
typedef NS_LIST_HEAD(reassembly_entry_t, link) reassembly_list_t;
typedef struct {
int8_t interface_id;
uint16_t timeout;
reassembly_list_t rx_list;
reassembly_list_t free_list;
reassembly_entry_t *entry_pointer_buffer;
ns_list_link_t link; /*!< List link entry */
} reassembly_interface_t;
static NS_LIST_DEFINE(reassembly_interface_list, reassembly_interface_t, link);
/* Reassembly structures and helpers - basically the same as in
* ipv6_fragmentation.c, as we are also using a variation of RFC 815, but there
* are enough minor differences that it doesn't seem worth trying to share code.
*/
/* We reassemble into the datagram buffer in basically the style of RFC 815 */
/* An 6-byte hole descriptor is placed directly in buffer holes */
/* We link them them by buffer offset (relative to start of fragmentable section) */
/* Note the possible need to align means we can't use more than 7 bytes */
typedef struct hole {
uint16_t first;
uint16_t last;
uint16_t next;
} hole_t;
/* Given the offset of a hole in the datagram buffer, return an aligned pointer
* to put a hole_t in it. We assume a "normal" platform requiring 2-byte
* alignment for hole_t, and letting us manipulate uintptr_t in the conventional
* fashion.
*/
static hole_t *hole_pointer(const buffer_t *buf, uint16_t offset)
{
uintptr_t ptr = (uintptr_t)(buffer_data_pointer(buf) + offset);
return (hole_t *)((ptr + 1) & ~(uintptr_t) 1);
}
static void delete_hole(buffer_t *buf, uint16_t hole, uint16_t *prev_ptr)
{
hole_t *hole_ptr = hole_pointer(buf, hole);
*prev_ptr = hole_ptr->next;
}
static hole_t *create_hole(buffer_t *buf, uint16_t first, uint16_t last, uint16_t *prev_ptr)
{
hole_t *hole_ptr = hole_pointer(buf, first);
hole_ptr->first = first;
hole_ptr->last = last;
hole_ptr->next = *prev_ptr;
*prev_ptr = first;
return hole_ptr;
}
/*
* RFC 4944 is oddly designed - it has blurred the header compression
* and fragmentation layers. The datagram_size and datagram_offset field are
* specified in terms of the uncompressed IPv6 datagram, not the actual 6LoWPAN
* payload.
*
* This complicates reassembly if you don't decompress first; we don't because
* the original upper layer works on IPHC headers directly, rather than native
* IPv6.
*
* To handle the general case, including arbitrary fragment order so we don't
* always know the 6LoWPAN size of the first fragment, the reassembly buffer
* always leaves space for the uncompressed IPv6 header, and 1 byte more for a
* 6LoWPAN "uncompressed IPv6" dispatch byte. This means non-first fragments
* are always placed at buffer_data_pointer() + datagram_offset.
*
* This routine doesn't explicitly distinguish the compressed and uncompressed
* cases - the difference arises purely from the output of "iphc_header_scan",
* which sets "pattern" to the difference between IPv6 and 6LoWPAN size -
* but to aid understanding, here's what it ends up doing in the two cases:
*
* IPHC compressed case
* --------------------
*
* -4 0 0x50
* +---------+--------+--------+ 0x50 bytes of 6LoWPAN data
* | FRAG1 | IPHC | data1 | 0x70 bytes of uncompressed IPv6 data
* +---------+--------+--------+ "pattern" = 0x70 - 0x50 = 0x20
*
* -5 0 0x60 (datagram_size = 0xD0)
* +----------+-------------+
* |FRAGN 0x70| data2 |
* +----------+-------------+
*
* During assembly, the data pointer points at the "0" position representing the
* virtual start of the IPv6 packet:
*
* -1 0 0x20 0x70 0xD0
* +-+---------+--------+--------+-------------+
* | | padding | IPHC | data1 | data2 |
* +-+---------+--------+--------+-------------+
*
* On completion of assembly, the start pointer moves forward to point at the
* IPHC header. (This means buffer size is slightly inefficient for an IPHC
* upper layer, but it does reserve headroom for decompression to native IPv6.)
*
* -0x21 0 0x50 0xB0
* +-----------+--------+--------+-------------+
* | headroom | IPHC | data1 | data2 |
* +-----------+--------+--------+-------------+
* Uncompressed case
* -----------------
* -4 0 1 0x71 D = "Uncompressed IPv6" dispatch type 0x41
* +---------+-+--------------+ 0x71 bytes of 6LoWPAN data
* | FRAG1 |D| data1 | 0x70 bytes of uncompressed IPv6 data
* +---------+-+--------------+ "pattern" = 0x70 - 0x71 = -1
*
* -5 0 0x60 (datagram_size = 0xD0)
* +----------+---------------+
* |FRAGN 0x70| data2 |
* +----------+---------------+
*
* During assembly, the data pointer points at the "0" position representing the
* start of the IPv6 packet:
*
* -1 0 0x70 0xD0
* +-+--------------+---------------+
* |D| data1 | data2 |
* +-+--------------+---------------+
*
* On completion of assembly, the start pointer moves back to point to the
* 6LoWPAN dispatch byte:
*
* 0 1 0x71 0xD1
* +-+--------------+---------------+
* |D| data1 | data2 |
* +-+--------------+---------------+
* (And if it's neither of these cases, a "native" 6LoWPAN reassembly happens
* with "pattern" set to 0 - what probably should have happened in the first
* place; offsets are treated as 6LoWPAN offsets from the start of the
* fragmented 6LoWPAN data).
*/
//Discover
static reassembly_interface_t *reassembly_interface_discover(int8_t interfaceId)
{
ns_list_foreach(reassembly_interface_t, interface_ptr, &reassembly_interface_list) {
if (interfaceId == interface_ptr->interface_id) {
return interface_ptr;
}
}
return NULL;
}
static void reassembly_entry_free(reassembly_interface_t *interface_ptr, reassembly_entry_t *entry)
{
ns_list_remove(&interface_ptr->rx_list, entry);
ns_list_add_to_start(&interface_ptr->free_list, entry);
if (entry->buf) {
entry->buf = buffer_free(entry->buf);
}
}
static void reassembly_list_free(reassembly_interface_t *interface_ptr )
{
ns_list_foreach_safe(reassembly_entry_t, reassembly_entry, &interface_ptr->rx_list) {
reassembly_entry_free(interface_ptr, reassembly_entry);
}
}
static reassembly_entry_t *reassembly_already_action(reassembly_list_t *reassembly_list, buffer_t *buf, uint16_t tag, uint16_t size)
{
ns_list_foreach(reassembly_entry_t, reassembly_entry, reassembly_list) {
if ((reassembly_entry->tag == tag) && (reassembly_entry->size == size) &&
reassembly_entry->buf->src_sa.addr_type == buf->src_sa.addr_type &&
reassembly_entry->buf->dst_sa.addr_type == buf->dst_sa.addr_type) {
/* Type will be either long or short 802.15.4 - we skip the PAN ID */
if (memcmp(reassembly_entry->buf->src_sa.address + 2, buf->src_sa.address + 2, addr_len_from_type(buf->src_sa.addr_type) - 2) == 0 &&
memcmp(reassembly_entry->buf->dst_sa.address + 2, buf->dst_sa.address + 2, addr_len_from_type(buf->dst_sa.addr_type) - 2) == 0) {
return reassembly_entry;
}
}
}
return NULL;
}
static reassembly_entry_t *lowpan_adaptation_reassembly_get(reassembly_interface_t *interface_ptr)
{
reassembly_entry_t *entry = ns_list_get_first(&interface_ptr->free_list);
if (!entry) {
return NULL;
}
ns_list_remove(&interface_ptr->free_list, entry);
memset(entry, 0, sizeof(reassembly_entry_t));
//Add to first
ns_list_add_to_start(&interface_ptr->rx_list, entry);
return entry;
}
buffer_t *cipv6_frag_reassembly(int8_t interface_id, buffer_t *buf)
{
reassembly_interface_t *interface_ptr = reassembly_interface_discover(interface_id);
if (!interface_ptr) {
return buffer_free(buf);
}
uint16_t datagram_size, datagram_tag;
uint16_t fragment_first;
uint8_t frag_header;
uint8_t *ptr = buffer_data_pointer(buf);
frag_header = ptr[0];
datagram_size = common_read_16_bit(ptr) & 0x07FF;
if (datagram_size == 0) {
goto resassembly_error;
}
ptr += 2;
datagram_tag = common_read_16_bit(ptr);
ptr += 2;
if (frag_header & LOWPAN_FRAGN_BIT) {
fragment_first = *ptr++ << 3;
} else {
fragment_first = 0;
}
/* Consume the fragment header. We don't distinguish FRAG1/FRAGN after this
* point (we treat FRAGN with offset 0 the same as FRAG1)
*/
buffer_data_pointer_set(buf, ptr);
reassembly_entry_t *frag_ptr = reassembly_already_action(&interface_ptr->rx_list, buf, datagram_tag, datagram_size);
if (!frag_ptr) {
frag_ptr = lowpan_adaptation_reassembly_get(interface_ptr);
if (!frag_ptr) {
goto resassembly_error;
}
buffer_t *reassembly_buffer = buffer_get(1 + ((datagram_size+7) & ~7));
if (!reassembly_buffer) {
//Put allocated back to free
reassembly_entry_free(interface_ptr, frag_ptr);
goto resassembly_error;
}
// Allocate the reassembly buffer.
// Allow 1 byte extra for an "Uncompressed IPv6" dispatch byte - the
// 6LoWPAN data can be 1 byte longer than the IPv6 data.
// Also, round datagram size up to a multiple of 8 to ensure we have
// room for a final hole descriptor (it can spill past the indicated
// datagram size if the last fragment is smaller than 8 bytes).
reassembly_buffer->src_sa = buf->src_sa;
reassembly_buffer->dst_sa = buf->dst_sa;
frag_ptr->ttl = interface_ptr->timeout;
frag_ptr->tag = datagram_tag;
frag_ptr->size = datagram_size;
// Set buffer length and adjust start pointer, so it represents the
// uncompressed IPv6 packet. (See comment block before this function).
buffer_data_length_set(reassembly_buffer, 1 + datagram_size);
buffer_data_strip_header(reassembly_buffer, 1);
// Write initial hole descriptor into buffer
frag_ptr->offset = 0xffff;
create_hole(reassembly_buffer, 0, datagram_size - 1, &frag_ptr->offset);
frag_ptr->buf = reassembly_buffer;
}
/* For the first link fragment, work out and remember the "pattern"
* (difference between6LoWPAN and IPv6 size), and also copy the buffer
* header metadata.
*/
uint16_t lowpan_size, ipv6_size;
if (fragment_first == 0) {
uint16_t uncompressed_header_size;
uint8_t compressed_header_size;
compressed_header_size = iphc_header_scan(buf, &uncompressed_header_size);
lowpan_size = buffer_data_length(buf);
ipv6_size = lowpan_size - compressed_header_size + uncompressed_header_size;
frag_ptr->pattern = ipv6_size - lowpan_size;
/* Clone the buffer header from this first fragment, preserving only size + pointers */
/* Also the security flag - this fragment's flag is merged in later */
bool buf_security = frag_ptr->buf->options.ll_security_bypass_rx;
buffer_copy_metadata(frag_ptr->buf, buf, true);
frag_ptr->buf->options.ll_security_bypass_rx = buf_security;
} else {
ipv6_size = lowpan_size = buffer_data_length(buf);
}
uint16_t fragment_last = fragment_first + ipv6_size - 1;
if (fragment_last >= datagram_size) {
tr_err("Frag out-of-range: last=%u, size=%u", fragment_last, datagram_size);
//Free Current entry
reassembly_entry_free(interface_ptr, frag_ptr);
goto resassembly_error;
}
/* Hole-filling algorithm, basically as per RFC 815, but with added
* checks for overlap. The hole list is kept sorted, as per
* ipv6_fragmentation.c, but that's not relevant in this version.
*/
uint16_t hole_off = frag_ptr->offset;
uint16_t *prev_ptr = &frag_ptr->offset;
do {
hole_t *hole = hole_pointer(frag_ptr->buf, hole_off);
uint_fast16_t hole_first = hole->first;
uint_fast16_t hole_last = hole->last;
/* Fragment is beyond this hole - move to next (RFC 815 step 2) */
/* Fragment is before this hole - move to next (RFC 815 step 3) */
if (fragment_first > hole_last || fragment_last < hole_first) {
prev_ptr = &hole->next;
hole_off = hole->next;
continue;
}
/* If any of the fragment lies outside the hole, it indicates a problem;
* we only expect repeat data from retransmission, so fragments should
* always lie entirely within a hole or existing data, not straddle
* them. If we see this happen then junk existing data, making this the
* first fragment of a new reassembly (RFC 4944).
*/
if (fragment_first < hole_first || fragment_last > hole_last) {
tr_err("Frag overlap: hole %"PRIuFAST16"-%"PRIuFAST16", frag %"PRIu16"-%"PRIu16, hole_first, hole_last, fragment_first, fragment_last);
protocol_stats_update(STATS_FRAG_RX_ERROR, 1);
/* Forget previous data by marking as "all hole" */
frag_ptr->offset = 0xffff;
create_hole(frag_ptr->buf, hole_off = hole_first = 0, hole_last = datagram_size - 1, prev_ptr = &frag_ptr->offset);
}
/* Unhook this hole from the hole list (RFC 815 step 4) */
delete_hole(frag_ptr->buf, hole_off, prev_ptr);
/* Create a new hole in front if necessary (RFC 815 step 5) */
if (fragment_first > hole_first) {
prev_ptr = &create_hole(frag_ptr->buf, hole_first, fragment_first - 1, prev_ptr)->next;
}
/* Create a following hole if necessary (RFC 815 step 6) */
if (fragment_last < hole_last) {
create_hole(frag_ptr->buf, fragment_last + 1, hole_last, prev_ptr);
}
/* Unlike RFC 815, we're now done. We don't allow overlaps, so we finish
* as soon as we identify one hole that it entirely or partially fills */
break;
} while (hole_off != 0xffff);
/* Hole list updated, can now copy in the fragment data - to make sure the
* initial fragment goes in the right place we use the end offset, rather
* than the start offset. */
memcpy(buffer_data_pointer(frag_ptr->buf) + fragment_last + 1 - lowpan_size, buffer_data_pointer(buf), lowpan_size);
/* Combine the "improper security" flags, so reassembled buffer's flag is set if any fragment wasn't secure */
/* XXX should have some sort of overall "merge buffer metadata" routine handling this and whatever else */
frag_ptr->buf->options.ll_security_bypass_rx |= buf->options.ll_security_bypass_rx;
/* We've finished with the original fragment buffer */
buf = buffer_free(buf);
/* Completion check - any holes left? */
if (frag_ptr->offset != 0xffff) {
/* Not yet complete - processing finished on this fragment */
return NULL;
}
/* No more holes, so our reassembly is complete */
buf = frag_ptr->buf;
frag_ptr->buf = NULL;
reassembly_entry_free(interface_ptr, frag_ptr);
/* Buffer start pointer is currently at the "start of uncompressed IPv6
* packet" position. Move it either forwards or backwards to match
* the IPHC data (could be compressed, or uncompressed with added dispatch
* byte).
*/
buf->buf_ptr += frag_ptr->pattern;
buf->info = (buffer_info_t)(B_DIR_UP | B_FROM_FRAGMENTATION | B_TO_IPV6_TXRX);
return buf;
resassembly_error:
protocol_stats_update(STATS_FRAG_RX_ERROR, 1);
return buffer_free(buf);
}
static void reassembly_entry_timer_update(reassembly_interface_t *interface_ptr, uint16_t seconds)
{
ns_list_foreach_safe(reassembly_entry_t, reassembly_entry, &interface_ptr->rx_list) {
if (reassembly_entry->ttl > seconds) {
reassembly_entry->ttl -= seconds;
} else {
protocol_stats_update(STATS_FRAG_RX_ERROR, 1);
tr_debug("Reassembly TO: src %s size %u",
trace_sockaddr(&reassembly_entry->buf->src_sa, true),
reassembly_entry->size);
reassembly_entry_free(interface_ptr, reassembly_entry);
}
}
}
void cipv6_frag_timer(uint16_t seconds)
{
ns_list_foreach(reassembly_interface_t, interface_ptr, &reassembly_interface_list) {
reassembly_entry_timer_update(interface_ptr, seconds);
}
}
int8_t reassembly_interface_free(int8_t interface_id)
{
//Discover
reassembly_interface_t *interface_ptr = reassembly_interface_discover(interface_id);
if (!interface_ptr) {
return -1;
}
ns_list_remove(&reassembly_interface_list, interface_ptr);
//Free Dynamic allocated entry buffer
ns_dyn_mem_free(interface_ptr->entry_pointer_buffer);
ns_dyn_mem_free(interface_ptr);
return 0;
}
int8_t reassembly_interface_init(int8_t interface_id, uint8_t reassembly_session_limit, uint16_t reassembly_timeout)
{
if (!reassembly_session_limit || !reassembly_timeout) {
return -2;
}
//Remove old interface
reassembly_interface_free(interface_id);
//Allocate new
reassembly_interface_t *interface_ptr = ns_dyn_mem_alloc(sizeof(reassembly_interface_t));
reassembly_entry_t *reassemply_ptr = ns_dyn_mem_alloc(sizeof(reassembly_entry_t) * reassembly_session_limit);
if (!interface_ptr || !reassemply_ptr) {
ns_dyn_mem_free(interface_ptr);
ns_dyn_mem_free(reassemply_ptr);
return -1;
}
memset(interface_ptr, 0 ,sizeof(reassembly_interface_t));
interface_ptr->interface_id = interface_id;
interface_ptr->timeout = reassembly_timeout;
interface_ptr->entry_pointer_buffer = reassemply_ptr;
ns_list_init(&interface_ptr->free_list);
ns_list_init(&interface_ptr->rx_list);
for (uint8_t i=0; i<reassembly_session_limit ; i++) {
ns_list_add_to_end(&interface_ptr->free_list, reassemply_ptr);
reassemply_ptr++;
}
ns_list_add_to_end(&reassembly_interface_list, interface_ptr);
return 0;
}
int8_t reassembly_interface_reset(int8_t interface_id)
{
//Discover
reassembly_interface_t *interface_ptr = reassembly_interface_discover(interface_id);
if (!interface_ptr) {
return -1;
}
//Free Reaasembled queue
reassembly_list_free(interface_ptr);
return 0;
}

View File

@ -0,0 +1,30 @@
/*
* Copyright (c) 2013-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef CIPV6_FRAGMENTER_H
#define CIPV6_FRAGMENTER_H
struct buffer;
int8_t reassembly_interface_reset(int8_t interface_id);
int8_t reassembly_interface_init(int8_t interface_id, uint8_t reassembly_session_limit, uint16_t reassembly_timeout);
int8_t reassembly_interface_free(int8_t interface_id);
void cipv6_frag_timer(uint16_t seconds);
struct buffer *cipv6_frag_reassembly(int8_t interface_id, struct buffer *buf);
#endif

View File

@ -0,0 +1,253 @@
/*
* Copyright (c) 2013-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "nsconfig.h"
#define HAVE_CIPV6
#ifdef HAVE_CIPV6
#include "ns_types.h"
#include "string.h"
#include "ns_trace.h"
#include "Common_Protocols/ipv6.h"
#include "Common_Protocols/ipv6_resolution.h"
#include "6LoWPAN/IPHC_Decode/cipv6.h"
#include "NWK_INTERFACE/Include/protocol.h"
#include "ipv6_stack/protocol_ipv6.h"
#include "6LoWPAN/IPHC_Decode/iphc_compress.h"
#include "6LoWPAN/IPHC_Decode/iphc_decompress.h"
#include "6LoWPAN/Mesh/mesh.h"
#include "6LoWPAN/Thread/thread_common.h"
#include "6LoWPAN/MAC/mac_helper.h"
#include "MLE/mle.h"
#include "6LoWPAN/Bootstraps/protocol_6lowpan.h"
#include "nwk_stats_api.h"
#include "NWK_INTERFACE/Include/protocol_stats.h"
#include "common_functions.h"
#define TRACE_GROUP "iphc"
/* Input: Final IP packet for transmission on link.
* Buffer destination = final destination
* Buffer source undefined.
* Route next hop address set.
* Output: Buffer destination+source = link-layer addresses
* Sent to mesh, LowPAN fragmentation or MAC layers
*/
buffer_t *lowpan_down(buffer_t *buf)
{
protocol_interface_info_entry_t *cur = buf->interface;
buf->options.type = 0;
if (!buf->route) {
tr_debug("lowpan_down route");
return buffer_free(buf);
}
const uint8_t *ip_src = buffer_data_pointer(buf) + 8;
const uint8_t *next_hop = buf->route->route_info.next_hop_addr;
bool link_local = addr_is_ipv6_link_local(next_hop);
bool stable_only = false;
/* We have IP next hop - figure out the MAC address */
if (addr_is_ipv6_multicast(next_hop)) {
buf->dst_sa.addr_type = ADDR_BROADCAST;
common_write_16_bit(cur->mac_parameters->pan_id, buf->dst_sa.address);
buf->dst_sa.address[2] = 0x80 | (next_hop[14] & 0x1f);
buf->dst_sa.address[3] = next_hop[15];
stable_only = true;
} else { /* unicast */
ipv6_neighbour_t *n = ipv6_interface_resolve_new(cur, buf);
if (!n) {
return NULL;
}
if (thread_info(cur)) {
mle_neigh_table_entry_t *mle_entry;
mle_entry = mle_class_get_by_link_address(cur->id, buf->dst_sa.address + 2, buf->dst_sa.addr_type);
if (mle_entry && thread_addr_is_child(mac_helper_mac16_address_get(cur), mle_entry->short_adr)) {
/* Check if the child can handle only stable network data (e.g. sleepy device) */
stable_only = !(mle_entry->mode & MLE_THREAD_REQ_FULL_DATA_SET);
}
}
}
if (!buf->link_specific.ieee802_15_4.useDefaultPanId) {
/* Override dest PAN ID (from multicast map above, or neighbour cache) */
common_write_16_bit(buf->link_specific.ieee802_15_4.dstPanId, buf->dst_sa.address);
}
/* Figure out which source MAC address to use. Usually try to match the
* source, for best compression, and to ensure if the layer above uses LL64
* (like MLE), it forces us to use our MAC64.
*/
if (thread_info(cur) && !(link_local && thread_insist_that_mesh_isnt_a_link(cur)) && buf->dst_sa.addr_type == ADDR_802_15_4_SHORT) {
/* For Thread, we want to always use short source address for unicast
* to non-link-local 16-bit addresses, which is the case where we want
* to use mesh headers.
*/
buf->src_sa.addr_type = ADDR_802_15_4_SHORT;
} else if (addr_iid_matches_eui64(ip_src + 8, cur->mac)) {
buf->src_sa.addr_type = ADDR_802_15_4_LONG;
} else if (cur->mac_parameters->mac_short_address < 0xfffe && addr_iid_matches_lowpan_short(ip_src + 8, cur->mac_parameters->mac_short_address)) {
buf->src_sa.addr_type = ADDR_802_15_4_SHORT;
} else {
/* This lets mac_mlme_write_our_addr choose based on address mode */
buf->src_sa.addr_type = ADDR_NONE;
}
if (!mac_helper_write_our_addr(cur, &buf->src_sa)) {
return buffer_free(buf);
}
/* Clear Link Layer Re Transmission Counter */
//buf->fhss_channel_retries_left = 1+ cur->mac_parameters->number_of_fhss_channel_retries;
if (buf->dst_sa.addr_type != ADDR_802_15_4_LONG && buf->dst_sa.addr_type != ADDR_802_15_4_SHORT && buf->dst_sa.addr_type != ADDR_BROADCAST) {
tr_debug("IP:Dest Pro. addr_type: %02x", buf->dst_sa.addr_type);
return buffer_free(buf);
}
uint_fast8_t mesh_size;
if (link_local && thread_insist_that_mesh_isnt_a_link(cur)) {
mesh_size = 0;
} else {
/* Allow the link-layer destination addresses passed from upper layers
* to be remapped - used to implement Thread anycast.
*
* Mapping function can change address and type - if it returns false,
* packet is dropped.
*
* Note that this mapping has to be done before IPHC compression, which
* is why it moved from mesh.c.
*/
if (!mesh_address_map(cur, &buf->dst_sa.addr_type, buf->dst_sa.address)) {
tr_debug("mesh_address_map fail");
return buffer_free(buf);
}
/* After mapping, compute final mesh header size (which depends on
* the final address).
*/
mesh_size = mesh_header_size(buf);
}
if (mesh_size == 0) {
if (buf->dst_sa.addr_type == ADDR_BROADCAST) {
/* Thread says multicasts other than MLE are sent to our parent, if we're an end device */
if (cur->ip_multicast_as_mac_unicast_to_parent && !buf->options.ll_broadcast_tx) {
if (protocol_6lowpan_interface_get_mac_coordinator_address(cur, &buf->dst_sa) < 0) {
tr_warn("IP: No parent for multicast as unicast");
return buffer_free(buf);
}
} else {
/*
* Not using a mesh header, so have to "purify" RFC 4944 multicast - we
* set a 100xxxxxxxxxxxxx RFC 4944 multicast address above, but
* IEEE 802.15.4 only supports broadcast in the real MAC header.
*/
common_write_16_bit(0xFFFF, buf->dst_sa.address + 2);
}
}
}
/* RFC 6282+4944 require that we limit compression to the first fragment.
* This check is slightly conservative - always allow 4 for first-fragment header
*/
uint_fast8_t overhead = mac_helper_frame_overhead(cur, buf);
uint_fast16_t max_iphc_size = mac_helper_max_payload_size(cur, overhead) - mesh_size - 4;
buf = iphc_compress(&cur->lowpan_contexts, buf, max_iphc_size, stable_only);
if (!buf) {
return NULL;
}
if (mesh_size != 0) {
buf->info = (buffer_info_t)(B_FROM_IPV6_TXRX | B_TO_MESH_ROUTING | B_DIR_DOWN);
return buf;
}
buf->info = (buffer_info_t)(B_FROM_IPV6_TXRX | B_TO_MAC | B_DIR_DOWN);
return buf;
}
buffer_t *lowpan_up(buffer_t *buf)
{
protocol_interface_info_entry_t *cur = buf->interface;
/* Reject:
* Packets without address
* Source broadcast PAN ID
* Short source addresses 0xfffe (illegal) and 0xffff (broadcast)
*/
if (buf->dst_sa.addr_type == ADDR_NONE || buf->src_sa.addr_type == ADDR_NONE ||
common_read_16_bit(buf->src_sa.address) == 0xffff ||
(buf->dst_sa.addr_type == ADDR_802_15_4_SHORT && common_read_16_bit(buf->src_sa.address + 2) > 0xfffd)) {
goto drop;
}
/* If our PAN ID is set to 0xffff (eg during beacon scan), the MAC will be
* receiving all packets to all PANs. "Mute" 6LoWPAN reception in this state.
*/
if (cur->mac_parameters->pan_id == 0xffff) {
goto drop;
}
const uint8_t *ip_hc = buffer_data_pointer(buf);
//tr_debug("IP-UP";
if (buffer_data_length(buf) < 4 || addr_check_broadcast(buf->src_sa.address, buf->src_sa.addr_type) == 0) {
tr_debug("cipv6_up() Too short or broadcast src");
goto drop;
} else if ((ip_hc[0] & LOWPAN_FRAG_MASK) == LOWPAN_FRAG) {
/* 11 x00xxx: FRAG1/FRAGN (RFC 4944) */
buf->info = (buffer_info_t)(B_DIR_UP | B_FROM_IPV6_TXRX | B_TO_FRAGMENTATION);
return buf;
} else if ((ip_hc[0] & LOWPAN_MESH_MASK) == LOWPAN_MESH) {
/* 10 xxxxxx: MESH (RFC 4944) */
buf->info = (buffer_info_t)(B_DIR_UP | B_FROM_IPV6_TXRX | B_TO_MESH_ROUTING);
return buf;
} else if (ip_hc[0] == LOWPAN_DISPATCH_IPV6) {
/* Send this to new handler */
buffer_data_strip_header(buf, 1);
buf->ip_routed_up = true;
buf->info = (buffer_info_t)(B_DIR_UP | B_FROM_IPV6_TXRX | B_TO_IPV6_FWD);
return buf;
} else if ((ip_hc[0] & LOWPAN_DISPATCH_IPHC_MASK) != LOWPAN_DISPATCH_IPHC) {
/* Not handled: LOWPAN_HC1/LOWPAN_BC0/IPv6 (RFC 4944), or extension */
tr_debug("LOWPAN: %02x %02x", ip_hc[0], ip_hc[1]);
goto drop;
}
/* Divert to new routing system - in final system, MAC/Mesh/Frag should send to IPV6_TXRX layer */
buf->ip_routed_up = true;
buf = iphc_decompress(&cur->lowpan_contexts, buf);
if (buf) {
buf->info = (buffer_info_t)(B_DIR_UP | B_FROM_IPV6_TXRX | B_TO_IPV6_FWD);
}
return buf;
drop:
protocol_stats_update(STATS_IP_RX_DROP, 1);
return buffer_free(buf);
}
#endif /* HAVE_CIPV6 */

View File

@ -0,0 +1,184 @@
/*
* Copyright (c) 2013-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _CIPV6_H
#define _CIPV6_H
/* MTU defined in RFC 4944 */
#ifndef LOWPAN_MTU
#define LOWPAN_MTU 1280
#endif
/* The max MTU we'll obey from a Router Advertisement */
#ifndef LOWPAN_MAX_MTU
#define LOWPAN_MAX_MTU LOWPAN_HARD_MTU_LIMIT
#endif
/* The "physical" limit - due to the datagram_size field in the FRAG headers */
#ifndef LOWPAN_HARD_MTU_LIMIT
#define LOWPAN_HARD_MTU_LIMIT 2047
#endif
buffer_t *lowpan_up(buffer_t *buf);
buffer_t *lowpan_down(buffer_t *buf);
/* Bits in IPHC header, first byte (RFC 6282)
* 0 1
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
* | 0 | 1 | 1 | TF |NH | HLIM |CID|SAC| SAM | M |DAC| DAM |
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
*
*/
#define HC_LOWPAN_DISPATCH LOWPAN_DISPATCH_IPHC /* 0x60 */
#define HC_TF_MASK 0x18
#define HC_TF_ECN_DSCP_FLOW_LABEL 0x00
#define HC_TF_ECN_FLOW_LABEL 0x08
#define HC_TF_ECN_DSCP 0x10
#define HC_TF_ELIDED 0x18
#define HC_NEXT_HEADER_MASK 0x04
#define HC_HOP_LIMIT_MASK 0x03
#define HC_HOP_LIMIT_CARRIED_IN_LINE 0x00
#define HC_HOP_LIMIT_1 0x01
#define HC_HOP_LIMIT_64 0x02
#define HC_HOP_LIMIT_255 0x03
/* Bits in IPHC Dispatch header, second byte */
#define HC_CIDE_COMP 0x80
#define HC_SRCADR_COMP 0x40
#define HC_SRC_ADR_MODE_MASK 0x30
#define HC_SRC_ADR_128_BIT 0x00
#define HC_SRC_ADR_64_BIT 0x10
#define HC_SRC_ADR_16_BIT 0x20
#define HC_SRC_ADR_FROM_MAC 0x30
#define HC_MULTICAST_COMP 0x08
#define HC_DSTADR_COMP 0x04
#define HC_DST_ADR_MODE_MASK 0x03
#define HC_DST_ADR_128_BIT 0x00
#define HC_DST_ADR_64_BIT 0x01
#define HC_DST_ADR_16_BIT 0x02
#define HC_DST_ADR_FROM_MAC 0x03
#define HC_128BIT_MULTICAST 0x00
#define HC_48BIT_MULTICAST 0x01 //FFxx::xx:xxxx:xxxx
#define HC_32BIT_MULTICAST 0x02 //FFxx::xx:xxxx
#define HC_8BIT_MULTICAST 0x03 //FF02::xx
#define HC_48BIT_CONTEXT_MULTICAST 0x04 //FFxx:xxLL:PPPP:PPPP:PPPP:PPPP:xxxx:xxxx
/* 6LoWPAN Types
*
* Pattern Header Type
* +------------+-----------------------------------------------+
* | 00 xxxxxx | NALP - Not a LoWPAN frame |
* | 01 000000 | ESC - Additional Dispatch byte follows |
* | 01 000001 | IPv6 - Uncompressed IPv6 Addresses |
* | 01 000010 | LOWPAN_HC1 - LOWPAN_HC1 compressed IPv6 |
* | 01 000011 | LOWPAN_DFF - Depth-First Forwarding (RFC6971) |
* | 01 000100 | reserved - Reserved for future use |
* | ... | reserved - Reserved for future use |
* | 01 001111 | reserved - Reserved for future use |
* | 01 010000 | LOWPAN_BC0 - LOWPAN_BC0 broadcast |
* | 01 010001 | reserved - Reserved for future use |
* | ... | reserved - Reserved for future use |
* | 01 011111 | reserved - Reserved for future use |
* | 01 1xxxxx | LOWPAN_IPHC- RFC 6282 IPv6 Header Compression |
* | 10 xxxxxx | MESH - Mesh Header |
* | 11 000xxx | FRAG1 - Fragmentation Header (first) |
* | 11 001000 | reserved - Reserved for future use |
* | ... | reserved - Reserved for future use |
* | 11 011111 | reserved - Reserved for future use |
* | 11 100xxx | FRAGN - Fragmentation Header (subsequent)|
* | 11 101000 | reserved - Reserved for future use |
* | ... | reserved - Reserved for future use |
* | 11 111111 | reserved - Reserved for future use |
* +------------+-----------------------------------------------+
*
*/
#define LOWPAN_NALP 0x00 /* 00 xxxxxx Not LoWPAN */
#define LOWPAN_NALP_MASK 0xC0
#define LOWPAN_DISPATCH_ESC 0x40 /* RFC 6282 supercedes RFC 4944 */
#define LOWPAN_DISPATCH_IPV6 0x41
#define LOWPAN_DISPATCH_HC1 0x42
#define LOWPAN_DISPATCH_DFF 0x43 /* RFC 6971 */
#define LOWPAN_DISPATCH_BC0 0x50
#define LOWPAN_DISPATCH_IPHC 0x60 /* 01 1xxxxx IPHC */
#define LOWPAN_DISPATCH_IPHC_MASK 0xE0
#define LOWPAN_MESH 0x80 /* 10 xxxxxx MESH */
#define LOWPAN_MESH_MASK 0xC0
#define LOWPAN_FRAG1 0xC0 /* 11 000xxx FRAG1 */
#define LOWPAN_FRAG1_MASK 0xF8
#define LOWPAN_FRAGN 0xE0 /* 11 100xxx FRAGN */
#define LOWPAN_FRAGN_MASK 0xF8
#define LOWPAN_FRAGN_BIT 0x20 /* xx 1xxxxx distinguish FRAGN */
#define LOWPAN_FRAG 0xC0 /* 11 x00xxx FRAG1/FRAGN */
#define LOWPAN_FRAG_MASK 0xD8
/*
* 6LoWPAN Next Header Compression codes
*
* 00000000 to 11011111: (unassigned)
* 1110000N: IPv6 Hop-by-Hop Options Header [RFC6282]
* 1110001N: IPv6 Routing Header [RFC6282]
* 1110010N: IPv6 Fragment Header [RFC6282]
* 1110011N: IPv6 Destination Options Header [RFC6282]
* 1110100N: IPv6 Mobility Header [RFC6282]
* 1110111N: IPv6 Header [RFC6282]
* 11110CPP: UDP Header [RFC6282]
* 11111000 to 11111110: (unassigned)
*
* XXX cipv6_up() currently relies on IPv6 Next Header values and NHC codes
* being disjoint - it does not distinguish the two code spaces.
*/
#define NHC_EXT_HEADER 0xE0 /* 1110xxxx */
#define NHC_EXT_HEADER_MASK 0xF0
#define NHC_UDP 0xF0 /* 11110xxx */
#define NHC_UDP_MASK 0xF8
#define NHC_EXT_NH 0x01
#define NHC_EXT_ID_MASK 0xFE
#define NHC_EXT_HOP_BY_HOP 0xE0
#define NHC_EXT_ROUTING 0xE2
#define NHC_EXT_FRAG 0xE4
#define NHC_EXT_DEST_OPT 0xE6
#define NHC_EXT_MOBILITY 0xE8
#define NHC_EXT_IPV6 0xEE
/*
* RFC 6282
*
* 4.3.3. UDP LOWPAN_NHC Format
*
*
* 0 1 2 3 4 5 6 7
* +---+---+---+---+---+---+---+---+
* | 1 | 1 | 1 | 1 | 0 | C | P |
* +---+---+---+---+---+---+---+---+
*
* Figure 14: UDP Header Encoding
*/
#define NHC_UDP_PORT_COMPRESS_NONE 0
#define NHC_UDP_PORT_COMPRESS_DST 1
#define NHC_UDP_PORT_COMPRESS_SRC 2
#define NHC_UDP_PORT_COMPRESS_BOTH 3
#define NHC_UDP_PORT_COMPRESS_MASK 3
#define NHC_UDP_CKSUM_COMPRESS 4
#endif

View File

@ -0,0 +1,613 @@
/*
* Copyright (c) 2014-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "nsconfig.h"
#include "ns_list.h"
#include "common_functions.h"
#include "ns_trace.h"
#include "nsdynmemLIB.h"
#include <string.h>
#include "NWK_INTERFACE/Include/protocol.h"
#include "Common_Protocols/ipv6_constants.h"
#include "6LoWPAN/IPHC_Decode/cipv6.h"
#define TRACE_GROUP "iphc"
typedef struct iphc_compress_state {
const lowpan_context_list_t * const context_list;
const uint8_t *in;
uint8_t *out;
uint16_t len;
uint16_t out_space;
uint16_t consumed;
uint16_t produced;
const uint8_t *outer_src_iid;
const uint8_t *outer_dst_iid;
const bool stable_only;
} iphc_compress_state_t;
static bool compress_nh(uint8_t nh, iphc_compress_state_t *restrict cs);
static inline bool context_ok_for_compression(const lowpan_context_t *ctx, bool stable_only)
{
return ctx->lifetime && ctx->compression && (!stable_only || ctx->stable);
}
/* Using a specified context, what's the best possible compression of addr? */
static uint_fast8_t addr_bytes_needed(const uint8_t *addr, const uint8_t *outer_iid, const uint8_t *ctx_prefix, uint_fast8_t ctx_len)
{
/* Quick test: context always gets priority, so all of context must match */
/* This handles intrusions into IID space, so don't have to recheck this below */
if (!bitsequal(addr, ctx_prefix, ctx_len)) {
return 16;
}
/* Okay, potential match, but getting next bit optimal is more complex. */
/* Try each of 3 possible cases in turn */
uint8_t template[16];
/* 0-bit case: 64 bits of IID from outer header */
/* Template contains 0s, then outer IID, then context on top */
if (ctx_len < 64) {
memset(template, 0, 8);
}
if (ctx_len < 128) {
memcpy(template + 8, outer_iid, 8);
}
bitcopy(template, ctx_prefix, ctx_len);
if (addr_ipv6_equal(template, addr)) {
return 0;
}
/* 16-bit case: need to match top 14 bytes. Respell top 6 bytes of IID */
/* from last test to contain 0000:00ff:fe00, unless they're fully */
/* covered by context, in which case template already hold the correct */
/* context bytes */
if (ctx_len < 112) {
memcpy(template + 8, ADDR_SHORT_ADR_SUFFIC, 6);
if (ctx_len > 64) {
bitcopy(template + 8, ctx_prefix + 8, ctx_len - 64);
}
}
if (memcmp(template, addr, 14) == 0) {
return 2;
}
/* 64-bit case: only need to match top 8 bytes */
if (memcmp(template, addr, 8) == 0) {
return 8;
}
/* Had a matching context, but didn't match enough. Example:
* Context = 2002:db4::/32, Addr = 2002:db4:1::1
* Matches all 32 bits of context length, but not enough to compress 64-bit
*/
return 16;
}
static uint8_t compress_mc_addr(const lowpan_context_list_t *context_list, const uint8_t *addr, uint8_t *cmp_addr_out, uint8_t *context, uint8_t *mode, bool stable_only)
{
*mode |= HC_MULTICAST_COMP;
if (memcmp(addr, ADDR_LINK_LOCAL_ALL_NODES, 15) == 0) {
// ff02:0000:0000:0000:0000:0000:0000:00XX
cmp_addr_out[0] = addr[15];
*mode |= HC_8BIT_MULTICAST;
return 1;
}
if (memcmp(addr + 2, ADDR_LINK_LOCAL_ALL_NODES + 2, 11) == 0) {
// ffXX:0000:0000:0000:0000:0000:00XX:XXXX
cmp_addr_out[0] = addr[1];
cmp_addr_out[1] = addr[13];
cmp_addr_out[2] = addr[14];
cmp_addr_out[3] = addr[15];
*mode |= HC_32BIT_MULTICAST;
return 4;
}
if (memcmp(addr + 2, ADDR_LINK_LOCAL_ALL_NODES + 2, 9) == 0) {
// ffXX:0000:0000:0000:0000:00XX:XXXX:XXXX
cmp_addr_out[0] = addr[1];
memcpy(cmp_addr_out + 1, addr + 11, 5);
*mode |= HC_48BIT_MULTICAST;
return 6;
}
/* Looking for addresses of the form ffxx:xxLL:PPPP:PPPP:PPPP:PPPP:xxxx:xxxx */
/* Context info is padded with zeros, so the 8-byte memcmp is okay for short contexts. */
/* RFCs are ambiguous about how this should work if prefix length is > 64 bits, */
/* so don't attempt compression against long contexts. */
ns_list_foreach(lowpan_context_t, ctx, context_list) {
if (context_ok_for_compression(ctx, stable_only) &&
ctx->length <= 64 &&
addr[3] == ctx->length && memcmp(addr + 4, ctx->prefix, 8) == 0) {
cmp_addr_out[0] = addr[1];
cmp_addr_out[1] = addr[2];
memcpy(cmp_addr_out + 2, addr + 12, 4);
*context |= ctx->cid;
*mode |= HC_48BIT_CONTEXT_MULTICAST;
return 6;
}
}
memcpy(cmp_addr_out, addr, 16);
*mode |= HC_128BIT_MULTICAST;
return 16;
}
static uint8_t compress_addr(const lowpan_context_list_t *context_list, const uint8_t *addr, bool is_dst, const uint8_t *outer_iid, uint8_t *cmp_addr_out, uint8_t *context, uint8_t *mode, bool stable_only)
{
if (is_dst && addr[0] == 0xff) {
return compress_mc_addr(context_list, addr, cmp_addr_out, context, mode, stable_only);
}
uint_fast8_t best_bytes = addr_bytes_needed(addr, outer_iid, ADDR_LINK_LOCAL_PREFIX, 64);
lowpan_context_t *best_ctx = NULL;
bool checked_ctx0 = false;
if (best_bytes > 0) {
ns_list_foreach(lowpan_context_t, ctx, context_list) {
if (!context_ok_for_compression(ctx, stable_only)) {
continue;
}
uint_fast8_t bytes = addr_bytes_needed(addr, outer_iid, ctx->prefix, ctx->length);
if (ctx->cid == 0) {
checked_ctx0 = true;
}
/* This context is better if:
* a) it means fewer inline bytes, or
* b) it needs the same inline bytes and might avoid a CID extension
*/
if (bytes < best_bytes || (bytes == best_bytes && ctx->cid == 0 && best_ctx && best_ctx->cid != 0)) {
best_ctx = ctx;
best_bytes = bytes;
/* Don't need to check further if we've reached 0 bytes, and we've considered context 0 */
if (best_bytes == 0 && checked_ctx0) {
break;
}
}
}
}
/* If not found a 0-byte match, one more (unlikely) possibility for source - special case for "unspecified" */
if (best_bytes > 0 && !is_dst && addr_is_ipv6_unspecified(addr)) {
*mode |= HC_SRCADR_COMP | HC_SRC_ADR_128_BIT;
return 0;
}
uint8_t mode_bits;
uint8_t context_bits;
if (best_ctx) {
context_bits = best_ctx->cid;
mode_bits = HC_DSTADR_COMP;
} else {
context_bits = 0;
mode_bits = 0;
}
switch (best_bytes) {
default:
mode_bits |= HC_DST_ADR_128_BIT;
break;
case 8:
mode_bits |= HC_DST_ADR_64_BIT;
break;
case 2:
mode_bits |= HC_DST_ADR_16_BIT;
break;
case 0:
mode_bits |= HC_DST_ADR_FROM_MAC;
break;
}
/* Convert from IPHC DST bits to SRC bits */
if (!is_dst) {
mode_bits <<= 4;
context_bits <<= 4;
}
*mode |= mode_bits;
*context |= context_bits;
memcpy(cmp_addr_out, addr + (16 - best_bytes), best_bytes);
return best_bytes;
}
static bool compress_udp(iphc_compress_state_t *restrict cs)
{
if (cs->len < 8) {
return false;
}
/* UDP length should be set to payload length - if it's not, we can't compress it */
uint16_t udp_len = common_read_16_bit(cs->in + 4);
if (udp_len != cs->len) {
return false;
}
uint16_t src_port = common_read_16_bit(cs->in + 0);
uint16_t dst_port = common_read_16_bit(cs->in + 2);
uint8_t *ptr = cs->out;
if ((src_port & 0xfff0) == 0xf0b0 &&
(dst_port & 0xfff0) == 0xf0b0) {
if (cs->out_space < 4) {
return false;
}
*ptr++ = NHC_UDP | NHC_UDP_PORT_COMPRESS_BOTH;
*ptr++ = (src_port & 0xF) << 4 |
(dst_port & 0xF);
} else if ((src_port & 0xff00) == 0xf000) {
if (cs->out_space < 7) {
return false;
}
*ptr++ = NHC_UDP | NHC_UDP_PORT_COMPRESS_SRC;
*ptr++ = src_port & 0xff;
ptr = common_write_16_bit(dst_port, ptr);
} else if ((dst_port & 0xff00) == 0xf000) {
if (cs->out_space < 7) {
return false;
}
*ptr++ = NHC_UDP | NHC_UDP_PORT_COMPRESS_DST;
ptr = common_write_16_bit(src_port, ptr);
*ptr++ = dst_port & 0xff;
} else {
if (cs->out_space < 8) {
return false;
}
*ptr++ = NHC_UDP | NHC_UDP_PORT_COMPRESS_NONE;
ptr = common_write_16_bit(src_port, ptr);
ptr = common_write_16_bit(dst_port, ptr);
}
/* Checksum */
*ptr++ = cs->in[6];
*ptr++ = cs->in[7];
uint_fast8_t outlen = ptr - cs->out;
cs->consumed += 8;
cs->in += 8;
cs->len -= 8;
cs->out_space -= outlen;
cs->out += outlen;
cs->produced += outlen;
return true;
}
static bool compress_exthdr(uint8_t nhc, iphc_compress_state_t *restrict cs)
{
if (cs->len < 8) {
return false;
}
const uint8_t *in = cs->in;
uint8_t nh = in[0];
uint16_t hdrlen;
if (nhc == NHC_EXT_FRAG) {
/* For fragment header, seems sensible to only handle first fragment;
* "Next header" field doesn't describe following data otherwise.
* Could still "compress" this header in all cases, but no point if we don't
* have following headers to compress - it takes 8 bytes either way.
*/
uint16_t offset = common_read_16_bit(in + 2) & 0xFFF8;
if (offset != 0) {
return false;
}
/* Second byte is reserved; it's not a length byte */
hdrlen = 8;
} else {
hdrlen = (in[1] + 1) * 8;
}
if (hdrlen > cs->len || hdrlen >= 256) {
return false;
}
/* If Options are well-formed, parse and remove final option if it's padding */
uint8_t hc_bytes = hdrlen;
if (nhc == NHC_EXT_DEST_OPT || nhc == NHC_EXT_HOP_BY_HOP) {
const uint8_t *opt = in + 2, *lastopt = opt;
uint8_t optrem = hdrlen - 2;
while (optrem) {
lastopt = opt;
if (opt[0] == IPV6_OPTION_PAD1) {
opt++;
optrem--;
continue;
}
if (optrem < 2 || optrem < 2 + opt[1]) {
lastopt = NULL;
break;
}
optrem -= 2 + opt[1];
opt += 2 + opt[1];
}
if (lastopt && (lastopt[0] == IPV6_OPTION_PAD1 || lastopt[0] == IPV6_OPTION_PADN)) {
hc_bytes = lastopt - in;
}
}
/* Include one for "next header" - we will either need this ourselves, or
* the next hdr will*/
if (cs->out_space < hc_bytes + 1) {
return false;
}
uint8_t *out = cs->out;
cs->in += hdrlen;
cs->len -= hdrlen;
cs->consumed += hdrlen;
cs->out += hc_bytes;
cs->out_space -= hc_bytes;
cs->produced += hc_bytes;
out[0] = nhc;
if (compress_nh(nh, cs)) {
out[0] |= NHC_EXT_NH;
}
uint8_t *ptr = out + 1;
if (!(out[0] & NHC_EXT_NH)) {
*ptr++ = nh;
cs->out++;
cs->out_space--;
cs->produced++;
}
if (nhc == NHC_EXT_FRAG) {
*ptr++ = in[1];
} else {
*ptr++ = hc_bytes - 2;
}
memcpy(ptr, in + 2, hc_bytes - 2);
return true;
}
static bool compress_ipv6(iphc_compress_state_t *restrict cs, bool from_nhc)
{
const uint8_t *const in = cs->in;
uint8_t *const out = cs->out;
/* Need at least 2 plus 1 for next header field or following NHC byte */
/* plus another 1 if coming from NHC (for NHC_EXT_IPV6 byte) */
if (cs->out_space < from_nhc + 3) {
return false;
}
if (cs->len < 40 || (in[0] & 0xF0) != 0x60) {
tr_debug("Not IPv6");
return false;
}
uint8_t iphc[2] = { LOWPAN_DISPATCH_IPHC, 0 };
uint_fast8_t iphc_bytes = from_nhc + 2;
/* Payload length field must match, or we can't compress */
if (common_read_16_bit(in + 4) != cs->len - 40) {
return false;
}
/* Compress addresses, get context byte */
uint8_t cid = 0;
uint8_t cmp_src[16], cmp_dst[16], cmp_src_len, cmp_dst_len;
cmp_src_len = compress_addr(cs->context_list, in + 8, false, cs->outer_src_iid, cmp_src, &cid, &iphc[1], cs->stable_only);
cmp_dst_len = compress_addr(cs->context_list, in + 24, true, cs->outer_dst_iid, cmp_dst, &cid, &iphc[1], cs->stable_only);
iphc_bytes += cmp_src_len + cmp_dst_len;
if (cid != 0) {
iphc_bytes += 1;
iphc[1] |= HC_CIDE_COMP;
}
/* Compress Hop Limit */
switch (cs->in[7]) {
case 255:
iphc[0] |= HC_HOP_LIMIT_255;
break;
case 64:
iphc[0] |= HC_HOP_LIMIT_64;
break;
case 1:
iphc[0] |= HC_HOP_LIMIT_1;
break;
default:
iphc[0] |= HC_HOP_LIMIT_CARRIED_IN_LINE;
iphc_bytes += 1;
break;
}
uint8_t ecn = (in[1] & 0x30) << 2;
uint8_t dscp = (in[0] & 0x0F) << 2 | (in[1] & 0xC0) >> 6;
uint_fast24_t flow = common_read_24_bit(in + 1) & 0xFFFFF;
if (flow == 0 && ecn == 0 && dscp == 0) {
iphc[0] |= HC_TF_ELIDED;
} else if (flow == 0) {
iphc[0] |= HC_TF_ECN_DSCP;
iphc_bytes += 1;
} else if (dscp == 0) {
iphc[0] |= HC_TF_ECN_FLOW_LABEL;
flow |= (uint_fast24_t) ecn << 16;
iphc_bytes += 3;
} else {
iphc[0] |= HC_TF_ECN_DSCP_FLOW_LABEL;
iphc_bytes += 4;
}
/* Include one for "next header" - we will either need this ourselves, or
* the next H will*/
if (cs->out_space < iphc_bytes + 1) {
return false;
}
/* Update state for next header */
cs->in += 40;
cs->len -= 40;
cs->consumed += 40;
cs->out += iphc_bytes;
cs->out_space -= iphc_bytes;
cs->produced += iphc_bytes;
cs->outer_src_iid = in + 16;
cs->outer_dst_iid = in + 32;
/* Check if next header can be compressed - potentially recursing */
if (compress_nh(in[6], cs)) {
iphc[0] |= HC_NEXT_HEADER_MASK;
} else {
/* We produce one more byte for Next Header */
iphc_bytes++;
cs->out++;
cs->out_space--;
cs->produced++;
}
uint8_t *ptr = out;
if (from_nhc) {
*ptr++ = NHC_EXT_IPV6;
}
*ptr++ = iphc[0];
*ptr++ = iphc[1];
if (cid != 0) {
*ptr++ = cid;
}
if ((iphc[0] & HC_TF_MASK) == HC_TF_ECN_DSCP_FLOW_LABEL || (iphc[0] & HC_TF_MASK) == HC_TF_ECN_DSCP) {
*ptr++ = (ecn | dscp);
}
if ((iphc[0] & HC_TF_MASK) == HC_TF_ECN_DSCP_FLOW_LABEL || (iphc[0] & HC_TF_MASK) == HC_TF_ECN_FLOW_LABEL) {
ptr = common_write_24_bit(flow, ptr); // "flow" includes ecn in 3-byte case
}
if (!(iphc[0] & HC_NEXT_HEADER_MASK)) {
*ptr++ = in[6];
}
if ((iphc[0] & HC_HOP_LIMIT_MASK) == HC_HOP_LIMIT_CARRIED_IN_LINE) {
*ptr++ = in[7];
}
ptr = (uint8_t *) memcpy(ptr, cmp_src, cmp_src_len) + cmp_src_len;
ptr = (uint8_t *) memcpy(ptr, cmp_dst, cmp_dst_len) + cmp_dst_len;
if (ptr != out + iphc_bytes) {
tr_debug("iphc error");
}
return true;
}
static bool compress_nh(uint8_t nh, iphc_compress_state_t *restrict cs)
{
switch (nh) {
uint8_t nhc;
case IPV6_NH_HOP_BY_HOP:
nhc = NHC_EXT_HOP_BY_HOP;
goto ext_hdr;
case IPV6_NH_ROUTING:
nhc = NHC_EXT_ROUTING;
goto ext_hdr;
case IPV6_NH_FRAGMENT:
nhc = NHC_EXT_FRAG;
goto ext_hdr;
case IPV6_NH_DEST_OPT:
nhc = NHC_EXT_DEST_OPT;
goto ext_hdr;
case IPV6_NH_MOBILITY:
nhc = NHC_EXT_MOBILITY;
ext_hdr:
return compress_exthdr(nhc, cs);
/* no break */
case IPV6_NH_IPV6:
return compress_ipv6(cs, true);
case IPV6_NH_UDP:
return compress_udp(cs);
default:
return false;
}
}
/* Input: An IPv6 frame, with outer layer 802.15.4 MAC (or IP) addresses in src+dst */
/* Output: 6LoWPAN frame - usually compressed. */
buffer_t *iphc_compress(const lowpan_context_list_t *context_list, buffer_t *buf, uint16_t hc_space, bool stable_only)
{
uint8_t *ptr = buffer_data_pointer(buf);
uint16_t len = buffer_data_length(buf);
uint8_t src_iid[8], dst_iid[8];
if (len < 40 || (ptr[0] & 0xF0) != 0x60) {
tr_debug("Not IPv6");
return buffer_free(buf);
}
/* No point allocating excessively */
if (hc_space > len) {
hc_space = len;
}
/* TODO: Could actually do it in-place with more care, working backwards
* in each header.
*/
uint8_t *hc_out = ns_dyn_mem_temporary_alloc(hc_space);
if (!hc_out) {
tr_debug("No mem");
return buffer_free(buf);
}
if (!addr_iid_from_outer(src_iid, &buf->src_sa) || !addr_iid_from_outer(dst_iid, &buf->dst_sa)) {
tr_debug("Bad outer addr");
ns_dyn_mem_free(hc_out);
return buffer_free(buf);
}
iphc_compress_state_t cs = {
.context_list = context_list,
.in = ptr,
.len = len,
.out = hc_out,
.out_space = hc_space,
.consumed = 0,
.produced = 0,
.outer_src_iid = src_iid,
.outer_dst_iid = dst_iid,
.stable_only = stable_only
};
if (!compress_ipv6(&cs, false) || cs.produced > cs.consumed) {
/* Compression failed, or made it bigger somehow (impossible?) */
/* Fall back to uncompressed, which means adding a dispatch byte */
buf = buffer_headroom(buf, 1);
if (buf) {
ptr = buffer_data_reserve_header(buf, 1);
*ptr = LOWPAN_DISPATCH_IPV6;
}
ns_dyn_mem_free(hc_out);
return buf;
}
buffer_data_strip_header(buf, cs.consumed);
buffer_data_reserve_header(buf, cs.produced);
/* XXX see note above - should be able to improve this to avoid the temp buffer */
memcpy(buffer_data_pointer(buf), hc_out, cs.produced);
ns_dyn_mem_free(hc_out);
return buf;
}

View File

@ -0,0 +1,22 @@
/*
* Copyright (c) 2014-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef IPHC_COMPRESS_H_
#define IPHC_COMPRESS_H_
buffer_t *iphc_compress(const lowpan_context_list_t *context_list, buffer_t *buf, uint16_t hc_space, bool stable_only);
#endif /* IPHC_COMPRESS_H_ */

View File

@ -0,0 +1,613 @@
/*
* Copyright (c) 2014-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "nsconfig.h"
#include "ns_trace.h"
#include "common_functions.h"
#include "nsdynmemLIB.h"
#include <string.h>
#include "NWK_INTERFACE/Include/protocol.h"
#include "6LoWPAN/IPHC_Decode/cipv6.h"
#include "Common_Protocols/ipv6_constants.h"
#include "6LoWPAN/IPHC_Decode/iphc_decompress.h"
#define TRACE_GROUP "iphc"
/* Analyse a 6LoWPAN datagram for fragmentation, checking header length */
/* Critical fact is that fragments are described with their size+offsets in */
/* terms of the UNCOMPRESSED IP datagram, so when presented with a 6LoWPAN datagram, */
/* we need to work backwards. Another constraint is that compressed headers */
/* must all lie within the first fragment - doesn't concern us here. */
/* Input: a potentially oversized 6LoWPAN-format datagram without fragmentation */
/* Return: size of compressed IPHC headers */
/* Output: uncompressed_size = uncompressed size of IPHC headers */
uint16_t iphc_header_scan(buffer_t *buf, uint16_t *uncompressed_size)
{
const uint8_t *ptr = buffer_data_pointer(buf);
const uint8_t *end = buffer_data_end(buf);
uint16_t uncomp_len = 0;
const uint8_t *ip_hc;
*uncompressed_size = 0;
/* Fragmentation needs us to handle uncompressed case */
if (ptr < end && ptr[0] == LOWPAN_DISPATCH_IPV6) {
return 1;
}
/* Handle compressed IP header (LOWPAN_IPHC) - LOWPAN_HC1 etc not handled */
IPv6START:
ip_hc = ptr;
ptr += 2;
uncomp_len += 40;
if (ptr > end) {
goto truncated;
}
if ((ip_hc[0] & LOWPAN_DISPATCH_IPHC_MASK) != LOWPAN_DISPATCH_IPHC) {
tr_warn("Unexpected 6LoWPAN ID");
return 0;
}
if (ip_hc[1] & HC_CIDE_COMP) {
ptr++;
}
switch (ip_hc[0] & HC_TF_MASK) {
case HC_TF_ECN_DSCP_FLOW_LABEL:
ptr += 4;
break;
case HC_TF_ECN_FLOW_LABEL:
ptr += 3;
break;
case HC_TF_ECN_DSCP:
ptr += 1;
break;
default:
break;
}
if (!(ip_hc[0] & HC_NEXT_HEADER_MASK)) {
ptr++;
}
if ((ip_hc[0] & HC_HOP_LIMIT_MASK) == HC_HOP_LIMIT_CARRIED_IN_LINE) {
ptr++;
}
switch (ip_hc[1] & HC_SRC_ADR_MODE_MASK) {
case HC_SRC_ADR_128_BIT:
if (!(ip_hc[1] & HC_SRCADR_COMP)) {
ptr += 16;
}
break;
case HC_SRC_ADR_64_BIT:
ptr += 8;
break;
case HC_SRC_ADR_16_BIT:
ptr += 2;
break;
case HC_SRC_ADR_FROM_MAC:
break;
}
if (ip_hc[1] & HC_MULTICAST_COMP) {
switch (ip_hc[1] & (HC_DSTADR_COMP | HC_DST_ADR_MODE_MASK)) {
case HC_128BIT_MULTICAST:
ptr += 16;
break;
case HC_48BIT_MULTICAST:
case HC_48BIT_CONTEXT_MULTICAST:
ptr += 6;
break;
case HC_32BIT_MULTICAST:
ptr += 4;
break;
case HC_8BIT_MULTICAST:
ptr += 1;
break;
default:
tr_warn("Unknown multicast compression");
return 0;
}
} else {
switch (ip_hc[1] & HC_DST_ADR_MODE_MASK) {
case HC_DST_ADR_128_BIT:
ptr += 16;
break;
case HC_DST_ADR_64_BIT:
ptr += 8;
break;
case HC_DST_ADR_16_BIT:
ptr += 2;
break;
case HC_DST_ADR_FROM_MAC:
break;
}
}
/* Handle following headers (LOWPAN_NHC) */
bool nhc_next_header = ip_hc[0] & HC_NEXT_HEADER_MASK;
while (nhc_next_header) {
uint8_t nhc_id;
if (ptr >= end) {
goto truncated;
}
nhc_id = *ptr++;
//tr_debug("IPNH: %02x", next_header);
if ((nhc_id & NHC_EXT_HEADER_MASK) == NHC_EXT_HEADER) {
uint8_t len = 0;
switch (nhc_id & NHC_EXT_ID_MASK) {
case NHC_EXT_IPV6:
goto IPv6START;
case NHC_EXT_HOP_BY_HOP:
case NHC_EXT_ROUTING:
case NHC_EXT_FRAG:
case NHC_EXT_DEST_OPT:
case NHC_EXT_MOBILITY:
nhc_next_header = nhc_id & NHC_EXT_NH;
if (!nhc_next_header) {
ptr++;
}
if (ptr >= end) {
goto truncated;
}
if ((nhc_id & NHC_EXT_ID_MASK) == NHC_EXT_FRAG) {
/* See notes in main decompress routine */
ptr += 7;
uncomp_len += 8;
} else {
len = *ptr++;
/* len is length of following data in bytes */
ptr += len;
/* Uncompressed headers must be multiple of 8 octets, so
* uncompressed length is 2+len ("NH" + "len" + data),
* rounded up to a multiple of 8.
*/
uncomp_len += ((2 + len) + 7) & ~ 7;
}
break;
default:
goto bad_nhc_id;
}
} else if ((nhc_id & NHC_UDP_MASK) == NHC_UDP) {
uncomp_len += 8;
nhc_next_header = false;
if (!(nhc_id & NHC_UDP_CKSUM_COMPRESS)) {
ptr += 2;
}
switch (nhc_id & NHC_UDP_PORT_COMPRESS_MASK) {
case NHC_UDP_PORT_COMPRESS_DST:
case NHC_UDP_PORT_COMPRESS_SRC:
ptr += 3;
break;
case NHC_UDP_PORT_COMPRESS_NONE:
ptr += 4;
break;
case NHC_UDP_PORT_COMPRESS_BOTH:
default:
ptr += 1;
break;
}
} else {
bad_nhc_id:
tr_warn("Unknown NHC ID: %02x", nhc_id);
nhc_next_header = false;
}
}
if (ptr > end) {
truncated:
tr_warn("Truncated packet");
return 0;
}
*uncompressed_size = uncomp_len;
return ptr - buffer_data_pointer(buf);
}
static bool decompress_mc_addr(const lowpan_context_list_t *context_list, uint8_t *addr, const uint8_t **in_ptr, const uint8_t *outer_iid, uint8_t context, uint8_t mode)
{
const uint8_t *in = *in_ptr;
(void) outer_iid;
switch (mode) {
case HC_128BIT_MULTICAST:
memcpy(addr, in, 16);
*in_ptr = in + 16;
return true;
case HC_48BIT_MULTICAST:
addr[0] = 0xff;
addr[1] = *in++;
memset(&addr[2], 0, 9);
memcpy(&addr[11], in, 5);
*in_ptr = in + 5;
return true;
case HC_32BIT_MULTICAST:
addr[0] = 0xff;
addr[1] = *in++;
memset(&addr[2], 0, 11);
memcpy(&addr[13], in, 3);
*in_ptr = in + 3;
return true;
case HC_8BIT_MULTICAST:
memcpy(addr, ADDR_LINK_LOCAL_ALL_NODES, 15);
addr[15] = *in++;
*in_ptr = in;
return true;
case HC_48BIT_CONTEXT_MULTICAST: {
lowpan_context_t *ctx = lowpan_contex_get_by_id(context_list, context);
if (!ctx) {
return false;
}
addr[0] = 0xff;
addr[1] = *in++;
addr[2] = *in++;
addr[3] = ctx->length;
memcpy(&addr[4], ctx->prefix, 8);
memcpy(&addr[12], in, 4);
*in_ptr = in + 4;
return true;
}
default:
return false;
}
}
static bool decompress_addr(const lowpan_context_list_t *context_list, uint8_t *addr, const uint8_t **in_ptr, bool is_dst, const uint8_t *outer_iid, uint8_t context, uint8_t mode)
{
if (!is_dst) {
/* Get SRC bits and move into DST position, without multicast bit */
mode = (mode >> 4) & (HC_DSTADR_COMP | HC_DST_ADR_MODE_MASK);
context >>= 4;
} else {
mode &= (HC_MULTICAST_COMP | HC_DSTADR_COMP | HC_DST_ADR_MODE_MASK);
context &= 0xf;
}
if (mode & HC_MULTICAST_COMP) {
return decompress_mc_addr(context_list, addr, in_ptr, outer_iid, context, mode & ~ HC_MULTICAST_COMP);
}
switch (mode & HC_DST_ADR_MODE_MASK) {
case HC_DST_ADR_128_BIT:
if (mode & HC_DSTADR_COMP) {
/* Special case - different for src and dst */
if (is_dst) {
return false;
} else {
memset(addr, 0, 16); // unspecified (::)
return true;
}
}
memcpy(addr, *in_ptr, 16);
*in_ptr += 16;
return true;
case HC_DST_ADR_64_BIT:
memcpy(addr + 8, *in_ptr, 8);
*in_ptr += 8;
break;
case HC_DST_ADR_16_BIT:
memcpy(addr + 8, ADDR_SHORT_ADR_SUFFIC, 6);
addr[14] = (*in_ptr)[0];
addr[15] = (*in_ptr)[1];
*in_ptr += 2;
break;
case HC_DST_ADR_FROM_MAC:
memcpy(addr + 8, outer_iid, 8);
break;
}
if (mode & HC_DSTADR_COMP) {
lowpan_context_t *ctx = lowpan_contex_get_by_id(context_list, context);
if (!ctx) {
return false;
}
/* Copy a minimum of 64 bits to get required zero fill up to IID -
* we rely on the context storage core having zero-padding in
* the prefix field for short contexts.
*/
bitcopy(addr, ctx->prefix, ctx->length < 64 ? 64 : ctx->length);
return true;
} else {
memcpy(addr, ADDR_LINK_LOCAL_PREFIX, 8);
return true;
}
}
typedef struct iphc_decompress_state {
const lowpan_context_list_t * const context_list;
const uint8_t *in;
const uint8_t *const end;
uint8_t *out;
uint8_t *nh_ptr;
const uint8_t *outer_src_iid;
const uint8_t *outer_dst_iid;
} iphc_decompress_state_t;
static bool decompress_ipv6(iphc_decompress_state_t *restrict ds)
{
const uint8_t *iphc = ds->in;
ds->in += 2;
uint8_t cid;
if (iphc[1] & HC_CIDE_COMP) {
cid = *ds->in++;
} else {
cid = 0;
}
/* First, Traffic Class and Flow Label */
uint8_t tc = 0;
uint8_t tf = iphc[0] & HC_TF_MASK;
/* Extract ECN */
if (tf != HC_TF_ELIDED) {
tc = *ds->in >> 6;
}
/* Extract DSCP */
if (tf == HC_TF_ECN_DSCP || tf == HC_TF_ECN_DSCP_FLOW_LABEL) {
tc |= *ds->in++ << 2;
}
*ds->out++ = 0x60 | (tc >> 4);
if (tf == HC_TF_ECN_FLOW_LABEL || tf == HC_TF_ECN_DSCP_FLOW_LABEL) {
*ds->out++ = (tc << 4) | (*ds->in++ & 0x0f);
*ds->out++ = *ds->in++;
*ds->out++ = *ds->in++;
} else {
*ds->out++ = tc << 4;
*ds->out++ = 0;
*ds->out++ = 0;
}
/* Compute payload length */
ds->out = common_write_16_bit(ds->end - (ds->out + 36), ds->out);
/* Next Header */
if (iphc[0] & HC_NEXT_HEADER_MASK) {
/* Reserve space for Next Header - will be filled later */
ds->nh_ptr = ds->out;
*ds->out++ = IPV6_NH_NONE;
} else {
ds->nh_ptr = NULL;
*ds->out++ = *ds->in++;
}
/* Hop Limit */
switch (iphc[0] & HC_HOP_LIMIT_MASK) {
case HC_HOP_LIMIT_1:
*ds->out++ = 1;
break;
case HC_HOP_LIMIT_64:
*ds->out++ = 64;
break;
case HC_HOP_LIMIT_255:
*ds->out++ = 255;
break;
case HC_HOP_LIMIT_CARRIED_IN_LINE:
default:
*ds->out++ = *ds->in++;
break;
}
if (!decompress_addr(ds->context_list, ds->out, &ds->in, false, ds->outer_src_iid, cid, iphc[1])) {
tr_warn("SRC Address decompress fail");
return false;
}
ds->outer_src_iid = ds->out + 8;
ds->out += 16;
if (!decompress_addr(ds->context_list, ds->out, &ds->in, true, ds->outer_dst_iid, cid, iphc[1])) {
tr_warn("DST Address decompress fail");
return false;
}
ds->outer_dst_iid = ds->out + 8;
ds->out += 16;
return true;
}
static bool decompress_exthdr(iphc_decompress_state_t *ds)
{
uint8_t nh;
switch (*ds->in & NHC_EXT_ID_MASK) {
case NHC_EXT_HOP_BY_HOP:
nh = IPV6_NH_HOP_BY_HOP;
break;
case NHC_EXT_ROUTING:
nh = IPV6_NH_ROUTING;
break;
case NHC_EXT_FRAG:
nh = IPV6_NH_FRAGMENT;
break;
case NHC_EXT_DEST_OPT:
nh = IPV6_NH_DEST_OPT;
break;
case NHC_EXT_MOBILITY:
nh = IPV6_NH_MOBILITY;
break;
case NHC_EXT_IPV6:
*ds->nh_ptr = IPV6_NH_IPV6;
ds->in++;
return decompress_ipv6(ds);
default:
return false;
}
*ds->nh_ptr = nh;
if (*ds->in++ & NHC_EXT_NH) {
/* Reserve space for Next Header - will be filled later */
ds->nh_ptr = ds->out;
*ds->out++ = IPV6_NH_NONE;
} else {
ds->nh_ptr = NULL;
*ds->out++ = *ds->in++;
}
uint8_t clen;
if (nh == IPV6_NH_FRAGMENT) {
/* Fragmentation header is awkward, and RFC 6282 isn't terribly clear */
/* Second byte is reserved. It isn't a length field. */
*ds->out++ = *ds->in++;
clen = 6;
} else {
clen = *ds->in++; /* Compressed data len */
*ds->out++ = (clen + 2 - 1) >> 3; /* Uncompressed header length byte (8-octet units, excluding first) */
}
/* Copy main option data */
memcpy(ds->out, ds->in, clen);
ds->out += clen;
ds->in += clen;
/* If not aligned, add a PAD1 or PADN */
if ((clen + 2) & 7) {
uint8_t pad = 8 - ((clen + 2) & 7);
if (pad == 1) {
*ds->out++ = IPV6_OPTION_PAD1;
} else {
*ds->out++ = IPV6_OPTION_PADN;
*ds->out++ = (pad -= 2);
while (pad) {
*ds->out++ = 0, pad--;
}
}
}
return true;
}
static bool decompress_udp(iphc_decompress_state_t *ds)
{
uint8_t nhc = *ds->in++;
/* Ports */
if ((nhc & NHC_UDP_PORT_COMPRESS_MASK) == NHC_UDP_PORT_COMPRESS_BOTH) {
*ds->out++ = 0xf0;
*ds->out++ = 0xb0 | (*ds->in >> 4);
*ds->out++ = 0xf0;
*ds->out++ = 0xb0 | (*ds->in++ & 0x0f);
} else {
*ds->out++ = (nhc & NHC_UDP_PORT_COMPRESS_MASK) == NHC_UDP_PORT_COMPRESS_SRC ? 0xf0 : *ds->in++;
*ds->out++ = *ds->in++;
*ds->out++ = (nhc & NHC_UDP_PORT_COMPRESS_MASK) == NHC_UDP_PORT_COMPRESS_DST ? 0xf0 : *ds->in++;
*ds->out++ = *ds->in++;
}
/* Length */
ds->out = common_write_16_bit(ds->end - (ds->out - 4), ds->out);
/* Don't currently allow checksum compression */
if (nhc & NHC_UDP_CKSUM_COMPRESS) {
return false;
}
*ds->out++ = *ds->in++;
*ds->out++ = *ds->in++;
*ds->nh_ptr = IPV6_NH_UDP;
ds->nh_ptr = NULL;
return true;
}
/* Input: A 6LoWPAN frame, starting with an IPHC header, with outer layer 802.15.4 MAC addresses in src+dst */
/* Output: An IPv6 frame */
buffer_t *iphc_decompress(const lowpan_context_list_t *context_list, buffer_t *buf)
{
uint8_t src_iid[8], dst_iid[8];
uint8_t *iphc = NULL;
/* Pre-scan to get compressed and uncompressed header size */
uint16_t ip_size;
uint16_t hc_size = iphc_header_scan(buf, &ip_size);
if (hc_size == 0) {
tr_warn("IPHC size 0");
goto decomp_error;
}
/* Copy compressed header into temporary buffer */
iphc = ns_dyn_mem_temporary_alloc(hc_size);
if (!iphc) {
tr_warn("IPHC header alloc fail %d",hc_size);
goto decomp_error;
}
memcpy(iphc, buffer_data_pointer(buf), hc_size);
/* Reserve buffer room for the uncompressed header */
buffer_data_strip_header(buf, hc_size);
buf = buffer_headroom(buf, ip_size);
if (!buf) {
tr_warn("IPHC headroom get fail %d",ip_size);
goto decomp_error;
}
buffer_data_reserve_header(buf, ip_size);
if (!addr_iid_from_outer(src_iid, &buf->src_sa) || !addr_iid_from_outer(dst_iid, &buf->dst_sa)) {
tr_warn("Bad outer addr");
goto decomp_error;
}
{
iphc_decompress_state_t ds = {
.context_list = context_list,
.in = iphc,
.nh_ptr = NULL,
.out = buffer_data_pointer(buf),
.end = buffer_data_end(buf),
.outer_src_iid = src_iid,
.outer_dst_iid = dst_iid,
};
/* Always start with the IP header */
if (!decompress_ipv6(&ds)) {
tr_warn("IPV6 decompres fail");
goto decomp_error;
}
/* After the first IP header, we switch on the NHC byte */
/* Know we're finished when there's no NH byte waiting to be filled */
while (ds.nh_ptr) {
bool ok = false;
if ((ds.in[0] & NHC_UDP_MASK) == NHC_UDP) {
ok = decompress_udp(&ds);
} else if ((ds.in[0] & NHC_EXT_HEADER_MASK) == NHC_EXT_HEADER) {
ok = decompress_exthdr(&ds);
}
if (!ok) {
tr_warn("Unknow NH");
goto decomp_error;
}
}
if (ds.out != buffer_data_pointer(buf) + ip_size) {
tr_err("IPHC decompression bug");
goto decomp_error;
}
}
ns_dyn_mem_free(iphc);
return buf;
decomp_error:
tr_warn("IPHC decompression error");
ns_dyn_mem_free(iphc);
return buffer_free(buf);
}

View File

@ -0,0 +1,24 @@
/*
* Copyright (c) 2014-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef IPHC_DECOMPRESS_H_
#define IPHC_DECOMPRESS_H_
uint16_t iphc_header_scan(buffer_t *buf, uint16_t *uncompressed_size);
buffer_t *iphc_decompress(const lowpan_context_list_t *context_list, buffer_t *buf);
#endif /* IPHC_DECOMPRESS_H_ */

View File

@ -0,0 +1,151 @@
/*
* Copyright (c) 2015-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* \file lowpan_context.c
* \brief API for Add,Remove and update timeouts for lowpan context's
*
*/
#include "nsconfig.h"
#include "string.h"
#include "ns_types.h"
#include "ns_trace.h"
#include "nsdynmemLIB.h"
#include "ns_list.h"
#include "6LoWPAN/IPHC_Decode/lowpan_context.h"
#include "common_functions.h"
#define TRACE_GROUP "lCon"
lowpan_context_t *lowpan_contex_get_by_id(const lowpan_context_list_t *list, uint8_t id)
{
id &= LOWPAN_CONTEXT_CID_MASK;
/* Check to see we already have info for this context */
ns_list_foreach(lowpan_context_t, entry, list) {
if (entry->cid == id) {
return entry;
}
}
return NULL;
}
lowpan_context_t *lowpan_context_get_by_address(const lowpan_context_list_t *list, const uint8_t *ipv6Address)
{
/* Check to see we already have info for this context
* List is already listed that longest prefix are first at list
*/
ns_list_foreach(lowpan_context_t, entry, list) {
if (bitsequal(entry->prefix, ipv6Address, entry->length)) {
//Take always longest match prefix
return entry;
}
}
return NULL;
}
int_fast8_t lowpan_context_update(lowpan_context_list_t *list, uint8_t cid_flags, uint16_t lifetime, const uint8_t *prefix, uint_fast8_t len, bool stable)
{
uint8_t cid = cid_flags & LOWPAN_CONTEXT_CID_MASK;
lowpan_context_t *ctx = NULL;
/* Check to see we already have info for this context */
ctx = lowpan_contex_get_by_id(list, cid);
if (ctx) {
//Remove from the list - it will be reinserted below, sorted by its
//new context length. (Don't need "safe" foreach, as we break
//immediately after the removal).
ns_list_remove(list, ctx);
}
if (lifetime == 0) {
/* This is a removal request: delete any existing entry, then exit */
if (ctx) {
ns_dyn_mem_free(ctx);
}
return 0;
}
if (!ctx) {
ctx = ns_dyn_mem_alloc(sizeof(lowpan_context_t));
}
if (!ctx) {
tr_error("No heap for New 6LoWPAN Context");
return -2;
}
bool inserted = false;
ns_list_foreach(lowpan_context_t, entry, list) {
if (len >= entry->length) {
ns_list_add_before(list, entry, ctx);
inserted = true;
break;
}
}
if (!inserted) {
ns_list_add_to_end(list, ctx);
}
ctx->length = len;
ctx->cid = cid;
ctx->expiring = false;
ctx->stable = stable;
ctx->compression = cid_flags & LOWPAN_CONTEXT_C;
ctx->lifetime = (uint32_t) lifetime * 600u; /* minutes -> 100ms ticks */
// Do our own zero-padding, just in case sender has done something weird
memset(ctx->prefix, 0, sizeof ctx->prefix);
bitcopy(ctx->prefix, prefix, len);
return 0;
}
void lowpan_context_list_free(lowpan_context_list_t *list)
{
ns_list_foreach_safe(lowpan_context_t, cur, list) {
ns_list_remove(list, cur);
ns_dyn_mem_free(cur);
}
}
/* ticks is in 1/10s */
void lowpan_context_timer(lowpan_context_list_t *list, uint_fast16_t ticks)
{
ns_list_foreach_safe(lowpan_context_t, ctx, list) {
if (ctx->lifetime > ticks) {
ctx->lifetime -= ticks;
continue;
}
if (!ctx->expiring) {
/* Main lifetime has run out. Clear compression flag, and retain a
* bit longer (RFC 6775 5.4.3).
*/
ctx->compression = false;
ctx->expiring = true;
ctx->lifetime = 2 * 18000u; /* 2 * default Router Lifetime = 2 * 1800s = 1 hour */
tr_debug("Context timed out - compression disabled");
} else {
/* 1-hour expiration timer set above has run out */
ns_list_remove(list, ctx);
ns_dyn_mem_free(ctx);
tr_debug("Delete Expired context");
}
}
}

View File

@ -0,0 +1,105 @@
/*
* Copyright (c) 2015-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* \file lowpan_context.h
* \brief This header define API how contexts are saved and listed at interface side.
*
* API:
* * Add/Update context, lowpan_context_update()
* * Delete full list Context, lowpan_context_list_free()
* * Timeout update, protocol_6lowpan_context_timer()
*
*/
#ifndef LOWPAN_CONTEXT_DEFINE_H_
#define LOWPAN_CONTEXT_DEFINE_H_
#include "ns_list.h"
/* Flags for decode or encode to context's information to 8-bit data from message or to message (cid_flags)*/
#define LOWPAN_CONTEXT_C 0x10 // Compression
#define LOWPAN_CONTEXT_CID_MASK 0x0F // Context ID MASK
#define LOWPAN_MAX_CONTEXT_COUNT 16
typedef struct lowpan_context {
uint32_t lifetime; // Remaining lifetime (100ms ticks)
unsigned length: 8; // Context length
unsigned cid: 4; // Context Identifier
bool compression: 1; // C (Compression) flag
bool expiring: 1; // True if main lifetime expired, pending deletion
bool stable: 1; // Thread stable network data (always true if not Thread)
uint8_t prefix[16]; // Context prefix
ns_list_link_t link;
} lowpan_context_t;
typedef NS_LIST_HEAD(lowpan_context_t, link) lowpan_context_list_t;
/**
* \brief Update lowpan current context or add new one
*
* \param list pointer to linked list for context
* \param cid_flags Define context id (LOWPAN_CONTEXT_CID_MASK) and Context compression mode (LOWPAN_CONTEXT_C)
* \param lifetime in minutes for context 0 delete contexts
* \param prefix pointer to context prefix
* \param len prefin length in bits
*
* \return 0 Update OK
* \return -2 Update fail Out of memory reason
*/
int_fast8_t lowpan_context_update(lowpan_context_list_t *list, uint8_t cid_flags, uint16_t lifetime, const uint8_t *prefix, uint_fast8_t len, bool stable);
/**
* \brief Cleand free full linked list about context
*
* \param list pointer to linked list for context
*
*/
void lowpan_context_list_free(lowpan_context_list_t *list);
/**
* \brief Update lowpan context timeout ticks
*
* \param list pointer to linked list for context
* \param ticks is in 1/10s
*
*/
void lowpan_context_timer(lowpan_context_list_t *list, uint_fast16_t ticks);
/**
* \brief Get Context entry from the list by context ID
*
* \param list pointer to linked list for context
* \param id Define 4-bit context id LOWPAN_CONTEXT_CID_MASK
*
* \return >0 Pointer to Entry
* \return NULL Not supported Context ID
*
*/
lowpan_context_t *lowpan_contex_get_by_id(const lowpan_context_list_t *list, uint8_t id);
/**
* \brief Get Longest match Context entry from the list for given IPv6 address
*
* \param list pointer to linked list for context
* \param ipv6Address pointer to
*
* \return >0 Pointer to Entry
* \return NULL Not supported Context for this address
*
*/
lowpan_context_t *lowpan_context_get_by_address(const lowpan_context_list_t *list, const uint8_t *ipv6Address);
#endif /* LOWPAN_CONTEXT_DEFINE_H_ */

View File

@ -0,0 +1,416 @@
/*
* Copyright (c) 2016-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "nsconfig.h"
#include <string.h>
#include "beacon_handler.h"
#include "nsdynmemLIB.h"
#include "mlme.h"
#include "mac_helper.h"
#include "Service_Libs/load_balance/load_balance_api.h"
#include "Service_Libs/pan_blacklist/pan_blacklist_api.h"
#include "NWK_INTERFACE/Include/protocol.h"
#include "ns_trace.h"
#include "common_functions.h"
#define TRACE_GROUP "BHlr"
static mlme_pan_descriptor_t *duplicate_pan_descriptor(const mlme_pan_descriptor_t *desc);
static nwk_pan_descriptor_t * get_local_description(uint16_t payload_length, uint8_t *payload_ptr);
static uint8_t *beacon_optional_tlv_field_get(uint8_t len, uint8_t *ptr, uint8_t offset, uint8_t type);
static bool beacon_join_priority_tlv_val_get(uint8_t len, uint8_t *ptr, uint8_t offset, uint8_t *join_priority);
static bool beacon_join_priority_tlv_val_set(uint8_t len, uint8_t *ptr, uint8_t offset, uint8_t join_priority);
static bool beacon_join_priority_tlv_add(uint8_t len, uint8_t *ptr, uint8_t offset, uint8_t join_priority);
void beacon_received(int8_t if_id, const mlme_beacon_ind_t* data)
{
protocol_interface_info_entry_t *interface = protocol_stack_interface_info_get_by_id(if_id);
if (!interface || !data) {
return;
}
if (pan_blacklist_filter(&interface->pan_blaclist_cache, data->PANDescriptor.CoordPANId)) {
tr_debug("Drop black listed beacon");
return;
}
uint8_t coord_pan_address[10];
common_write_16_bit(data->PANDescriptor.CoordPANId, coord_pan_address);
memcpy(coord_pan_address + 2,data->PANDescriptor.CoordAddress, 8 );
if (data->PANDescriptor.CoordAddrMode == MAC_ADDR_MODE_16_BIT) {
memset(coord_pan_address +4, 0, 6);
}
if (pan_cordinator_blacklist_filter(&interface->pan_cordinator_black_list, coord_pan_address)) {
tr_debug("Drop black listed beacon by coordinator");
return;
}
nwk_scan_params_t *scan_params = &interface->mac_parameters->nwk_scan_params;
if (!scan_params || !scan_params->active_scan_active) {
if (interface->lb_api && data->PANDescriptor.CoordPANId != interface->mac_parameters->pan_id) {
uint8_t priority;
if (interface->mac_parameters->beacon_ind && beacon_join_priority_tlv_val_get(data->beacon_data_length, data->beacon_data, PLAIN_BEACON_PAYLOAD_SIZE, &priority)) {
if (interface->mac_parameters->beacon_ind(data->beacon_data, data->beacon_data_length, interface)) {
interface->lb_api->lb_beacon_notify(interface->lb_api, data, priority);
}
}
}
return;
}
nwk_filter_params_s *filter = &(interface->mac_parameters->nwk_filter_params);
if (filter->net_pan_id_filter != 0xffff) {
if (filter->net_pan_id_filter != data->PANDescriptor.CoordPANId) {
tr_debug("PAN-id Filter drop");
return;
}
}
tr_debug("Beacon indication: %s", trace_array(data->beacon_data, data->beacon_data_length));
if (filter->nwk_active_scan_level) {
bool dropBeacon = false;
if (interface->mac_parameters->beacon_ind && data->beacon_data_length) {
if (interface->mac_parameters->beacon_ind(data->beacon_data, data->beacon_data_length, interface) == 0) {
tr_debug("Beacon payload filter drop");
dropBeacon = true;
}
} else {
tr_debug("Beacon dropped: No payload");
dropBeacon = true;
}
if (dropBeacon) {
return;
}
}
//Here possible dynamic function API Call
uint8_t *b_data = ns_dyn_mem_temporary_alloc(data->beacon_data_length);
if( !b_data ){
return;
}
uint16_t b_len = data->beacon_data_length;
memcpy(b_data, data->beacon_data, b_len);
uint8_t lqi = data->PANDescriptor.LinkQuality;
if (interface->mac_parameters->beacon_compare_rx_cb_ptr) {
uint8_t join_priority;
if (beacon_join_priority_tlv_val_get(b_len, b_data, PLAIN_BEACON_PAYLOAD_SIZE, &join_priority)) {
lqi = interface->mac_parameters->beacon_compare_rx_cb_ptr(
interface->id, join_priority, data->PANDescriptor.LinkQuality);
}
}
if (scan_params->nwk_response_info) {
nwk_pan_descriptor_t *cur = scan_params->nwk_response_info;
nwk_pan_descriptor_t *prev = 0;
mlme_pan_descriptor_t *cur_desc;
while (cur) {
cur_desc = cur->pan_descriptor;
if (cur_desc->LogicalChannel == data->PANDescriptor.LogicalChannel &&
cur_desc->CoordPANId == data->PANDescriptor.CoordPANId) {
//Compare address to primary we need to check that we are not storage same parent twice FHSS
if (memcmp(cur_desc->CoordAddress,data->PANDescriptor.CoordAddress , 8) == 0) {
//Update allways better LQI
if (cur_desc->LinkQuality < lqi) {
cur_desc->LinkQuality = lqi;
}
} else {
//Compare LQI
if (cur_desc->LinkQuality < lqi) {
if (cur->beacon_length != b_len) {
if (b_len) {
uint8_t *temp_payload = ns_dyn_mem_alloc(b_len);
if (!temp_payload) {
ns_dyn_mem_free(b_data);
return;
}
ns_dyn_mem_free(cur->beacon_payload);
cur->beacon_payload = temp_payload;
memcpy(cur->beacon_payload, b_data,b_len);
} else {
ns_dyn_mem_free(cur->beacon_payload);
cur->beacon_payload = NULL;
}
cur->beacon_length = b_len;
}
cur->alternative_parent.CoordAddrMode = cur_desc->CoordAddrMode;
memcpy(cur->alternative_parent.CoordAddress, cur_desc->CoordAddress, 8);
cur->alternative_parent.LinkQuality = cur_desc->LinkQuality;
cur_desc->CoordAddrMode = data->PANDescriptor.CoordAddrMode;
memcpy(cur_desc->CoordAddress, data->PANDescriptor.CoordAddress, 8);
cur_desc->LinkQuality = lqi;
} else if (cur->alternative_parent.CoordAddrMode == MAC_ADDR_MODE_NONE || cur->alternative_parent.LinkQuality < lqi) {
cur->alternative_parent.CoordAddrMode = data->PANDescriptor.CoordAddrMode;
memcpy(cur->alternative_parent.CoordAddress, data->PANDescriptor.CoordAddress, 8);
cur->alternative_parent.LinkQuality = lqi;
}
}
ns_dyn_mem_free(b_data);
return;
}
if (cur) {
prev = cur;
cur = cur->next;
}
}
nwk_pan_descriptor_t *new_entry = get_local_description(b_len, b_data);
ns_dyn_mem_free(b_data);
b_data = NULL;
if (!new_entry) {
return;
}
new_entry->pan_descriptor = duplicate_pan_descriptor(&data->PANDescriptor);
if( !new_entry->pan_descriptor ){
ns_dyn_mem_free(new_entry->beacon_payload);
ns_dyn_mem_free(new_entry);
return;
}
new_entry->pan_descriptor->LinkQuality = lqi;
tr_debug("Beacon:Link new Last");
prev->next = new_entry;
scan_params->nwk_scan_res_size++;
} else {
nwk_pan_descriptor_t *new_entry = get_local_description(b_len, b_data);
ns_dyn_mem_free(b_data);
b_data = NULL;
if (!new_entry) {
return;
}
new_entry->pan_descriptor = duplicate_pan_descriptor(&data->PANDescriptor);
if( !new_entry->pan_descriptor ){
ns_dyn_mem_free(new_entry->beacon_payload);
ns_dyn_mem_free(new_entry);
return;
}
new_entry->pan_descriptor->LinkQuality = lqi;
scan_params->nwk_response_info = new_entry;
scan_params->nwk_scan_res_size++;
return;
}
}
static bool beacon_join_priority_tlv_val_get(uint8_t len, uint8_t *ptr, uint8_t offset, uint8_t *join_priority)
{
const uint8_t *tlv_ptr = beacon_optional_tlv_field_get(len, ptr, offset, BEACON_OPTION_JOIN_PRIORITY_TYPE);
// If TLV is found and its contains value field
if (tlv_ptr && ((*tlv_ptr & 0x0F) >= BEACON_OPTION_JOIN_PRIORITY_VAL_LEN)) {
*join_priority = *(++tlv_ptr);
return true;
}
return false;
}
static bool beacon_join_priority_tlv_val_set(uint8_t len, uint8_t *ptr, uint8_t offset, uint8_t join_priority)
{
uint8_t *tlv_ptr = beacon_optional_tlv_field_get(len, ptr, offset, BEACON_OPTION_JOIN_PRIORITY_TYPE);
// If TLV is found and its contains value field
if (tlv_ptr && ((*tlv_ptr & 0x0F) >= BEACON_OPTION_JOIN_PRIORITY_VAL_LEN)) {
*(++tlv_ptr) = join_priority;
return true;
}
return false;
}
static bool beacon_join_priority_tlv_add(uint8_t len, uint8_t *ptr, uint8_t offset, uint8_t join_priority)
{
// Invalid length
if (len < offset + BEACON_OPTION_JOIN_PRIORITY_LEN) {
return false;
}
ptr += offset;
offset += BEACON_OPTION_JOIN_PRIORITY_LEN;
// If there is already data adds TLV right after the plain beacon data
if (len > offset) {
memmove(ptr + BEACON_OPTION_JOIN_PRIORITY_LEN, ptr, len - offset);
}
*ptr++ = BEACON_OPTION_JOIN_PRIORITY_TYPE_LEN;
*ptr = join_priority;
return true;
}
static nwk_pan_descriptor_t * get_local_description(uint16_t payload_length, uint8_t *payload_ptr) {
nwk_pan_descriptor_t *description = ns_dyn_mem_temporary_alloc(sizeof(nwk_pan_descriptor_t));
if (description) {
memset(description, 0, sizeof(nwk_pan_descriptor_t));
if (payload_length) {
description->beacon_payload = ns_dyn_mem_temporary_alloc(payload_length);
if (!description->beacon_payload) {
ns_dyn_mem_free(description);
return NULL;
}
memcpy(description->beacon_payload, payload_ptr, payload_length);
description->beacon_length = payload_length;
}
description->alternative_parent.CoordAddrMode = MAC_ADDR_MODE_NONE;
}
return description;
}
static uint8_t *beacon_optional_tlv_field_get(uint8_t len, uint8_t *ptr, uint8_t offset, uint8_t type)
{
uint8_t tlvs_len = 0;
while (len > offset + tlvs_len) {
uint8_t *tlv_ptr;
tlv_ptr = ptr + offset + tlvs_len;
if (*tlv_ptr == BEACON_OPTION_END_DELIMITER) {
break;
// If TLV is found
} else if (*tlv_ptr >> 4 == type) {
// Validates TLV length
if (len >= offset + tlvs_len + 1 + (*tlv_ptr & 0x0F)) {
return tlv_ptr;
} else {
break;
}
} else {
// Length/type octet and value octets
tlvs_len += 1 + (*tlv_ptr & 0x0F);
}
}
return NULL;
}
static mlme_pan_descriptor_t *duplicate_pan_descriptor(const mlme_pan_descriptor_t *desc)
{
mlme_pan_descriptor_t *ret = ns_dyn_mem_temporary_alloc(sizeof(mlme_pan_descriptor_t));
if(!ret){
return NULL;
}
memset(ret, 0, sizeof(mlme_pan_descriptor_t));
ret->CoordAddrMode = desc->CoordAddrMode;
ret->CoordPANId = desc->CoordPANId;
memcpy(ret->CoordAddress, desc->CoordAddress, 8);
ret->LogicalChannel = desc->LogicalChannel;
ret->ChannelPage = desc->ChannelPage;
memcpy(ret->SuperframeSpec, desc->SuperframeSpec, 2);
ret->GTSPermit = desc->GTSPermit;
ret->LinkQuality = desc->LinkQuality;
ret->Timestamp = desc->Timestamp;
ret->SecurityFailure = desc->SecurityFailure;
ret->Key.SecurityLevel = desc->Key.SecurityLevel;
ret->Key.KeyIdMode = desc->Key.KeyIdMode;
ret->Key.KeyIndex = desc->Key.KeyIndex;
memcpy(ret->Key.Keysource, desc->Key.Keysource, 8);
return ret;
}
int8_t mac_beacon_link_beacon_compare_rx_callback_set(int8_t interface_id, beacon_compare_rx_cb *beacon_compare_rx_cb_ptr)
{
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
if (!cur || !cur->mac_parameters) {
return -1;
}
cur->mac_parameters->beacon_compare_rx_cb_ptr = beacon_compare_rx_cb_ptr;
return 0;
}
static void mac_beacon_joining_priority_update(protocol_interface_info_entry_t *cur, uint8_t join_priority)
{
uint8_t beacon_payload_len = mac_helper_beacon_payload_length_get(cur);
uint8_t *beacon_payload_ptr = mac_helper_beacon_payload_pointer_get(cur);
// Checks if join priority TLV exists
if (beacon_payload_len >= PLAIN_BEACON_PAYLOAD_SIZE + BEACON_OPTION_JOIN_PRIORITY_LEN) {
// If TLV list exists
if (beacon_payload_ptr[PLAIN_BEACON_PAYLOAD_SIZE] != BEACON_OPTION_END_DELIMITER) {
uint8_t current_join_priority;
uint8_t tlv_exists = beacon_join_priority_tlv_val_get(beacon_payload_len, beacon_payload_ptr, PLAIN_BEACON_PAYLOAD_SIZE, &current_join_priority);
if (tlv_exists) {
if (current_join_priority != join_priority) {
beacon_join_priority_tlv_val_set(beacon_payload_len, beacon_payload_ptr, PLAIN_BEACON_PAYLOAD_SIZE, join_priority);
// Updates beacon to MAC
(void) mac_helper_beacon_payload_register(cur);
}
return;
}
}
}
// Adds join priority TLV as first field after plain beacon data
if (beacon_payload_len >= PLAIN_BEACON_PAYLOAD_SIZE) {
beacon_payload_len = beacon_payload_len + BEACON_OPTION_JOIN_PRIORITY_LEN;
beacon_payload_ptr = mac_helper_beacon_payload_reallocate(cur, beacon_payload_len);
beacon_join_priority_tlv_add(beacon_payload_len, beacon_payload_ptr,
PLAIN_BEACON_PAYLOAD_SIZE, join_priority);
// Updates beacon to MAC
(void) mac_helper_beacon_payload_register(cur);
}
}
int8_t mac_beacon_link_beacon_join_priority_tx_callback_set(int8_t interface_id, beacon_join_priority_tx_cb *beacon_join_priority_tx_cb_ptr)
{
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
if (!cur || !cur->mac_parameters) {
return -1;
}
cur->mac_parameters->beacon_join_priority_tx_cb_ptr = beacon_join_priority_tx_cb_ptr;
return 0;
}
void beacon_join_priority_update(int8_t interface_id)
{
protocol_interface_info_entry_t *interface = protocol_stack_interface_info_get_by_id(interface_id);
if (!interface || !interface->mac_parameters ||
!interface->mac_parameters->beacon_join_priority_tx_cb_ptr) {
return;
}
uint8_t join_priority = interface->mac_parameters->beacon_join_priority_tx_cb_ptr(interface_id);
mac_beacon_joining_priority_update(interface, join_priority);
}

View File

@ -0,0 +1,49 @@
/*
* Copyright (c) 2016-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef BEACON_HANDLER_H
#define BEACON_HANDLER_H
#include <inttypes.h>
#include "net_interface.h"
// 1 byte for protocol id, 1 byte for accept join, 16 bytes for network id
#define PLAIN_BEACON_PAYLOAD_SIZE (1 + 1 + sizeof((border_router_setup_s *)0)->network_id)
#define BEACON_OPTION_END_DELIMITER 0x00
#define BEACON_OPTION_JOIN_PRIORITY_TYPE 0x0c
#define BEACON_OPTION_JOIN_PRIORITY_VAL_LEN 0x01
#define BEACON_OPTION_JOIN_PRIORITY_LEN 0x02
#define BEACON_OPTION_JOIN_PRIORITY_TYPE_LEN 0xc1
struct mlme_beacon_ind_s;
void beacon_received(int8_t if_id, const struct mlme_beacon_ind_s *data);
void beacon_optional_tlv_fields_skip(uint16_t *len, uint8_t **ptr, uint8_t offset);
/* Beacon */
int8_t mac_beacon_link_beacon_compare_rx_callback_set(int8_t interface_id,
beacon_compare_rx_cb *beacon_compare_rx_cb_ptr);
int8_t mac_beacon_link_beacon_join_priority_tx_callback_set(int8_t interface_id,
beacon_join_priority_tx_cb *beacon_join_priority_tx_cb_ptr);
void beacon_join_priority_update(int8_t interface_id);
//TODO: beacon storage here if needed by 6loWPAN?
#endif // BEACON_HANDLER_H

View File

@ -0,0 +1,541 @@
/*
* Copyright (c) 2014-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* \file mac_data_poll.c
* \brief Add short description about this file!!!
*
*/
#include "nsconfig.h"
#include "ns_types.h"
#include "eventOS_event.h"
#include "eventOS_scheduler.h"
#include "eventOS_callback_timer.h"
#include "string.h"
#include "ns_trace.h"
#include "nsdynmemLIB.h"
#include "mac_api.h"
#include "mlme.h"
#include "NWK_INTERFACE/Include/protocol_stats.h"
#include "NWK_INTERFACE/Include/protocol.h"
#include "platform/arm_hal_interrupt.h"
#include "common_functions.h"
#include "6LoWPAN/Bootstraps/protocol_6lowpan.h"
#include "6LoWPAN/Bootstraps/network_lib.h"
#include "6LoWPAN/Thread/thread_common.h"
#include "6LoWPAN/Thread/thread_bootstrap.h"
#ifndef NO_MLE
#include "MLE/mle.h"
#endif
#include "6LoWPAN/MAC/mac_helper.h"
#include "6LoWPAN/MAC/mac_data_poll.h"
#define TRACE_GROUP "mPol"
#define MAC_DATA_POLL_DEFAULT_RATE 20
#define MAC_DATA_POLL_REQUEST_EVENT 1
static int8_t mac_data_poll_tasklet = -1;
static void mac_data_poll_cb_run(int8_t interface_id);
static void mac_data_poll_cb(arm_event_s *event)
{
uint8_t event_type = event->event_type;
switch (event_type) {
case MAC_DATA_POLL_REQUEST_EVENT:
mac_data_poll_cb_run((int8_t)event->event_id);
break;
default:
break;
}
}
static int8_t mac_data_poll_tasklet_init(void)
{
if (mac_data_poll_tasklet < 0) {
mac_data_poll_tasklet = eventOS_event_handler_create(&mac_data_poll_cb, 0);
}
return mac_data_poll_tasklet;
}
static int8_t host_link_configuration(bool rx_on_idle, protocol_interface_info_entry_t *cur)
{
bool backUp_bool = cur->mac_parameters->RxOnWhenIdle;
if (rx_on_idle) {
cur->lowpan_info &= ~INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE;
} else {
tr_debug("Enable Poll state by host Link");
cur->lowpan_info |= INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE;
}
mac_helper_pib_boolean_set(cur, macRxOnWhenIdle, rx_on_idle);
if (thread_info(cur)) {
if(rx_on_idle != backUp_bool){
//If mode have been changed, send child update
thread_bootstrap_child_update_trig(cur);
}
return 0;
} else {
if (protocol_6lowpan_child_update(cur) == 0) {
mac_data_poll_init_protocol_poll(cur);
return 0;
}
}
//Swap back If Send Fail
if (!backUp_bool) {
cur->lowpan_info |= INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE;
} else {
cur->lowpan_info &= ~INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE;
}
mac_helper_pib_boolean_set(cur, macRxOnWhenIdle, backUp_bool);
return -1;
}
static void mac_data_poll_protocol_internal(protocol_interface_info_entry_t *cur)
{
if (cur->rfd_poll_info->protocol_poll == 0) {
if (cur->rfd_poll_info->host_mode == NET_HOST_SLOW_POLL_MODE) {
if (!cur->rfd_poll_info->pollActive) {
mac_poll_timer_trig(1, cur);
}
}
}
cur->rfd_poll_info->protocol_poll++;
tr_debug("Protocol Poll: %02x", cur->rfd_poll_info->protocol_poll);
}
static void mac_data_poll_protocol_poll_internal_cancel(struct protocol_interface_info_entry *cur)
{
nwk_rfd_poll_setups_s *rf_ptr = cur->rfd_poll_info;
if (rf_ptr->protocol_poll == 0) {
return;
}
if (--rf_ptr->protocol_poll == 0) {
tr_debug("Disable Protocol Poll");
if (!rf_ptr->pollActive) {
if (rf_ptr->nwk_app_poll_time) {
mac_poll_timer_trig(1, cur);
} else {
eventOS_event_timer_cancel(cur->id, mac_data_poll_tasklet);
tr_debug("Stop Poll");
}
}
}
}
void mac_data_poll_init_protocol_poll(protocol_interface_info_entry_t *cur)
{
if (!cur || !cur->rfd_poll_info || !(cur->lowpan_info & INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE)) {
return;
}
mac_data_poll_protocol_internal(cur);
}
uint32_t mac_data_poll_host_poll_time_max(protocol_interface_info_entry_t *cur)
{
if (!cur || !cur->rfd_poll_info) {
return 0;
}
return cur->rfd_poll_info->slow_poll_rate_seconds;
}
uint32_t mac_data_poll_host_timeout(protocol_interface_info_entry_t *cur)
{
if (!cur || !cur->rfd_poll_info) {
return 0;
}
return cur->rfd_poll_info->timeOutInSeconds;
}
uint32_t mac_data_poll_get_max_sleep_period(protocol_interface_info_entry_t *cur)
{
if (cur && cur->if_stack_buffer_handler && (cur->rfd_poll_info && !cur->rfd_poll_info->pollActive)) { // Verify That TX is not active
if (cur->rfd_poll_info->protocol_poll) {
return 300;
} else {
return cur->rfd_poll_info->nwk_app_poll_time;
}
}
return 0;
}
void mac_data_poll_protocol_poll_mode_decrement(struct protocol_interface_info_entry *cur)
{
if (!cur || !cur->rfd_poll_info) {
return;
}
if (!(cur->lowpan_info & INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE)) {
return;
}
mac_data_poll_protocol_poll_internal_cancel(cur);
}
void mac_data_poll_protocol_poll_mode_disable(struct protocol_interface_info_entry *cur)
{
if (!cur || !cur->rfd_poll_info) {
return;
}
if (!(cur->lowpan_info & INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE)) {
return;
}
mac_data_poll_protocol_poll_internal_cancel(cur);
}
void mac_data_poll_disable(struct protocol_interface_info_entry *cur)
{
if (!cur || !cur->rfd_poll_info) {
return;
}
eventOS_event_timer_cancel(cur->id, mac_data_poll_tasklet);
cur->rfd_poll_info->protocol_poll = 0;
cur->rfd_poll_info->pollActive = false;
}
void mac_data_poll_enable_check(protocol_interface_info_entry_t *cur)
{
if (!cur || !cur->rfd_poll_info ) {
return;
}
if (!(cur->lowpan_info & INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE)) {
return;
}
mac_data_poll_protocol_internal(cur);
}
int8_t mac_data_poll_host_mode_get(struct protocol_interface_info_entry *cur, net_host_mode_t *mode)
{
if (!cur || !cur->rfd_poll_info) {
return -1;
}
*mode = cur->rfd_poll_info->host_mode;
return 0;
}
void mac_poll_timer_trig(uint32_t poll_time, protocol_interface_info_entry_t *cur)
{
if( !cur ){
return;
}
eventOS_event_timer_cancel(cur->id, mac_data_poll_tasklet);
if (poll_time) {
if (cur->lowpan_info & INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE) {
if (poll_time < 20) {
arm_event_s event = {
.receiver = mac_data_poll_tasklet,
.sender = mac_data_poll_tasklet,
.event_id = cur->id,
.data_ptr = NULL,
.event_type = MAC_DATA_POLL_REQUEST_EVENT,
.priority = ARM_LIB_MED_PRIORITY_EVENT,
};
if (eventOS_event_send(&event) != 0) {
tr_error("eventOS_event_send() failed");
}
} else {
if (eventOS_event_timer_request(cur->id, MAC_DATA_POLL_REQUEST_EVENT, mac_data_poll_tasklet, poll_time)!= 0) {
tr_error("Poll Timer start Fail");
}
}
}
}
}
void mac_mlme_poll_confirm(protocol_interface_info_entry_t *cur, const mlme_poll_conf_t *confirm)
{
if( !cur || !confirm ){
return;
}
uint32_t poll_time = 1;
nwk_rfd_poll_setups_s *rf_ptr = cur->rfd_poll_info;
if( !rf_ptr ){
return;
}
rf_ptr->pollActive = false;
switch (confirm->status) {
case MLME_SUCCESS:
//tr_debug("Poll Confirm: Data with Data");
rf_ptr->nwk_parent_poll_fail = 0;
//Trig new Data Poll immediately
mle_refresh_entry_timeout(cur->id, rf_ptr->poll_req.CoordAddress, (addrtype_t)rf_ptr->poll_req.CoordAddrMode, true);
poll_time = 1;
break;
case MLME_NO_DATA:
//Start next case timer
rf_ptr->nwk_parent_poll_fail = 0;
mle_refresh_entry_timeout(cur->id, rf_ptr->poll_req.CoordAddress, (addrtype_t)rf_ptr->poll_req.CoordAddrMode, true);
//tr_debug("Poll Confirm: No Data");
if (rf_ptr->protocol_poll == 0) {
poll_time = rf_ptr->nwk_app_poll_time;
} else {
poll_time = 300;
}
break;
default:
tr_debug("Poll Confirm: fail %x", confirm->status);
rf_ptr->nwk_parent_poll_fail++;
if (rf_ptr->nwk_parent_poll_fail > 3) {
//tr_debug("Parent Poll Fail");
poll_time = 0;
rf_ptr->nwk_parent_poll_fail = 0;
if( rf_ptr->pollFailCb ){
rf_ptr->pollFailCb(cur->id);
}
} else {
poll_time = 2000;
}
break;
}
mac_poll_timer_trig(poll_time, cur);
}
static void mac_data_poll_cb_run(int8_t interface_id)
{
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
if (!cur) {
return;
}
nwk_rfd_poll_setups_s *rf_ptr = cur->rfd_poll_info;
if (!rf_ptr) {
return;
}
rf_ptr->poll_req.CoordAddrMode = (unsigned)mac_helper_coordinator_address_get(cur, rf_ptr->poll_req.CoordAddress);
if (rf_ptr->poll_req.CoordAddrMode == MAC_ADDR_MODE_NONE) {
return;
}
memset(&rf_ptr->poll_req.Key, 0, sizeof(mlme_security_t));
rf_ptr->poll_req.CoordPANId = mac_helper_panid_get(cur);
rf_ptr->poll_req.Key.SecurityLevel = mac_helper_default_security_level_get(cur);
if (rf_ptr->poll_req.Key.SecurityLevel) {
rf_ptr->poll_req.Key.KeyIndex = mac_helper_default_key_index_get(cur);
rf_ptr->poll_req.Key.KeyIdMode = mac_helper_default_security_key_id_mode_get(cur);
}
if (cur->mac_api && cur->mac_api->mlme_req) {
rf_ptr->pollActive = true;
cur->mac_api->mlme_req(cur->mac_api, MLME_POLL, (void*) &rf_ptr->poll_req);
} else {
tr_error("MAC not registered to interface");
}
}
int8_t mac_data_poll_host_mode_set(struct protocol_interface_info_entry *cur, net_host_mode_t mode, uint32_t poll_time)
{
#ifndef NO_MLE
if( !cur){
return -1;
}
int8_t ret_val = 0;
nwk_rfd_poll_setups_s *rf_ptr = cur->rfd_poll_info;
//Check IF Bootsrap Ready and type is Host
if (!rf_ptr ) {
return -1;
}
if (cur->lowpan_info & INTERFACE_NWK_ROUTER_DEVICE) {
return -3;
}
switch (mode) {
case NET_HOST_SLOW_POLL_MODE:
//slow mode
//Check Host current sleep state
if (rf_ptr->host_mode == NET_HOST_FAST_POLL_MODE || rf_ptr->host_mode == NET_HOST_SLOW_POLL_MODE || rf_ptr->host_mode == NET_HOST_RX_ON_IDLE) {
uint32_t new_poll_time;
uint32_t new_Timeout;
if (poll_time == 0 || poll_time > 864001) {
return -2;
}
//Calculate
//Timeout from Poll Time
new_Timeout = poll_time * 4;
if (new_Timeout < 32) { //Keep Timeout always to 32 seconds min
new_Timeout = 32;
}
if (new_Timeout != rf_ptr->timeOutInSeconds) {
rf_ptr->timeOutInSeconds = new_Timeout;
}
rf_ptr->slow_poll_rate_seconds = poll_time;
new_poll_time = (poll_time * 1000);
if (rf_ptr->host_mode == NET_HOST_RX_ON_IDLE) {
tr_debug("Init Poll timer and period");
mle_class_mode_set(cur->id, MLE_CLASS_SLEEPY_END_DEVICE);
}
rf_ptr->nwk_app_poll_time = new_poll_time;
tr_debug("Enable Poll state slow poll");
if (host_link_configuration(false, cur) != 0) {
return -3;
}
mac_poll_timer_trig(1, cur);
rf_ptr->host_mode = NET_HOST_SLOW_POLL_MODE;
}
break;
case NET_HOST_FAST_POLL_MODE:
//fast mode
//Check Host current sleep state
if (rf_ptr->host_mode == NET_HOST_FAST_POLL_MODE || rf_ptr->host_mode == NET_HOST_SLOW_POLL_MODE || rf_ptr->host_mode == NET_HOST_RX_ON_IDLE) {
if (rf_ptr->host_mode != NET_HOST_FAST_POLL_MODE) {
tr_debug("Enable Fast poll mode");
if (rf_ptr->host_mode == NET_HOST_RX_ON_IDLE) {
tr_debug("Init Poll timer and period");
if (host_link_configuration(false, cur) != 0) {
return -3;
}
}
}
tr_debug("Enable Poll By APP");
mle_class_mode_set(cur->id, MLE_CLASS_SLEEPY_END_DEVICE);
mac_helper_pib_boolean_set(cur, macRxOnWhenIdle, false);
mac_poll_timer_trig(1, cur);
rf_ptr->nwk_app_poll_time = 300;
rf_ptr->host_mode = NET_HOST_FAST_POLL_MODE;
}
break;
case NET_HOST_RX_ON_IDLE:
// Non-sleep mode
if (rf_ptr->host_mode == NET_HOST_FAST_POLL_MODE || rf_ptr->host_mode == NET_HOST_SLOW_POLL_MODE) {
if (host_link_configuration(true, cur) == 0) {
rf_ptr->host_mode = NET_HOST_RX_ON_IDLE;
rf_ptr->nwk_app_poll_time = 0;
} else {
ret_val = -3;
}
}
break;
default:
ret_val = -1;
break;
}
return ret_val;
#else /* MLE_DRAFT */
return -1;
#endif /* MLE_DRAFT */
}
void mac_data_poll_init(struct protocol_interface_info_entry *cur)
{
if (!cur) {
return;
}
if (cur->lowpan_info & INTERFACE_NWK_ROUTER_DEVICE) {
if (cur->rfd_poll_info) {
ns_dyn_mem_free(cur->rfd_poll_info);
cur->rfd_poll_info = NULL;
}
mac_helper_pib_boolean_set(cur, macRxOnWhenIdle, true);
return;
}
//Allocate and Init
nwk_rfd_poll_setups_s *rfd_ptr = cur->rfd_poll_info;
if (!rfd_ptr) {
if (mac_data_poll_tasklet_init() < 0 ) {
tr_error("Mac data poll tasklet init fail");
} else {
rfd_ptr = ns_dyn_mem_alloc(sizeof(nwk_rfd_poll_setups_s));
if (rfd_ptr) {
rfd_ptr->timeOutInSeconds = 0;
rfd_ptr->nwk_parent_poll_fail = false;
rfd_ptr->protocol_poll = 0;
rfd_ptr->slow_poll_rate_seconds = 0;
rfd_ptr->pollActive = false;
cur->rfd_poll_info = rfd_ptr;
}
}
}
if (!rfd_ptr) {
return;
}
//Set MAc Data poll Fail Callback
rfd_ptr->pollFailCb = nwk_parent_poll_fail_cb;
if (cur->mac_parameters->RxOnWhenIdle) {
tr_debug("Set Non-Sleepy HOST");
rfd_ptr->host_mode = NET_HOST_RX_ON_IDLE;
mle_class_mode_set(cur->id, MLE_CLASS_END_DEVICE);
} else {
rfd_ptr->protocol_poll = 1;
mac_poll_timer_trig(200, cur);
tr_debug("Set Sleepy HOST configure");
rfd_ptr->host_mode = NET_HOST_FAST_POLL_MODE;
mle_class_mode_set(cur->id, MLE_CLASS_SLEEPY_END_DEVICE);
rfd_ptr->slow_poll_rate_seconds = 3;
rfd_ptr->timeOutInSeconds = 32;
rfd_ptr->nwk_app_poll_time = 300;
rfd_ptr->nwk_parent_poll_fail = 0;
}
}

View File

@ -0,0 +1,49 @@
/*
* Copyright (c) 2014-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* \file mac_data_poll.h
* \brief Add short description about this file!!!
*
*/
#ifndef MAC_DATA_POLL_H_
#define MAC_DATA_POLL_H_
#include "net_polling_api.h"
struct nwk_rfd_poll_setups;
struct protocol_interface_info_entry;
struct mlme_poll_conf_s;
void mac_poll_timer_trig(uint32_t poll_time, struct protocol_interface_info_entry *cur);
void mac_mlme_poll_confirm(struct protocol_interface_info_entry *cur, const struct mlme_poll_conf_s *confirm);
void mac_data_poll_init_protocol_poll(struct protocol_interface_info_entry *cur);
uint32_t mac_data_poll_host_poll_time_max(struct protocol_interface_info_entry *cur);
uint32_t mac_data_poll_host_timeout(struct protocol_interface_info_entry *cur);
void mac_data_poll_protocol_poll_mode_decrement(struct protocol_interface_info_entry *cur);
void mac_data_poll_protocol_poll_mode_disable(struct protocol_interface_info_entry *cur);
void mac_data_poll_enable_check(struct protocol_interface_info_entry *cur);
void mac_data_poll_disable(struct protocol_interface_info_entry *cur);
int8_t mac_data_poll_host_mode_get(struct protocol_interface_info_entry *cur, net_host_mode_t *mode);
int8_t mac_data_poll_host_mode_set(struct protocol_interface_info_entry *cur, net_host_mode_t mode, uint32_t poll_time);
void mac_data_poll_init(struct protocol_interface_info_entry *cur);
uint32_t mac_data_poll_get_max_sleep_period(struct protocol_interface_info_entry *cur);
#endif /* MAC_DATA_POLL_H_ */

View File

@ -0,0 +1,877 @@
/*
* Copyright (c) 2016-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "nsconfig.h"
#include <string.h>
#include "NWK_INTERFACE/Include/protocol.h"
#include "mlme.h"
#include "mac_helper.h"
#include "mac_common_defines.h"
#include "nsdynmemLIB.h"
#include "net_nwk_scan.h"
#include "ns_trace.h"
#include "common_functions.h"
#include "MLE/mle_tlv.h"
#include "mac_api.h"
#define TRACE_GROUP "MACh"
static const uint8_t mac_helper_default_key_source[8] = {0xff,0,0,0,0,0,0,0};
static uint8_t mac_helper_header_security_aux_header_length(uint8_t keyIdmode);
static uint8_t mac_helper_security_mic_length_get(uint8_t security_level);
static void mac_helper_keytable_pairwise_descriptor_set(struct mac_api_s *api, const uint8_t *key, const uint8_t *mac64, uint8_t attribute_id);
static int8_t mac_helper_pib_8bit_set(protocol_interface_info_entry_t *interface, mlme_attr_t attribute, uint8_t value)
{
switch (attribute) {
case macAutoRequestKeyIdMode:
interface->mac_parameters->mac_key_id_mode = value;
break;
case macAutoRequestKeyIndex:
interface->mac_parameters->mac_default_key_index = value;
break;
case macAutoRequestSecurityLevel:
default:
interface->mac_parameters->mac_security_level = value;
break;
}
if (interface->mac_api && interface->mac_api->mlme_req ) {
mlme_set_t set_req;
set_req.attr = attribute;
set_req.attr_index = 0;
set_req.value_pointer = &value;
set_req.value_size = 1;
interface->mac_api->mlme_req(interface->mac_api,MLME_SET , &set_req);
}
return 0;
}
void mac_create_scan_request(mac_scan_type_t type, channel_list_s *chanlist, uint8_t scan_duration, mlme_scan_t *request)
{
if( !chanlist || !request ){
return;
}
memset(request, 0, sizeof(mlme_scan_t));
request->ScanType = type;
request->ScanChannels = *chanlist;
request->ScanDuration = scan_duration;
}
nwk_pan_descriptor_t *mac_helper_select_best_lqi(nwk_pan_descriptor_t *list)
{
nwk_pan_descriptor_t *best = list;
//Analyze Best Result
while (list) {
tr_debug("LinkQuality: %i, LogicalCh: %i", list->pan_descriptor->LinkQuality, list->pan_descriptor->LogicalChannel);
if (best->pan_descriptor->LinkQuality < list->pan_descriptor->LinkQuality) {
best = list;
}
list = list->next;
}
return best;
}
void mac_helper_drop_selected_from_the_scanresult(nwk_scan_params_t *scanParams, nwk_pan_descriptor_t *selected)
{
if( !scanParams || !selected ){
return;
}
nwk_pan_descriptor_t *cur;
nwk_pan_descriptor_t *prev = 0;
cur = scanParams->nwk_response_info;
while (cur) {
if (cur == selected) {
tr_debug("Clean Selected out from the list");
if (prev) {
prev->next = cur->next;
} else {
scanParams->nwk_response_info = cur->next;
}
scanParams->nwk_scan_res_size--;
cur = 0;
}
if (cur) {
prev = cur;
cur = cur->next;
}
}
}
void mac_helper_free_scan_confirm(nwk_scan_params_t *params)
{
if( !params ){
return;
}
if (params->nwk_scan_res_size) {
nwk_pan_descriptor_t *cur = params->nwk_response_info;
nwk_pan_descriptor_t *tmp;
tr_debug("Scanned Results");
while (cur) {
tmp = cur;
cur = cur->next;
tr_debug("Free NWK Structure");
mac_helper_free_pan_descriptions(tmp);
}
params->nwk_response_info = 0;
params->nwk_scan_res_size = 0;
}
params->nwk_cur_active = mac_helper_free_pan_descriptions(params->nwk_cur_active);
}
nwk_pan_descriptor_t * mac_helper_free_pan_descriptions(nwk_pan_descriptor_t *nwk_cur_active)
{
if (nwk_cur_active) {
ns_dyn_mem_free(nwk_cur_active->pan_descriptor);
ns_dyn_mem_free(nwk_cur_active->beacon_payload);
ns_dyn_mem_free(nwk_cur_active);
}
return NULL;
}
int8_t mac_helper_nwk_id_filter_set(const uint8_t *nw_id, nwk_filter_params_s *filter)
{
if( !filter ){
return -1;
}
int8_t ret_val = 0;
if (nw_id) {
if (filter->beacon_nwk_id_filter == 0) {
filter->beacon_nwk_id_filter = ns_dyn_mem_alloc(16);
}
if (filter->beacon_nwk_id_filter) {
memcpy(filter->beacon_nwk_id_filter, nw_id, 16);
} else {
ret_val = -1;
}
} else {
ns_dyn_mem_free(filter->beacon_nwk_id_filter);
filter->beacon_nwk_id_filter = 0;
}
return ret_val;
}
void mac_helper_panid_set(protocol_interface_info_entry_t *interface, uint16_t panId)
{
interface->mac_parameters->pan_id = panId;
mlme_set_t set_req;
set_req.attr = macPANId;
set_req.attr_index = 0;
set_req.value_pointer = &panId;
set_req.value_size = 2;
interface->mac_api->mlme_req(interface->mac_api,MLME_SET , &set_req);
}
void mac_helper_mac16_address_set(protocol_interface_info_entry_t *interface, uint16_t mac16)
{
interface->mac_parameters->mac_short_address = mac16;
if (mac16 < 0xfffe) {
interface->mac_parameters->shortAdressValid = true;
} else {
interface->mac_parameters->shortAdressValid = false;
}
mlme_set_t set_req;
set_req.attr = macShortAddress;
set_req.attr_index = 0;
set_req.value_pointer = &mac16;
set_req.value_size = 2;
interface->mac_api->mlme_req(interface->mac_api,MLME_SET , &set_req);
}
uint16_t mac_helper_mac16_address_get(const protocol_interface_info_entry_t *interface)
{
uint16_t shortAddress = 0xfffe;
if (interface ) {
shortAddress = interface->mac_parameters->mac_short_address;
}
return shortAddress;
}
uint16_t mac_helper_panid_get(const protocol_interface_info_entry_t *interface)
{
uint16_t panId = 0xffff;
if (interface) {
panId = interface->mac_parameters->pan_id;
}
return panId;
}
void mac_helper_default_key_index_set(protocol_interface_info_entry_t *interface, uint8_t keyIndex)
{
interface->mac_parameters->mac_default_key_index = keyIndex;
}
uint8_t mac_helper_default_key_index_get(protocol_interface_info_entry_t *interface)
{
return interface->mac_parameters->mac_default_key_index;
}
void mac_helper_set_default_key_source(protocol_interface_info_entry_t *interface)
{
mlme_set_t set_req;
set_req.attr_index = 0;
set_req.value_pointer = (void*)mac_helper_default_key_source;
set_req.value_size = 8;
//Set first default key source
set_req.attr = macDefaultKeySource;
interface->mac_api->mlme_req(interface->mac_api,MLME_SET , &set_req);
//Set first default key source
set_req.attr = macAutoRequestKeySource;
interface->mac_api->mlme_req(interface->mac_api,MLME_SET , &set_req);
}
void mac_helper_default_security_level_set(protocol_interface_info_entry_t *interface, uint8_t securityLevel)
{
bool security_enabled;
if (securityLevel) {
security_enabled = true;
} else {
security_enabled = false;
}
mac_helper_pib_8bit_set(interface,macAutoRequestSecurityLevel, securityLevel);
mac_helper_pib_boolean_set(interface, macSecurityEnabled, security_enabled);
}
uint8_t mac_helper_default_security_level_get(protocol_interface_info_entry_t *interface)
{
return interface->mac_parameters->mac_security_level;
}
void mac_helper_default_security_key_id_mode_set(protocol_interface_info_entry_t *interface, uint8_t keyIdMode)
{
mac_helper_pib_8bit_set(interface,macAutoRequestKeyIdMode, keyIdMode);
}
uint8_t mac_helper_default_security_key_id_mode_get(protocol_interface_info_entry_t *interface)
{
return interface->mac_parameters->mac_key_id_mode;
}
static void mac_helper_key_lookup_set(mlme_key_id_lookup_descriptor_t *lookup, uint8_t id)
{
memcpy(lookup->LookupData, mac_helper_default_key_source, 8);
lookup->LookupData[8] = id;
lookup->LookupDataSize = 1;
}
static void mac_helper_keytable_descriptor_set(struct mac_api_s *api, const uint8_t *key, uint8_t id, uint8_t attribute_id) {
mlme_set_t set_req;
mlme_key_id_lookup_descriptor_t lookup_description;
mlme_key_descriptor_entry_t key_description;
if (key) {
mac_helper_key_lookup_set(&lookup_description, id);
memset(&key_description, 0, sizeof(mlme_key_descriptor_entry_t));
memcpy(key_description.Key, key, 16);
key_description.KeyIdLookupList = &lookup_description;
key_description.KeyIdLookupListEntries = 1;
} else {
memset(&key_description, 0, sizeof(mlme_key_descriptor_entry_t));
}
set_req.attr = macKeyTable;
set_req.attr_index = attribute_id;
set_req.value_pointer = &key_description;
set_req.value_size = sizeof(mlme_key_descriptor_entry_t);
api->mlme_req(api, MLME_SET, &set_req);
}
static void mac_helper_keytable_pairwise_descriptor_set(struct mac_api_s *api, const uint8_t *key, const uint8_t *mac64, uint8_t attribute_id) {
mlme_set_t set_req;
mlme_key_id_lookup_descriptor_t lookup_description;
mlme_key_descriptor_entry_t key_description;
if (key) {
memcpy(lookup_description.LookupData, mac64, 8);
lookup_description.LookupData[8] = 0;
lookup_description.LookupDataSize = 1;
tr_debug("Key add %u index %s", attribute_id,trace_array(lookup_description.LookupData, 9));
memset(&key_description, 0, sizeof(mlme_key_descriptor_entry_t));
memcpy(key_description.Key, key, 16);
key_description.KeyIdLookupList = &lookup_description;
key_description.KeyIdLookupListEntries = 1;
} else {
memset(&key_description, 0, sizeof(mlme_key_descriptor_entry_t));
}
set_req.attr = macKeyTable;
set_req.attr_index = attribute_id;
set_req.value_pointer = &key_description;
set_req.value_size = sizeof(mlme_key_descriptor_entry_t);
api->mlme_req(api,MLME_SET , &set_req);
}
int8_t mac_helper_security_default_key_set(protocol_interface_info_entry_t *interface, const uint8_t *key, uint8_t id, uint8_t keyid_mode)
{
if (id == 0 || keyid_mode > 3) {
return -1;
}
mac_helper_pib_8bit_set(interface,macAutoRequestKeyIndex, id);
mac_helper_keytable_descriptor_set(interface->mac_api, key, id, interface->mac_parameters->mac_default_key_attribute_id);
return 0;
}
int8_t mac_helper_security_pairwisekey_set(protocol_interface_info_entry_t *interface, const uint8_t *key, const uint8_t *mac_64, uint8_t key_attribute)
{
if (key && !mac_64) {
return -1;
}
mac_helper_keytable_pairwise_descriptor_set(interface->mac_api, key, mac_64, key_attribute);
return 0;
}
int8_t mac_helper_security_next_key_set(protocol_interface_info_entry_t *interface, uint8_t *key, uint8_t id, uint8_t keyid_mode)
{
if (id == 0 || keyid_mode > 3) {
return -1;
}
interface->mac_parameters->mac_next_key_index = id;
mac_helper_keytable_descriptor_set(interface->mac_api, key, id, interface->mac_parameters->mac_next_key_attribute_id);
return 0;
}
int8_t mac_helper_security_prev_key_set(protocol_interface_info_entry_t *interface, uint8_t *key, uint8_t id, uint8_t keyid_mode)
{
if (id == 0 || keyid_mode > 3) {
return -1;
}
interface->mac_parameters->mac_prev_key_index = id;
mac_helper_keytable_descriptor_set(interface->mac_api, key, id, interface->mac_parameters->mac_prev_key_attribute_id);
return 0;
}
void mac_helper_security_key_swap_next_to_default(protocol_interface_info_entry_t *interface)
{
//Free old prev key
/*
* Update key setup next way
*
* Current Key -> Prev key
* Next Key -> Current key
* Prev Key ->Overwrite by for next Purpose
*/
//Free current prev
mac_helper_keytable_descriptor_set(interface->mac_api, NULL, 0, interface->mac_parameters->mac_prev_key_attribute_id);
uint8_t prev_attribute = interface->mac_parameters->mac_prev_key_attribute_id; //save current pre for next purpose
interface->mac_parameters->mac_prev_key_index = interface->mac_parameters->mac_default_key_index;
interface->mac_parameters->mac_prev_key_attribute_id = interface->mac_parameters->mac_default_key_attribute_id;
interface->mac_parameters->mac_default_key_index = interface->mac_parameters->mac_next_key_index;
interface->mac_parameters->mac_default_key_attribute_id = interface->mac_parameters->mac_next_key_attribute_id;
interface->mac_parameters->mac_next_key_index = 0;
interface->mac_parameters->mac_next_key_attribute_id = prev_attribute;
mac_helper_pib_8bit_set(interface,macAutoRequestKeyIndex, interface->mac_parameters->mac_default_key_index);
}
void mac_helper_security_key_clean(protocol_interface_info_entry_t *interface) {
if (interface->mac_api ) {
mlme_set_t set_req;
mlme_key_descriptor_entry_t key_description;
memset(&key_description, 0, sizeof(mlme_key_descriptor_entry_t));
set_req.attr = macKeyTable;
set_req.value_pointer = &key_description;
set_req.value_size = sizeof(mlme_key_descriptor_entry_t);
set_req.attr_index = interface->mac_parameters->mac_prev_key_attribute_id;
interface->mac_api->mlme_req(interface->mac_api,MLME_SET , &set_req);
set_req.attr_index = interface->mac_parameters->mac_default_key_attribute_id;
interface->mac_api->mlme_req(interface->mac_api,MLME_SET , &set_req);
set_req.attr_index = interface->mac_parameters->mac_next_key_attribute_id;
interface->mac_api->mlme_req(interface->mac_api,MLME_SET , &set_req);
}
interface->mac_parameters->mac_prev_key_index = 0;
interface->mac_parameters->mac_default_key_index = 0;
interface->mac_parameters->mac_next_key_index = 0;
}
void mac_helper_coordinator_address_set(protocol_interface_info_entry_t *interface, addrtype_t adr_type, uint8_t *adr_ptr)
{
mlme_set_t set_req;
set_req.attr_index = 0;
if (adr_type == ADDR_802_15_4_SHORT) {
memcpy(interface->mac_parameters->mac_cordinator_info.mac_mlme_coord_address, adr_ptr, 2);
interface->mac_parameters->mac_cordinator_info.cord_adr_mode = MAC_ADDR_MODE_16_BIT;
set_req.attr = macCoordShortAddress;
set_req.value_pointer = &interface->mac_parameters->mac_cordinator_info.mac_mlme_coord_address;
set_req.value_size = 2;
} else if (adr_type == ADDR_802_15_4_LONG) {
memcpy(interface->mac_parameters->mac_cordinator_info.mac_mlme_coord_address, adr_ptr, 8);
interface->mac_parameters->mac_cordinator_info.cord_adr_mode = MAC_ADDR_MODE_64_BIT;
set_req.attr = macCoordExtendedAddress;
set_req.value_pointer = &interface->mac_parameters->mac_cordinator_info.mac_mlme_coord_address;
set_req.value_size = 8;
}
if (interface->mac_api) {
interface->mac_api->mlme_req(interface->mac_api, MLME_SET , &set_req);
}
}
addrtype_t mac_helper_coordinator_address_get(protocol_interface_info_entry_t *interface, uint8_t *adr_ptr)
{
addrtype_t ret = ADDR_NONE;
if (!interface) {
return ret;
}
if (interface->mac_parameters->mac_cordinator_info.cord_adr_mode == MAC_ADDR_MODE_16_BIT) {
memcpy(adr_ptr,interface->mac_parameters->mac_cordinator_info.mac_mlme_coord_address, 2);
ret = ADDR_802_15_4_SHORT;
} else if (interface->mac_parameters->mac_cordinator_info.cord_adr_mode == MAC_ADDR_MODE_64_BIT) {
memcpy(adr_ptr,interface->mac_parameters->mac_cordinator_info.mac_mlme_coord_address, 8);
ret = ADDR_802_15_4_LONG;
}
return ret;
}
#define MIN(a, b) (((a) <= (b)) ? (a) : (b))
static void mac_helper_beacon_payload_length_set_to_mac(protocol_interface_info_entry_t *interface, uint8_t len)
{
if (interface->mac_api) {
mlme_set_t set_req;
set_req.attr = macBeaconPayloadLength;
set_req.attr_index = 0;
set_req.value_pointer = &len;
set_req.value_size = 1;
interface->mac_api->mlme_req(interface->mac_api,MLME_SET , &set_req);
}
}
static void mac_helper_beacon_payload_set_to_mac(protocol_interface_info_entry_t *interface, const uint8_t *payload, uint8_t length)
{
if (interface->mac_api) {
mlme_set_t set_req;
set_req.attr = macBeaconPayload;
set_req.attr_index = 0;
set_req.value_pointer = payload;
set_req.value_size = length;
interface->mac_api->mlme_req(interface->mac_api,MLME_SET , &set_req);
}
}
// XXX: a ns_dyn_mem_realloc() would be nice to have
uint8_t *mac_helper_beacon_payload_reallocate(protocol_interface_info_entry_t *interface, uint8_t len)
{
if (len == interface->mac_parameters->mac_beacon_payload_size) {
// no change to size, return the existing buff
//Set allways length to zero for safe beacon payload manipulate
mac_helper_beacon_payload_length_set_to_mac(interface,0);
return interface->mac_parameters->mac_beacon_payload;
}
if (len == 0) {
//SET MAC beacon payload to length to zero
mac_helper_beacon_payload_length_set_to_mac(interface,0);
ns_dyn_mem_free(interface->mac_parameters->mac_beacon_payload);
interface->mac_parameters->mac_beacon_payload = NULL;
interface->mac_parameters->mac_beacon_payload_size = 0;
return NULL;
}
tr_debug("mac_helper_beacon_payload_reallocate, old len: %d, new: %d", interface->mac_parameters->mac_beacon_payload_size, len);
uint8_t* temp_buff = ns_dyn_mem_alloc(len);
if (temp_buff == NULL) {
// no need to proceed, could not allocate more space
return NULL;
}
//SET MAC beacon payload to length to zero
mac_helper_beacon_payload_length_set_to_mac(interface,0);
// copy data into new buffer before freeing old one
if (interface->mac_parameters->mac_beacon_payload_size > 0) {
const uint8_t min_len = MIN(len, interface->mac_parameters->mac_beacon_payload_size);
memcpy(temp_buff, interface->mac_parameters->mac_beacon_payload, min_len);
ns_dyn_mem_free(interface->mac_parameters->mac_beacon_payload);
}
//Set New Length and pointer to MAC
interface->mac_parameters->mac_beacon_payload = temp_buff;
interface->mac_parameters->mac_beacon_payload_size = len;
return interface->mac_parameters->mac_beacon_payload;
}
int8_t mac_helper_beacon_payload_register(protocol_interface_info_entry_t *interface)
{
mac_helper_beacon_payload_set_to_mac(interface, interface->mac_parameters->mac_beacon_payload, interface->mac_parameters->mac_beacon_payload_size);
mac_helper_beacon_payload_length_set_to_mac(interface, interface->mac_parameters->mac_beacon_payload_size);
return 0;
}
uint8_t *mac_helper_beacon_payload_pointer_get(protocol_interface_info_entry_t *interface)
{
return interface->mac_parameters->mac_beacon_payload;
}
uint8_t mac_helper_beacon_payload_length_get(protocol_interface_info_entry_t *interface)
{
return interface->mac_parameters->mac_beacon_payload_size;
}
int8_t mac_helper_pib_boolean_set(protocol_interface_info_entry_t *interface, mlme_attr_t attribute, bool value)
{
switch (attribute) {
case macSecurityEnabled:
interface->mac_parameters->SecurityEnabled = value;
break;
case macRxOnWhenIdle:
interface->mac_parameters->RxOnWhenIdle = value;
break;
case macPromiscuousMode:
interface->mac_parameters->PromiscuousMode = value;
break;
case macGTSPermit:
interface->mac_parameters->GTSPermit = value;
break;
case macAssociationPermit:
interface->mac_parameters->AssociationPermit = value;
break;
case macAssociatedPANCoord:
interface->mac_parameters->AssociatedPANCoord = value;
break;
case macTimestampSupported:
interface->mac_parameters->TimestampSupported = value;
break;
case macBattLifeExt:
interface->mac_parameters->BattLifeExt = value;
break;
case macAutoRequest:
interface->mac_parameters->AutoRequest = value;
break;
case macThreadForceLongAddressForBeacon:
break;
default:
return -1;
}
if (interface->mac_api && interface->mac_api->mlme_req) {
mlme_set_t set_req;
set_req.attr = attribute;
set_req.attr_index = 0;
set_req.value_pointer = &value;
set_req.value_size = sizeof(bool);
interface->mac_api->mlme_req(interface->mac_api,MLME_SET , &set_req);
}
return 0;
}
int8_t mac_helper_mac_channel_set(protocol_interface_info_entry_t *interface, uint8_t new_channel)
{
if (interface->mac_parameters->mac_channel != new_channel) {
interface->mac_parameters->mac_channel = new_channel;
if (interface->mac_api && interface->mac_api->mlme_req ) {
mlme_set_t set_req;
set_req.attr = phyCurrentChannel;
set_req.attr_index = 0;
set_req.value_pointer = &new_channel;
set_req.value_size = 1;
interface->mac_api->mlme_req(interface->mac_api,MLME_SET , &set_req);
}
}
return 0;
}
static bool mac_helper_write_16bit(uint16_t temp16, uint8_t *addrPtr)
{
common_write_16_bit(temp16, addrPtr);
return temp16 != 0xffff;
}
/* Write functions return "false" if they write an "odd" address, true if they
* write a "normal" address. They still write odd addresses, as certain special
* packets may want them, but this allows normal data paths to check and block
* odd cases.
* "Odd" is currently defined as PAN ID == 0xffff, or short address > 0xfffd.
*/
bool mac_helper_write_our_addr(protocol_interface_info_entry_t *interface, sockaddr_t *ptr)
{
bool normal = true;
//Set First PANID
normal &= mac_helper_write_16bit(interface->mac_parameters->pan_id, ptr->address);
if (ptr->addr_type != ADDR_802_15_4_LONG && ptr->addr_type != ADDR_802_15_4_SHORT) {
if (interface->mac_parameters->shortAdressValid) {
ptr->addr_type = ADDR_802_15_4_SHORT;
} else {
ptr->addr_type = ADDR_802_15_4_LONG;
}
}
if (ptr->addr_type == ADDR_802_15_4_SHORT) {
normal &= mac_helper_write_16bit(interface->mac_parameters->mac_short_address, &ptr->address[2]);
} else {
memcpy(&ptr->address[2], interface->mac, 8);
}
return normal;
}
int8_t mac_helper_mac64_set(protocol_interface_info_entry_t *interface, const uint8_t *mac64)
{
memcpy(interface->mac, mac64, 8);
if (interface->mac_api ) {
interface->mac_api->mac64_set(interface->mac_api, mac64);
}
return 0;
}
/*
* Given a buffer, with address and security flags set, compute the maximum
* MAC payload that could be put in that buffer.
*/
uint_fast16_t mac_helper_max_payload_size(protocol_interface_info_entry_t *cur, uint_fast8_t frame_overhead)
{
uint16_t max;
max = cur->mac_api->phyMTU - frame_overhead;
/* But if we want IEEE 802.15.4-2003 compatibility (and it looks like a
* standard PHY), limit ourselves to the 2003 maximum */
if (cur->mac_parameters->MacUnsusecured_2003_cab && max > MAC_IEEE_802_15_4_MAX_MAC_SAFE_PAYLOAD_SIZE &&
cur->mac_api->phyMTU == MAC_IEEE_802_15_4_MAX_PHY_PACKET_SIZE) {
max = MAC_IEEE_802_15_4_MAX_MAC_SAFE_PAYLOAD_SIZE;
}
return max;
}
/*
* Given a buffer, with address and security flags set, compute the MAC overhead
* size once MAC header and footer are added.
* May not be accurate if MAC_MAX_PHY_PACKET_SIZE isn't set, implying a
* non-standard MAC.
*/
uint_fast8_t mac_helper_frame_overhead(protocol_interface_info_entry_t *cur, const buffer_t *buf)
{
uint_fast8_t length = 15;
/*8bytes src address, 2 frame control, 1 sequence, 2 pan-id, 2 FCS*/
if (buf->src_sa.addr_type == ADDR_NONE) {
if (cur->mac_parameters->shortAdressValid) {
length -= 6; //Cut 6 bytes from src address
}
} else if (buf->src_sa.addr_type == ADDR_802_15_4_SHORT) {
length -= 6; //Cut 6 bytes from src address
}
if (memcmp(buf->dst_sa.address, buf->src_sa.address, 2) == 0) {
length -= 2; // Cut Pan-id
}
if (buf->dst_sa.addr_type == ADDR_802_15_4_LONG) {
length += 10;
} else if (buf->dst_sa.addr_type == ADDR_802_15_4_SHORT || buf->dst_sa.addr_type == ADDR_BROADCAST) {
length += 4;
}
if (cur->mac_parameters->mac_security_level && (!buf->options.ll_security_bypass_tx)) {
length += mac_helper_header_security_aux_header_length(cur->mac_parameters->mac_key_id_mode);
length += mac_helper_security_mic_length_get(cur->mac_parameters->mac_security_level);
}
return length;
}
static uint8_t mac_helper_security_mic_length_get(uint8_t security_level) {
uint8_t mic_length;
switch (security_level) {
case SEC_MIC32:
case SEC_ENC_MIC32:
mic_length = 4;
break;
case SEC_MIC64:
case SEC_ENC_MIC64:
mic_length = 8;
break;
case SEC_MIC128:
case SEC_ENC_MIC128:
mic_length = 16;
break;
case SEC_NONE:
case SEC_ENC:
default:
mic_length = 0;
break;
}
return mic_length;
}
static uint8_t mac_helper_header_security_aux_header_length(uint8_t keyIdmode) {
uint8_t header_length = 5; //Header + 32-bit counter
switch (keyIdmode) {
case MAC_KEY_ID_MODE_SRC8_IDX:
header_length += 4; //64-bit key source first part
case MAC_KEY_ID_MODE_SRC4_IDX:
header_length += 4; //32-bit key source inline
case MAC_KEY_ID_MODE_IDX:
header_length += 1;
break;
default:
break;
}
return header_length;
}
int8_t mac_helper_link_frame_counter_read(int8_t interface_id, uint32_t *seq_ptr)
{
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
if (!cur || !cur->mac_api || !seq_ptr) {
return -1;
}
mlme_get_t get_req;
get_req.attr = macFrameCounter;
get_req.attr_index = 0;
cur->mac_api->mlme_req(cur->mac_api, MLME_GET, &get_req);
*seq_ptr = cur->mac_parameters->security_frame_counter;
return 0;
}
int8_t mac_helper_link_frame_counter_set(int8_t interface_id, uint32_t seq_ptr)
{
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
if (!cur || !cur->mac_api) {
return -1;
}
mlme_set_t set_req;
set_req.attr = macFrameCounter;
set_req.attr_index = 0;
set_req.value_pointer = &seq_ptr;
set_req.value_size = 4;
cur->mac_api->mlme_req(cur->mac_api, MLME_SET, &set_req);
return 0;
}
void mac_helper_devicetable_remove(mac_api_t *mac_api, uint8_t attribute_index)
{
if (!mac_api) {
return;
}
mlme_device_descriptor_t device_desc;
mlme_set_t set_req;
memset(&device_desc, 0xff, sizeof(mlme_device_descriptor_t));
set_req.attr = macDeviceTable;
set_req.attr_index = attribute_index;
set_req.value_pointer = (void*)&device_desc;
set_req.value_size = sizeof(mlme_device_descriptor_t);
tr_debug("unRegister Device");
mac_api->mlme_req(mac_api,MLME_SET , &set_req);
}
void mac_helper_devicetable_set(mle_neigh_table_entry_t *entry_temp, protocol_interface_info_entry_t *cur, uint32_t frame_counter, uint8_t keyID)
{
if (!cur->mac_api) {
return;
}
if (cur->mac_parameters->SecurityEnabled && cur->mac_parameters->mac_default_key_index != keyID) {
tr_debug("Do not set counter by index %u != %u", cur->mac_parameters->mac_default_key_index, keyID);
return;
}
mlme_device_descriptor_t device_desc;
mlme_set_t set_req;
device_desc.FrameCounter = frame_counter;
device_desc.Exempt = false;
device_desc.ShortAddress = entry_temp->short_adr;
memcpy(device_desc.ExtAddress, entry_temp->mac64, 8);
device_desc.PANId = mac_helper_panid_get(cur);
set_req.attr = macDeviceTable;
set_req.attr_index = entry_temp->attribute_index;
set_req.value_pointer = (void*)&device_desc;
set_req.value_size = sizeof(mlme_device_descriptor_t);
tr_debug("Register Device");
cur->mac_api->mlme_req(cur->mac_api,MLME_SET , &set_req);
}
int8_t mac_helper_mac_mlme_max_retry_set(int8_t interface_id, uint8_t mac_retry_set)
{
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
if (!cur || !cur->mac_api) {
return -1;
}
mlme_set_t set_req;
set_req.attr = macMaxFrameRetries;
set_req.attr_index = 0;
set_req.value_pointer = &mac_retry_set;
set_req.value_size = 1;
cur->mac_api->mlme_req(cur->mac_api, MLME_SET, &set_req);
return 0;
}

View File

@ -0,0 +1,117 @@
/*
* Copyright (c) 2016-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MAC_HELPER_H
#define MAC_HELPER_H
#include "mlme.h"
#include "Core/include/address.h"
struct channel_list_s;
struct nwk_scan_params;
struct nwk_filter_params;
struct nwk_pan_descriptor_t;
struct protocol_interface_info_entry;
struct ns_sockaddr;
struct buffer;
struct mac_api_s;
struct mle_neigh_table_entry_t;
void mac_create_scan_request(mac_scan_type_t type, struct channel_list_s *chanlist, uint8_t scan_duration, struct mlme_scan_s *request);
struct nwk_pan_descriptor_t *mac_helper_select_best_lqi(struct nwk_pan_descriptor_t *list);
void mac_helper_drop_selected_from_the_scanresult(struct nwk_scan_params *scanParams, struct nwk_pan_descriptor_t *selected);
void mac_helper_free_scan_confirm(struct nwk_scan_params *params);
struct nwk_pan_descriptor_t * mac_helper_free_pan_descriptions(struct nwk_pan_descriptor_t *nwk_cur_active);
int8_t mac_helper_nwk_id_filter_set(const uint8_t *nw_id, struct nwk_filter_params *filter);
void mac_helper_panid_set(struct protocol_interface_info_entry *interface, uint16_t panId);
void mac_helper_mac16_address_set(struct protocol_interface_info_entry *interface, uint16_t mac16);
uint16_t mac_helper_mac16_address_get(const struct protocol_interface_info_entry *interface);
uint16_t mac_helper_panid_get(const struct protocol_interface_info_entry *interface);
void mac_helper_set_default_key_source(struct protocol_interface_info_entry *interface);
void mac_helper_default_security_level_set(struct protocol_interface_info_entry *interface, uint8_t securityLevel);
uint8_t mac_helper_default_security_level_get(struct protocol_interface_info_entry *interface);
void mac_helper_default_security_key_id_mode_set(struct protocol_interface_info_entry *interface, uint8_t keyIdMode);
uint8_t mac_helper_default_security_key_id_mode_get(struct protocol_interface_info_entry *interface);
void mac_helper_default_key_index_set(struct protocol_interface_info_entry *interface, uint8_t keyIndex);
uint8_t mac_helper_default_key_index_get(struct protocol_interface_info_entry *interface);
int8_t mac_helper_security_default_key_set(struct protocol_interface_info_entry *interface, const uint8_t *key, uint8_t id, uint8_t keyid_mode);
int8_t mac_helper_security_next_key_set(struct protocol_interface_info_entry *interface, uint8_t *key, uint8_t id, uint8_t keyid_mode);
int8_t mac_helper_security_prev_key_set(struct protocol_interface_info_entry *interface, uint8_t *key, uint8_t id, uint8_t keyid_mode);
void mac_helper_security_key_swap_next_to_default(struct protocol_interface_info_entry *interface);
int8_t mac_helper_security_pairwisekey_set(struct protocol_interface_info_entry *interface, const uint8_t *key, const uint8_t *mac_64, uint8_t key_attribute);
void mac_helper_security_key_clean(struct protocol_interface_info_entry *interface);
void mac_helper_coordinator_address_set(struct protocol_interface_info_entry *interface, addrtype_t adr_type, uint8_t *adr_ptr);
addrtype_t mac_helper_coordinator_address_get(struct protocol_interface_info_entry *interface, uint8_t *adr_ptr);
/* Beacon Payload API */
uint8_t *mac_helper_beacon_payload_reallocate(struct protocol_interface_info_entry *interface, uint8_t len);
int8_t mac_helper_beacon_payload_register(struct protocol_interface_info_entry *interface);
uint8_t *mac_helper_beacon_payload_pointer_get(struct protocol_interface_info_entry *interface);
uint8_t mac_helper_beacon_payload_length_get(struct protocol_interface_info_entry *interface);
/* Beacon Payload API end*/
int8_t mac_helper_pib_boolean_set(struct protocol_interface_info_entry *interface, mlme_attr_t attribute, bool value);
int8_t mac_helper_mac_channel_set(struct protocol_interface_info_entry *interface, uint8_t new_channel);
bool mac_helper_write_our_addr(struct protocol_interface_info_entry *interface, struct ns_sockaddr *ptr);
int8_t mac_helper_mac64_set(struct protocol_interface_info_entry *interface, const uint8_t *mac64);
uint_fast16_t mac_helper_max_payload_size(struct protocol_interface_info_entry *cur, uint_fast8_t frame_overhead);
uint_fast8_t mac_helper_frame_overhead(struct protocol_interface_info_entry *cur, const struct buffer *buf);
int8_t mac_helper_link_frame_counter_read(int8_t interface_id, uint32_t *seq_ptr);
int8_t mac_helper_link_frame_counter_set(int8_t interface_id, uint32_t seq_ptr);
void mac_helper_devicetable_remove(struct mac_api_s *mac_api, uint8_t attribute_index);
void mac_helper_devicetable_set(struct mle_neigh_table_entry_t *entry_temp, struct protocol_interface_info_entry *cur, uint32_t frame_counter, uint8_t keyID);
int8_t mac_helper_mac_mlme_max_retry_set(int8_t interface_id, uint8_t mac_retry_set);
#endif // MAC_HELPER_H

View File

@ -0,0 +1,350 @@
/*
* Copyright (c) 2015-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* \file mac_pairwise_key.c
*
*/
#include "nsconfig.h"
#include <string.h>
#include "ns_types.h"
#include "ns_trace.h"
#include "nsdynmemLIB.h"
#include "mac_common_defines.h"
#include "6LoWPAN/MAC/mac_helper.h"
#include "6LoWPAN/MAC/mac_pairwise_key.h"
#include "MLE/mle.h"
#include "NWK_INTERFACE/Include/protocol.h"
#define TRACE_GROUP "mPKe"
typedef struct mac_pairwise_key_entry {
uint8_t eui64[8]; /*!< eui64 which is key source */
uint8_t pairwiseKey[16]; /*!< Paiwise key */
uint32_t frameCounterRX;
ns_list_link_t link; /*!< List link entry */
} mac_pairwise_key_entry_t;
typedef struct mac_pairwise_key_info {
uint8_t device_descriptor_attribute;
uint8_t key_decriptor_attribute;
} mac_pairwise_key_info_t;
typedef NS_LIST_HEAD(mac_pairwise_key_entry_t, link) mac_pairwise_key_list_t;
typedef struct mac_pairwise_interface_entry {
int8_t interfaceId;
mac_pairwise_key_info_t *mac_pairwise_key_table;
uint8_t key_table_size;
uint8_t key_list_size;
uint8_t network_key_offset;
ns_list_link_t link; /*!< List link entry */
} mac_pairwise_interface_entry_t;
static NS_LIST_DEFINE(mac_pairwise_info, mac_pairwise_interface_entry_t, link);
static mac_pairwise_interface_entry_t *mac_pairwise_key_list_allocate(uint8_t list_size)
{
mac_pairwise_interface_entry_t *newEntry = ns_dyn_mem_alloc(sizeof(mac_pairwise_interface_entry_t));
mac_pairwise_key_info_t *key_table = ns_dyn_mem_alloc(sizeof(mac_pairwise_key_info_t) * list_size);
if (!newEntry || !key_table) {
ns_dyn_mem_free(newEntry);
ns_dyn_mem_free(key_table);
return NULL;
}
memset(newEntry, 0, sizeof(mac_pairwise_interface_entry_t));
memset(key_table, 0, sizeof(mac_pairwise_key_info_t) * list_size);
newEntry->mac_pairwise_key_table = key_table;
newEntry->key_list_size = list_size;
return newEntry;
}
static bool mac_pairwise_key_deacriptro_attribute_get(mac_pairwise_interface_entry_t *main_list, uint8_t key_attribute) {
mac_pairwise_key_info_t *key_table = main_list->mac_pairwise_key_table;
for (uint8_t i = 0; i<main_list->key_table_size; i++) {
if (key_table->key_decriptor_attribute == key_attribute) {
return false;
}
key_table++;
}
return true;
}
mac_pairwise_key_info_t *mac_pairwise_key_info_get(mac_pairwise_interface_entry_t *main_list, uint8_t device_id) {
mac_pairwise_key_info_t *key_table = main_list->mac_pairwise_key_table;
for (uint8_t i = 0; i<main_list->key_table_size; i++) {
if (key_table->device_descriptor_attribute == device_id) {
return key_table;
}
key_table++;
}
if (main_list->key_table_size == main_list->key_list_size ) {
return NULL;
}
bool unique_id = false;
mac_pairwise_key_info_t *new_entry = main_list->mac_pairwise_key_table + main_list->key_table_size;
new_entry->device_descriptor_attribute = device_id;
new_entry->key_decriptor_attribute = main_list->network_key_offset;
//Allocate key id
while(!unique_id) {
unique_id = mac_pairwise_key_deacriptro_attribute_get(main_list, new_entry->key_decriptor_attribute);
if (!unique_id) {
new_entry->key_decriptor_attribute++;
}
}
main_list->key_table_size++;
return new_entry;
}
static bool mac_pairwise_key_info_delete(mac_pairwise_interface_entry_t *main_list, uint8_t device_id, uint8_t *key_attribute) {
bool removed_entry = false;
mac_pairwise_key_info_t *cur = main_list->mac_pairwise_key_table;
mac_pairwise_key_info_t *prev = NULL;
for (uint8_t i = 0; i<main_list->key_table_size; i++) {
if (removed_entry) {
*prev = *cur;
} else {
if (cur->device_descriptor_attribute == device_id) {
removed_entry = true;
*key_attribute = cur->key_decriptor_attribute;
}
}
prev = cur;
cur++;
}
if (removed_entry) {
main_list->key_table_size--;
}
return removed_entry;
}
static mac_pairwise_interface_entry_t *mac_pairwise_key_main_class_discover(int8_t interfaceId)
{
ns_list_foreach(mac_pairwise_interface_entry_t, cur, &mac_pairwise_info) {
if (interfaceId == cur->interfaceId) {
return cur;
}
}
return NULL;
}
static mac_pairwise_interface_entry_t *mac_pairwise_key_main_class(uint8_t key_list_size)
{
mac_pairwise_interface_entry_t *main_list = mac_pairwise_key_list_allocate(key_list_size);
if (!main_list) {
return NULL;
}
tr_debug("Set new Key main Class");
ns_list_add_to_end(&mac_pairwise_info, main_list);
return main_list;
}
static void mac_pairwise_key_list_free(protocol_interface_info_entry_t *interface, mac_pairwise_interface_entry_t *main_list) {
//Delete mle entries & Keys
mle_neigh_table_entry_t *cur_entry;
mac_pairwise_key_info_t *cur = main_list->mac_pairwise_key_table;
for (uint8_t i = 0; i< main_list->key_table_size; i++) {
cur_entry = mle_class_get_by_device_attribute_id(interface->id, cur->device_descriptor_attribute);
if (cur_entry) {
mle_class_remove_entry(interface->id, cur_entry);
}
mac_helper_security_pairwisekey_set(interface, NULL, NULL, cur->key_decriptor_attribute);
}
main_list->key_table_size = 0;
}
int mac_pairwise_key_interface_register(int8_t interface_id, uint8_t mac_supported_key_decription_size, uint8_t network_key_size)
{
if (!mac_supported_key_decription_size || !network_key_size ) {
return -2;
}
if (mac_supported_key_decription_size < network_key_size) {
return -2;
}
protocol_interface_info_entry_t *interface = protocol_stack_interface_info_get_by_id(interface_id);
if (!interface) {
return -1;
}
if (mac_pairwise_key_main_class_discover(interface_id)) {
return -2;
}
uint8_t pairwise_key_list_size;
uint8_t network_key_offset;
if (mac_supported_key_decription_size == network_key_size) {
pairwise_key_list_size = 1;
network_key_offset = 0;
} else {
pairwise_key_list_size = (mac_supported_key_decription_size - network_key_size);
network_key_offset = network_key_size;
}
mac_pairwise_interface_entry_t *main_list = mac_pairwise_key_main_class(pairwise_key_list_size);
if (!main_list) {
return -1;
}
main_list->interfaceId = interface_id;
main_list->network_key_offset = network_key_offset;
return 0;
}
int mac_pairwise_key_interface_unregister(int8_t interface_id)
{
protocol_interface_info_entry_t *interface = protocol_stack_interface_info_get_by_id(interface_id);
if (!interface) {
return -1;
}
mac_pairwise_interface_entry_t *main_list = mac_pairwise_key_main_class_discover(interface_id);
if (!main_list) {
return -1;
}
mac_pairwise_key_list_free(interface, main_list);
//Can delete Main Class also
ns_list_remove(&mac_pairwise_info, main_list);
ns_dyn_mem_free(main_list->mac_pairwise_key_table);
ns_dyn_mem_free(main_list);
return 0;
}
int mac_pairwise_key_add(int8_t interface_id, uint32_t valid_life_time, const uint8_t eui64[static 8], const uint8_t key[static 16])
{
protocol_interface_info_entry_t *interface = protocol_stack_interface_info_get_by_id(interface_id);
if (!interface || !interface->mac_api) {
return -1;
}
(void)valid_life_time;
tr_debug("Pairwise_key addr %s, key %s", trace_array(eui64, 8), trace_array(key, 16));
mac_pairwise_interface_entry_t *main_list = mac_pairwise_key_main_class_discover(interface_id);
if (!main_list) {
return -1;
}
//Allocate mle entry
mle_neigh_table_entry_t *mle_entry = mle_class_get_entry_by_mac64(interface_id, 0, eui64, true);
if (!mle_entry) {
return -1;
}
mle_entry->thread_commission = true;
mle_entry->short_adr = 0xffff;
mle_entry->ttl = 20;
//Allocate key description
mac_pairwise_key_info_t *key_desc = mac_pairwise_key_info_get(main_list, mle_entry->attribute_index);
if (!key_desc) {
mle_class_remove_entry(interface_id, mle_entry);
return -1;
}
//Set device descriptor
mac_helper_devicetable_set(mle_entry, interface, 0, interface->mac_parameters->mac_default_key_index);
//set key descriptor
if (mac_helper_security_pairwisekey_set(interface, key, eui64, key_desc->key_decriptor_attribute) != 0) {
main_list->key_table_size--;
mle_class_remove_entry(interface_id, mle_entry);
return -1;
}
return 0;
}
int mac_pairwise_key_del(int8_t interface_id, const uint8_t eui64[static 8])
{
protocol_interface_info_entry_t *interface = protocol_stack_interface_info_get_by_id(interface_id);
if (!interface || !interface->mac_api) {
return -1;
}
mac_pairwise_interface_entry_t *main_list;
tr_debug("Pairwise_key delete %s", trace_array(eui64, 8));
main_list = mac_pairwise_key_main_class_discover(interface_id);
if (!main_list) {
return -1;
}
//Get from mle
mle_neigh_table_entry_t *mle_entry = mle_class_get_entry_by_mac64(interface_id, 0, eui64, true);
if (!mle_entry) {
return -1;
}
//discover by mle entry attribute
uint8_t key_attribute;
if (!mac_pairwise_key_info_delete(main_list, mle_entry->attribute_index, &key_attribute)) {
return -1;
}
//kill Entry & overwrite key
mac_helper_security_pairwisekey_set(interface, NULL, NULL, key_attribute);
mle_class_remove_entry(interface_id, mle_entry);
return 0;
}
int mac_pairwise_key_flush_list(int8_t interface_id)
{
protocol_interface_info_entry_t *interface = protocol_stack_interface_info_get_by_id(interface_id);
if (!interface) {
return -1;
}
tr_debug("Pairwise_key flush");
mac_pairwise_interface_entry_t *main_list = mac_pairwise_key_main_class_discover(interface_id);
if (!main_list) {
return -1;
}
mac_pairwise_key_list_free(interface, main_list);
return 0;
}

View File

@ -0,0 +1,39 @@
/*
* Copyright (c) 2014-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* \file mac_pairwise_key.h
* \brief Add short description about this file!!!
*
*/
#ifndef MAC_PAIRWISE_KEY_H_
#define MAC_PAIRWISE_KEY_H_
#include "ns_list.h"
int mac_pairwise_key_add(int8_t interface_id, uint32_t valid_life_time, const uint8_t eui64[static 8], const uint8_t key[static 16]);
int mac_pairwise_key_del(int8_t interface_id, const uint8_t eui64[static 8]);
int mac_pairwise_key_interface_register(int8_t interface_id, uint8_t mac_supported_key_decription_size, uint8_t network_key_size);
int mac_pairwise_key_interface_unregister(int8_t interface_id);
int mac_pairwise_key_flush_list(int8_t interface_id);
#endif /* MAC_PAIRWISE_KEY_H_ */

View File

@ -0,0 +1,314 @@
/*
* Copyright (c) 2016-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "nsconfig.h"
#include <string.h>
#include "mlme.h"
#include "common_functions.h"
#include "ns_trace.h"
#include "NWK_INTERFACE/Include/protocol_abstract.h"
#include "NWK_INTERFACE/Include/protocol_timer.h"
#include "Service_Libs/mle_service/mle_service_api.h"
#include "Core/include/address.h"
#include "Core/include/socket.h"
#include "6LoWPAN/Thread/thread_common.h"
#include "6LoWPAN/Thread/thread_management_internal.h"
#include "6LoWPAN/MAC/mac_helper.h"
#include "MLE/mle.h"
#include "mac_mcps.h"
#include "6LoWPAN/MAC/mac_data_poll.h"
#include "6LoWPAN/MAC/mac_response_handler.h"
#include "6LoWPAN/lowpan_adaptation_interface.h"
static bool mac_data_is_broadcast_addr(const sockaddr_t *addr);
#define TRACE_GROUP "MRsH"
static void mac_mlme_device_table_confirmation_handle(protocol_interface_info_entry_t *info_entry, mlme_get_conf_t *confirmation) {
if (confirmation->value_size != sizeof(mlme_device_descriptor_t)) {
return;
}
mlme_device_descriptor_t *descpription = (mlme_device_descriptor_t*)confirmation->value_pointer;
tr_debug("Dev stable get confirmation %x", confirmation->status);
if (confirmation->status == MLME_SUCCESS) {
//GET ME table by extended mac64 address
mle_neigh_table_entry_t * entry = mle_class_get_by_link_address(info_entry->id, descpription->ExtAddress, ADDR_802_15_4_LONG);
if (!entry) {
return;
}
if (entry->short_adr != descpription->ShortAddress) {
//Refresh Short ADDRESS
mlme_set_t set_request;
descpription->ShortAddress = entry->short_adr;
//CALL MLME-SET
set_request.attr = macDeviceTable;
set_request.attr_index = confirmation->attr_index;
set_request.value_pointer = descpription;
set_request.value_size = confirmation->value_size;
info_entry->mac_api->mlme_req(info_entry->mac_api, MLME_SET, &set_request);
}
}
}
static void mac_mlme_frame_counter_confirmation_handle(protocol_interface_info_entry_t *info_entry, mlme_get_conf_t *confirmation) {
if (confirmation->value_size != 4) {
return;
}
uint32_t *temp_ptr = (uint32_t*)confirmation->value_pointer;
info_entry->mac_parameters->security_frame_counter = *temp_ptr;
}
static void mac_mlme_get_confirmation_handler(protocol_interface_info_entry_t *info_entry, mlme_get_conf_t *confirmation) {
if (!confirmation) {
return;
}
switch (confirmation->attr) {
case macDeviceTable:
mac_mlme_device_table_confirmation_handle(info_entry, confirmation);
break;
case macFrameCounter:
mac_mlme_frame_counter_confirmation_handle(info_entry, confirmation);
break;
default:
break;
}
}
void mcps_data_confirm_handler( const mac_api_t* api, const mcps_data_conf_t *data )
{
protocol_interface_info_entry_t *info_entry = protocol_stack_interface_info_get_by_id(api->parent_id);
//TODO: create buffer_t and call correct function
//Update protocol_status
lowpan_adaptation_interface_tx_confirm(info_entry, data);
}
static bool mcps_data_indication_neighbor_validate(int8_t interface_id, const sockaddr_t *addr)
{
/* If MLE is enabled, we will talk if we have an MLE association */
mle_neigh_table_entry_t *mle_entry = mle_class_get_by_link_address(interface_id, addr->address + 2, addr->addr_type);
if (mle_entry && (mle_entry->handshakeReady || mle_entry->thread_commission)) {
return true;
}
/* Otherwise, we don't know them */
return false;
}
void mcps_data_indication_handler( const mac_api_t* api, const mcps_data_ind_t *data_ind )
{
protocol_interface_info_entry_t *info_entry = protocol_stack_interface_info_get_by_id(api->parent_id);
buffer_t *buf = buffer_get(data_ind->msduLength);
if (!buf || !info_entry) {
return;
}
uint8_t *ptr;
buffer_data_add(buf, data_ind->msdu_ptr, data_ind->msduLength);
//tr_debug("MAC Paylod size %u %s",data_ind->msduLength, trace_array(data_ind->msdu_ptr, 8));
buf->options.lqi = data_ind->mpduLinkQuality;
buf->options.dbm = data_ind->signal_dbm;
buf->src_sa.addr_type = (addrtype_t)data_ind->SrcAddrMode;
ptr = common_write_16_bit(data_ind->SrcPANId, buf->src_sa.address);
memcpy(ptr, data_ind->SrcAddr, 8);
buf->dst_sa.addr_type = (addrtype_t)data_ind->DstAddrMode;
ptr = common_write_16_bit(data_ind->DstPANId, buf->dst_sa.address);
memcpy(ptr, data_ind->DstAddr, 8);
//Set Link spesific stuff to seperately
buf->link_specific.ieee802_15_4.srcPanId = data_ind->SrcPANId;
buf->link_specific.ieee802_15_4.dstPanId = data_ind->DstPANId;
if (mac_data_is_broadcast_addr(&buf->dst_sa)) {
buf->options.ll_broadcast_rx = true;
}
buf->interface = info_entry;
if (data_ind->Key.SecurityLevel) {
buf->link_specific.ieee802_15_4.fc_security = true;
if (info_entry->mac_security_key_usage_update_cb) {
info_entry->mac_security_key_usage_update_cb(info_entry, &data_ind->Key);
}
} else {
buf->link_specific.ieee802_15_4.fc_security = false;
if (mac_helper_default_security_level_get(info_entry) ||
!mcps_data_indication_neighbor_validate(info_entry->id, &buf->src_sa)) {
//SET By Pass
buf->options.ll_security_bypass_rx = true;
}
}
buf->info = (buffer_info_t)(B_TO_IPV6_TXRX | B_FROM_MAC | B_DIR_UP);
protocol_push(buf);
}
void mcps_purge_confirm_handler( const mac_api_t* api, mcps_purge_conf_t *data )
{
(void)api;
tr_info("MCPS Data Purge confirm status %u, for handle %u", data->status, data->msduHandle);
}
static void stop_bootstrap_timer(protocol_interface_info_entry_t *info_entry)
{
if (info_entry->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) {
protocol_timer_stop(PROTOCOL_TIMER_BOOTSTRAP_TIM);
}
}
void mlme_confirm_handler( const mac_api_t* api, mlme_primitive id, const void *data )
{
protocol_interface_info_entry_t *info_entry = protocol_stack_interface_info_get_by_id(api->parent_id);
if (!info_entry) {
return;
}
//TODO: create buffer_t and call correct function
switch(id){
case MLME_ASSOCIATE:{
//Unsupported
break;
}
case MLME_DISASSOCIATE:{
//Unsupported
break;
}
case MLME_GET:{
mlme_get_conf_t *dat = (mlme_get_conf_t*)data;
mac_mlme_get_confirmation_handler(info_entry, dat);
break;
}
case MLME_GTS:{
//Unsupported
break;
}
case MLME_RESET:{
// mlme_reset_conf_t *dat = (mlme_reset_conf_t*)data;
break;
}
case MLME_RX_ENABLE:{
//Unsupported
break;
}
case MLME_SCAN:{
const mlme_scan_conf_t *dat = (mlme_scan_conf_t*)data;
stop_bootstrap_timer(info_entry);
info_entry->scan_cb(api->parent_id, dat);
break;
}
case MLME_SET:{
// mlme_set_conf_t *dat = (mlme_set_conf_t*)data;
break;
}
case MLME_START:{
// mlme_start_conf_t *dat = (mlme_start_conf_t*)data;
stop_bootstrap_timer(info_entry);
break;
}
case MLME_POLL:{
const mlme_poll_conf_t *dat = (mlme_poll_conf_t*)data;
mac_mlme_poll_confirm(info_entry, dat);
break;
}
case MLME_BEACON_NOTIFY:
case MLME_ORPHAN:
case MLME_COMM_STATUS:
case MLME_SYNC:
case MLME_SYNC_LOSS:
default:{
tr_error("Invalid state in mlme_confirm_handler(): %d", id);
break;
}
}
}
void mlme_indication_handler( const mac_api_t* api, mlme_primitive id, const void *data )
{
switch(id){
case MLME_ASSOCIATE:{
//Unsupported
//mlme_associate_ind_t *dat = (mlme_associate_ind_t*)data;
break;
}
case MLME_DISASSOCIATE:{
//Unsupported
//mlme_disassociate_ind_t *dat = (mlme_disassociate_ind_t*)data;
break;
}
case MLME_BEACON_NOTIFY:{
const mlme_beacon_ind_t *dat = (mlme_beacon_ind_t*)data;
protocol_interface_info_entry_t *info_entry = protocol_stack_interface_info_get_by_id(api->parent_id);
if( info_entry && info_entry->beacon_cb ){
info_entry->beacon_cb(api->parent_id, dat);
}
break;
}
case MLME_GTS:{
//Unsupported
break;
}
case MLME_ORPHAN:{
//Unsupported
break;
}
case MLME_COMM_STATUS:{
mlme_comm_status_t *dat = (mlme_comm_status_t*)data;
protocol_interface_info_entry_t *info_entry = protocol_stack_interface_info_get_by_id(api->parent_id);
if( info_entry && info_entry->comm_status_ind_cb ){
info_entry->comm_status_ind_cb(api->parent_id, dat);
}
break;
}
case MLME_SYNC_LOSS:{
mlme_sync_loss_t *dat = (mlme_sync_loss_t*)data;
protocol_interface_info_entry_t *info_entry = protocol_stack_interface_info_get_by_id(api->parent_id);
if (info_entry) {
if (dat->LossReason == BEACON_LOST) {
nwk_bootsrap_state_update(ARM_NWK_NWK_SCAN_FAIL, info_entry);
}
}
break;
}
case MLME_GET:
case MLME_RESET:
case MLME_RX_ENABLE:
case MLME_SCAN:
case MLME_SET:
case MLME_START:
case MLME_SYNC:
case MLME_POLL:
default:{
tr_error("Invalid state in mlme_indication_handler(): %d", id);
break;
}
}
}
bool mac_data_is_broadcast_addr(const sockaddr_t *addr)
{
return (addr->addr_type == ADDR_802_15_4_SHORT) &&
(addr->address[2] == 0xFF && addr->address[3] == 0xFF);
}

View File

@ -0,0 +1,36 @@
/*
* Copyright (c) 2016-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MAC_RESPONSE_HANDLER_H
#define MAC_RESPONSE_HANDLER_H
#include "mac_api.h"
struct mcps_data_ind_s;
struct mcps_data_conf_t;
void mcps_data_confirm_handler( const mac_api_t* api, const struct mcps_data_conf_s *data );
void mcps_data_indication_handler( const mac_api_t* api, const struct mcps_data_ind_s *data );
void mcps_purge_confirm_handler( const mac_api_t* api, mcps_purge_conf_t *data );
void mlme_confirm_handler( const mac_api_t* api, mlme_primitive id, const void *data );
void mlme_indication_handler( const mac_api_t* api, mlme_primitive id, const void *data );
#endif // MAC_RESPONSE_HANDLER_H

469
source/6LoWPAN/Mesh/mesh.c Normal file
View File

@ -0,0 +1,469 @@
/*
* Copyright (c) 2014-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* \file mesh.c
* \brief 6LoWPAN Mesh header handling (RFC 4944: S5.2, S11)
*
*/
#include "nsconfig.h"
#include <string.h>
#include <ns_types.h>
#include <ns_list.h>
#include "ns_trace.h"
#include "common_functions.h"
#include "NWK_INTERFACE/Include/protocol.h"
#include "NWK_INTERFACE/Include/protocol_stats.h"
#include "6LoWPAN/IPHC_Decode/cipv6.h"
#include "Core/include/socket.h"
#include "6LoWPAN/Mesh/mesh.h"
#include "6LoWPAN/MAC/mac_helper.h"
#define TRACE_GROUP "mesh"
#ifdef HAVE_MESH
/* Nit - this should really be per-interface */
static uint8_t mesh_bc0_sequence;
/* Thread wants to treat RFC 4944 S.9 multicast addresses as unicast, so
* have to allow a hook to disable multicast functionality. (Also, should
* really be per-interface)
*/
static bool support_mesh_multicast = true;
bool mesh_supports_multicast(void)
{
return support_mesh_multicast;
}
void mesh_all_addresses_unicast(bool flag)
{
support_mesh_multicast = !flag;
}
bool mesh_short_address_is_multicast(uint16_t addr)
{
return ((addr & 0xE000) == 0x8000) && support_mesh_multicast;
}
bool mesh_short_address_is_broadcast_or_multicast(uint16_t addr)
{
return addr == 0xffff || mesh_short_address_is_multicast(addr);
}
buffer_t *mesh_up(buffer_t *buf)
{
uint8_t *ptr = buffer_data_pointer(buf);
uint_fast16_t len = buffer_data_length(buf);
uint_fast8_t orig_addrlen, final_addrlen, last_hop_addrlen;
uint_fast8_t hops;
const uint8_t *orig_addr, *final_addr, *last_hop_addr;
bool for_us = false;
protocol_interface_info_entry_t *cur = buf->interface;
if (!cur) {
goto drop;
}
/* Sanity check - must have 5 bytes (header + 2x16-bit addresses) */
if (len < 5) {
goto drop;
}
orig_addrlen = ptr[0] & 0x20 ? 2 : 8;
final_addrlen = ptr[0] & 0x10 ? 2 : 8;
hops = ptr[0] & 0x0F;
ptr++, len--;
/* Hops up to 14 can be stored in first byte; can use extra byte for more */
if (hops == 0x0F) {
hops = *ptr++;
len--;
}
if (hops == 0) {
goto drop;
}
if (len < orig_addrlen + final_addrlen) {
goto drop;
}
orig_addr = ptr;
ptr += orig_addrlen;
final_addr = ptr;
ptr += final_addrlen;
/* Also consume any BC0 header (we don't need its contents) */
if (len >= 2 && ptr[0] == LOWPAN_DISPATCH_BC0) {
ptr += 2;
}
/* Routing functions may need to see last hop to avoid loops */
last_hop_addrlen = buf->src_sa.addr_type == ADDR_802_15_4_LONG ? 8 : 2;
last_hop_addr = buf->src_sa.address + 2;
if (!for_us && final_addrlen == 2) {
uint16_t addr = common_read_16_bit(final_addr);
/* At this layer, we accept all broadcasts, and all multicasts.
* No point in software filtering multicasts here - let the higher
* layers do it. Simplifies code below too.
*/
if (mesh_short_address_is_broadcast_or_multicast(addr)) {
if (addr == 0xFFFF) {
buf->options.ll_broadcast_rx = true;
} else {
buf->options.ll_broadcast_rx = false;
buf->options.ll_multicast_rx = true;
}
for_us = true;
/* Potentially let a multicast forwarder deal with it too - if they
* want to retransmit, they'll have to take a copy.
*/
if (cur->mesh_callbacks && cur->mesh_callbacks->multicast) {
cur->mesh_callbacks->multicast(cur, addr, buf);
}
} else if (addr == 0xFFFE) { /* definitely reserved */
goto drop;
} else if ((addr & 0x8000) && mesh_supports_multicast()) {
/* Reserved, but allow use as unicast if mesh_supports_multicast() is false */
goto drop;
}
}
/* Mirror IP's behaviour with respect to link-layer addresses - it doesn't
* like receiving IP unicasts that aren't link-layer unicasts. Similarly,
* we don't like receiving mesh unicasts that aren't IEEE 802.15.4 unicasts.
*/
if (!for_us && buf->options.ll_broadcast_rx) {
goto drop;
}
if (!for_us) {
for_us = nwk_interface_compare_mac_address(cur, final_addrlen, final_addr);
}
if (for_us) {
intercept:
/* Set the source MAC address from the Mesh header */
/* XXX any more sanity checks needed here? */
buf->src_sa.addr_type = orig_addrlen == 2 ? ADDR_802_15_4_SHORT : ADDR_802_15_4_LONG;
/* src_sa is in 802.15.4 header form - ie 2-byte PAN ID, followed by
* 2 or 8 byte address. Leave PAN ID in place and overwrite address */
memcpy(buf->src_sa.address + 2, orig_addr, orig_addrlen);
/* Set the buffer dest MAC address from the Mesh header */
buf->dst_sa.addr_type = final_addrlen == 2 ? ADDR_802_15_4_SHORT : ADDR_802_15_4_LONG;
memcpy(buf->dst_sa.address + 2, final_addr, final_addrlen);
buf->options.lowpan_mesh_rx = true;
/* Remove the Mesh header */
buffer_data_pointer_set(buf, ptr);
/* XXX check - any side-effects of not being B_FROM_MAC? */
buf->info = (buffer_info_t)(B_DIR_UP | B_FROM_MESH_ROUTING | B_TO_IPV6_TXRX);
return buf;
}
/* Now we know it's not addressed to us, we can check security - had
* to allow bypass so far for MLE packets to us.
*/
if (buf->options.ll_security_bypass_rx) {
goto drop;
}
/* We are not the final destination; if we've been given no routing
* routing function pointer, then we just drop the packet. */
if (!cur->mesh_callbacks || !cur->mesh_callbacks->route) {
goto drop;
}
/*
* Note that all multicast/broadcast are treated as "for us", so only
* unicasts reach here.
*/
/* Do not forward unicast packets that were sent to a broadcast address */
if (addr_check_broadcast(buf->dst_sa.address, buf->dst_sa.addr_type) == 0) {
goto drop;
}
/* Decrement and check the hops count */
if (--hops == 0) {
goto drop;
}
/* Ask the routing function where to send this */
mesh_routing_route_response_t route;
route.intercept = false;
if (cur->mesh_callbacks->route(cur, last_hop_addrlen, last_hop_addr, final_addrlen, final_addr, &route)) {
goto drop;
}
/* If the function says to intercept the packet, do so */
if (route.intercept) {
buf->options.ll_not_ours_rx = true;
goto intercept;
}
/* Rewind to rewrite the Mesh Hops Left field */
ptr = buffer_data_pointer(buf);
if ((ptr[0] & 0x0F) != 0x0F) {
/* Modify 4-bit hops field */
ptr[0] = (ptr[0] & 0xF0) | hops;
} else {
/* Modify 8-bit hops field */
if (hops < 0x0F) {
/* 8 bits no longer needed - convert to 4-bit header, save a byte */
ptr[1] = (ptr[0] & 0xF0) | hops;
buffer_data_strip_header(buf, 1);
} else {
ptr[1] = hops;
}
}
/* Set dest MAC address from routing response */
buf->dst_sa.addr_type = route.addr_len == 2 ? ADDR_802_15_4_SHORT : ADDR_802_15_4_LONG;
memcpy(buf->dst_sa.address + 2, route.address, route.addr_len);
/* Set src MAC address from our interface */
if (!mac_helper_write_our_addr(cur, &buf->src_sa)) {
goto drop;
}
/* Send back down to MAC */
buf->ip_routed_up = true;
buf->info = (buffer_info_t)(B_FROM_MESH_ROUTING | B_TO_MAC);
buf->options.code = 0;
return buf;
drop:
protocol_stats_update(STATS_IP_RX_DROP, 1);
return buffer_free(buf);
}
static bool always_add_mesh_header_as_originator;
void force_mesh_headers(bool force)
{
always_add_mesh_header_as_originator = force;
}
bool mesh_forwardable_address(const protocol_interface_info_entry_t *cur, addrtype_t addr_type, const uint8_t *addr)
{
if (cur->mesh_callbacks) {
if (cur->mesh_callbacks->forwardable_address) {
return cur->mesh_callbacks->forwardable_address(cur, addr_type, addr);
}
/* Default to true if no callback */
return true;
}
return false;
}
bool mesh_address_map(protocol_interface_info_entry_t *cur, addrtype_t *addr_type, uint8_t *addr)
{
if (cur->mesh_callbacks && cur->mesh_callbacks->address_map) {
return cur->mesh_callbacks->address_map(cur, addr_type, addr);
}
/* Default to true if no callback - address is untouched */
return true;
}
bool mesh_header_needed(const buffer_t *buf)
{
protocol_interface_info_entry_t *cur;
if (always_add_mesh_header_as_originator) {
return true;
}
cur = buf->interface;
if (cur && cur->mesh_callbacks && cur->mesh_callbacks->header_needed) {
if (cur->mesh_callbacks->header_needed(cur, buf)) {
return true;
}
}
return false;
}
uint_fast8_t mesh_header_size(const buffer_t *buf)
{
if (!mesh_header_needed(buf)) {
return 0;
}
uint_fast8_t hdrlen = 1;
if (MESH_DEFAULT_HOPS_LEFT > 14) {
hdrlen++;
}
if (buf->src_sa.addr_type == ADDR_802_15_4_LONG) {
hdrlen += 8;
} else {
hdrlen += 2;
}
if (buf->dst_sa.addr_type == ADDR_802_15_4_LONG) {
hdrlen += 8;
} else {
hdrlen += 2;
if (buf->dst_sa.addr_type == ADDR_BROADCAST) {
hdrlen += 2; // LOWPAN_BC0 header
}
}
return hdrlen;
}
uint_fast8_t mesh_header_len_from_type_byte(uint8_t type)
{
if ((type & LOWPAN_MESH_MASK) != LOWPAN_MESH) {
return 0;
}
uint_fast8_t hdrlen = 1;
hdrlen += type & 0x20 ? 2 : 8;
hdrlen += type & 0x10 ? 2 : 8;
if ((type & 0x0F) == 0x0F) {
hdrlen += 1;
}
return hdrlen;
}
uint_fast8_t mesh_header_len_from_buffer_type_byte(const buffer_t *buf)
{
if (buffer_data_length(buf) == 0) {
return 0;
}
uint8_t type = buffer_data_pointer(buf)[0];
return mesh_header_len_from_type_byte(type);
}
/* If header points to a Mesh Header, and it has a following BC0 header, give
* it a new sequence number.
*/
void mesh_rewrite_bc0_header(uint8_t *header)
{
uint_fast8_t mesh_len = mesh_header_len_from_type_byte(header[0]);
if (mesh_len) {
header += mesh_len;
if (header[0] == LOWPAN_DISPATCH_BC0) {
header[1] = mesh_bc0_sequence++;
}
}
}
/* On entry, buf is an unfragmented 6LoWPAN packet, starting with an
* IPHC header.
* buf->dst_sa is set, and type may be ADDR_802_15_4_SHORT, LONG or BROADCAST
* (if BROADCAST, it may contain a RFC 4944 S.9 multicast address)
* buf->src_sa is set, and type may be ADDR_802_15_4_SHORT or LONG
*/
buffer_t *mesh_down(buffer_t *buf)
{
protocol_interface_info_entry_t *cur;
uint8_t mesh_sz = mesh_header_size(buf);
if (mesh_sz == 0) {
/* Shouldn't have come here - should have gone straight to MAC */
tr_error("mesh_down unexpected");
return buffer_free(buf);
}
buf = buffer_headroom(buf, mesh_sz);
if (!buf) {
tr_warn("mesh_down headroom");
return NULL;
}
cur = buf->interface;
if (!cur) {
return buffer_free(buf);
}
uint8_t *ptr = buffer_data_reserve_header(buf, mesh_sz);
uint_fast8_t src_addrlen = 8, dst_addrlen = 8;
*ptr = LOWPAN_MESH;
if (buf->src_sa.addr_type != ADDR_802_15_4_LONG) {
/* Source is ADDR_802_15_4_SHORT */
*ptr |= 0x20;
src_addrlen = 2;
}
if (buf->dst_sa.addr_type != ADDR_802_15_4_LONG) {
/* Dest is ADDR_802_15_4_SHORT or ADDR_BROADCAST */
*ptr |= 0x10;
dst_addrlen = 2;
}
if (MESH_DEFAULT_HOPS_LEFT > 14) {
*ptr++ |= 0xF;
*ptr++ = MESH_DEFAULT_HOPS_LEFT;
} else {
*ptr++ |= MESH_DEFAULT_HOPS_LEFT;
}
memcpy(ptr, buf->src_sa.address + 2, src_addrlen);
ptr += src_addrlen;
memcpy(ptr, buf->dst_sa.address + 2, dst_addrlen);
ptr += dst_addrlen;
if (buf->dst_sa.addr_type == ADDR_BROADCAST) {
/* Multicast or broadcast */
*ptr++ = LOWPAN_DISPATCH_BC0;
*ptr++ = mesh_bc0_sequence++;
/* We've noted any multicast address in the mesh header; for the MAC
* it has to be a broadcast. (Actually, in principle could unicast
* if the routing said it was appropriate, but RFC 4944 says broadcast)
*/
common_write_16_bit(0xffff, buf->dst_sa.address + 2);
} else {
/* Determine first hop - default behaviour is to just transmit to the
* final destination (useful for testing). But if we have a first-hop
* function, ask it where to send it. If it doesn't know, then drop the
* packet.
*/
if (cur->mesh_callbacks && cur->mesh_callbacks->first_hop) {
mesh_routing_route_response_t route;
if (cur->mesh_callbacks->first_hop(cur, dst_addrlen, buf->dst_sa.address + 2, &route)) {
tr_warn("mesh_down no first hop to %s", trace_array(buf->dst_sa.address + 2, dst_addrlen));
socket_tx_buffer_event_and_free(buf, SOCKET_NO_ROUTE);
return NULL;
}
/* Modify buffer dest MAC address to first hop response */
buf->dst_sa.addr_type = route.addr_len == 2 ? ADDR_802_15_4_SHORT : ADDR_802_15_4_LONG;
memcpy(buf->dst_sa.address + 2, route.address, route.addr_len);
}
}
/* We're the originator here, so address in buf->src_sa that we already used
* as in the Mesh header is also what we want in the MAC header */
buf->info = (buffer_info_t)(B_FROM_MESH_ROUTING | B_TO_MAC | B_DIR_DOWN);
buf->options.code = 0;
return buf;
}
#endif

View File

@ -0,0 +1,84 @@
/*
* Copyright (c) 2014-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MESH_H_
#define MESH_H_
#ifdef __cplusplus
extern "C" {
#endif
/* Thread network has routing cost limit 16. */
#ifndef MESH_DEFAULT_HOPS_LEFT
#define MESH_DEFAULT_HOPS_LEFT 16
#endif
typedef struct mesh_routing_route_response_s {
uint8_t addr_len;
uint8_t address[8];
bool intercept;
} mesh_routing_route_response_t;
typedef int_fast8_t mesh_first_hop_fn_t(protocol_interface_info_entry_t *cur,
uint_fast8_t dest_addr_len, const uint8_t dest_addr[],
mesh_routing_route_response_t *resp);
typedef int_fast8_t mesh_route_fn_t(protocol_interface_info_entry_t *cur,
uint_fast8_t last_hop_addr_len, const uint8_t last_hop_addr[],
uint_fast8_t dest_addr_len, const uint8_t dest_addr[],
mesh_routing_route_response_t *resp);
typedef int_fast8_t mesh_multicast_fn_t(protocol_interface_info_entry_t *cur, uint16_t addr, buffer_t *buf);
typedef bool mesh_header_needed_fn_t(const protocol_interface_info_entry_t *cur, const buffer_t *buf);
typedef bool mesh_forwardable_address_t(const protocol_interface_info_entry_t *cur, addrtype_t addr_type, const uint8_t *addr);
typedef bool mesh_address_map_fn_t(protocol_interface_info_entry_t *cur, addrtype_t *addr_type, uint8_t *addr);
typedef struct mesh_callbacks_s {
mesh_first_hop_fn_t *first_hop;
mesh_route_fn_t *route;
mesh_multicast_fn_t *multicast;
mesh_header_needed_fn_t *header_needed;
mesh_forwardable_address_t *forwardable_address;
mesh_address_map_fn_t *address_map;
} mesh_callbacks_t;
#ifdef HAVE_MESH
buffer_t *mesh_up(buffer_t *buf);
buffer_t *mesh_down(buffer_t *buf);
bool mesh_address_map(protocol_interface_info_entry_t *cur, addrtype_t *addr_type, uint8_t *addr);
bool mesh_forwardable_address(const protocol_interface_info_entry_t *cur, addrtype_t addr_type, const uint8_t *addr);
bool mesh_header_needed(const buffer_t *buf);
bool mesh_supports_multicast(void);
void mesh_all_addresses_unicast(bool flag);
bool mesh_short_address_is_multicast(uint16_t addr);
bool mesh_short_address_is_broadcast_or_multicast(uint16_t addr);
void mesh_rewrite_bc0_header(uint8_t *header);
uint_fast8_t mesh_header_size(const buffer_t *buf);
uint_fast8_t mesh_header_len_from_type_byte(uint8_t type);
uint_fast8_t mesh_header_len_from_buffer_type_byte(const buffer_t *buf);
#else
#define mesh_address_map(cur, addr_type, addr) true
#define mesh_forwardable_address(cur, addr_type, addr) false
#define mesh_header_needed(buf) false
#define mesh_rewrite_bc0_header(header) ((void) 0)
#define mesh_header_size(buf) false
#define mesh_header_len_from_type_byte(type) 0
#endif
#ifdef __cplusplus
}
#endif
#endif /* MESH_H_ */

View File

@ -0,0 +1,94 @@
/*
* Copyright (c) 2014-2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ND_DEFINES_H_
#define ND_DEFINES_H_
#include "Core/include/address.h"
#include "ns_list.h"
#include "6LoWPAN/IPHC_Decode/lowpan_context.h"
#include "Common_Protocols/icmpv6_prefix.h"
typedef enum {
ND_READY = 0,
ND_BR_READY = 1,
ND_RS_UNCAST = 2,
ND_RS_MULTICAST = 3,
} nd_obj_state;
#define nd_is_ready_state(state) ((state) == ND_READY || (state) == ND_BR_READY)
#define nd_is_bootstrap_state(state) (!nd_is_ready_state(state))
typedef enum {
ND_ADDRESS_PRIMARY = 0,
ND_ADDRESS_SECONDARY = 1,
} nd_multi_address_type;
typedef struct nd_router_next_hop {
addrtype_t addrtype;
uint8_t address[8];
uint8_t LQI;
} nd_router_next_hop;
// This structure conflates a few things, confusingly. It's basically
// a "per-border-router"/"per-ABRO" (RFC 6775) structure.
// This is sensible for a 6LR, which has to store prefixes and contexts
// per-ABRO for relaying, and needs to time them out, but it's not the same
// structure needed as a host (or for the host part of the router). For a host,
// contexts and prefixes and addresses are needed per-interface, and they
// shouldn't time out just because an ABRO timed out.
// Also, because of this structure, we always end up requiring ABROs as a host,
// which isn't really necessary.
// This also isn't the RFC 4861 "Default Router List", alas.
// Note also that this is used both to describe a remote border router, and
// ourselves as a border router, with some confusing effects on lifetimes
// (we're in danger of timing ourselves out as a border router)
typedef struct nd_router {
nwk_interface_id nwk_id;
uint8_t border_router[16];
uint8_t flags;
uint16_t life_time;
uint16_t nd_re_validate;
nd_obj_state nd_state;
uint16_t ns_forward_timer;
uint16_t nd_timer;
uint16_t mle_advert_timer;
uint8_t mle_purge_timer;
uint8_t nd_bootstrap_tick;
uint8_t ns_retry;
uint32_t abro_version_num;
bool trig_address_reg;
ipv6_ra_timing_t ra_timing;
prefix_list_t prefix_list;
lowpan_context_list_t context_list;
nd_router_next_hop default_hop;
nd_router_next_hop *secondaty_hop;
ns_list_link_t link;
} nd_router_t;
/* XXX why isn't this a substructure of nd_router_t? or share one */
typedef struct nd_router_setup {
uint16_t life_time;
uint32_t abro_version_num;
prefix_list_t prefix_list;
lowpan_context_list_t context_list;
} nd_router_setup_t;
#endif /* ND_DEFINES_H_ */

Some files were not shown because too many files have changed in this diff Show More