Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8bb9a2772a | ||
|
|
3dc9fd0b82 | ||
|
|
c0c089314b | ||
|
|
9f6a7d97bc | ||
|
|
0bba81df36 | ||
|
|
2377ada11a | ||
|
|
b7e72c3a0a | ||
|
|
c1d4837b6f | ||
|
|
bc0e617e48 | ||
|
|
5bafd2c7c4 | ||
|
|
13d582abec | ||
|
|
d82134b850 | ||
|
|
ebc20f6000 | ||
|
|
fdc0645d77 | ||
|
|
e1cf4ba46a | ||
|
|
6bead9b6de | ||
|
|
f3bc3ae906 | ||
|
|
a158370ecb | ||
|
|
34b2b57831 | ||
|
|
1f237abbf1 | ||
|
|
3a2339a1b4 | ||
|
|
1752159ae0 | ||
|
|
4995bf960d | ||
|
|
c68b2e8a46 | ||
|
|
c29eb7f50e | ||
|
|
9d283adac4 | ||
|
|
b93fb6c831 | ||
|
|
8f290fc884 | ||
|
|
cb27d91658 | ||
|
|
9cec699867 | ||
|
|
d656aff913 | ||
|
|
22974904d3 | ||
|
|
69857c37c2 | ||
|
|
feeb918ea8 | ||
|
|
13ff259ec8 | ||
|
|
cb6551e96f | ||
|
|
56c68a364a | ||
|
|
51cf75c8f0 | ||
|
|
854866f424 | ||
|
|
32f7eac7cd | ||
|
|
5ab4cf83d9 | ||
|
|
f3ee808927 | ||
|
|
97f26a2618 | ||
|
|
e89118e8be |
No files matched your search
+1
-1
@@ -26,4 +26,4 @@ __pycache__/
|
||||
*.py[cod]
|
||||
|
||||
# Other
|
||||
/VERSION
|
||||
/VERSION.info
|
||||
@@ -1,9 +1,14 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
source .jenkins.d/util.sh
|
||||
|
||||
export CACHE_DIR=${CACHE_DIR:-/tmp}
|
||||
export WAF_JOBS=${WAF_JOBS:-1}
|
||||
[[ $JOB_NAME == *"code-coverage" ]] && export DISABLE_ASAN=yes
|
||||
|
||||
nanos() {
|
||||
# Cannot use date(1) because macOS does not support %N format specifier
|
||||
python -c 'import time; print(int(time.time() * 1e9))'
|
||||
python3 -c 'import time; print(int(time.time() * 1e9))'
|
||||
}
|
||||
|
||||
for file in .jenkins.d/*; do
|
||||
|
||||
+29
-36
@@ -1,48 +1,41 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
JDIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||
source "$JDIR"/util.sh
|
||||
|
||||
set -x
|
||||
set -ex
|
||||
|
||||
if has OSX $NODE_LABELS; then
|
||||
FORMULAE=(boost openssl pkg-config)
|
||||
brew update
|
||||
if [[ -n $TRAVIS ]]; then
|
||||
# Travis images come with a large number of brew packages
|
||||
# pre-installed, don't waste time upgrading all of them
|
||||
for FORMULA in "${FORMULAE[@]}"; do
|
||||
brew outdated $FORMULA || brew upgrade $FORMULA
|
||||
done
|
||||
else
|
||||
brew upgrade
|
||||
if has OSX-10.13 $NODE_LABELS || has OSX-10.14 $NODE_LABELS; then
|
||||
FORMULAE+=(python)
|
||||
fi
|
||||
brew install "${FORMULAE[@]}"
|
||||
brew cleanup
|
||||
fi
|
||||
|
||||
if has Ubuntu $NODE_LABELS; then
|
||||
if [[ -n $TRAVIS ]]; then
|
||||
# Travis images come with a large number of pre-installed
|
||||
# brew packages, don't waste time upgrading all of them
|
||||
brew list --versions "${FORMULAE[@]}" || brew update
|
||||
for FORMULA in "${FORMULAE[@]}"; do
|
||||
brew list --versions "$FORMULA" || brew install "$FORMULA"
|
||||
done
|
||||
# Ensure /usr/local/opt/openssl exists
|
||||
brew reinstall openssl
|
||||
else
|
||||
brew update
|
||||
brew upgrade
|
||||
brew install "${FORMULAE[@]}"
|
||||
brew cleanup
|
||||
fi
|
||||
|
||||
elif has Ubuntu $NODE_LABELS; then
|
||||
sudo apt-get -qq update
|
||||
sudo apt-get -qy install build-essential pkg-config libboost-all-dev \
|
||||
libsqlite3-dev libssl-dev libpcap-dev libsystemd-dev
|
||||
sudo apt-get -qy install build-essential pkg-config python3-minimal \
|
||||
libboost-all-dev libssl-dev libsqlite3-dev \
|
||||
libpcap-dev libsystemd-dev
|
||||
|
||||
if [[ $JOB_NAME == *"code-coverage" ]]; then
|
||||
sudo apt-get -qy install gcovr lcov libgd-perl
|
||||
sudo apt-get -qy install gcovr lcov
|
||||
fi
|
||||
fi
|
||||
|
||||
if has CentOS-7 $NODE_LABELS; then
|
||||
sudo yum -y install yum-utils pkgconfig \
|
||||
openssl-devel libtranslit-icu \
|
||||
python-devel sqlite-devel \
|
||||
libpcap-devel systemd-devel \
|
||||
devtoolset-7-libasan-devel \
|
||||
devtoolset-7-liblsan-devel
|
||||
sudo yum -y groupinstall 'Development Tools'
|
||||
|
||||
svn checkout https://github.com/cmscaltech/sandie-ndn/trunk/packaging/RPMS/x86_64/boost1_58_0
|
||||
pushd boost1_58_0 >/dev/null
|
||||
sudo rpm -Uv --replacepkgs --replacefiles boost-devel* boost-license* libboost_*
|
||||
popd >/dev/null
|
||||
elif has CentOS-8 $NODE_LABELS; then
|
||||
sudo dnf config-manager --enable PowerTools
|
||||
sudo dnf -y install gcc-c++ libasan pkgconf-pkg-config python3 \
|
||||
boost-devel openssl-devel sqlite-devel \
|
||||
libpcap-devel systemd-devel
|
||||
fi
|
||||
+17
-18
@@ -1,12 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
set -ex
|
||||
|
||||
JDIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||
source "$JDIR"/util.sh
|
||||
|
||||
set -x
|
||||
|
||||
pushd "${CACHE_DIR:-/tmp}" >/dev/null
|
||||
pushd "$CACHE_DIR" >/dev/null
|
||||
|
||||
INSTALLED_VERSION=
|
||||
if has OSX $NODE_LABELS; then
|
||||
@@ -22,17 +17,15 @@ if [[ -z $INSTALLED_VERSION ]]; then
|
||||
INSTALLED_VERSION=$(git -C ndn-cxx rev-parse HEAD 2>/dev/null || echo NONE)
|
||||
fi
|
||||
|
||||
sudo rm -Rf ndn-cxx-latest
|
||||
|
||||
git clone --depth 1 git://github.com/named-data/ndn-cxx ndn-cxx-latest
|
||||
|
||||
sudo rm -rf ndn-cxx-latest
|
||||
git clone --depth 1 https://github.com/named-data/ndn-cxx.git ndn-cxx-latest
|
||||
LATEST_VERSION=$(git -C ndn-cxx-latest rev-parse HEAD 2>/dev/null || echo UNKNOWN)
|
||||
|
||||
if [[ $INSTALLED_VERSION != $LATEST_VERSION ]]; then
|
||||
sudo rm -Rf ndn-cxx
|
||||
sudo rm -rf ndn-cxx
|
||||
mv ndn-cxx-latest ndn-cxx
|
||||
else
|
||||
sudo rm -Rf ndn-cxx-latest
|
||||
sudo rm -rf ndn-cxx-latest
|
||||
fi
|
||||
|
||||
sudo rm -f /usr/local/bin/ndnsec*
|
||||
@@ -42,15 +35,21 @@ sudo rm -f /usr/local/lib{,64}/pkgconfig/libndn-cxx.pc
|
||||
|
||||
pushd ndn-cxx >/dev/null
|
||||
|
||||
./waf configure --color=yes --enable-shared --disable-static --without-osx-keychain
|
||||
./waf build --color=yes -j${WAF_JOBS:-1}
|
||||
sudo_preserve_env PATH -- ./waf install --color=yes
|
||||
if has CentOS-8 $NODE_LABELS; then
|
||||
# https://bugzilla.redhat.com/show_bug.cgi?id=1721553
|
||||
PCH="--without-pch"
|
||||
fi
|
||||
|
||||
./waf --color=yes configure --disable-static --enable-shared --without-osx-keychain $PCH
|
||||
./waf --color=yes build -j$WAF_JOBS
|
||||
sudo_preserve_env PATH -- ./waf --color=yes install
|
||||
|
||||
popd >/dev/null
|
||||
popd >/dev/null
|
||||
|
||||
if has CentOS-8 $NODE_LABELS; then
|
||||
sudo tee /etc/ld.so.conf.d/ndn.conf >/dev/null <<< /usr/local/lib64
|
||||
fi
|
||||
if has Linux $NODE_LABELS; then
|
||||
sudo ldconfig
|
||||
elif has FreeBSD10 $NODE_LABELS; then
|
||||
sudo ldconfig -m
|
||||
fi
|
||||
+29
-33
@@ -1,45 +1,41 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
set -ex
|
||||
|
||||
JDIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||
source "$JDIR"/util.sh
|
||||
|
||||
set -x
|
||||
|
||||
git submodule init
|
||||
git submodule sync
|
||||
git submodule update
|
||||
git submodule update --init
|
||||
|
||||
if [[ $JOB_NAME == *"code-coverage" ]]; then
|
||||
COVERAGE="--with-coverage"
|
||||
elif [[ -z $DISABLE_ASAN ]]; then
|
||||
if [[ -z $DISABLE_ASAN ]]; then
|
||||
ASAN="--with-sanitizer=address"
|
||||
fi
|
||||
|
||||
# Cleanup
|
||||
sudo_preserve_env PATH -- ./waf --color=yes distclean
|
||||
|
||||
if [[ $JOB_NAME != *"code-coverage" && $JOB_NAME != *"limited-build" ]]; then
|
||||
# Configure/build in optimized mode with tests
|
||||
./waf --color=yes configure --with-tests
|
||||
./waf --color=yes build -j${WAF_JOBS:-1}
|
||||
|
||||
# Cleanup
|
||||
sudo_preserve_env PATH -- ./waf --color=yes distclean
|
||||
|
||||
# Configure/build in optimized mode without tests, but with "other tests"
|
||||
./waf --color=yes configure --with-other-tests
|
||||
./waf --color=yes build -j${WAF_JOBS:-1}
|
||||
|
||||
# Cleanup
|
||||
sudo_preserve_env PATH -- ./waf --color=yes distclean
|
||||
if [[ $JOB_NAME == *"code-coverage" ]]; then
|
||||
COVERAGE="--with-coverage"
|
||||
fi
|
||||
if has CentOS-8 $NODE_LABELS; then
|
||||
# https://bugzilla.redhat.com/show_bug.cgi?id=1721553
|
||||
PCH="--without-pch"
|
||||
fi
|
||||
|
||||
# Configure/build in debug mode with tests and without precompiled headers
|
||||
./waf --color=yes configure --debug --with-tests --without-pch $ASAN $COVERAGE
|
||||
./waf --color=yes build -j${WAF_JOBS:-1}
|
||||
if [[ $JOB_NAME != *"code-coverage" && $JOB_NAME != *"limited-build" ]]; then
|
||||
# Build in release mode with tests and without precompiled headers
|
||||
./waf --color=yes configure --with-tests --without-pch
|
||||
./waf --color=yes build -j$WAF_JOBS
|
||||
|
||||
# (tests will be run against debug version)
|
||||
# Cleanup
|
||||
./waf --color=yes distclean
|
||||
|
||||
# Build in release mode without tests, but with "other tests"
|
||||
./waf --color=yes configure --with-other-tests $PCH
|
||||
./waf --color=yes build -j$WAF_JOBS
|
||||
|
||||
# Cleanup
|
||||
./waf --color=yes distclean
|
||||
fi
|
||||
|
||||
# Build in debug mode with tests
|
||||
./waf --color=yes configure --debug --with-tests $ASAN $COVERAGE $PCH
|
||||
./waf --color=yes build -j$WAF_JOBS
|
||||
|
||||
# (tests will be run against the debug version)
|
||||
|
||||
# Install
|
||||
sudo_preserve_env PATH -- ./waf --color=yes install
|
||||
+15
-29
@@ -1,13 +1,8 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
JDIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||
source "$JDIR"/util.sh
|
||||
|
||||
set -x
|
||||
set -ex
|
||||
|
||||
# Prepare environment
|
||||
rm -Rf ~/.ndn
|
||||
rm -rf ~/.ndn
|
||||
|
||||
if has OSX $NODE_LABELS; then
|
||||
security unlock-keychain -p named-data
|
||||
@@ -15,34 +10,25 @@ fi
|
||||
|
||||
ndnsec-keygen "/tmp/jenkins/$NODE_NAME" | ndnsec-install-cert -
|
||||
|
||||
BOOST_VERSION=$(python -c "import sys; sys.path.append('build/c4che'); import _cache; print(_cache.BOOST_VERSION_NUMBER);")
|
||||
|
||||
ut_log_args() {
|
||||
if (( BOOST_VERSION >= 106200 )); then
|
||||
echo --logger=HRF,test_suite,stdout:XML,all,build/xunit-${1:-report}.xml
|
||||
else
|
||||
if [[ -n $XUNIT ]]; then
|
||||
echo --log_level=all $( (( BOOST_VERSION >= 106000 )) && echo -- ) \
|
||||
--log_format2=XML --log_sink2=build/xunit-${1:-report}.xml
|
||||
else
|
||||
echo --log_level=test_suite
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# https://github.com/google/sanitizers/wiki/AddressSanitizerFlags
|
||||
ASAN_OPTIONS="color=always"
|
||||
ASAN_OPTIONS+=":detect_leaks=false"
|
||||
ASAN_OPTIONS+=":detect_stack_use_after_return=true"
|
||||
ASAN_OPTIONS+=":check_initialization_order=true"
|
||||
ASAN_OPTIONS+=":strict_init_order=true"
|
||||
ASAN_OPTIONS+=":detect_invalid_pointer_pairs=1"
|
||||
ASAN_OPTIONS+=":detect_container_overflow=false"
|
||||
ASAN_OPTIONS+=":strict_string_checks=true"
|
||||
ASAN_OPTIONS+=":check_initialization_order=1"
|
||||
ASAN_OPTIONS+=":detect_stack_use_after_return=1"
|
||||
ASAN_OPTIONS+=":strict_init_order=1"
|
||||
ASAN_OPTIONS+=":strict_string_checks=1"
|
||||
ASAN_OPTIONS+=":detect_invalid_pointer_pairs=2"
|
||||
ASAN_OPTIONS+=":detect_container_overflow=0"
|
||||
ASAN_OPTIONS+=":detect_leaks=0"
|
||||
ASAN_OPTIONS+=":strip_path_prefix=${PWD}/"
|
||||
export ASAN_OPTIONS
|
||||
|
||||
export BOOST_TEST_BUILD_INFO=1
|
||||
export BOOST_TEST_COLOR_OUTPUT=1
|
||||
export BOOST_TEST_DETECT_MEMORY_LEAK=0
|
||||
|
||||
ut_log_args() {
|
||||
echo --logger=HRF,test_suite,stdout:XML,all,build/xunit-log${1:+-$1}.xml
|
||||
}
|
||||
|
||||
# First run all tests as unprivileged user
|
||||
./build/unit-tests-core $(ut_log_args core)
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
JDIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||
source "$JDIR"/util.sh
|
||||
|
||||
set -x
|
||||
set -ex
|
||||
|
||||
if [[ $JOB_NAME == *"code-coverage" ]]; then
|
||||
gcovr --object-directory=build \
|
||||
@@ -33,7 +28,6 @@ if [[ $JOB_NAME == *"code-coverage" ]]; then
|
||||
|
||||
genhtml --branch-coverage \
|
||||
--demangle-cpp \
|
||||
--frames \
|
||||
--legend \
|
||||
--output-directory build/coverage \
|
||||
--title "NFD unit tests" \
|
||||
|
||||
+16
-24
@@ -1,36 +1,28 @@
|
||||
CONTINUOUS INTEGRATION SCRIPTS
|
||||
==============================
|
||||
# CONTINUOUS INTEGRATION SCRIPTS
|
||||
|
||||
Environment Variables Used in Build Scripts
|
||||
-------------------------------------------
|
||||
## Environment Variables Used in Build Scripts
|
||||
|
||||
- `NODE_LABELS`: the variable defines a list of OS properties. The set values are used by the
|
||||
build scripts to select proper behavior for different OS.
|
||||
- `NODE_LABELS`: space-separated list of platform properties. The included values are used by
|
||||
the build scripts to select the proper behavior for different operating systems and versions.
|
||||
|
||||
The list should include at least `[OS_TYPE]`, `[DISTRO_TYPE]`, and `[DISTRO_VERSION]`.
|
||||
The list should normally contain `[OS_TYPE]`, `[DISTRO_TYPE]`, and `[DISTRO_VERSION]`.
|
||||
|
||||
Possible values for Linux:
|
||||
Example values:
|
||||
|
||||
* `[OS_TYPE]`: `Linux`
|
||||
* `[DISTRO_TYPE]`: `Ubuntu`
|
||||
* `[DISTRO_VERSION]`: `Ubuntu-16.04`, `Ubuntu-18.04`
|
||||
- `[OS_TYPE]`: `Linux`, `OSX`
|
||||
- `[DISTRO_TYPE]`: `Ubuntu`, `CentOS`
|
||||
- `[DISTRO_VERSION]`: `Ubuntu-16.04`, `Ubuntu-18.04`, `CentOS-8`, `OSX-10.14`, `OSX-10.15`
|
||||
|
||||
Possible values for OS X / macOS:
|
||||
|
||||
* `[OS_TYPE]`: `OSX`
|
||||
* `[DISTRO_TYPE]`: `OSX` (can be absent)
|
||||
* `[DISTRO_VERSION]`: `OSX-10.11`, `OSX-10.12`, `OSX-10.13`
|
||||
|
||||
- `JOB_NAME`: optional variable to define type of the job. Depending on the defined job type,
|
||||
- `JOB_NAME`: optional variable that defines the type of build job. Depending on the job type,
|
||||
the build scripts can perform different tasks.
|
||||
|
||||
Possible values:
|
||||
|
||||
* empty: default build process
|
||||
* `code-coverage` (Ubuntu Linux is assumed): debug build with tests and code coverage analysis
|
||||
* `limited-build`: only a single debug build with tests
|
||||
- empty: default build task
|
||||
- `code-coverage`: debug build with tests and code coverage analysis (Ubuntu Linux is assumed)
|
||||
- `limited-build`: only a single debug build with tests
|
||||
|
||||
- `CACHE_DIR`: the variable defines a path to folder containing cached files from previous builds,
|
||||
e.g., a compiled version of ndn-cxx library. If not set, `/tmp` is used.
|
||||
- `CACHE_DIR`: directory containing cached files from previous builds, e.g., a compiled version
|
||||
of ndn-cxx. If not set, `/tmp` is used.
|
||||
|
||||
- `WAF_JOBS`: number of parallel build jobs used by waf, defaults to 1.
|
||||
- `WAF_JOBS`: number of parallel build threads used by waf, defaults to 1.
|
||||
@@ -16,6 +16,7 @@ has() {
|
||||
set ${saved_xtrace}
|
||||
return ${ret}
|
||||
}
|
||||
export -f has
|
||||
|
||||
sudo_preserve_env() {
|
||||
local saved_xtrace
|
||||
@@ -35,3 +36,4 @@ sudo_preserve_env() {
|
||||
set ${saved_xtrace}
|
||||
sudo env "${vars[@]}" "$@"
|
||||
}
|
||||
export -f sudo_preserve_env
|
||||
+80
-67
@@ -1,102 +1,115 @@
|
||||
version: ~> 1.0
|
||||
language: cpp
|
||||
os: linux
|
||||
dist: bionic
|
||||
|
||||
arch:
|
||||
- amd64
|
||||
#- arm64 # Too slow, exceeds time limit
|
||||
#- ppc64le # Fails transport tests
|
||||
#- s390x # Fails transport tests
|
||||
|
||||
env:
|
||||
global:
|
||||
- JOB_NAME=limited-build
|
||||
- WAF_JOBS=2
|
||||
- COMPILER=g++-7
|
||||
- COMPILER=g++-9
|
||||
- COMPILER=clang++-6.0
|
||||
- COMPILER=clang++-9
|
||||
|
||||
matrix:
|
||||
jobs:
|
||||
include:
|
||||
# Linux/gcc
|
||||
# https://launchpad.net/~ubuntu-toolchain-r/+archive/ubuntu/test/+packages
|
||||
- os: linux
|
||||
env: COMPILER=g++-5
|
||||
- os: linux
|
||||
env: COMPILER=g++-6
|
||||
- os: linux
|
||||
env: COMPILER=g++-7
|
||||
- os: linux
|
||||
env: COMPILER=g++-8
|
||||
- os: linux
|
||||
env: COMPILER=g++-9
|
||||
# Linux
|
||||
- env: COMPILER=g++-5
|
||||
- env: COMPILER=g++-6
|
||||
- env: COMPILER=g++-8
|
||||
- env: COMPILER=clang++-4.0
|
||||
- env: COMPILER=clang++-5.0
|
||||
- env: COMPILER=clang++-7
|
||||
- env: COMPILER=clang++-8
|
||||
- env: COMPILER=clang++-10
|
||||
- env: COMPILER=clang++-11
|
||||
- env: COMPILER=clang++-12
|
||||
|
||||
# Linux/clang
|
||||
# https://apt.llvm.org/
|
||||
- os: linux
|
||||
env: COMPILER=clang++-3.9
|
||||
- os: linux
|
||||
env: COMPILER=clang++-4.0
|
||||
- os: linux
|
||||
env: COMPILER=clang++-5.0
|
||||
- os: linux
|
||||
env: COMPILER=clang++-6.0
|
||||
# disable AddressSanitizer with clang 7 and 8
|
||||
# due to https://bugs.llvm.org/show_bug.cgi?id=40808
|
||||
- os: linux
|
||||
env: COMPILER=clang++-7 DISABLE_ASAN=yes
|
||||
- os: linux
|
||||
env: COMPILER=clang++-8 DISABLE_ASAN=yes
|
||||
- os: linux
|
||||
env: COMPILER=clang++-9
|
||||
- os: linux
|
||||
env: COMPILER=clang++-10
|
||||
|
||||
# macOS/clang
|
||||
# https://docs.travis-ci.com/user/reference/osx/#macos-version
|
||||
- os: osx
|
||||
osx_image: xcode9.2
|
||||
env: OSX_VERSION=10.12
|
||||
# macOS
|
||||
- os: osx
|
||||
osx_image: xcode9.4
|
||||
env: OSX_VERSION=10.13
|
||||
env: # default compiler
|
||||
- os: osx
|
||||
osx_image: xcode10.1
|
||||
env: OSX_VERSION=10.13
|
||||
env: # default compiler
|
||||
- os: osx
|
||||
osx_image: xcode10.3
|
||||
env: OSX_VERSION=10.14
|
||||
env: # default compiler
|
||||
- os: osx
|
||||
osx_image: xcode11
|
||||
env: OSX_VERSION=10.14
|
||||
osx_image: xcode11.3
|
||||
env: # default compiler
|
||||
- os: osx
|
||||
osx_image: xcode11.6
|
||||
env: # default compiler
|
||||
- os: osx
|
||||
osx_image: xcode12
|
||||
env: # default compiler
|
||||
|
||||
allow_failures:
|
||||
- env: COMPILER=clang++-10
|
||||
- env: COMPILER=g++-5
|
||||
- env: COMPILER=g++-6
|
||||
- env: COMPILER=clang++-4.0
|
||||
- env: COMPILER=clang++-12
|
||||
|
||||
fast_finish: true
|
||||
|
||||
before_install: |
|
||||
before_install:
|
||||
- |
|
||||
: Adding apt repositories
|
||||
case ${COMPILER} in
|
||||
g++-[567]|clang++-[3456].*)
|
||||
;;
|
||||
g++-*)
|
||||
g++-9)
|
||||
# https://launchpad.net/~ubuntu-toolchain-r/+archive/ubuntu/test/+packages
|
||||
travis_retry sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
|
||||
travis_retry sudo apt-get -qq update
|
||||
;;
|
||||
clang++-*)
|
||||
clang++-1?)
|
||||
# https://apt.llvm.org/
|
||||
LLVM_REPO=${COMPILER/clang++/llvm-toolchain-${TRAVIS_DIST}}
|
||||
travis_retry wget -nv -O - "https://apt.llvm.org/llvm-snapshot.gpg.key" | sudo apt-key add -
|
||||
travis_retry sudo add-apt-repository -y "deb http://apt.llvm.org/${TRAVIS_DIST}/ ${LLVM_REPO%-10} main"
|
||||
travis_retry sudo add-apt-repository -y "deb http://apt.llvm.org/${TRAVIS_DIST}/ ${LLVM_REPO%-12} main"
|
||||
travis_retry sudo apt-get -qq update
|
||||
;;
|
||||
esac
|
||||
|
||||
install:
|
||||
- if [[ -n ${COMPILER} ]]; then travis_retry sudo apt-get -qy install "${COMPILER/clang++/clang}"; fi
|
||||
- |
|
||||
: Installing C++ compiler
|
||||
if [[ -n ${COMPILER} ]]; then
|
||||
travis_retry sudo apt-get -qy install ${COMPILER/clang++/clang}
|
||||
fi
|
||||
|
||||
before_script:
|
||||
- if [[ ${TRAVIS_OS_NAME} == linux ]]; then export NODE_LABELS="Linux Ubuntu Ubuntu-18.04"; fi
|
||||
- if [[ ${TRAVIS_OS_NAME} == linux ]]; then sudo sysctl -e -w net.ipv6.conf.all.disable_ipv6=0; fi
|
||||
- if [[ ${TRAVIS_OS_NAME} == osx ]]; then export NODE_LABELS="OSX OSX-${OSX_VERSION}"; fi
|
||||
# do not waste time upgrading useless packages
|
||||
- if [[ ${TRAVIS_OS_NAME} == osx ]]; then brew pin cgal gdal numpy postgis sfcgal || true; fi
|
||||
- if [[ ${OSX_VERSION} == 10.12 ]]; then brew update; fi
|
||||
# workaround for https://github.com/Homebrew/homebrew-core/issues/26358
|
||||
- if [[ ${OSX_VERSION} == 10.12 ]]; then brew outdated python || brew upgrade python; fi
|
||||
# workaround for https://github.com/travis-ci/travis-ci/issues/6688
|
||||
- if [[ ${OSX_VERSION} == 10.12 ]]; then /usr/bin/yes | pip2 uninstall numpy || true; fi
|
||||
- if [[ -n ${COMPILER} ]]; then export CXX=${COMPILER}; fi
|
||||
- |
|
||||
: Setting environment variables
|
||||
if [[ -n ${COMPILER} ]]; then
|
||||
export CXX=${COMPILER}
|
||||
fi
|
||||
case ${TRAVIS_OS_NAME} in
|
||||
linux) export NODE_LABELS="Linux Ubuntu Ubuntu-18.04" ;;
|
||||
osx) export NODE_LABELS="OSX OSX-$(sw_vers -productVersion | cut -d . -f -2)" ;;
|
||||
esac
|
||||
export JOB_NAME=limited-build
|
||||
export WAF_JOBS=2
|
||||
- |
|
||||
: Enabling workarounds
|
||||
case "${TRAVIS_CPU_ARCH},${COMPILER}" in
|
||||
ppc64le,g++-7)
|
||||
# AddressSanitizer does not seem to be working
|
||||
export DISABLE_ASAN=yes
|
||||
;;
|
||||
*,clang++-8)
|
||||
# https://bugs.llvm.org/show_bug.cgi?id=40808
|
||||
export DISABLE_ASAN=yes
|
||||
;;
|
||||
esac
|
||||
if [[ ${TRAVIS_OS_NAME} == linux ]]; then
|
||||
sudo sysctl -e -w net.ipv6.conf.all.disable_ipv6=0
|
||||
fi
|
||||
- ${CXX:-c++} --version
|
||||
- python --version
|
||||
|
||||
script:
|
||||
- ./.jenkins
|
||||
@@ -1,30 +0,0 @@
|
||||
# -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
|
||||
|
||||
"""
|
||||
Copyright (c) 2014-2016, Regents of the University of California,
|
||||
Arizona Board of Regents,
|
||||
Colorado State University,
|
||||
University Pierre & Marie Curie, Sorbonne University,
|
||||
Washington University in St. Louis,
|
||||
Beijing Institute of Technology,
|
||||
The University of Memphis.
|
||||
|
||||
This file is part of NFD (Named Data Networking Forwarding Daemon).
|
||||
See AUTHORS.md for complete list of NFD authors and contributors.
|
||||
|
||||
NFD is free software: you can redistribute it and/or modify it under the terms
|
||||
of the GNU General Public License as published by the Free Software Foundation,
|
||||
either version 3 of the License, or (at your option) any later version.
|
||||
|
||||
NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
from waflib.Configure import conf
|
||||
|
||||
def configure(conf):
|
||||
pass
|
||||
@@ -1,10 +1,11 @@
|
||||
# -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
|
||||
|
||||
import platform
|
||||
from waflib import Configure, Logs, Utils
|
||||
|
||||
def options(opt):
|
||||
opt.add_option('--debug', '--with-debug', action='store_true', default=False,
|
||||
help='Compile in debugging mode with minimal optimizations (-O0 or -Og)')
|
||||
help='Compile in debugging mode with minimal optimizations (-Og)')
|
||||
|
||||
def configure(conf):
|
||||
conf.start_msg('Checking C++ compiler version')
|
||||
@@ -17,15 +18,21 @@ def configure(conf):
|
||||
if cxx == 'gcc':
|
||||
if ccver < (5, 3, 0):
|
||||
errmsg = ('The version of gcc you are using is too old.\n'
|
||||
'The minimum supported gcc version is 5.3.0.')
|
||||
'The minimum supported gcc version is 7.4.0.')
|
||||
elif ccver < (7, 4, 0):
|
||||
warnmsg = ('Using a version of gcc older than 7.4.0 is not '
|
||||
'officially supported and may result in build failures.')
|
||||
conf.flags = GccFlags()
|
||||
elif cxx == 'clang':
|
||||
if ccver < (3, 6, 0):
|
||||
if Utils.unversioned_sys_platform() == 'darwin' and ccver < (9, 0, 0):
|
||||
errmsg = ('The version of Xcode you are using is too old.\n'
|
||||
'The minimum supported Xcode version is 9.0.')
|
||||
elif ccver < (4, 0, 0):
|
||||
errmsg = ('The version of clang you are using is too old.\n'
|
||||
'The minimum supported clang version is 3.6.0.')
|
||||
'The minimum supported clang version is 4.0.')
|
||||
conf.flags = ClangFlags()
|
||||
else:
|
||||
warnmsg = 'Note: %s compiler is unsupported' % cxx
|
||||
warnmsg = '%s compiler is unsupported' % cxx
|
||||
conf.flags = CompilerFlags()
|
||||
|
||||
if errmsg:
|
||||
@@ -33,7 +40,7 @@ def configure(conf):
|
||||
conf.fatal(errmsg)
|
||||
elif warnmsg:
|
||||
conf.end_msg(ccverstr, color='YELLOW')
|
||||
Logs.warn(warnmsg)
|
||||
Logs.warn('WARNING: ' + warnmsg)
|
||||
else:
|
||||
conf.end_msg(ccverstr)
|
||||
|
||||
@@ -137,13 +144,14 @@ class GccBasicFlags(CompilerFlags):
|
||||
|
||||
def getDebugFlags(self, conf):
|
||||
flags = super(GccBasicFlags, self).getDebugFlags(conf)
|
||||
flags['CXXFLAGS'] += ['-O0',
|
||||
'-Og', # gcc >= 4.8, clang >= 4.0
|
||||
flags['CXXFLAGS'] += ['-Og',
|
||||
'-g3',
|
||||
'-pedantic',
|
||||
'-Wall',
|
||||
'-Wextra',
|
||||
'-Werror',
|
||||
'-Wcatch-value=2',
|
||||
'-Wextra-semi',
|
||||
'-Wnon-virtual-dtor',
|
||||
'-Wno-error=deprecated-declarations', # Bug #3795
|
||||
'-Wno-error=maybe-uninitialized', # Bug #1615
|
||||
@@ -159,6 +167,8 @@ class GccBasicFlags(CompilerFlags):
|
||||
'-pedantic',
|
||||
'-Wall',
|
||||
'-Wextra',
|
||||
'-Wcatch-value=2',
|
||||
'-Wextra-semi',
|
||||
'-Wnon-virtual-dtor',
|
||||
'-Wno-unused-parameter',
|
||||
]
|
||||
@@ -168,49 +178,50 @@ class GccBasicFlags(CompilerFlags):
|
||||
class GccFlags(GccBasicFlags):
|
||||
def getDebugFlags(self, conf):
|
||||
flags = super(GccFlags, self).getDebugFlags(conf)
|
||||
flags['CXXFLAGS'] += ['-fdiagnostics-color']
|
||||
flags['CXXFLAGS'] += ['-fdiagnostics-color',
|
||||
'-Wredundant-tags',
|
||||
]
|
||||
if platform.machine() == 'armv7l' and self.getCompilerVersion(conf) >= (7, 1, 0):
|
||||
flags['CXXFLAGS'] += ['-Wno-psabi'] # Bug #5106
|
||||
return flags
|
||||
|
||||
def getOptimizedFlags(self, conf):
|
||||
flags = super(GccFlags, self).getOptimizedFlags(conf)
|
||||
flags['CXXFLAGS'] += ['-fdiagnostics-color']
|
||||
flags['CXXFLAGS'] += ['-fdiagnostics-color',
|
||||
'-Wredundant-tags',
|
||||
]
|
||||
if platform.machine() == 'armv7l' and self.getCompilerVersion(conf) >= (7, 1, 0):
|
||||
flags['CXXFLAGS'] += ['-Wno-psabi'] # Bug #5106
|
||||
return flags
|
||||
|
||||
class ClangFlags(GccBasicFlags):
|
||||
def getGeneralFlags(self, conf):
|
||||
flags = super(ClangFlags, self).getGeneralFlags(conf)
|
||||
if Utils.unversioned_sys_platform() == 'darwin' and self.getCompilerVersion(conf) >= (9, 0, 0):
|
||||
if Utils.unversioned_sys_platform() == 'darwin':
|
||||
# Bug #4296
|
||||
flags['CXXFLAGS'] += [['-isystem', '/usr/local/include'], # for Homebrew
|
||||
['-isystem', '/opt/local/include']] # for MacPorts
|
||||
if Utils.unversioned_sys_platform() == 'freebsd':
|
||||
flags['CXXFLAGS'] += [['-isystem', '/usr/local/include']] # Bug #4790
|
||||
elif Utils.unversioned_sys_platform() == 'freebsd':
|
||||
# Bug #4790
|
||||
flags['CXXFLAGS'] += [['-isystem', '/usr/local/include']]
|
||||
return flags
|
||||
|
||||
def getDebugFlags(self, conf):
|
||||
flags = super(ClangFlags, self).getDebugFlags(conf)
|
||||
flags['CXXFLAGS'] += ['-fcolor-diagnostics',
|
||||
'-Wextra-semi',
|
||||
'-Wundefined-func-template',
|
||||
'-Wno-unused-local-typedef', # Bugs #2657 and #3209
|
||||
]
|
||||
version = self.getCompilerVersion(conf)
|
||||
if version < (3, 9, 0) or (Utils.unversioned_sys_platform() == 'darwin' and version < (8, 1, 0)):
|
||||
flags['CXXFLAGS'] += ['-Wno-unknown-pragmas']
|
||||
if version < (6, 0, 0):
|
||||
if self.getCompilerVersion(conf) < (6, 0, 0):
|
||||
flags['CXXFLAGS'] += ['-Wno-missing-braces'] # Bug #4721
|
||||
return flags
|
||||
|
||||
def getOptimizedFlags(self, conf):
|
||||
flags = super(ClangFlags, self).getOptimizedFlags(conf)
|
||||
flags['CXXFLAGS'] += ['-fcolor-diagnostics',
|
||||
'-Wextra-semi',
|
||||
'-Wundefined-func-template',
|
||||
'-Wno-unused-local-typedef', # Bugs #2657 and #3209
|
||||
]
|
||||
version = self.getCompilerVersion(conf)
|
||||
if version < (3, 9, 0) or (Utils.unversioned_sys_platform() == 'darwin' and version < (8, 1, 0)):
|
||||
flags['CXXFLAGS'] += ['-Wno-unknown-pragmas']
|
||||
if version < (6, 0, 0):
|
||||
if self.getCompilerVersion(conf) < (6, 0, 0):
|
||||
flags['CXXFLAGS'] += ['-Wno-missing-braces'] # Bug #4721
|
||||
return flags
|
||||
+58
-78
@@ -1,82 +1,62 @@
|
||||
NFD Authors
|
||||
===========
|
||||
# NFD Authors
|
||||
|
||||
NFD is an open source project started in late 2013, includes contributions
|
||||
from many people around the world, and open for new contributions from new
|
||||
volunteers.
|
||||
The following lists maintainers, primary developers, and all much-appreciated contributors to NFD in alphabetic order.
|
||||
The specific contributions of individual authors can be obtained from the git history of the [official NFD repository](https://github.com/named-data/NFD).
|
||||
If you would like to become a contributor to the official repository, please follow the recommendations in https://github.com/named-data/.github/blob/master/CONTRIBUTING.md.
|
||||
|
||||
* Jerald Paul Abraham <https://cs.arizona.edu/~jeraldabraham>
|
||||
* ***(Maintainer)*** Alexander Afanasyev <https://users.cs.fiu.edu/~afanasyev>
|
||||
* Syed Obai Amin <http://obaidamin.weebly.com>
|
||||
* Hila Ben Abraham <https://sites.wustl.edu/hbabraham>
|
||||
* Muktadir R Chowdhury <https://github.com/alvyC>
|
||||
* Tai-Lin Chu <https://www.linkedin.com/pub/tai-lin-chu/55/5b2/669>
|
||||
* Stephanie DiBenedetto
|
||||
* Saurab Dulal <https://dulalsaurab.github.io>
|
||||
* Chengyu Fan <https://github.com/chengyu>
|
||||
* Ashlesh Gawande <https://www.linkedin.com/in/agawande>
|
||||
* Chavoosh Ghasemi <https://chavoosh.github.io>
|
||||
* Mathias Gibbens <https://calenhad.com>
|
||||
* Nick Gordon <https://github.com/gorgonical>
|
||||
* Giulio Grassi <https://www.lip6.fr/actualite/personnes-fiche.php?ident=D1461>
|
||||
* Yi Huang <https://www.linkedin.com/in/yihuang1991>
|
||||
* Jongseok Lee <https://github.com/imwhiz>
|
||||
* Spencer Lee <https://www.linkedin.com/in/spenlee>
|
||||
* Vince Lehman <http://vslehman.com>
|
||||
* Yanbiao Li <https://www.linkedin.com/pub/yanbiao-li/24/7a1/4ba>
|
||||
* Teng Liang <https://cs.arizona.edu/~philoliang>
|
||||
* Weiwei Liu <https://www.linkedin.com/in/weiweiliu10>
|
||||
* Spyridon Mastorakis <https://sites.google.com/site/spyridonmastorakis>
|
||||
* Ernest McCracken <https://github.com/emccrckn>
|
||||
* Ilya Moiseenko <https://www.linkedin.com/in/ilya-moiseenko-52884317>
|
||||
* Eric Newberry <https://ericnewberry.com>
|
||||
* Ju Pan <https://cs-jupan.com>
|
||||
* João Pereira <http://website.jpereira.co.uk>
|
||||
* Davide Pesavento <https://github.com/Pesa>
|
||||
* Felix Rabe <https://twitter.com/felixrabe>
|
||||
* Md Ashiqur Rahman <https://ashiqrahman.com>
|
||||
* Matteo Sammarco <https://www.linkedin.com/in/matteo-sammarco-9b544530>
|
||||
* Niv Sardi <http://core.evilgiggle.com>
|
||||
* Klaus Schneider <https://cs.arizona.edu/~klaus>
|
||||
* Wentao Shang <https://irl.cs.ucla.edu/~wentao>
|
||||
* Susmit Shannigrahi <https://susm.it>
|
||||
* ***(Former Maintainer)*** Junxiao Shi <https://cs.arizona.edu/~shijunxiao>
|
||||
* Yukai Tu <https://irl.cs.ucla.edu/~yukai>
|
||||
* Sebastian Wölke <https://inet.haw-hamburg.de/members/alumni-1/sebastian-woelke>
|
||||
* Yumin Xia <https://github.com/Stumble>
|
||||
* Yingdi Yu <https://irl.cs.ucla.edu/~yingdi>
|
||||
* Haowei Yuan <http://www.cse.wustl.edu/~yuanh>
|
||||
* Hang Zhang <http://netlab.bit.edu.cn/z_hang>
|
||||
* Minsheng Zhang <https://github.com/mzhang4>
|
||||
* Zhiyi Zhang <https://zhiyi-zhang.com>
|
||||
* Qi Zhao <https://web.cs.ucla.edu/~qi.zhao>
|
||||
* Wenkai Zheng <https://github.com/wenkaizheng>
|
||||
|
||||
## Project technical leads:
|
||||
## Technical Advisors
|
||||
|
||||
* Alexander Afanasyev <http://lasr.cs.ucla.edu/afanasyev/index.html>
|
||||
* Junxiao Shi <http://www.cs.arizona.edu/people/shijunxiao/>
|
||||
|
||||
|
||||
## Technical advisors:
|
||||
|
||||
* Beichuan Zhang <http://www.cs.arizona.edu/~bzhang/>
|
||||
* Lixia Zhang <http://www.cs.ucla.edu/~lixia/>
|
||||
|
||||
|
||||
## Main project authors and their affiliations:
|
||||
|
||||
* University of California, Los Angeles
|
||||
|
||||
* Alexander Afanasyev <http://lasr.cs.ucla.edu/afanasyev/index.html>
|
||||
* Ilya Moiseenko <http://ilyamoiseenko.com/>
|
||||
* Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/web/index.html>
|
||||
* Wentao Shang <http://irl.cs.ucla.edu/~wentao/>
|
||||
* Lixia Zhang <http://www.cs.ucla.edu/~lixia/>
|
||||
|
||||
* The University of Arizona
|
||||
|
||||
* Junxiao Shi <http://www.cs.arizona.edu/people/shijunxiao/>
|
||||
* Yi Huang <ethanhuang1991@gmail.com>
|
||||
* Jerald Paul Abraham <http://www.cs.arizona.edu/people/jeraldabraham/>
|
||||
* Beichuan Zhang <http://www.cs.arizona.edu/~bzhang/>
|
||||
|
||||
* Colorado State University
|
||||
|
||||
* Steve DiBenedetto <http://www.cs.colostate.edu/~dibenede/>
|
||||
* Chengyu Fan <chengyu@cs.colostate.edu>
|
||||
* Christos Papadopoulos <http://www.cs.colostate.edu/~christos/>
|
||||
|
||||
* University Pierre & Marie Curie, Sorbonne University
|
||||
|
||||
* Davide Pesavento <https://www.linkedin.com/in/davidepesavento>
|
||||
* Giulio Grassi <http://www.lip6.fr/actualite/personnes-fiche.php?ident=D1461>
|
||||
* Giovanni Pau <http://www.cs.ucla.edu/~gpau/Giovanni_Paus_Home_Page/Home.html>
|
||||
|
||||
* Beijing Institute of Technology
|
||||
|
||||
* Hang Zhang <http://netlab.bit.edu.cn/z_hang>
|
||||
* Tian Song <http://cs.bit.edu.cn/songtian>
|
||||
|
||||
* Washington University in St. Louis
|
||||
|
||||
* Haowei Yuan <http://www.cse.wustl.edu/~yuanh/>
|
||||
* Hila Ben Abraham <http://research.engineering.wustl.edu/~abrahamh/>
|
||||
* Patrick Crowley <http://www.arl.wustl.edu/~pcrowley/>
|
||||
|
||||
* The University of Memphis
|
||||
|
||||
* Syed Obaid Amin <http://obaidamin.weebly.com/>
|
||||
* Vince Lehman <vslehman@memphis.edu>
|
||||
* Minsheng Zhang <mzhang4@memphis.edu>
|
||||
* Lan Wang <http://www.cs.memphis.edu/~lanwang/>
|
||||
|
||||
## Project contributors
|
||||
|
||||
The following is an inevitably incomplete list of MUCH-APPRECIATED CONTRIBUTORS,
|
||||
people who have reported bugs, submitted patches, and implemented new features
|
||||
in the library:
|
||||
|
||||
* Tai-Lin Chu <https://www.linkedin.com/pub/tai-lin-chu/55/5b2/669>
|
||||
* Spyridon Mastorakis <http://cs.ucla.edu/~mastorakis/>
|
||||
* Eric Newberry <http://cs.arizona.edu/~enewberry/>
|
||||
* Yukai Tu <tuyukai1994@gmail.com>
|
||||
* João Pereira <http://website.jpereira.co.uk>
|
||||
* Mathias Gibbens <gibmat@cs.arizona.edu>
|
||||
* Yanbiao Li <https://www.linkedin.com/pub/yanbiao-li/24/7a1/4ba>
|
||||
* Weiwei Liu <https://www.linkedin.com/in/weiweiliu10>
|
||||
* Spencer Lee <https://www.linkedin.com/in/spenlee>
|
||||
* Patrick Crowley <https://www.arl.wustl.edu/~pcrowley>
|
||||
* Christos Papadopoulos <https://www.cs.colostate.edu/~christos>
|
||||
* Giovanni Pau <http://www.cs.ucla.edu/~gpau/Giovanni_Paus_Home_Page/Home.html>
|
||||
* Tian Song <http://www.bit-netlab.org/songtian>
|
||||
* Lan Wang <http://www.cs.memphis.edu/~lanwang>
|
||||
* Beichuan Zhang <https://cs.arizona.edu/~bzhang>
|
||||
* Lixia Zhang <https://cs.ucla.edu/~lixia>
|
||||
+5
-6
@@ -1,7 +1,7 @@
|
||||
# Notes for NFD developers
|
||||
|
||||
If you are new to the NDN software community, please read the
|
||||
[Contributor's Guide](https://github.com/named-data/NFD/blob/master/CONTRIBUTING.md).
|
||||
[Contributor's Guide](https://github.com/named-data/.github/blob/master/CONTRIBUTING.md).
|
||||
|
||||
## Code style
|
||||
|
||||
@@ -61,12 +61,12 @@ The simplest way to run the tests is to launch the compiled binary without any p
|
||||
# Run NFD RIB management tests
|
||||
./build/unit-tests-rib
|
||||
|
||||
[Boost.Test framework](https://www.boost.org/doc/libs/1_58_0/libs/test/doc/html/index.html)
|
||||
The [Boost.Test framework](https://www.boost.org/doc/libs/1_65_1/libs/test/doc/html/index.html)
|
||||
is very flexible and allows a number of run-time customization of what tests should be run.
|
||||
For example, it is possible to choose to run only a specific test suite, only a specific
|
||||
test case within a suite, or specific test cases within specific test suites:
|
||||
|
||||
# Run only TCP Face test suite of NFD daemon tests (see tests/daemon/face/tcp.cpp)
|
||||
# Run only the TCP Face test suite of NFD daemon tests
|
||||
./build/unit-tests-daemon -t FaceTcp
|
||||
|
||||
# Run only test case EndToEnd4 from the same test suite
|
||||
@@ -93,6 +93,5 @@ or `-p` to show a progress bar:
|
||||
./build/unit-tests-core -p
|
||||
|
||||
There are many more command line options available, information about which can be obtained
|
||||
either from the command line using `--help` switch, or online on
|
||||
[Boost.Test library](https://www.boost.org/doc/libs/1_58_0/libs/test/doc/html/index.html)
|
||||
website.
|
||||
either from the command line using the `--help` switch, or online on the
|
||||
[Boost.Test website](https://www.boost.org/doc/libs/1_65_1/libs/test/doc/html/index.html).
|
||||
@@ -44,11 +44,12 @@ it already contains significant contributions from people outside the project te
|
||||
since broader community support is key for NDN to succeed as a new Internet architecture.
|
||||
|
||||
If you are new to the NDN software community, please read [`README-dev.md`](README-dev.md)
|
||||
and the [Contributor's Guide](CONTRIBUTING.md) to get started.
|
||||
and the [Contributor's Guide](https://github.com/named-data/.github/blob/master/CONTRIBUTING.md)
|
||||
to get started.
|
||||
|
||||
## License
|
||||
|
||||
NFD is an open and free software package licensed under the GPL version 3 and is the
|
||||
centerpiece of our committement to making NDN's core technology open and free to all
|
||||
Internet users and developers. For more information about the licensing details and
|
||||
limitations, refer to [`COPYING.md`](COPYING.md).
|
||||
NFD is a free and open-source software package licensed under the GPL version 3 and
|
||||
is the centerpiece of our committement to making NDN's core technology free and open
|
||||
to all Internet users and developers. For more information about licensing, refer to
|
||||
[`COPYING.md`](COPYING.md).
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -74,8 +74,8 @@
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/core/noncopyable.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
|
||||
namespace nfd {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -108,7 +108,9 @@ public: // parse helpers
|
||||
static_assert(std::is_arithmetic<T>::value, "T must be an arithmetic type");
|
||||
|
||||
boost::optional<T> value = node.get_value_optional<T>();
|
||||
if (value) {
|
||||
// Unsigned logic is workaround for https://redmine.named-data.net/issues/4489
|
||||
if (value &&
|
||||
(std::is_signed<T>() || node.get_value<std::string>().find("-") == std::string::npos)) {
|
||||
return *value;
|
||||
}
|
||||
NDN_THROW(Error("Invalid value '" + node.get_value<std::string>() +
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -63,25 +63,23 @@ PrivilegeHelper::initialize(const std::string& userName, const std::string& grou
|
||||
groupSize = FALLBACK_GROUP_BUFFER_SIZE;
|
||||
|
||||
std::vector<char> groupBuffer(static_cast<size_t>(groupSize));
|
||||
struct group group;
|
||||
struct group* groupResult = nullptr;
|
||||
group gr;
|
||||
group* grResult = nullptr;
|
||||
|
||||
int errorCode = getgrnam_r(groupName.data(), &group,
|
||||
groupBuffer.data(), groupBuffer.size(), &groupResult);
|
||||
int errorCode = getgrnam_r(groupName.data(), &gr, groupBuffer.data(), groupBuffer.size(), &grResult);
|
||||
|
||||
while (errorCode == ERANGE) {
|
||||
if (groupBuffer.size() * 2 > MAX_GROUP_BUFFER_SIZE)
|
||||
throw Error("Cannot allocate large enough buffer for struct group");
|
||||
|
||||
groupBuffer.resize(groupBuffer.size() * 2);
|
||||
errorCode = getgrnam_r(groupName.data(), &group,
|
||||
groupBuffer.data(), groupBuffer.size(), &groupResult);
|
||||
errorCode = getgrnam_r(groupName.data(), &gr, groupBuffer.data(), groupBuffer.size(), &grResult);
|
||||
}
|
||||
|
||||
if (errorCode != 0 || !groupResult)
|
||||
if (errorCode != 0 || !grResult)
|
||||
throw Error("Failed to get gid for \"" + groupName + "\"");
|
||||
|
||||
s_normalGid = group.gr_gid;
|
||||
s_normalGid = gr.gr_gid;
|
||||
}
|
||||
|
||||
if (!userName.empty()) {
|
||||
@@ -91,25 +89,23 @@ PrivilegeHelper::initialize(const std::string& userName, const std::string& grou
|
||||
passwdSize = FALLBACK_PASSWD_BUFFER_SIZE;
|
||||
|
||||
std::vector<char> passwdBuffer(static_cast<size_t>(passwdSize));
|
||||
struct passwd passwd;
|
||||
struct passwd* passwdResult = nullptr;
|
||||
passwd pw;
|
||||
passwd* pwResult = nullptr;
|
||||
|
||||
int errorCode = getpwnam_r(userName.data(), &passwd,
|
||||
passwdBuffer.data(), passwdBuffer.size(), &passwdResult);
|
||||
int errorCode = getpwnam_r(userName.data(), &pw, passwdBuffer.data(), passwdBuffer.size(), &pwResult);
|
||||
|
||||
while (errorCode == ERANGE) {
|
||||
if (passwdBuffer.size() * 2 > MAX_PASSWD_BUFFER_SIZE)
|
||||
throw Error("Cannot allocate large enough buffer for struct passwd");
|
||||
|
||||
passwdBuffer.resize(passwdBuffer.size() * 2);
|
||||
errorCode = getpwnam_r(userName.data(), &passwd,
|
||||
passwdBuffer.data(), passwdBuffer.size(), &passwdResult);
|
||||
errorCode = getpwnam_r(userName.data(), &pw, passwdBuffer.data(), passwdBuffer.size(), &pwResult);
|
||||
}
|
||||
|
||||
if (errorCode != 0 || !passwdResult)
|
||||
if (errorCode != 0 || !pwResult)
|
||||
throw Error("Failed to get uid for \"" + userName + "\"");
|
||||
|
||||
s_normalUid = passwd.pw_uid;
|
||||
s_normalUid = pw.pw_uid;
|
||||
}
|
||||
#else
|
||||
if (!userName.empty() || !groupName.empty()) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -38,7 +38,7 @@ namespace face {
|
||||
* A channel can listen on a local endpoint and initiate outgoing connection from a local endpoint.
|
||||
* A channel creates Face objects and retains shared ownership of them.
|
||||
*/
|
||||
class Channel : noncopyable
|
||||
class Channel : public std::enable_shared_from_this<Channel>, noncopyable
|
||||
{
|
||||
public:
|
||||
virtual
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -69,7 +69,7 @@ protected:
|
||||
doClose() override;
|
||||
|
||||
void
|
||||
doSend(const Block& packet, const EndpointId& endpoint) override;
|
||||
doSend(const Block& packet) override;
|
||||
|
||||
void
|
||||
handleSend(const boost::system::error_code& error, size_t nBytesSent);
|
||||
@@ -157,7 +157,7 @@ DatagramTransport<T, U>::doClose()
|
||||
|
||||
template<class T, class U>
|
||||
void
|
||||
DatagramTransport<T, U>::doSend(const Block& packet, const EndpointId&)
|
||||
DatagramTransport<T, U>::doSend(const Block& packet)
|
||||
{
|
||||
NFD_LOG_FACE_TRACE(__func__);
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -201,12 +201,15 @@ EthernetChannel::createFace(const ethernet::Address& remoteEndpoint,
|
||||
options.allowFragmentation = true;
|
||||
options.allowReassembly = true;
|
||||
options.reliabilityOptions.isEnabled = params.wantLpReliability;
|
||||
if (params.mtu) {
|
||||
options.overrideMtu = *params.mtu;
|
||||
}
|
||||
|
||||
auto linkService = make_unique<GenericLinkService>(options);
|
||||
auto transport = make_unique<UnicastEthernetTransport>(*m_localEndpoint, remoteEndpoint,
|
||||
params.persistency, m_idleFaceTimeout,
|
||||
params.mtu);
|
||||
params.persistency, m_idleFaceTimeout);
|
||||
auto face = make_shared<Face>(std::move(linkService), std::move(transport));
|
||||
face->setChannel(shared_from_this()); // use weak_from_this() in C++17
|
||||
|
||||
m_channelFaces[remoteEndpoint] = face;
|
||||
connectFaceClosedSignal(*face, [this, remoteEndpoint] {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -197,10 +197,10 @@ EthernetFactory::doCreateFace(const CreateFaceRequest& req,
|
||||
return;
|
||||
}
|
||||
|
||||
if (req.params.mtu && *req.params.mtu < Transport::MIN_MTU) {
|
||||
if (req.params.mtu && *req.params.mtu < MIN_MTU) {
|
||||
// The specified MTU must be greater than the minimum possible
|
||||
NFD_LOG_TRACE("createFace cannot create a face with an MTU less than " << Transport::MIN_MTU);
|
||||
onFailure(406, "MTU cannot be less than " + to_string(Transport::MIN_MTU));
|
||||
NFD_LOG_TRACE("createFace: override MTU cannot be less than " << MIN_MTU);
|
||||
onFailure(406, "Override MTU cannot be less than " + to_string(MIN_MTU));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -257,6 +257,9 @@ EthernetFactory::createMulticastFace(const ndn::net::NetworkInterface& netif,
|
||||
m_mcastFaces[key] = face;
|
||||
connectFaceClosedSignal(*face, [this, key] { m_mcastFaces.erase(key); });
|
||||
|
||||
auto channelIt = m_channels.find(netif.getName());
|
||||
face->setChannel(channelIt != m_channels.end() ? channelIt->second : nullptr);
|
||||
|
||||
return face;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -58,11 +58,19 @@ EthernetTransport::EthernetTransport(const ndn::net::NetworkInterface& localEndp
|
||||
NDN_THROW_NESTED(Error(e.what()));
|
||||
}
|
||||
|
||||
m_netifStateConn = localEndpoint.onStateChanged.connect(
|
||||
[=] (ndn::net::InterfaceState, ndn::net::InterfaceState newState) {
|
||||
// Set initial transport state based upon the state of the underlying NetworkInterface
|
||||
handleNetifStateChange(localEndpoint.getState());
|
||||
|
||||
m_netifStateChangedConn = localEndpoint.onStateChanged.connect(
|
||||
[this] (ndn::net::InterfaceState, ndn::net::InterfaceState newState) {
|
||||
handleNetifStateChange(newState);
|
||||
});
|
||||
|
||||
m_netifMtuChangedConn = localEndpoint.onMtuChanged.connect(
|
||||
[this] (uint32_t, uint32_t mtu) {
|
||||
setMtu(mtu);
|
||||
});
|
||||
|
||||
asyncRead();
|
||||
}
|
||||
|
||||
@@ -102,7 +110,7 @@ EthernetTransport::handleNetifStateChange(ndn::net::InterfaceState netifState)
|
||||
}
|
||||
|
||||
void
|
||||
EthernetTransport::doSend(const Block& packet, const EndpointId&)
|
||||
EthernetTransport::doSend(const Block& packet)
|
||||
{
|
||||
NFD_LOG_FACE_TRACE(__func__);
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -81,7 +81,7 @@ private:
|
||||
handleNetifStateChange(ndn::net::InterfaceState netifState);
|
||||
|
||||
void
|
||||
doSend(const Block& packet, const EndpointId& endpoint) final;
|
||||
doSend(const Block& packet) final;
|
||||
|
||||
/**
|
||||
* @brief Sends the specified TLV block on the network wrapped in an Ethernet frame
|
||||
@@ -106,7 +106,8 @@ protected:
|
||||
std::string m_interfaceName;
|
||||
|
||||
private:
|
||||
signal::ScopedConnection m_netifStateConn;
|
||||
signal::ScopedConnection m_netifStateChangedConn;
|
||||
signal::ScopedConnection m_netifMtuChangedConn;
|
||||
bool m_hasRecentlyReceived;
|
||||
#ifdef _DEBUG
|
||||
/// number of frames dropped by the kernel, as reported by libpcap
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -54,6 +54,12 @@ const FaceId FACEID_NULL = 255;
|
||||
/// upper bound of reserved FaceIds
|
||||
const FaceId FACEID_RESERVED_MAX = 255;
|
||||
|
||||
/** \brief Minimum MTU that may be set
|
||||
*
|
||||
* This is done to ensure the NDNLPv2 fragmentation feature functions properly.
|
||||
*/
|
||||
const ssize_t MIN_MTU = 64;
|
||||
|
||||
/** \brief Identifies a remote endpoint on the link.
|
||||
*
|
||||
* This ID is only meaningful in the context of the same Transport.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -32,7 +32,7 @@ FaceCounters::FaceCounters(const LinkService::Counters& linkServiceCounters,
|
||||
const Transport::Counters& transportCounters)
|
||||
: nInInterests(linkServiceCounters.nInInterests)
|
||||
, nOutInterests(linkServiceCounters.nOutInterests)
|
||||
, nDroppedInterests(linkServiceCounters.nDroppedInterests)
|
||||
, nInterestsExceededRetx(linkServiceCounters.nInterestsExceededRetx)
|
||||
, nInData(linkServiceCounters.nInData)
|
||||
, nOutData(linkServiceCounters.nOutData)
|
||||
, nInNacks(linkServiceCounters.nInNacks)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -70,18 +70,25 @@ public:
|
||||
public:
|
||||
const PacketCounter& nInInterests;
|
||||
const PacketCounter& nOutInterests;
|
||||
const PacketCounter& nDroppedInterests;
|
||||
const PacketCounter& nInterestsExceededRetx;
|
||||
const PacketCounter& nInData;
|
||||
const PacketCounter& nOutData;
|
||||
const PacketCounter& nInNacks;
|
||||
const PacketCounter& nOutNacks;
|
||||
PacketCounter nKeptInterests;
|
||||
|
||||
const PacketCounter& nInPackets;
|
||||
const PacketCounter& nOutPackets;
|
||||
const ByteCounter& nInBytes;
|
||||
const ByteCounter& nOutBytes;
|
||||
|
||||
/** \brief count of incoming Interests dropped due to HopLimit == 0
|
||||
*/
|
||||
PacketCounter nInHopLimitZero;
|
||||
|
||||
/** \brief count of outgoing Interests dropped due to HopLimit == 0 on non-local faces
|
||||
*/
|
||||
PacketCounter nOutHopLimitZero;
|
||||
|
||||
private:
|
||||
const LinkService::Counters& m_linkServiceCounters;
|
||||
const Transport::Counters& m_transportCounters;
|
||||
|
||||
+66
-34
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -34,6 +34,8 @@
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
|
||||
class Channel;
|
||||
|
||||
/** \brief indicates the state of a face
|
||||
*/
|
||||
typedef TransportState FaceState;
|
||||
@@ -60,21 +62,33 @@ public:
|
||||
Transport*
|
||||
getTransport() const;
|
||||
|
||||
/** \brief Request that the face be closed
|
||||
*
|
||||
* This operation is effective only if face is in the UP or DOWN state; otherwise, it has no effect.
|
||||
* The face will change state to CLOSING, and then perform a cleanup procedure.
|
||||
* When the cleanup is complete, the state will be changed to CLOSED, which may happen
|
||||
* synchronously or asynchronously.
|
||||
*
|
||||
* \warning The face must not be deallocated until its state changes to CLOSED.
|
||||
*/
|
||||
void
|
||||
close();
|
||||
|
||||
public: // upper interface connected to forwarding
|
||||
/** \brief send Interest to \p endpointId
|
||||
/** \brief send Interest
|
||||
*/
|
||||
void
|
||||
sendInterest(const Interest& interest, const EndpointId& endpointId);
|
||||
sendInterest(const Interest& interest);
|
||||
|
||||
/** \brief send Data to \p endpointId
|
||||
/** \brief send Data
|
||||
*/
|
||||
void
|
||||
sendData(const Data& data, const EndpointId& endpointId);
|
||||
sendData(const Data& data);
|
||||
|
||||
/** \brief send Nack to \p endpointId
|
||||
/** \brief send Nack
|
||||
*/
|
||||
void
|
||||
sendNack(const lp::Nack& nack, const EndpointId& endpointId);
|
||||
sendNack(const lp::Nack& nack);
|
||||
|
||||
/** \brief signals on Interest received
|
||||
*/
|
||||
@@ -92,7 +106,7 @@ public: // upper interface connected to forwarding
|
||||
*/
|
||||
signal::Signal<LinkService, Interest>& onDroppedInterest;
|
||||
|
||||
public: // static properties
|
||||
public: // properties
|
||||
/** \return face ID
|
||||
*/
|
||||
FaceId
|
||||
@@ -134,7 +148,13 @@ public: // static properties
|
||||
ndn::nfd::LinkType
|
||||
getLinkType() const;
|
||||
|
||||
public: // dynamic properties
|
||||
/** \brief Returns face effective MTU
|
||||
*
|
||||
* This function is a wrapper. The effective MTU of a face is determined by the link service.
|
||||
*/
|
||||
ssize_t
|
||||
getMtu() const;
|
||||
|
||||
/** \return face state
|
||||
*/
|
||||
FaceState
|
||||
@@ -150,27 +170,33 @@ public: // dynamic properties
|
||||
time::steady_clock::TimePoint
|
||||
getExpirationTime() const;
|
||||
|
||||
/** \brief request the face to be closed
|
||||
*
|
||||
* This operation is effective only if face is in UP or DOWN state,
|
||||
* otherwise it has no effect.
|
||||
* The face changes state to CLOSING, and performs cleanup procedure.
|
||||
* The state will be changed to CLOSED when cleanup is complete, which may
|
||||
* happen synchronously or asynchronously.
|
||||
*
|
||||
* \warning the face must not be deallocated until its state changes to CLOSED
|
||||
*/
|
||||
void
|
||||
close();
|
||||
|
||||
const FaceCounters&
|
||||
getCounters() const;
|
||||
|
||||
/**
|
||||
* \brief Get channel on which face was created (unicast) or the associated channel (multicast)
|
||||
*/
|
||||
weak_ptr<Channel>
|
||||
getChannel() const
|
||||
{
|
||||
return m_channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set channel on which face was created (unicast) or the associated channel (multicast)
|
||||
*/
|
||||
void
|
||||
setChannel(weak_ptr<Channel> channel)
|
||||
{
|
||||
m_channel = std::move(channel);
|
||||
}
|
||||
|
||||
private:
|
||||
FaceId m_id;
|
||||
unique_ptr<LinkService> m_service;
|
||||
unique_ptr<Transport> m_transport;
|
||||
FaceCounters m_counters;
|
||||
weak_ptr<Channel> m_channel;
|
||||
};
|
||||
|
||||
inline LinkService*
|
||||
@@ -186,21 +212,27 @@ Face::getTransport() const
|
||||
}
|
||||
|
||||
inline void
|
||||
Face::sendInterest(const Interest& interest, const EndpointId& endpointId)
|
||||
Face::close()
|
||||
{
|
||||
m_service->sendInterest(interest, endpointId);
|
||||
m_transport->close();
|
||||
}
|
||||
|
||||
inline void
|
||||
Face::sendData(const Data& data, const EndpointId& endpointId)
|
||||
Face::sendInterest(const Interest& interest)
|
||||
{
|
||||
m_service->sendData(data, endpointId);
|
||||
m_service->sendInterest(interest);
|
||||
}
|
||||
|
||||
inline void
|
||||
Face::sendNack(const lp::Nack& nack, const EndpointId& endpointId)
|
||||
Face::sendData(const Data& data)
|
||||
{
|
||||
m_service->sendNack(nack, endpointId);
|
||||
m_service->sendData(data);
|
||||
}
|
||||
|
||||
inline void
|
||||
Face::sendNack(const lp::Nack& nack)
|
||||
{
|
||||
m_service->sendNack(nack);
|
||||
}
|
||||
|
||||
inline FaceId
|
||||
@@ -251,6 +283,12 @@ Face::getLinkType() const
|
||||
return m_transport->getLinkType();
|
||||
}
|
||||
|
||||
inline ssize_t
|
||||
Face::getMtu() const
|
||||
{
|
||||
return m_service->getEffectiveMtu();
|
||||
}
|
||||
|
||||
inline FaceState
|
||||
Face::getState() const
|
||||
{
|
||||
@@ -263,12 +301,6 @@ Face::getExpirationTime() const
|
||||
return m_transport->getExpirationTime();
|
||||
}
|
||||
|
||||
inline void
|
||||
Face::close()
|
||||
{
|
||||
m_transport->close();
|
||||
}
|
||||
|
||||
inline const FaceCounters&
|
||||
Face::getCounters() const
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -62,18 +62,38 @@ GenericLinkService::setOptions(const GenericLinkService::Options& options)
|
||||
m_reliability.setOptions(m_options.reliabilityOptions);
|
||||
}
|
||||
|
||||
void
|
||||
GenericLinkService::requestIdlePacket(const EndpointId& endpointId)
|
||||
ssize_t
|
||||
GenericLinkService::getEffectiveMtu() const
|
||||
{
|
||||
// No need to request Acks to attach to this packet from LpReliability, as they are already
|
||||
// attached in sendLpPacket
|
||||
this->sendLpPacket({}, endpointId);
|
||||
// Since MTU_UNLIMITED is negative, it will implicitly override any finite override MTU
|
||||
return std::min(m_options.overrideMtu, getTransport()->getMtu());
|
||||
}
|
||||
|
||||
bool
|
||||
GenericLinkService::canOverrideMtuTo(ssize_t mtu) const
|
||||
{
|
||||
// Not allowed to override unlimited transport MTU
|
||||
if (getTransport()->getMtu() == MTU_UNLIMITED) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Override MTU must be at least MIN_MTU (also implicitly forbids MTU_UNLIMITED and MTU_INVALID)
|
||||
return mtu >= MIN_MTU;
|
||||
}
|
||||
|
||||
void
|
||||
GenericLinkService::sendLpPacket(lp::Packet&& pkt, const EndpointId& endpointId)
|
||||
GenericLinkService::requestIdlePacket()
|
||||
{
|
||||
const ssize_t mtu = this->getTransport()->getMtu();
|
||||
// No need to request Acks to attach to this packet from LpReliability, as they are already
|
||||
// attached in sendLpPacket
|
||||
NFD_LOG_FACE_TRACE("IDLE packet requested");
|
||||
this->sendLpPacket({});
|
||||
}
|
||||
|
||||
void
|
||||
GenericLinkService::sendLpPacket(lp::Packet&& pkt)
|
||||
{
|
||||
const ssize_t mtu = getEffectiveMtu();
|
||||
|
||||
if (m_options.reliabilityOptions.isEnabled) {
|
||||
m_reliability.piggyback(pkt, mtu);
|
||||
@@ -89,38 +109,46 @@ GenericLinkService::sendLpPacket(lp::Packet&& pkt, const EndpointId& endpointId)
|
||||
NFD_LOG_FACE_WARN("attempted to send packet over MTU limit");
|
||||
return;
|
||||
}
|
||||
this->sendPacket(block, endpointId);
|
||||
this->sendPacket(block);
|
||||
}
|
||||
|
||||
void
|
||||
GenericLinkService::doSendInterest(const Interest& interest, const EndpointId& endpointId)
|
||||
GenericLinkService::doSendInterest(const Interest& interest)
|
||||
{
|
||||
lp::Packet lpPacket(interest.wireEncode());
|
||||
|
||||
encodeLpFields(interest, lpPacket);
|
||||
|
||||
this->sendNetPacket(std::move(lpPacket), endpointId, true);
|
||||
this->sendNetPacket(std::move(lpPacket), true);
|
||||
}
|
||||
|
||||
void
|
||||
GenericLinkService::doSendData(const Data& data, const EndpointId& endpointId)
|
||||
GenericLinkService::doSendData(const Data& data)
|
||||
{
|
||||
lp::Packet lpPacket(data.wireEncode());
|
||||
|
||||
encodeLpFields(data, lpPacket);
|
||||
|
||||
this->sendNetPacket(std::move(lpPacket), endpointId, false);
|
||||
this->sendNetPacket(std::move(lpPacket), false);
|
||||
}
|
||||
|
||||
void
|
||||
GenericLinkService::doSendNack(const lp::Nack& nack, const EndpointId& endpointId)
|
||||
GenericLinkService::doSendNack(const lp::Nack& nack)
|
||||
{
|
||||
lp::Packet lpPacket(nack.getInterest().wireEncode());
|
||||
lpPacket.add<lp::NackField>(nack.getHeader());
|
||||
|
||||
encodeLpFields(nack, lpPacket);
|
||||
|
||||
this->sendNetPacket(std::move(lpPacket), endpointId, false);
|
||||
this->sendNetPacket(std::move(lpPacket), false);
|
||||
}
|
||||
|
||||
void
|
||||
GenericLinkService::assignSequences(std::vector<lp::Packet>& pkts)
|
||||
{
|
||||
std::for_each(pkts.begin(), pkts.end(), [this] (lp::Packet& pkt) {
|
||||
pkt.set<lp::SequenceField>(++m_lastSeqNo);
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
@@ -157,10 +185,10 @@ GenericLinkService::encodeLpFields(const ndn::PacketBase& netPkt, lp::Packet& lp
|
||||
}
|
||||
|
||||
void
|
||||
GenericLinkService::sendNetPacket(lp::Packet&& pkt, const EndpointId& endpointId, bool isInterest)
|
||||
GenericLinkService::sendNetPacket(lp::Packet&& pkt, bool isInterest)
|
||||
{
|
||||
std::vector<lp::Packet> frags;
|
||||
ssize_t mtu = this->getTransport()->getMtu();
|
||||
ssize_t mtu = getEffectiveMtu();
|
||||
|
||||
// Make space for feature fields in fragments
|
||||
if (m_options.reliabilityOptions.isEnabled && mtu != MTU_UNLIMITED) {
|
||||
@@ -171,7 +199,8 @@ GenericLinkService::sendNetPacket(lp::Packet&& pkt, const EndpointId& endpointId
|
||||
mtu -= CONGESTION_MARK_SIZE;
|
||||
}
|
||||
|
||||
BOOST_ASSERT(mtu == MTU_UNLIMITED || mtu > 0);
|
||||
// An MTU of 0 is allowed but will cause all packets to be dropped before transmission
|
||||
BOOST_ASSERT(mtu == MTU_UNLIMITED || mtu >= 0);
|
||||
|
||||
if (m_options.allowFragmentation && mtu != MTU_UNLIMITED) {
|
||||
bool isOk = false;
|
||||
@@ -198,8 +227,8 @@ GenericLinkService::sendNetPacket(lp::Packet&& pkt, const EndpointId& endpointId
|
||||
BOOST_ASSERT(!frags.front().has<lp::FragCountField>());
|
||||
}
|
||||
|
||||
// Only assign sequences to fragments if packet contains more than 1 fragment
|
||||
if (frags.size() > 1) {
|
||||
// Only assign sequences to fragments if reliability enabled or if packet contains >1 fragment
|
||||
if (m_options.reliabilityOptions.isEnabled || frags.size() > 1) {
|
||||
// Assign sequences to all fragments
|
||||
this->assignSequences(frags);
|
||||
}
|
||||
@@ -209,22 +238,10 @@ GenericLinkService::sendNetPacket(lp::Packet&& pkt, const EndpointId& endpointId
|
||||
}
|
||||
|
||||
for (lp::Packet& frag : frags) {
|
||||
this->sendLpPacket(std::move(frag), endpointId);
|
||||
this->sendLpPacket(std::move(frag));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GenericLinkService::assignSequence(lp::Packet& pkt)
|
||||
{
|
||||
pkt.set<lp::SequenceField>(++m_lastSeqNo);
|
||||
}
|
||||
|
||||
void
|
||||
GenericLinkService::assignSequences(std::vector<lp::Packet>& pkts)
|
||||
{
|
||||
std::for_each(pkts.begin(), pkts.end(), [this] (auto& pkt) { this->assignSequence(pkt); });
|
||||
}
|
||||
|
||||
void
|
||||
GenericLinkService::checkCongestionLevel(lp::Packet& pkt)
|
||||
{
|
||||
@@ -277,7 +294,11 @@ GenericLinkService::doReceivePacket(const Block& packet, const EndpointId& endpo
|
||||
lp::Packet pkt(packet);
|
||||
|
||||
if (m_options.reliabilityOptions.isEnabled) {
|
||||
m_reliability.processIncomingPacket(pkt);
|
||||
if (!m_reliability.processIncomingPacket(pkt)) {
|
||||
NFD_LOG_FACE_TRACE("received duplicate fragment: DROP");
|
||||
++this->nDuplicateSequence;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!pkt.has<lp::FragmentField>()) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -81,6 +81,10 @@ public:
|
||||
*/
|
||||
PacketCounter nRetxExhausted;
|
||||
|
||||
/** \brief count of LpPackets dropped due to duplicate Sequence numbers
|
||||
*/
|
||||
PacketCounter nDuplicateSequence;
|
||||
|
||||
/** \brief count of outgoing LpPackets that were marked with congestion marks
|
||||
*/
|
||||
PacketCounter nCongestionMarked;
|
||||
@@ -98,7 +102,6 @@ public:
|
||||
class Options
|
||||
{
|
||||
public:
|
||||
constexpr
|
||||
Options() noexcept
|
||||
{
|
||||
}
|
||||
@@ -151,6 +154,16 @@ public:
|
||||
/** \brief enables self-learning forwarding support
|
||||
*/
|
||||
bool allowSelfLearning = true;
|
||||
|
||||
/** \brief overrides MTU provided by Transport
|
||||
*
|
||||
* This MTU value will be used instead of the MTU provided by the transport if it is less than
|
||||
* the transport MTU. However, it will not be utilized when the transport MTU is unlimited.
|
||||
*
|
||||
* Acceptable values for the override MTU are values >= MIN_MTU, which can be validated before
|
||||
* being set with canOverrideMtuTo().
|
||||
*/
|
||||
ssize_t overrideMtu = std::numeric_limits<ssize_t>::max();
|
||||
};
|
||||
|
||||
/** \brief counters provided by GenericLinkService
|
||||
@@ -173,31 +186,40 @@ public:
|
||||
const Counters&
|
||||
getCounters() const OVERRIDE_WITH_TESTS_ELSE_FINAL;
|
||||
|
||||
ssize_t
|
||||
getEffectiveMtu() const OVERRIDE_WITH_TESTS_ELSE_FINAL;
|
||||
|
||||
/** \brief Whether MTU can be overridden to the specified value
|
||||
*
|
||||
* If the transport MTU is unlimited, then this will always return false.
|
||||
*/
|
||||
bool
|
||||
canOverrideMtuTo(ssize_t mtu) const;
|
||||
|
||||
PROTECTED_WITH_TESTS_ELSE_PRIVATE: // send path
|
||||
/** \brief request an IDLE packet to transmit pending service fields
|
||||
*/
|
||||
void
|
||||
requestIdlePacket(const EndpointId& endpointId);
|
||||
requestIdlePacket();
|
||||
|
||||
/** \brief send an LpPacket to \p endpointId
|
||||
/** \brief send an LpPacket
|
||||
*/
|
||||
void
|
||||
sendLpPacket(lp::Packet&& pkt, const EndpointId& endpointId);
|
||||
sendLpPacket(lp::Packet&& pkt);
|
||||
|
||||
/** \brief send Interest
|
||||
void
|
||||
doSendInterest(const Interest& interest) OVERRIDE_WITH_TESTS_ELSE_FINAL;
|
||||
|
||||
void
|
||||
doSendData(const Data& data) OVERRIDE_WITH_TESTS_ELSE_FINAL;
|
||||
|
||||
void
|
||||
doSendNack(const ndn::lp::Nack& nack) OVERRIDE_WITH_TESTS_ELSE_FINAL;
|
||||
|
||||
/** \brief assign consecutive sequence numbers to LpPackets
|
||||
*/
|
||||
void
|
||||
doSendInterest(const Interest& interest, const EndpointId& endpointId) OVERRIDE_WITH_TESTS_ELSE_FINAL;
|
||||
|
||||
/** \brief send Data
|
||||
*/
|
||||
void
|
||||
doSendData(const Data& data, const EndpointId& endpointId) OVERRIDE_WITH_TESTS_ELSE_FINAL;
|
||||
|
||||
/** \brief send Nack
|
||||
*/
|
||||
void
|
||||
doSendNack(const ndn::lp::Nack& nack, const EndpointId& endpointId) OVERRIDE_WITH_TESTS_ELSE_FINAL;
|
||||
assignSequences(std::vector<lp::Packet>& pkts);
|
||||
|
||||
private: // send path
|
||||
/** \brief encode link protocol fields from tags onto an outgoing LpPacket
|
||||
@@ -209,21 +231,10 @@ private: // send path
|
||||
|
||||
/** \brief send a complete network layer packet
|
||||
* \param pkt LpPacket containing a complete network layer packet
|
||||
* \param endpointId destination endpoint to which LpPacket will be sent
|
||||
* \param isInterest whether the network layer packet is an Interest
|
||||
*/
|
||||
void
|
||||
sendNetPacket(lp::Packet&& pkt, const EndpointId& endpointId, bool isInterest);
|
||||
|
||||
/** \brief assign a sequence number to an LpPacket
|
||||
*/
|
||||
void
|
||||
assignSequence(lp::Packet& pkt);
|
||||
|
||||
/** \brief assign consecutive sequence numbers to LpPackets
|
||||
*/
|
||||
void
|
||||
assignSequences(std::vector<lp::Packet>& pkts);
|
||||
sendNetPacket(lp::Packet&& pkt, bool isInterest);
|
||||
|
||||
/** \brief if the send queue is found to be congested, add a congestion mark to the packet
|
||||
* according to CoDel
|
||||
@@ -233,8 +244,6 @@ private: // send path
|
||||
checkCongestionLevel(lp::Packet& pkt);
|
||||
|
||||
private: // receive path
|
||||
/** \brief receive Packet from Transport
|
||||
*/
|
||||
void
|
||||
doReceivePacket(const Block& packet, const EndpointId& endpoint) OVERRIDE_WITH_TESTS_ELSE_FINAL;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -55,7 +55,7 @@ InternalForwarderTransport::receivePacket(const Block& packet)
|
||||
}
|
||||
|
||||
void
|
||||
InternalForwarderTransport::doSend(const Block& packet, const EndpointId&)
|
||||
InternalForwarderTransport::doSend(const Block& packet)
|
||||
{
|
||||
NFD_LOG_FACE_TRACE("Sending to " << m_peer);
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -71,7 +71,7 @@ protected:
|
||||
|
||||
private:
|
||||
void
|
||||
doSend(const Block& packet, const EndpointId& endpoint) final;
|
||||
doSend(const Block& packet) final;
|
||||
|
||||
private:
|
||||
NFD_LOG_MEMBER_DECL();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -52,36 +52,36 @@ LinkService::setFaceAndTransport(Face& face, Transport& transport)
|
||||
}
|
||||
|
||||
void
|
||||
LinkService::sendInterest(const Interest& interest, const EndpointId& endpoint)
|
||||
LinkService::sendInterest(const Interest& interest)
|
||||
{
|
||||
BOOST_ASSERT(m_transport != nullptr);
|
||||
NFD_LOG_FACE_TRACE(__func__);
|
||||
|
||||
++this->nOutInterests;
|
||||
|
||||
doSendInterest(interest, endpoint);
|
||||
doSendInterest(interest);
|
||||
}
|
||||
|
||||
void
|
||||
LinkService::sendData(const Data& data, const EndpointId& endpoint)
|
||||
LinkService::sendData(const Data& data)
|
||||
{
|
||||
BOOST_ASSERT(m_transport != nullptr);
|
||||
NFD_LOG_FACE_TRACE(__func__);
|
||||
|
||||
++this->nOutData;
|
||||
|
||||
doSendData(data, endpoint);
|
||||
doSendData(data);
|
||||
}
|
||||
|
||||
void
|
||||
LinkService::sendNack(const ndn::lp::Nack& nack, const EndpointId& endpoint)
|
||||
LinkService::sendNack(const ndn::lp::Nack& nack)
|
||||
{
|
||||
BOOST_ASSERT(m_transport != nullptr);
|
||||
NFD_LOG_FACE_TRACE(__func__);
|
||||
|
||||
++this->nOutNacks;
|
||||
|
||||
doSendNack(nack, endpoint);
|
||||
doSendNack(nack);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -117,7 +117,7 @@ LinkService::receiveNack(const ndn::lp::Nack& nack, const EndpointId& endpoint)
|
||||
void
|
||||
LinkService::notifyDroppedInterest(const Interest& interest)
|
||||
{
|
||||
++this->nDroppedInterests;
|
||||
++this->nInterestsExceededRetx;
|
||||
onDroppedInterest(interest);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -50,7 +50,7 @@ public:
|
||||
|
||||
/** \brief count of Interests dropped by reliability system for exceeding allowed number of retx
|
||||
*/
|
||||
PacketCounter nDroppedInterests;
|
||||
PacketCounter nInterestsExceededRetx;
|
||||
|
||||
/** \brief count of incoming Data packets
|
||||
*/
|
||||
@@ -109,24 +109,27 @@ public:
|
||||
virtual const Counters&
|
||||
getCounters() const;
|
||||
|
||||
virtual ssize_t
|
||||
getEffectiveMtu() const;
|
||||
|
||||
public: // upper interface to be used by forwarding
|
||||
/** \brief Send Interest to \p endpoint
|
||||
/** \brief Send Interest
|
||||
* \pre setTransport has been called
|
||||
*/
|
||||
void
|
||||
sendInterest(const Interest& interest, const EndpointId& endpoint);
|
||||
sendInterest(const Interest& interest);
|
||||
|
||||
/** \brief Send Data to \p endpoint
|
||||
/** \brief Send Data
|
||||
* \pre setTransport has been called
|
||||
*/
|
||||
void
|
||||
sendData(const Data& data, const EndpointId& endpoint);
|
||||
sendData(const Data& data);
|
||||
|
||||
/** \brief Send Nack to \p endpoint
|
||||
/** \brief Send Nack
|
||||
* \pre setTransport has been called
|
||||
*/
|
||||
void
|
||||
sendNack(const ndn::lp::Nack& nack, const EndpointId& endpoint);
|
||||
sendNack(const ndn::lp::Nack& nack);
|
||||
|
||||
/** \brief signals on Interest received
|
||||
*/
|
||||
@@ -167,30 +170,30 @@ protected: // upper interface to be invoked in subclass (receive path terminatio
|
||||
receiveNack(const lp::Nack& nack, const EndpointId& endpoint);
|
||||
|
||||
protected: // lower interface to be invoked in subclass (send path termination)
|
||||
/** \brief send a lower-layer packet via Transport to \p endpoint
|
||||
/** \brief send a lower-layer packet via Transport
|
||||
*/
|
||||
void
|
||||
sendPacket(const Block& packet, const EndpointId& endpoint);
|
||||
sendPacket(const Block& packet);
|
||||
|
||||
protected:
|
||||
void
|
||||
notifyDroppedInterest(const Interest& packet);
|
||||
|
||||
private: // upper interface to be overridden in subclass (send path entrypoint)
|
||||
/** \brief performs LinkService specific operations to send an Interest to \p endpoint
|
||||
/** \brief performs LinkService specific operations to send an Interest
|
||||
*/
|
||||
virtual void
|
||||
doSendInterest(const Interest& interest, const EndpointId& endpoint) = 0;
|
||||
doSendInterest(const Interest& interest) = 0;
|
||||
|
||||
/** \brief performs LinkService specific operations to send a Data to \p endpoint
|
||||
/** \brief performs LinkService specific operations to send a Data
|
||||
*/
|
||||
virtual void
|
||||
doSendData(const Data& data, const EndpointId& endpoint) = 0;
|
||||
doSendData(const Data& data) = 0;
|
||||
|
||||
/** \brief performs LinkService specific operations to send a Nack to \p endpoint
|
||||
/** \brief performs LinkService specific operations to send a Nack
|
||||
*/
|
||||
virtual void
|
||||
doSendNack(const lp::Nack& nack, const EndpointId& endpoint) = 0;
|
||||
doSendNack(const lp::Nack& nack) = 0;
|
||||
|
||||
private: // lower interface to be overridden in subclass
|
||||
virtual void
|
||||
@@ -225,6 +228,12 @@ LinkService::getCounters() const
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline ssize_t
|
||||
LinkService::getEffectiveMtu() const
|
||||
{
|
||||
return m_transport->getMtu();
|
||||
}
|
||||
|
||||
inline void
|
||||
LinkService::receivePacket(const Block& packet, const EndpointId& endpoint)
|
||||
{
|
||||
@@ -232,9 +241,9 @@ LinkService::receivePacket(const Block& packet, const EndpointId& endpoint)
|
||||
}
|
||||
|
||||
inline void
|
||||
LinkService::sendPacket(const Block& packet, const EndpointId& endpoint)
|
||||
LinkService::sendPacket(const Block& packet)
|
||||
{
|
||||
m_transport->send(packet, endpoint);
|
||||
m_transport->send(packet);
|
||||
}
|
||||
|
||||
std::ostream&
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -31,6 +31,8 @@
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
|
||||
NFD_LOG_INIT(LpReliability);
|
||||
|
||||
LpReliability::LpReliability(const LpReliability::Options& options, GenericLinkService* linkService)
|
||||
: m_options(options)
|
||||
, m_linkService(linkService)
|
||||
@@ -71,6 +73,9 @@ LpReliability::handleOutgoing(std::vector<lp::Packet>& frags, lp::Packet&& pkt,
|
||||
netPkt->unackedFrags.reserve(frags.size());
|
||||
|
||||
for (lp::Packet& frag : frags) {
|
||||
// Non-IDLE packets are required to have assigned Sequence numbers with LpReliability enabled
|
||||
BOOST_ASSERT(frag.has<lp::SequenceField>());
|
||||
|
||||
// Assign TxSequence number
|
||||
lp::Sequence txSeq = assignTxSequence(frag);
|
||||
|
||||
@@ -80,8 +85,13 @@ LpReliability::handleOutgoing(std::vector<lp::Packet>& frags, lp::Packet&& pkt,
|
||||
std::forward_as_tuple(txSeq),
|
||||
std::forward_as_tuple(frag));
|
||||
unackedFragsIt->second.sendTime = sendTime;
|
||||
unackedFragsIt->second.rtoTimer = getScheduler().schedule(m_rttEst.getEstimatedRto(),
|
||||
[=] { onLpPacketLost(txSeq); });
|
||||
auto rto = m_rttEst.getEstimatedRto();
|
||||
lp::Sequence seq = frag.get<lp::SequenceField>();
|
||||
NFD_LOG_FACE_TRACE("transmitting seq=" << seq << ", txseq=" << txSeq << ", rto=" <<
|
||||
time::duration_cast<time::milliseconds>(rto).count() << "ms");
|
||||
unackedFragsIt->second.rtoTimer = getScheduler().schedule(rto, [=] {
|
||||
onLpPacketLost(txSeq, true);
|
||||
});
|
||||
unackedFragsIt->second.netPkt = netPkt;
|
||||
|
||||
if (m_unackedFrags.size() == 1) {
|
||||
@@ -93,18 +103,20 @@ LpReliability::handleOutgoing(std::vector<lp::Packet>& frags, lp::Packet&& pkt,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
LpReliability::processIncomingPacket(const lp::Packet& pkt)
|
||||
{
|
||||
BOOST_ASSERT(m_options.isEnabled);
|
||||
|
||||
bool isDuplicate = false;
|
||||
auto now = time::steady_clock::now();
|
||||
|
||||
// Extract and parse Acks
|
||||
for (lp::Sequence ackSeq : pkt.list<lp::AckField>()) {
|
||||
auto fragIt = m_unackedFrags.find(ackSeq);
|
||||
for (lp::Sequence ackTxSeq : pkt.list<lp::AckField>()) {
|
||||
auto fragIt = m_unackedFrags.find(ackTxSeq);
|
||||
if (fragIt == m_unackedFrags.end()) {
|
||||
// Ignore an Ack for an unknown TxSequence number
|
||||
NFD_LOG_FACE_DEBUG("received ack for unknown txseq=" << ackTxSeq);
|
||||
continue;
|
||||
}
|
||||
auto& frag = fragIt->second;
|
||||
@@ -113,12 +125,19 @@ LpReliability::processIncomingPacket(const lp::Packet& pkt)
|
||||
frag.rtoTimer.cancel();
|
||||
|
||||
if (frag.retxCount == 0) {
|
||||
NFD_LOG_FACE_TRACE("received ack for seq=" << frag.pkt.get<lp::SequenceField>() << ", txseq=" <<
|
||||
ackTxSeq << ", retx=0, rtt=" <<
|
||||
time::duration_cast<time::milliseconds>(now - frag.sendTime).count() << "ms");
|
||||
// This sequence had no retransmissions, so use it to estimate the RTO
|
||||
m_rttEst.addMeasurement(now - frag.sendTime);
|
||||
}
|
||||
else {
|
||||
NFD_LOG_FACE_TRACE("received ack for seq=" << frag.pkt.get<lp::SequenceField>() << ", txseq=" <<
|
||||
ackTxSeq << ", retx=" << frag.retxCount);
|
||||
}
|
||||
|
||||
// Look for frags with TxSequence numbers < ackSeq (allowing for wraparound) and consider them
|
||||
// lost if a configurable number of Acks containing greater TxSequence numbers have been
|
||||
// Look for frags with TxSequence numbers < ackTxSeq (allowing for wraparound) and consider
|
||||
// them lost if a configurable number of Acks containing greater TxSequence numbers have been
|
||||
// received.
|
||||
auto lostLpPackets = findLostLpPackets(fragIt);
|
||||
|
||||
@@ -135,8 +154,8 @@ LpReliability::processIncomingPacket(const lp::Packet& pkt)
|
||||
// Resend or fail fragments considered lost. Potentially increment the start of the window.
|
||||
for (lp::Sequence txSeq : lostLpPackets) {
|
||||
if (removedLpPackets.find(txSeq) == removedLpPackets.end()) {
|
||||
auto removedThisTxSeq = onLpPacketLost(txSeq);
|
||||
for (auto removedTxSeq : removedThisTxSeq) {
|
||||
auto removedTxSeqs = onLpPacketLost(txSeq, false);
|
||||
for (auto removedTxSeq : removedTxSeqs) {
|
||||
removedLpPackets.insert(removedTxSeq);
|
||||
}
|
||||
}
|
||||
@@ -145,9 +164,29 @@ LpReliability::processIncomingPacket(const lp::Packet& pkt)
|
||||
|
||||
// If packet has Fragment and TxSequence fields, extract TxSequence and add to AckQueue
|
||||
if (pkt.has<lp::FragmentField>() && pkt.has<lp::TxSequenceField>()) {
|
||||
NFD_LOG_FACE_TRACE("queueing ack for remote txseq=" << pkt.get<lp::TxSequenceField>());
|
||||
m_ackQueue.push(pkt.get<lp::TxSequenceField>());
|
||||
|
||||
// Check for received frames with duplicate Sequences
|
||||
if (pkt.has<lp::SequenceField>()) {
|
||||
lp::Sequence pktSequence = pkt.get<lp::SequenceField>();
|
||||
isDuplicate = m_recentRecvSeqs.count(pktSequence) > 0;
|
||||
// Check for recent received Sequences to remove
|
||||
auto now = time::steady_clock::now();
|
||||
auto rto = m_rttEst.getEstimatedRto();
|
||||
while (m_recentRecvSeqsQueue.size() > 0 &&
|
||||
now > m_recentRecvSeqs[m_recentRecvSeqsQueue.front()] + rto) {
|
||||
m_recentRecvSeqs.erase(m_recentRecvSeqsQueue.front());
|
||||
m_recentRecvSeqsQueue.pop();
|
||||
}
|
||||
m_recentRecvSeqs.emplace(pktSequence, now);
|
||||
m_recentRecvSeqsQueue.push(pktSequence);
|
||||
}
|
||||
|
||||
startIdleAckTimer();
|
||||
}
|
||||
|
||||
return !isDuplicate;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -164,7 +203,7 @@ LpReliability::piggyback(lp::Packet& pkt, ssize_t mtu)
|
||||
remainingSpace -= pktSize;
|
||||
|
||||
while (!m_ackQueue.empty()) {
|
||||
lp::Sequence ackSeq = m_ackQueue.front();
|
||||
lp::Sequence ackTxSeq = m_ackQueue.front();
|
||||
// Ack size = Ack TLV-TYPE (3 octets) + TLV-LENGTH (1 octet) + lp::Sequence (8 octets)
|
||||
const ssize_t ackSize = tlv::sizeOfVarNumber(lp::tlv::Ack) +
|
||||
tlv::sizeOfVarNumber(sizeof(lp::Sequence)) +
|
||||
@@ -174,7 +213,9 @@ LpReliability::piggyback(lp::Packet& pkt, ssize_t mtu)
|
||||
break;
|
||||
}
|
||||
|
||||
pkt.add<lp::AckField>(ackSeq);
|
||||
NFD_LOG_FACE_TRACE("piggybacking ack for remote txseq=" << ackTxSeq);
|
||||
|
||||
pkt.add<lp::AckField>(ackTxSeq);
|
||||
m_ackQueue.pop();
|
||||
remainingSpace -= ackSize;
|
||||
}
|
||||
@@ -201,7 +242,7 @@ LpReliability::startIdleAckTimer()
|
||||
|
||||
m_idleAckTimer = getScheduler().schedule(m_options.idleAckTimerPeriod, [this] {
|
||||
while (!m_ackQueue.empty()) {
|
||||
m_linkService->requestIdlePacket(0);
|
||||
m_linkService->requestIdlePacket();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -222,6 +263,8 @@ LpReliability::findLostLpPackets(LpReliability::UnackedFrags::iterator ackIt)
|
||||
|
||||
auto& unackedFrag = it->second;
|
||||
unackedFrag.nGreaterSeqAcks++;
|
||||
NFD_LOG_FACE_TRACE("received ack=" << ackIt->first << " before=" << it->first <<
|
||||
", before count=" << unackedFrag.nGreaterSeqAcks);
|
||||
|
||||
if (unackedFrag.nGreaterSeqAcks >= m_options.seqNumLossThreshold) {
|
||||
lostLpPackets.push_back(it->first);
|
||||
@@ -232,7 +275,7 @@ LpReliability::findLostLpPackets(LpReliability::UnackedFrags::iterator ackIt)
|
||||
}
|
||||
|
||||
std::vector<lp::Sequence>
|
||||
LpReliability::onLpPacketLost(lp::Sequence txSeq)
|
||||
LpReliability::onLpPacketLost(lp::Sequence txSeq, bool isTimeout)
|
||||
{
|
||||
BOOST_ASSERT(m_unackedFrags.count(txSeq) > 0);
|
||||
auto txSeqIt = m_unackedFrags.find(txSeq);
|
||||
@@ -241,9 +284,19 @@ LpReliability::onLpPacketLost(lp::Sequence txSeq)
|
||||
txFrag.rtoTimer.cancel();
|
||||
auto netPkt = txFrag.netPkt;
|
||||
std::vector<lp::Sequence> removedThisTxSeq;
|
||||
lp::Sequence seq = txFrag.pkt.get<lp::SequenceField>();
|
||||
|
||||
if (isTimeout) {
|
||||
NFD_LOG_FACE_TRACE("rto timer expired for seq=" << seq << ", txseq=" << txSeq);
|
||||
}
|
||||
else { // lost due to out-of-order TxSeqs
|
||||
NFD_LOG_FACE_TRACE("seq=" << seq << ", txseq=" << txSeq <<
|
||||
" considered lost from acks for more recent txseqs");
|
||||
}
|
||||
|
||||
// Check if maximum number of retransmissions exceeded
|
||||
if (txFrag.retxCount >= m_options.maxRetx) {
|
||||
NFD_LOG_FACE_DEBUG("seq=" << seq << " exceeded allowed retransmissions: DROP");
|
||||
// Delete all LpPackets of NetPkt from m_unackedFrags (except this one)
|
||||
for (size_t i = 0; i < netPkt->unackedFrags.size(); i++) {
|
||||
if (netPkt->unackedFrags[i] != txSeqIt) {
|
||||
@@ -263,6 +316,7 @@ LpReliability::onLpPacketLost(lp::Sequence txSeq)
|
||||
onDroppedInterest(Interest(frag));
|
||||
}
|
||||
|
||||
// Delete this LpPacket from m_unackedFrags
|
||||
removedThisTxSeq.push_back(txSeqIt->first);
|
||||
deleteUnackedFrag(txSeqIt);
|
||||
}
|
||||
@@ -292,11 +346,17 @@ LpReliability::onLpPacketLost(lp::Sequence txSeq)
|
||||
deleteUnackedFrag(txSeqIt);
|
||||
|
||||
// Retransmit fragment
|
||||
m_linkService->sendLpPacket(lp::Packet(newTxFrag.pkt), 0);
|
||||
m_linkService->sendLpPacket(lp::Packet(newTxFrag.pkt));
|
||||
|
||||
auto rto = m_rttEst.getEstimatedRto();
|
||||
NFD_LOG_FACE_TRACE("retransmitting seq=" << seq << ", txseq=" << newTxSeq << ", retx=" <<
|
||||
txFrag.retxCount << ", rto=" <<
|
||||
time::duration_cast<time::milliseconds>(rto).count() << "ms");
|
||||
|
||||
// Start RTO timer for this sequence
|
||||
newTxFrag.rtoTimer = getScheduler().schedule(m_rttEst.getEstimatedRto(),
|
||||
[=] { onLpPacketLost(newTxSeq); });
|
||||
newTxFrag.rtoTimer = getScheduler().schedule(rto, [=] {
|
||||
onLpPacketLost(newTxSeq, true);
|
||||
});
|
||||
}
|
||||
|
||||
return removedThisTxSeq;
|
||||
@@ -362,5 +422,17 @@ LpReliability::NetPkt::NetPkt(lp::Packet&& pkt, bool isInterest)
|
||||
{
|
||||
}
|
||||
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, const FaceLogHelper<LpReliability>& flh)
|
||||
{
|
||||
if (flh.obj.getLinkService() == nullptr) {
|
||||
os << "[id=0,local=unknown,remote=unknown] ";
|
||||
}
|
||||
else {
|
||||
os << FaceLogHelper<LinkService>(*flh.obj.getLinkService());
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -26,7 +26,7 @@
|
||||
#ifndef NFD_DAEMON_FACE_LP_RELIABILITY_HPP
|
||||
#define NFD_DAEMON_FACE_LP_RELIABILITY_HPP
|
||||
|
||||
#include "core/common.hpp"
|
||||
#include "face-common.hpp"
|
||||
|
||||
#include <ndn-cxx/lp/packet.hpp>
|
||||
#include <ndn-cxx/lp/sequence.hpp>
|
||||
@@ -93,8 +93,9 @@ public:
|
||||
|
||||
/** \brief extract and parse all Acks and add Ack for contained Fragment (if any) to AckQueue
|
||||
* \param pkt incoming LpPacket
|
||||
* \return whether incoming LpPacket is new and not a duplicate
|
||||
*/
|
||||
void
|
||||
bool
|
||||
processIncomingPacket(const lp::Packet& pkt);
|
||||
|
||||
/** \brief called by GenericLinkService to attach Acks onto an outgoing LpPacket
|
||||
@@ -139,7 +140,7 @@ PUBLIC_WITH_TESTS_ELSE_PRIVATE:
|
||||
* \return vector of the TxSequences of fragments removed due to a network packet being removed
|
||||
*/
|
||||
std::vector<lp::Sequence>
|
||||
onLpPacketLost(lp::Sequence txSeq);
|
||||
onLpPacketLost(lp::Sequence txSeq, bool isTimeout);
|
||||
|
||||
/** \brief remove the fragment with the given sequence number from the map of unacknowledged
|
||||
* fragments, as well as its associated network packet (if any)
|
||||
@@ -210,11 +211,16 @@ PUBLIC_WITH_TESTS_ELSE_PRIVATE:
|
||||
*/
|
||||
UnackedFrags::iterator m_firstUnackedFrag;
|
||||
std::queue<lp::Sequence> m_ackQueue;
|
||||
std::map<lp::Sequence, time::steady_clock::TimePoint> m_recentRecvSeqs;
|
||||
std::queue<lp::Sequence> m_recentRecvSeqsQueue;
|
||||
lp::Sequence m_lastTxSeqNo;
|
||||
scheduler::ScopedEventId m_idleAckTimer;
|
||||
ndn::util::RttEstimator m_rttEst;
|
||||
};
|
||||
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, const FaceLogHelper<LpReliability>& flh);
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -82,7 +82,7 @@ MulticastUdpTransport::getSendQueueLength()
|
||||
}
|
||||
|
||||
void
|
||||
MulticastUdpTransport::doSend(const Block& packet, const EndpointId&)
|
||||
MulticastUdpTransport::doSend(const Block& packet)
|
||||
{
|
||||
NFD_LOG_FACE_TRACE(__func__);
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -84,7 +84,7 @@ public:
|
||||
|
||||
private:
|
||||
void
|
||||
doSend(const Block& packet, const EndpointId& endpoint) final;
|
||||
doSend(const Block& packet) final;
|
||||
|
||||
void
|
||||
doClose() final;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -37,17 +37,17 @@ class NullLinkService final : public LinkService
|
||||
{
|
||||
private:
|
||||
void
|
||||
doSendInterest(const Interest&, const EndpointId&) final
|
||||
doSendInterest(const Interest&) final
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
doSendData(const Data&, const EndpointId&) final
|
||||
doSendData(const Data&) final
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
doSendNack(const lp::Nack&, const EndpointId&) final
|
||||
doSendNack(const lp::Nack&) final
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -51,7 +51,7 @@ protected:
|
||||
|
||||
private:
|
||||
void
|
||||
doSend(const Block&, const EndpointId&) OVERRIDE_WITH_TESTS_ELSE_FINAL
|
||||
doSend(const Block&) OVERRIDE_WITH_TESTS_ELSE_FINAL
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -63,7 +63,7 @@ protected:
|
||||
deferredClose();
|
||||
|
||||
void
|
||||
doSend(const Block& packet, const EndpointId& endpoint) override;
|
||||
doSend(const Block& packet) override;
|
||||
|
||||
void
|
||||
sendFromQueue();
|
||||
@@ -180,7 +180,7 @@ StreamTransport<T>::deferredClose()
|
||||
|
||||
template<class T>
|
||||
void
|
||||
StreamTransport<T>::doSend(const Block& packet, const EndpointId&)
|
||||
StreamTransport<T>::doSend(const Block& packet)
|
||||
{
|
||||
NFD_LOG_FACE_TRACE(__func__);
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -129,6 +129,7 @@ TcpChannel::createFace(ip::tcp::socket&& socket,
|
||||
socket.remote_endpoint().address());
|
||||
auto transport = make_unique<TcpTransport>(std::move(socket), params.persistency, faceScope);
|
||||
face = make_shared<Face>(std::move(linkService), std::move(transport));
|
||||
face->setChannel(shared_from_this()); // use weak_from_this() in C++17
|
||||
|
||||
m_channelFaces[remoteEndpoint] = face;
|
||||
connectFaceClosedSignal(*face, [this, remoteEndpoint] { m_channelFaces.erase(remoteEndpoint); });
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -31,8 +31,6 @@ namespace face {
|
||||
|
||||
NFD_LOG_INIT(Transport);
|
||||
|
||||
const ssize_t Transport::MIN_MTU;
|
||||
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, TransportState state)
|
||||
{
|
||||
@@ -91,7 +89,7 @@ Transport::close()
|
||||
}
|
||||
|
||||
void
|
||||
Transport::send(const Block& packet, const EndpointId& endpoint)
|
||||
Transport::send(const Block& packet)
|
||||
{
|
||||
BOOST_ASSERT(packet.isValid());
|
||||
BOOST_ASSERT(this->getMtu() == MTU_UNLIMITED ||
|
||||
@@ -108,7 +106,7 @@ Transport::send(const Block& packet, const EndpointId& endpoint)
|
||||
this->nOutBytes += packet.size();
|
||||
}
|
||||
|
||||
this->doSend(packet, endpoint);
|
||||
this->doSend(packet);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -124,6 +122,22 @@ Transport::receive(const Block& packet, const EndpointId& endpoint)
|
||||
m_service->receivePacket(packet, endpoint);
|
||||
}
|
||||
|
||||
void
|
||||
Transport::setMtu(ssize_t mtu)
|
||||
{
|
||||
BOOST_ASSERT(mtu == MTU_UNLIMITED || mtu >= 0);
|
||||
|
||||
if (mtu == m_mtu) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_mtu != MTU_INVALID) {
|
||||
NFD_LOG_FACE_INFO("setMtu " << m_mtu << " -> " << mtu);
|
||||
}
|
||||
|
||||
m_mtu = mtu;
|
||||
}
|
||||
|
||||
bool
|
||||
Transport::canChangePersistencyTo(ndn::nfd::FacePersistency newPersistency) const
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -165,12 +165,11 @@ public: // upper interface
|
||||
|
||||
/** \brief Send a link-layer packet
|
||||
* \param packet the packet to be sent, must be a valid and well-formed TLV block
|
||||
* \param endpoint the destination endpoint
|
||||
* \note This operation has no effect if getState() is neither UP nor DOWN
|
||||
* \warning Behavior is undefined if packet size exceeds the MTU limit
|
||||
*/
|
||||
void
|
||||
send(const Block& packet, const EndpointId& endpoint = 0);
|
||||
send(const Block& packet);
|
||||
|
||||
public: // static properties
|
||||
/** \return a FaceUri representing local endpoint
|
||||
@@ -333,18 +332,10 @@ protected: // to be overridden by subclass
|
||||
private: // to be overridden by subclass
|
||||
/** \brief performs Transport specific operations to send a packet
|
||||
* \param packet the packet to be sent, can be assumed to be valid and well-formed
|
||||
* \param endpoint the destination endpoint
|
||||
* \pre transport state is either UP or DOWN
|
||||
*/
|
||||
virtual void
|
||||
doSend(const Block& packet, const EndpointId& endpoint) = 0;
|
||||
|
||||
public:
|
||||
/** \brief minimum MTU that may be set on a transport
|
||||
*
|
||||
* This is done to ensure the NDNLPv2 fragmentation feature functions properly.
|
||||
*/
|
||||
static constexpr ssize_t MIN_MTU = 64;
|
||||
doSend(const Block& packet) = 0;
|
||||
|
||||
private:
|
||||
Face* m_face;
|
||||
@@ -444,13 +435,6 @@ Transport::getMtu() const
|
||||
return m_mtu;
|
||||
}
|
||||
|
||||
inline void
|
||||
Transport::setMtu(ssize_t mtu)
|
||||
{
|
||||
BOOST_ASSERT(mtu == MTU_UNLIMITED || mtu > 0);
|
||||
m_mtu = mtu;
|
||||
}
|
||||
|
||||
inline ssize_t
|
||||
Transport::getSendQueueCapacity() const
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -180,10 +180,15 @@ UdpChannel::createFace(const udp::Endpoint& remoteEndpoint,
|
||||
options.defaultCongestionThreshold = *params.defaultCongestionThreshold;
|
||||
}
|
||||
|
||||
if (params.mtu) {
|
||||
options.overrideMtu = *params.mtu;
|
||||
}
|
||||
|
||||
auto linkService = make_unique<GenericLinkService>(options);
|
||||
auto transport = make_unique<UnicastUdpTransport>(std::move(socket), params.persistency,
|
||||
m_idleFaceTimeout, params.mtu);
|
||||
m_idleFaceTimeout);
|
||||
auto face = make_shared<Face>(std::move(linkService), std::move(transport));
|
||||
face->setChannel(shared_from_this()); // use weak_from_this() in C++17
|
||||
|
||||
m_channelFaces[remoteEndpoint] = face;
|
||||
connectFaceClosedSignal(*face, [this, remoteEndpoint] { m_channelFaces.erase(remoteEndpoint); });
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -268,10 +268,10 @@ UdpFactory::doCreateFace(const CreateFaceRequest& req,
|
||||
return;
|
||||
}
|
||||
|
||||
if (req.params.mtu && *req.params.mtu < Transport::MIN_MTU) {
|
||||
if (req.params.mtu && *req.params.mtu < MIN_MTU) {
|
||||
// The specified MTU must be greater than the minimum possible
|
||||
NFD_LOG_TRACE("createFace cannot create a face with MTU less than " << Transport::MIN_MTU);
|
||||
onFailure(406, "MTU cannot be less than " + to_string(Transport::MIN_MTU));
|
||||
NFD_LOG_TRACE("createFace: override MTU cannot be less than " << MIN_MTU);
|
||||
onFailure(406, "Override MTU cannot be less than " + to_string(MIN_MTU));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -362,6 +362,13 @@ UdpFactory::createMulticastFace(const shared_ptr<const net::NetworkInterface>& n
|
||||
m_mcastFaces[localEp] = face;
|
||||
connectFaceClosedSignal(*face, [this, localEp] { m_mcastFaces.erase(localEp); });
|
||||
|
||||
// Associate with the first available channel of the same protocol family
|
||||
auto channelIt = std::find_if(m_channels.begin(), m_channels.end(),
|
||||
[isV4 = localEp.address().is_v4()] (const auto& it) {
|
||||
return it.first.address().is_v4() == isV4;
|
||||
});
|
||||
face->setChannel(channelIt != m_channels.end() ? channelIt->second : nullptr);
|
||||
|
||||
return face;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -36,8 +36,7 @@ NFD_LOG_INIT(UnicastEthernetTransport);
|
||||
UnicastEthernetTransport::UnicastEthernetTransport(const ndn::net::NetworkInterface& localEndpoint,
|
||||
const ethernet::Address& remoteEndpoint,
|
||||
ndn::nfd::FacePersistency persistency,
|
||||
time::nanoseconds idleTimeout,
|
||||
optional<ssize_t> overrideMtu)
|
||||
time::nanoseconds idleTimeout)
|
||||
: EthernetTransport(localEndpoint, remoteEndpoint)
|
||||
, m_idleTimeout(idleTimeout)
|
||||
{
|
||||
@@ -46,13 +45,7 @@ UnicastEthernetTransport::UnicastEthernetTransport(const ndn::net::NetworkInterf
|
||||
this->setScope(ndn::nfd::FACE_SCOPE_NON_LOCAL);
|
||||
this->setPersistency(persistency);
|
||||
this->setLinkType(ndn::nfd::LINK_TYPE_POINT_TO_POINT);
|
||||
|
||||
if (overrideMtu) {
|
||||
this->setMtu(std::min<ssize_t>(localEndpoint.getMtu(), *overrideMtu));
|
||||
}
|
||||
else {
|
||||
this->setMtu(localEndpoint.getMtu());
|
||||
}
|
||||
this->setMtu(localEndpoint.getMtu());
|
||||
|
||||
NFD_LOG_FACE_DEBUG("Creating transport");
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -43,8 +43,7 @@ public:
|
||||
UnicastEthernetTransport(const ndn::net::NetworkInterface& localEndpoint,
|
||||
const ethernet::Address& remoteEndpoint,
|
||||
ndn::nfd::FacePersistency persistency,
|
||||
time::nanoseconds idleTimeout,
|
||||
optional<ssize_t> overrideMtu = {});
|
||||
time::nanoseconds idleTimeout);
|
||||
|
||||
protected:
|
||||
bool
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -41,8 +41,7 @@ NFD_LOG_MEMBER_INIT_SPECIALIZED((DatagramTransport<boost::asio::ip::udp, Unicast
|
||||
|
||||
UnicastUdpTransport::UnicastUdpTransport(protocol::socket&& socket,
|
||||
ndn::nfd::FacePersistency persistency,
|
||||
time::nanoseconds idleTimeout,
|
||||
optional<ssize_t> overrideMtu)
|
||||
time::nanoseconds idleTimeout)
|
||||
: DatagramTransport(std::move(socket))
|
||||
, m_idleTimeout(idleTimeout)
|
||||
{
|
||||
@@ -51,14 +50,7 @@ UnicastUdpTransport::UnicastUdpTransport(protocol::socket&& socket,
|
||||
this->setScope(ndn::nfd::FACE_SCOPE_NON_LOCAL);
|
||||
this->setPersistency(persistency);
|
||||
this->setLinkType(ndn::nfd::LINK_TYPE_POINT_TO_POINT);
|
||||
|
||||
if (overrideMtu) {
|
||||
this->setMtu(std::min(udp::computeMtu(m_socket.local_endpoint()), *overrideMtu));
|
||||
}
|
||||
else {
|
||||
this->setMtu(udp::computeMtu(m_socket.local_endpoint()));
|
||||
}
|
||||
BOOST_ASSERT(this->getMtu() >= MIN_MTU);
|
||||
this->setMtu(udp::computeMtu(m_socket.local_endpoint()));
|
||||
|
||||
NFD_LOG_FACE_DEBUG("Creating transport");
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -41,8 +41,7 @@ class UnicastUdpTransport final : public DatagramTransport<boost::asio::ip::udp,
|
||||
public:
|
||||
UnicastUdpTransport(protocol::socket&& socket,
|
||||
ndn::nfd::FacePersistency persistency,
|
||||
time::nanoseconds idleTimeout,
|
||||
optional<ssize_t> overrideMtu = {});
|
||||
time::nanoseconds idleTimeout);
|
||||
|
||||
protected:
|
||||
bool
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -137,6 +137,7 @@ UnixStreamChannel::handleAccept(const boost::system::error_code& error,
|
||||
auto linkService = make_unique<GenericLinkService>(options);
|
||||
auto transport = make_unique<UnixStreamTransport>(std::move(m_socket));
|
||||
auto face = make_shared<Face>(std::move(linkService), std::move(transport));
|
||||
face->setChannel(shared_from_this()); // use weak_from_this() in C++17
|
||||
|
||||
++m_size;
|
||||
connectFaceClosedSignal(*face, [this] { --m_size; });
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -46,7 +46,8 @@ UnixStreamFactory::doProcessConfig(OptionalConfigSection configSection,
|
||||
{
|
||||
// unix
|
||||
// {
|
||||
// path /var/run/nfd.sock
|
||||
// path /run/nfd.sock ; on Linux
|
||||
// path /var/run/nfd.sock ; on other platforms
|
||||
// }
|
||||
|
||||
m_wantCongestionMarking = context.generalConfig.wantCongestionMarking;
|
||||
@@ -58,7 +59,11 @@ UnixStreamFactory::doProcessConfig(OptionalConfigSection configSection,
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
std::string path = "/run/nfd.sock";
|
||||
#else
|
||||
std::string path = "/var/run/nfd.sock";
|
||||
#endif // __linux__
|
||||
|
||||
for (const auto& pair : *configSection) {
|
||||
const std::string& key = pair.first;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -126,6 +126,7 @@ WebSocketChannel::handleOpen(websocketpp::connection_hdl hdl)
|
||||
auto linkService = make_unique<GenericLinkService>();
|
||||
auto transport = make_unique<WebSocketTransport>(hdl, m_server, m_pingInterval);
|
||||
auto face = make_shared<Face>(std::move(linkService), std::move(transport));
|
||||
face->setChannel(shared_from_this()); // use weak_from_this() in C++17
|
||||
|
||||
BOOST_ASSERT(m_channelFaces.count(hdl) == 0);
|
||||
m_channelFaces[hdl] = face;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -78,7 +78,7 @@ WebSocketTransport::WebSocketTransport(websocketpp::connection_hdl hdl,
|
||||
}
|
||||
|
||||
void
|
||||
WebSocketTransport::doSend(const Block& packet, const EndpointId&)
|
||||
WebSocketTransport::doSend(const Block& packet)
|
||||
{
|
||||
NFD_LOG_FACE_TRACE(__func__);
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -83,7 +83,7 @@ protected:
|
||||
|
||||
private:
|
||||
void
|
||||
doSend(const Block& packet, const EndpointId& endpoint) final;
|
||||
doSend(const Block& packet) final;
|
||||
|
||||
void
|
||||
schedulePing();
|
||||
|
||||
@@ -0,0 +1,174 @@
|
||||
#include "PCONStrategy.hpp"
|
||||
#include <ndn-cxx/lp/tags.hpp>
|
||||
|
||||
namespace nfd
|
||||
{
|
||||
namespace fw
|
||||
{
|
||||
NFD_REGISTER_STRATEGY(PCONStrategy);
|
||||
NFD_LOG_INIT(PCONStrategy);
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//// PCONStrategy
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
const time::milliseconds PCONStrategy::RETX_SUPPRESSION_INITIAL(10);
|
||||
const time::milliseconds PCONStrategy::RETX_SUPPRESSION_MAX(250);
|
||||
|
||||
PCONStrategy::PCONStrategy(nfd::Forwarder &forwarder, const ndn::Name &name)
|
||||
: Strategy(forwarder), ProcessNackTraits<PCONStrategy>(this), m_retxSuppression(RETX_SUPPRESSION_INITIAL,
|
||||
RetxSuppressionExponential::DEFAULT_MULTIPLIER,
|
||||
RETX_SUPPRESSION_MAX)
|
||||
{
|
||||
this->setInstanceName(makeInstanceName(name, getStrategyName()));
|
||||
}
|
||||
|
||||
const Name &
|
||||
PCONStrategy::getStrategyName()
|
||||
{
|
||||
static Name strategyName("/localhost/nfd/strategy/PCON/%FD%01");
|
||||
return strategyName;
|
||||
}
|
||||
|
||||
void
|
||||
PCONStrategy::afterReceiveInterest(const nfd::FaceEndpoint &ingress, const ndn::Interest &interest,
|
||||
const std::shared_ptr<nfd::pit::Entry> &pitEntry)
|
||||
{
|
||||
const fib::Entry &fibEntry = this->lookupFib(*pitEntry);
|
||||
const fib::NextHopList &nexthops = fibEntry.getNextHops();
|
||||
MtForwardingInfo *measurementInfo = this->getPrefixMeasurements(fibEntry);
|
||||
|
||||
if (measurementInfo == nullptr)
|
||||
{
|
||||
measurementInfo = this->addPrefixMeasurements(fibEntry);
|
||||
const Name prefixName = fibEntry.getPrefix();
|
||||
measurementInfo->setPrefix(prefixName.toUri());
|
||||
initializeForwMap(measurementInfo, nexthops);
|
||||
}
|
||||
|
||||
RetxSuppressionResult suppression = m_retxSuppression.decidePerPitEntry(*pitEntry);
|
||||
if (suppression == RetxSuppressionResult::SUPPRESS)
|
||||
{
|
||||
NFD_LOG_DEBUG(interest << " from=" << ingress << " suppressed");
|
||||
return;
|
||||
}
|
||||
|
||||
Face *outFace = nullptr;
|
||||
if (ingress.face.getScope() != ndn::nfd::FACE_SCOPE_NON_LOCAL)
|
||||
{
|
||||
auto selected = std::find_if(nexthops.begin(), nexthops.end(), [&](const auto &nexthop) {
|
||||
return isNextHopEligible(ingress.face, interest, nexthop, pitEntry);
|
||||
});
|
||||
if (selected != nexthops.end())
|
||||
{
|
||||
outFace = &((*selected).getFace());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Random number between 0 and 1.
|
||||
double r = ((double)rand() / (RAND_MAX));
|
||||
|
||||
double percSum = 0;
|
||||
|
||||
// Add all eligbile faces to list (excludes current downstream)
|
||||
std::vector<Face *> eligbleFaces;
|
||||
for (auto &n : fibEntry.getNextHops())
|
||||
{
|
||||
if (isNextHopEligible(ingress.face, interest, n, pitEntry))
|
||||
{
|
||||
// Add up percentage Sum.
|
||||
percSum += measurementInfo->getforwPerc(n.getFace().getId());
|
||||
eligbleFaces.push_back(&n.getFace());
|
||||
}
|
||||
}
|
||||
|
||||
if (eligbleFaces.size() < 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if (eligbleFaces.size() == 1)
|
||||
{
|
||||
outFace = eligbleFaces.front();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Choose face according to current forwarding percentage:
|
||||
double forwPerc = 0;
|
||||
for (auto face : eligbleFaces)
|
||||
{
|
||||
forwPerc += measurementInfo->getforwPerc(face->getId()) / percSum;
|
||||
if (r < forwPerc)
|
||||
{
|
||||
outFace = face;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (outFace == nullptr)
|
||||
{
|
||||
lp::NackHeader nackHeader;
|
||||
nackHeader.setReason(lp::NackReason::NO_ROUTE);
|
||||
this->sendNack(pitEntry, ingress.face, nackHeader);
|
||||
this->rejectPendingInterest(pitEntry);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->sendInterest(pitEntry, *outFace, interest);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
PCONStrategy::beforeSatisfyInterest(const shared_ptr<pit::Entry> &pitEntry,
|
||||
const FaceEndpoint &ingress, const Data &data)
|
||||
{
|
||||
Name currentPrefix;
|
||||
MtForwardingInfo *measurementInfo;
|
||||
std::tie(currentPrefix, measurementInfo) = this->findPrefixMeasurementsLPM(
|
||||
*pitEntry);
|
||||
|
||||
if (data.getCongestionMark() > 0 && ingress.face.getId() > 256)
|
||||
{
|
||||
// std::cout << ">>2: " << data.getCongestionMark() << std::endl;
|
||||
double fwPerc = measurementInfo->getforwPerc(ingress.face.getId());
|
||||
double change_perc = CHANGE_PER_MARK * fwPerc;
|
||||
this->reduceFwPerc(measurementInfo, ingress.face.getId(), change_perc);
|
||||
}
|
||||
}
|
||||
|
||||
void PCONStrategy::afterReceiveNack(const nfd::FaceEndpoint &ingress, const ndn::lp::Nack &nack,
|
||||
const std::shared_ptr<nfd::pit::Entry> &pitEntry)
|
||||
{
|
||||
this->processNack(ingress.face, nack, pitEntry);
|
||||
}
|
||||
|
||||
void
|
||||
PCONStrategy::initializeForwMap(MtForwardingInfo *measurementInfo,
|
||||
const fib::NextHopList &nextHops)
|
||||
{
|
||||
int lowestId = std::numeric_limits<int>::max();
|
||||
int minCost = std::numeric_limits<int>::max();
|
||||
|
||||
for (auto &n : nextHops)
|
||||
{
|
||||
if (n.getCost() < minCost)
|
||||
{
|
||||
minCost = n.getCost();
|
||||
lowestId = n.getFace().getId();
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &n : nextHops)
|
||||
{
|
||||
double perc = 0.0;
|
||||
if (n.getFace().getId() == lowestId)
|
||||
{
|
||||
perc = 1.0;
|
||||
}
|
||||
measurementInfo->setforwPerc(n.getFace().getId(), perc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
#ifndef NFD_DAEMON_FW_PCON_STRATEGY_HPP
|
||||
#define NFD_DAEMON_FW_PCON_STRATEGY_HPP
|
||||
|
||||
#include <boost/random/mersenne_twister.hpp>
|
||||
#include "face/face.hpp"
|
||||
#include "fw/strategy.hpp"
|
||||
#include "fw/retx-suppression-exponential.hpp"
|
||||
#include "fw/algorithm.hpp"
|
||||
#include "fw/process-nack-traits.hpp"
|
||||
#include <unordered_map>
|
||||
#include <limits>
|
||||
#include "mt-forward-info.hpp"
|
||||
|
||||
namespace nfd
|
||||
{
|
||||
namespace fw
|
||||
{
|
||||
class PCONStrategy : public Strategy, public ProcessNackTraits<PCONStrategy>
|
||||
{
|
||||
public:
|
||||
explicit PCONStrategy(Forwarder &forwarder, const Name &name = getStrategyName());
|
||||
|
||||
~PCONStrategy() override = default;
|
||||
|
||||
void
|
||||
afterReceiveInterest(const FaceEndpoint &ingress, const Interest &interest,
|
||||
const shared_ptr<pit::Entry> &pitEntry) override;
|
||||
|
||||
void
|
||||
beforeSatisfyInterest(const shared_ptr<pit::Entry> &pitEntry,
|
||||
const FaceEndpoint &ingress, const Data &data) override;
|
||||
|
||||
void
|
||||
afterReceiveNack(const FaceEndpoint &ingress, const lp::Nack &nack,
|
||||
const shared_ptr<pit::Entry> &pitEntry) override;
|
||||
|
||||
static const Name &
|
||||
getStrategyName();
|
||||
|
||||
protected:
|
||||
friend ProcessNackTraits<PCONStrategy>;
|
||||
|
||||
private:
|
||||
void
|
||||
initializeForwMap(MtForwardingInfo *measurementInfo,
|
||||
const fib::NextHopList &nextHops);
|
||||
|
||||
MtForwardingInfo *
|
||||
getPrefixMeasurements(const fib::Entry &fibEntry)
|
||||
{
|
||||
std::string key = fibEntry.getPrefix().getPrefix(1).toUri();
|
||||
if (this->innerMap.count(key) == 0)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
return this->innerMap[key].get();
|
||||
}
|
||||
}
|
||||
|
||||
MtForwardingInfo *
|
||||
addPrefixMeasurements(const fib::Entry &fibEntry)
|
||||
{
|
||||
std::string key = fibEntry.getPrefix().getPrefix(1).toUri();
|
||||
if (this->innerMap.count(key) == 0)
|
||||
{
|
||||
this->innerMap[key] = make_unique<MtForwardingInfo>();
|
||||
}
|
||||
return this->innerMap[key].get();
|
||||
// measurements::Entry* me = measurements.get(fibEntry);
|
||||
// // std::cout << fibEntry.getPrefix().toUri() << std::endl;
|
||||
// measurements.extendLifetime(*me, 8_s);
|
||||
// return me->insertStrategyInfo<MtForwardingInfo>().first;
|
||||
}
|
||||
|
||||
std::tuple<Name, MtForwardingInfo *>
|
||||
findPrefixMeasurementsLPM(const pit::Entry &pitEntry)
|
||||
{
|
||||
|
||||
std::string key = pitEntry.getName().getPrefix(1).toUri();
|
||||
if (this->innerMap.count(key) == 0) {
|
||||
return std::forward_as_tuple(Name(), nullptr);
|
||||
}
|
||||
|
||||
return std::forward_as_tuple(pitEntry.getName().getPrefix(1), this->innerMap[key].get());
|
||||
// measurements::Entry *me = measurements.findLongestPrefixMatch(pitEntry);
|
||||
// if (me == nullptr)
|
||||
// {
|
||||
// std::cout << "Name " << pitEntry.getName().toUri() << " not found!\n";
|
||||
// return std::forward_as_tuple(Name(), nullptr);
|
||||
// }
|
||||
// return std::forward_as_tuple(me->getName(), me->getStrategyInfo<MtForwardingInfo>());
|
||||
}
|
||||
|
||||
static void
|
||||
reduceFwPerc(MtForwardingInfo *forwInfo,
|
||||
const FaceId reducedFaceId,
|
||||
const double change)
|
||||
{
|
||||
if (forwInfo->getFaceCount() == 1)
|
||||
{
|
||||
// std::cout << "reduce1" << std::endl;
|
||||
return;
|
||||
}
|
||||
// Reduction is at most the current forwarding percentage of the face that is reduced.
|
||||
double changeRate = 0 - std::min(change, forwInfo->getforwPerc(reducedFaceId));
|
||||
|
||||
// std::cout << "reduce2: " << changeRate << std::endl;
|
||||
// Decrease fw percentage of the given face:
|
||||
forwInfo->increaseforwPerc(reducedFaceId, changeRate);
|
||||
double sumFWPerc = 0;
|
||||
sumFWPerc += forwInfo->getforwPerc(reducedFaceId);
|
||||
const auto forwMap = forwInfo->getForwPercMap();
|
||||
|
||||
// std::cout << "\n";
|
||||
for (auto f : forwMap)
|
||||
{
|
||||
auto tempChangeRate = changeRate;
|
||||
auto &faceId = f.first;
|
||||
if (faceId == reducedFaceId)
|
||||
{ // Do nothing. Percentage has already been added.
|
||||
}
|
||||
else
|
||||
{
|
||||
// Increase forwarding percentage of all other faces by and equal amount.
|
||||
tempChangeRate = std::abs(changeRate / (double)(forwMap.size() - 1));
|
||||
forwInfo->increaseforwPerc((faceId), tempChangeRate);
|
||||
sumFWPerc += forwInfo->getforwPerc(faceId);
|
||||
}
|
||||
}
|
||||
|
||||
// if (sumFWPerc < 0.999 || sumFWPerc > 1.001)
|
||||
// {
|
||||
// std::cout << StrHelper::getTime() << "ERROR! Sum of fw perc out of range: " << sumFWPerc
|
||||
// << "\n";
|
||||
// }
|
||||
}
|
||||
|
||||
private:
|
||||
static const time::milliseconds RETX_SUPPRESSION_INITIAL;
|
||||
static const time::milliseconds RETX_SUPPRESSION_MAX;
|
||||
double CHANGE_PER_MARK = 0.1;
|
||||
std::unordered_map<std::string, unique_ptr<MtForwardingInfo>> innerMap;
|
||||
RetxSuppressionExponential m_retxSuppression;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -144,14 +144,15 @@ AccessStrategy::sendToLastNexthop(const FaceEndpoint& ingress, const Interest& i
|
||||
NFD_LOG_DEBUG(pitEntry->getInterest() << " interestTo " << mi.lastNexthop
|
||||
<< " last-nexthop rto=" << time::duration_cast<time::microseconds>(rto).count());
|
||||
|
||||
this->sendInterest(pitEntry, FaceEndpoint(*outFace, 0), interest);
|
||||
if (!this->sendInterest(pitEntry, *outFace, interest)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// schedule RTO timeout
|
||||
PitInfo* pi = pitEntry->insertStrategyInfo<PitInfo>().first;
|
||||
pi->rtoTimer = getScheduler().schedule(rto,
|
||||
[this, pitWeak = weak_ptr<pit::Entry>(pitEntry), face = ingress.face.getId(),
|
||||
endpoint = ingress.endpoint, lastNexthop = mi.lastNexthop] {
|
||||
afterRtoTimeout(pitWeak, face, endpoint, lastNexthop);
|
||||
[this, pitWeak = weak_ptr<pit::Entry>(pitEntry), face = ingress.face.getId(), nh = mi.lastNexthop] {
|
||||
afterRtoTimeout(pitWeak, face, nh);
|
||||
});
|
||||
|
||||
return true;
|
||||
@@ -159,7 +160,7 @@ AccessStrategy::sendToLastNexthop(const FaceEndpoint& ingress, const Interest& i
|
||||
|
||||
void
|
||||
AccessStrategy::afterRtoTimeout(const weak_ptr<pit::Entry>& pitWeak,
|
||||
FaceId inFaceId, EndpointId inEndpointId, FaceId firstOutFaceId)
|
||||
FaceId inFaceId, FaceId firstOutFaceId)
|
||||
{
|
||||
shared_ptr<pit::Entry> pitEntry = pitWeak.lock();
|
||||
// if PIT entry is gone, RTO timer should have been cancelled
|
||||
@@ -199,8 +200,9 @@ AccessStrategy::multicast(const Face& inFace, const Interest& interest,
|
||||
continue;
|
||||
}
|
||||
NFD_LOG_DEBUG(pitEntry->getInterest() << " interestTo " << outFace.getId() << " multicast");
|
||||
this->sendInterest(pitEntry, FaceEndpoint(outFace, 0), interest);
|
||||
++nSent;
|
||||
if (this->sendInterest(pitEntry, outFace, interest)) {
|
||||
++nSent;
|
||||
}
|
||||
}
|
||||
return nSent;
|
||||
}
|
||||
@@ -253,15 +255,15 @@ AccessStrategy::updateMeasurements(const Face& inFace, const Data& data, time::n
|
||||
std::tuple<Name, AccessStrategy::MtInfo*>
|
||||
AccessStrategy::findPrefixMeasurements(const pit::Entry& pitEntry)
|
||||
{
|
||||
measurements::Entry* me = this->getMeasurements().findLongestPrefixMatch(pitEntry);
|
||||
auto me = this->getMeasurements().findLongestPrefixMatch(pitEntry);
|
||||
if (me == nullptr) {
|
||||
return std::make_tuple(Name(), nullptr);
|
||||
}
|
||||
|
||||
MtInfo* mi = me->getStrategyInfo<MtInfo>();
|
||||
BOOST_ASSERT(mi != nullptr);
|
||||
// XXX after runtime strategy change, it's possible that me exists but mi doesn't exist;
|
||||
// this case needs another longest prefix match until mi is found
|
||||
auto mi = me->getStrategyInfo<MtInfo>();
|
||||
// TODO: after a runtime strategy change, it's possible that a measurements::Entry exists but
|
||||
// the corresponding MtInfo doesn't exist (mi == nullptr); this case needs another longest
|
||||
// prefix match until an MtInfo is found.
|
||||
return std::make_tuple(me->getName(), mi);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -44,8 +44,6 @@ namespace fw {
|
||||
* the granularity of this knowledge is the parent of Data Name.
|
||||
* 3. Forward subsequent Interests to the last working nexthop.
|
||||
* If it doesn't respond, multicast again.
|
||||
*
|
||||
* \note This strategy is not EndpointId-aware.
|
||||
*/
|
||||
class AccessStrategy : public Strategy
|
||||
{
|
||||
@@ -152,7 +150,7 @@ private: // forwarding procedures
|
||||
|
||||
void
|
||||
afterRtoTimeout(const weak_ptr<pit::Entry>& pitWeak,
|
||||
FaceId inFaceId, EndpointId inEndpointId, FaceId firstOutFaceId);
|
||||
FaceId inFaceId, FaceId firstOutFaceId);
|
||||
|
||||
/** \brief multicast to all nexthops
|
||||
* \param exceptFace don't forward to this face; also, \p inFace is always excluded
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -75,7 +75,7 @@ canForwardToLegacy(const pit::Entry& pitEntry, const Face& face)
|
||||
}
|
||||
|
||||
int
|
||||
findDuplicateNonce(const pit::Entry& pitEntry, uint32_t nonce, const Face& face)
|
||||
findDuplicateNonce(const pit::Entry& pitEntry, Interest::Nonce nonce, const Face& face)
|
||||
{
|
||||
int dnw = DUPLICATE_NONCE_NONE;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -23,8 +23,8 @@
|
||||
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef NFD_DAEMON_FW_PIT_ALGORITHM_HPP
|
||||
#define NFD_DAEMON_FW_PIT_ALGORITHM_HPP
|
||||
#ifndef NFD_DAEMON_FW_ALGORITHM_HPP
|
||||
#define NFD_DAEMON_FW_ALGORITHM_HPP
|
||||
|
||||
#include "fw/scope-prefix.hpp"
|
||||
#include "table/fib.hpp"
|
||||
@@ -70,7 +70,7 @@ enum DuplicateNonceWhere {
|
||||
* \return OR'ed DuplicateNonceWhere
|
||||
*/
|
||||
int
|
||||
findDuplicateNonce(const pit::Entry& pitEntry, uint32_t nonce, const Face& face);
|
||||
findDuplicateNonce(const pit::Entry& pitEntry, Interest::Nonce nonce, const Face& face);
|
||||
|
||||
/** \brief determine whether \p pitEntry has any pending out-records
|
||||
* \return true if there is at least one out-record waiting for Data
|
||||
@@ -110,4 +110,4 @@ isNextHopEligible(const Face& inFace, const Interest& interest,
|
||||
} // namespace fw
|
||||
} // namespace nfd
|
||||
|
||||
#endif // NFD_DAEMON_FW_PIT_ALGORITHM_HPP
|
||||
#endif // NFD_DAEMON_FW_ALGORITHM_HPP
|
||||
+24
-23
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -58,7 +58,7 @@ AsfStrategy::AsfStrategy(Forwarder& forwarder, const Name& name)
|
||||
this->setInstanceName(makeInstanceName(name, getStrategyName()));
|
||||
|
||||
NFD_LOG_DEBUG("probing-interval=" << m_probing.getProbingInterval()
|
||||
<< " n-silent-timeouts=" << m_maxSilentTimeouts);
|
||||
<< " n-silent-timeouts=" << m_nMaxSilentTimeouts);
|
||||
}
|
||||
|
||||
const Name&
|
||||
@@ -98,7 +98,7 @@ AsfStrategy::processParams(const PartialName& parsed)
|
||||
m_probing.setProbingInterval(getParamValue(f, s));
|
||||
}
|
||||
else if (f == "n-silent-timeouts") {
|
||||
m_maxSilentTimeouts = getParamValue(f, s);
|
||||
m_nMaxSilentTimeouts = getParamValue(f, s);
|
||||
}
|
||||
else {
|
||||
NDN_THROW(std::invalid_argument("Parameter should be probing-interval or n-silent-timeouts"));
|
||||
@@ -123,7 +123,7 @@ AsfStrategy::afterReceiveInterest(const FaceEndpoint& ingress, const Interest& i
|
||||
if (suppressResult == RetxSuppressionResult::NEW) {
|
||||
if (nexthops.size() == 0) {
|
||||
NFD_LOG_DEBUG(interest << " new-interest from=" << ingress << " no-nexthop");
|
||||
sendNoRouteNack(ingress, pitEntry);
|
||||
sendNoRouteNack(ingress.face, pitEntry);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@ AsfStrategy::afterReceiveInterest(const FaceEndpoint& ingress, const Interest& i
|
||||
}
|
||||
else {
|
||||
NFD_LOG_DEBUG(interest << " new-interest from=" << ingress << " no-nexthop");
|
||||
sendNoRouteNack(ingress, pitEntry);
|
||||
sendNoRouteNack(ingress.face, pitEntry);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -158,9 +158,8 @@ AsfStrategy::afterReceiveInterest(const FaceEndpoint& ingress, const Interest& i
|
||||
NFD_LOG_DEBUG(interest << " retx-interest from=" << ingress << " no-nexthop");
|
||||
}
|
||||
else {
|
||||
auto egress = FaceEndpoint(it->getFace(), 0);
|
||||
NFD_LOG_DEBUG(interest << " retx-interest from=" << ingress << " retry-to=" << egress);
|
||||
this->sendInterest(pitEntry, egress, interest);
|
||||
NFD_LOG_DEBUG(interest << " retx-interest from=" << ingress << " retry-to=" << it->getFace().getId());
|
||||
this->sendInterest(pitEntry, it->getFace(), interest);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,7 +192,8 @@ AsfStrategy::beforeSatisfyInterest(const shared_ptr<pit::Entry>& pitEntry,
|
||||
|
||||
// Extend lifetime for measurements associated with Face
|
||||
namespaceInfo->extendFaceInfoLifetime(*faceInfo, ingress.face.getId());
|
||||
|
||||
// Extend PIT entry timer to allow slower probes to arrive
|
||||
this->setExpiryTimer(pitEntry, 50_ms);
|
||||
faceInfo->cancelTimeout(data.getName());
|
||||
}
|
||||
|
||||
@@ -202,37 +202,38 @@ AsfStrategy::afterReceiveNack(const FaceEndpoint& ingress, const lp::Nack& nack,
|
||||
const shared_ptr<pit::Entry>& pitEntry)
|
||||
{
|
||||
NFD_LOG_DEBUG(nack.getInterest() << " nack from=" << ingress << " reason=" << nack.getReason());
|
||||
onTimeout(pitEntry->getName(), ingress.face.getId());
|
||||
onTimeoutOrNack(pitEntry->getName(), ingress.face.getId(), true);
|
||||
}
|
||||
|
||||
void
|
||||
AsfStrategy::forwardInterest(const Interest& interest, Face& outFace, const fib::Entry& fibEntry,
|
||||
const shared_ptr<pit::Entry>& pitEntry, bool wantNewNonce)
|
||||
{
|
||||
auto egress = FaceEndpoint(outFace, 0);
|
||||
auto faceId = outFace.getId();
|
||||
|
||||
if (wantNewNonce) {
|
||||
// Send probe: interest with new Nonce
|
||||
Interest probeInterest(interest);
|
||||
probeInterest.refreshNonce();
|
||||
NFD_LOG_TRACE("Sending probe for " << probeInterest << " to=" << egress);
|
||||
this->sendInterest(pitEntry, egress, probeInterest);
|
||||
NFD_LOG_TRACE("Sending probe for " << probeInterest << " to=" << faceId);
|
||||
this->sendInterest(pitEntry, outFace, probeInterest);
|
||||
}
|
||||
else {
|
||||
this->sendInterest(pitEntry, egress, interest);
|
||||
this->sendInterest(pitEntry, outFace, interest);
|
||||
}
|
||||
|
||||
FaceInfo& faceInfo = m_measurements.getOrCreateFaceInfo(fibEntry, interest, egress.face.getId());
|
||||
FaceInfo& faceInfo = m_measurements.getOrCreateFaceInfo(fibEntry, interest, faceId);
|
||||
|
||||
// Refresh measurements since Face is being used for forwarding
|
||||
NamespaceInfo& namespaceInfo = m_measurements.getOrCreateNamespaceInfo(fibEntry, interest);
|
||||
namespaceInfo.extendFaceInfoLifetime(faceInfo, egress.face.getId());
|
||||
namespaceInfo.extendFaceInfoLifetime(faceInfo, faceId);
|
||||
|
||||
if (!faceInfo.isTimeoutScheduled()) {
|
||||
auto timeout = faceInfo.scheduleTimeout(interest.getName(),
|
||||
[this, name = interest.getName(), faceId = egress.face.getId()] {
|
||||
onTimeout(name, faceId);
|
||||
[this, name = interest.getName(), faceId] {
|
||||
onTimeoutOrNack(name, faceId, false);
|
||||
});
|
||||
NFD_LOG_TRACE("Scheduled timeout for " << fibEntry.getPrefix() << " to=" << egress
|
||||
NFD_LOG_TRACE("Scheduled timeout for " << fibEntry.getPrefix() << " to=" << faceId
|
||||
<< " in " << time::duration_cast<time::milliseconds>(timeout) << " ms");
|
||||
}
|
||||
}
|
||||
@@ -318,7 +319,7 @@ AsfStrategy::getBestFaceForForwarding(const Interest& interest, const Face& inFa
|
||||
}
|
||||
|
||||
void
|
||||
AsfStrategy::onTimeout(const Name& interestName, FaceId faceId)
|
||||
AsfStrategy::onTimeoutOrNack(const Name& interestName, FaceId faceId, bool isNack)
|
||||
{
|
||||
NamespaceInfo* namespaceInfo = m_measurements.getNamespaceInfo(interestName);
|
||||
if (namespaceInfo == nullptr) {
|
||||
@@ -336,7 +337,7 @@ AsfStrategy::onTimeout(const Name& interestName, FaceId faceId)
|
||||
size_t nTimeouts = faceInfo.getNSilentTimeouts() + 1;
|
||||
faceInfo.setNSilentTimeouts(nTimeouts);
|
||||
|
||||
if (nTimeouts <= m_maxSilentTimeouts) {
|
||||
if (nTimeouts <= m_nMaxSilentTimeouts && !isNack) {
|
||||
NFD_LOG_TRACE(interestName << " face=" << faceId << " timeout-count=" << nTimeouts << " ignoring");
|
||||
// Extend lifetime for measurements associated with Face
|
||||
namespaceInfo->extendFaceInfoLifetime(faceInfo, faceId);
|
||||
@@ -349,11 +350,11 @@ AsfStrategy::onTimeout(const Name& interestName, FaceId faceId)
|
||||
}
|
||||
|
||||
void
|
||||
AsfStrategy::sendNoRouteNack(const FaceEndpoint& ingress, const shared_ptr<pit::Entry>& pitEntry)
|
||||
AsfStrategy::sendNoRouteNack(Face& face, const shared_ptr<pit::Entry>& pitEntry)
|
||||
{
|
||||
lp::NackHeader nackHeader;
|
||||
nackHeader.setReason(lp::NackReason::NO_ROUTE);
|
||||
this->sendNack(pitEntry, ingress, nackHeader);
|
||||
this->sendNack(pitEntry, face, nackHeader);
|
||||
this->rejectPendingInterest(pitEntry);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -40,8 +40,6 @@ namespace asf {
|
||||
* \see Vince Lehman, Ashlesh Gawande, Rodrigo Aldecoa, Dmitri Krioukov, Beichuan Zhang, Lixia Zhang, and Lan Wang,
|
||||
* "An Experimental Investigation of Hyperbolic Routing with a Smart Forwarding Plane in NDN,"
|
||||
* NDN Technical Report NDN-0042, 2016. http://named-data.net/techreports.html
|
||||
*
|
||||
* \note This strategy is not EndpointId-aware.
|
||||
*/
|
||||
class AsfStrategy : public Strategy
|
||||
{
|
||||
@@ -83,16 +81,16 @@ private:
|
||||
bool isNewInterest = true);
|
||||
|
||||
void
|
||||
onTimeout(const Name& interestName, FaceId faceId);
|
||||
onTimeoutOrNack(const Name& interestName, FaceId faceId, bool isNack);
|
||||
|
||||
void
|
||||
sendNoRouteNack(const FaceEndpoint& ingress, const shared_ptr<pit::Entry>& pitEntry);
|
||||
sendNoRouteNack(Face& face, const shared_ptr<pit::Entry>& pitEntry);
|
||||
|
||||
private:
|
||||
AsfMeasurements m_measurements;
|
||||
ProbingModule m_probing;
|
||||
RetxSuppressionExponential m_retxSuppression;
|
||||
size_t m_maxSilentTimeouts = 0;
|
||||
size_t m_nMaxSilentTimeouts = 3;
|
||||
|
||||
static const time::milliseconds RETX_SUPPRESSION_INITIAL;
|
||||
static const time::milliseconds RETX_SUPPRESSION_MAX;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -48,7 +48,7 @@ BestRouteStrategyBase::afterReceiveInterest(const FaceEndpoint& ingress, const I
|
||||
Face& outFace = nexthop.getFace();
|
||||
if (!wouldViolateScope(ingress.face, interest, outFace) &&
|
||||
canForwardToLegacy(*pitEntry, outFace)) {
|
||||
this->sendInterest(pitEntry, FaceEndpoint(outFace, 0), interest);
|
||||
this->sendInterest(pitEntry, outFace, interest);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -52,8 +52,6 @@ protected:
|
||||
* \note This strategy is superceded by Best Route strategy version 2,
|
||||
* which allows consumer retransmissions. This version is kept for
|
||||
* comparison purposes and is not recommended for general usage.
|
||||
*
|
||||
* \note This strategy is not EndpointId-aware.
|
||||
*/
|
||||
class BestRouteStrategy : public BestRouteStrategyBase
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -86,27 +86,28 @@ BestRouteStrategy2::afterReceiveInterest(const FaceEndpoint& ingress, const Inte
|
||||
|
||||
lp::NackHeader nackHeader;
|
||||
nackHeader.setReason(lp::NackReason::NO_ROUTE);
|
||||
this->sendNack(pitEntry, ingress, nackHeader);
|
||||
this->sendNack(pitEntry, ingress.face, nackHeader);
|
||||
|
||||
this->rejectPendingInterest(pitEntry);
|
||||
return;
|
||||
}
|
||||
|
||||
auto egress = FaceEndpoint(it->getFace(), 0);
|
||||
NFD_LOG_DEBUG(interest << " from=" << ingress << " newPitEntry-to=" << egress);
|
||||
this->sendInterest(pitEntry, egress, interest);
|
||||
Face& outFace = it->getFace();
|
||||
NFD_LOG_DEBUG(interest << " from=" << ingress << " newPitEntry-to=" << outFace.getId());
|
||||
this->sendInterest(pitEntry, outFace, interest);
|
||||
return;
|
||||
}
|
||||
|
||||
// find an unused upstream with lowest cost except downstream
|
||||
it = std::find_if(nexthops.begin(), nexthops.end(), [&] (const auto& nexthop) {
|
||||
return isNextHopEligible(ingress.face, interest, nexthop, pitEntry, true, time::steady_clock::now());
|
||||
});
|
||||
it = std::find_if(nexthops.begin(), nexthops.end(),
|
||||
[&, now = time::steady_clock::now()] (const auto& nexthop) {
|
||||
return isNextHopEligible(ingress.face, interest, nexthop, pitEntry, true, now);
|
||||
});
|
||||
|
||||
if (it != nexthops.end()) {
|
||||
auto egress = FaceEndpoint(it->getFace(), 0);
|
||||
this->sendInterest(pitEntry, egress, interest);
|
||||
NFD_LOG_DEBUG(interest << " from=" << ingress << " retransmit-unused-to=" << egress);
|
||||
Face& outFace = it->getFace();
|
||||
this->sendInterest(pitEntry, outFace, interest);
|
||||
NFD_LOG_DEBUG(interest << " from=" << ingress << " retransmit-unused-to=" << outFace.getId());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -116,9 +117,9 @@ BestRouteStrategy2::afterReceiveInterest(const FaceEndpoint& ingress, const Inte
|
||||
NFD_LOG_DEBUG(interest << " from=" << ingress << " retransmitNoNextHop");
|
||||
}
|
||||
else {
|
||||
auto egress = FaceEndpoint(it->getFace(), 0);
|
||||
this->sendInterest(pitEntry, egress, interest);
|
||||
NFD_LOG_DEBUG(interest << " from=" << ingress << " retransmit-retry-to=" << egress);
|
||||
Face& outFace = it->getFace();
|
||||
this->sendInterest(pitEntry, outFace, interest);
|
||||
NFD_LOG_DEBUG(interest << " from=" << ingress << " retransmit-retry-to=" << outFace.getId());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -49,8 +49,6 @@ namespace fw {
|
||||
*
|
||||
* This strategy returns Nack to all downstreams if all upstreams have returned Nacks.
|
||||
* The reason of the sent Nack equals the least severe reason among received Nacks.
|
||||
*
|
||||
* \note This strategy is not EndpointId-aware.
|
||||
*/
|
||||
class BestRouteStrategy2 : public Strategy
|
||||
, public ProcessNackTraits<BestRouteStrategy2>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
namespace nfd {
|
||||
|
||||
/** \brief counters provided by Forwarder
|
||||
/** \brief Counters provided by Forwarder
|
||||
*/
|
||||
class ForwarderCounters
|
||||
{
|
||||
@@ -41,8 +41,10 @@ public:
|
||||
PacketCounter nOutData;
|
||||
PacketCounter nInNacks;
|
||||
PacketCounter nOutNacks;
|
||||
|
||||
PacketCounter nSatisfiedInterests;
|
||||
PacketCounter nUnsatisfiedInterests;
|
||||
PacketCounter nUnsolicitedData;
|
||||
|
||||
PacketCounter nCsHits;
|
||||
PacketCounter nCsMisses;
|
||||
|
||||
+74
-44
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "common/logger.hpp"
|
||||
#include "table/cleanup.hpp"
|
||||
|
||||
#include <ndn-cxx/lp/pit-token.hpp>
|
||||
#include <ndn-cxx/lp/tags.hpp>
|
||||
|
||||
namespace nfd {
|
||||
@@ -67,7 +68,7 @@ Forwarder::Forwarder(FaceTable& faceTable)
|
||||
});
|
||||
face.onDroppedInterest.connect(
|
||||
[this, &face] (const Interest& interest) {
|
||||
this->onDroppedInterest(FaceEndpoint(face, 0), interest);
|
||||
this->onDroppedInterest(face, interest);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -92,6 +93,18 @@ Forwarder::onIncomingInterest(const FaceEndpoint& ingress, const Interest& inter
|
||||
interest.setTag(make_shared<lp::IncomingFaceIdTag>(ingress.face.getId()));
|
||||
++m_counters.nInInterests;
|
||||
|
||||
// drop if HopLimit zero, decrement otherwise (if present)
|
||||
if (interest.getHopLimit()) {
|
||||
if (*interest.getHopLimit() < 1) {
|
||||
NFD_LOG_DEBUG("onIncomingInterest in=" << ingress << " interest=" << interest.getName()
|
||||
<< " hop-limit=0");
|
||||
++const_cast<PacketCounter&>(ingress.face.getCounters().nInHopLimitZero);
|
||||
return;
|
||||
}
|
||||
|
||||
const_cast<Interest&>(interest).setHopLimit(*interest.getHopLimit() - 1);
|
||||
}
|
||||
|
||||
// /localhost scope control
|
||||
bool isViolatingLocalhost = ingress.face.getScope() == ndn::nfd::FACE_SCOPE_NON_LOCAL &&
|
||||
scope_prefix::LOCALHOST.isPrefixOf(interest.getName());
|
||||
@@ -162,7 +175,7 @@ Forwarder::onInterestLoop(const FaceEndpoint& ingress, const Interest& interest)
|
||||
// note: Don't enter outgoing Nack pipeline because it needs an in-record.
|
||||
lp::Nack nack(interest);
|
||||
nack.setReason(lp::NackReason::DUPLICATE);
|
||||
ingress.face.sendNack(nack, ingress.endpoint);
|
||||
ingress.face.sendNack(nack);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -193,7 +206,7 @@ Forwarder::onContentStoreMiss(const FaceEndpoint& ingress,
|
||||
<< " nexthop-faceid=" << nextHopFace->getId());
|
||||
// go to outgoing Interest pipeline
|
||||
// scope control is unnecessary, because privileged app explicitly wants to forward
|
||||
this->onOutgoingInterest(pitEntry, FaceEndpoint(*nextHopFace, 0), interest);
|
||||
this->onOutgoingInterest(pitEntry, *nextHopFace, interest);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -213,6 +226,7 @@ Forwarder::onContentStoreHit(const FaceEndpoint& ingress, const shared_ptr<pit::
|
||||
++m_counters.nCsHits;
|
||||
|
||||
data.setTag(make_shared<lp::IncomingFaceIdTag>(face::FACEID_CONTENT_STORE));
|
||||
data.setTag(interest.getTag<lp::PitToken>());
|
||||
// FIXME Should we lookup PIT for other Interests that also match the data?
|
||||
|
||||
pitEntry->isSatisfied = true;
|
||||
@@ -226,18 +240,28 @@ Forwarder::onContentStoreHit(const FaceEndpoint& ingress, const shared_ptr<pit::
|
||||
[&] (fw::Strategy& strategy) { strategy.afterContentStoreHit(pitEntry, ingress, data); });
|
||||
}
|
||||
|
||||
void
|
||||
pit::OutRecord*
|
||||
Forwarder::onOutgoingInterest(const shared_ptr<pit::Entry>& pitEntry,
|
||||
const FaceEndpoint& egress, const Interest& interest)
|
||||
Face& egress, const Interest& interest)
|
||||
{
|
||||
NFD_LOG_DEBUG("onOutgoingInterest out=" << egress << " interest=" << pitEntry->getName());
|
||||
// drop if HopLimit == 0 but sending on non-local face
|
||||
if (interest.getHopLimit() == 0 && egress.getScope() == ndn::nfd::FACE_SCOPE_NON_LOCAL) {
|
||||
NFD_LOG_DEBUG("onOutgoingInterest out=" << egress.getId() << " interest=" << pitEntry->getName()
|
||||
<< " non-local hop-limit=0");
|
||||
++const_cast<PacketCounter&>(egress.getCounters().nOutHopLimitZero);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
NFD_LOG_DEBUG("onOutgoingInterest out=" << egress.getId() << " interest=" << pitEntry->getName());
|
||||
|
||||
// insert out-record
|
||||
pitEntry->insertOrUpdateOutRecord(egress.face, interest);
|
||||
auto it = pitEntry->insertOrUpdateOutRecord(egress, interest);
|
||||
BOOST_ASSERT(it != pitEntry->out_end());
|
||||
|
||||
// send Interest
|
||||
egress.face.sendInterest(interest, egress.endpoint);
|
||||
egress.sendInterest(interest);
|
||||
++m_counters.nOutInterests;
|
||||
return &*it;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -307,7 +331,7 @@ Forwarder::onIncomingData(const FaceEndpoint& ingress, const Data& data)
|
||||
pitEntry->isSatisfied = true;
|
||||
pitEntry->dataFreshnessPeriod = data.getFreshnessPeriod();
|
||||
|
||||
// Dead Nonce List insert if necessary (for out-record of inFace)
|
||||
// Dead Nonce List insert if necessary (for out-record of ingress face)
|
||||
this->insertDeadNonceList(*pitEntry, &ingress.face);
|
||||
|
||||
// delete PIT entry's out-record
|
||||
@@ -316,7 +340,7 @@ Forwarder::onIncomingData(const FaceEndpoint& ingress, const Data& data)
|
||||
// when more than one PIT entry is matched, trigger strategy: before satisfy Interest,
|
||||
// and send Data to all matched out faces
|
||||
else {
|
||||
std::set<std::pair<Face*, EndpointId>> pendingDownstreams;
|
||||
std::set<Face*> pendingDownstreams;
|
||||
auto now = time::steady_clock::now();
|
||||
|
||||
for (const auto& pitEntry : pitMatches) {
|
||||
@@ -325,7 +349,7 @@ Forwarder::onIncomingData(const FaceEndpoint& ingress, const Data& data)
|
||||
// remember pending downstreams
|
||||
for (const pit::InRecord& inRecord : pitEntry->getInRecords()) {
|
||||
if (inRecord.getExpiry() > now) {
|
||||
pendingDownstreams.emplace(&inRecord.getFace(), 0);
|
||||
pendingDownstreams.insert(&inRecord.getFace());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -340,7 +364,7 @@ Forwarder::onIncomingData(const FaceEndpoint& ingress, const Data& data)
|
||||
pitEntry->isSatisfied = true;
|
||||
pitEntry->dataFreshnessPeriod = data.getFreshnessPeriod();
|
||||
|
||||
// Dead Nonce List insert if necessary (for out-record of inFace)
|
||||
// Dead Nonce List insert if necessary (for out-record of ingress face)
|
||||
this->insertDeadNonceList(*pitEntry, &ingress.face);
|
||||
|
||||
// clear PIT entry's in and out records
|
||||
@@ -350,13 +374,12 @@ Forwarder::onIncomingData(const FaceEndpoint& ingress, const Data& data)
|
||||
|
||||
// foreach pending downstream
|
||||
for (const auto& pendingDownstream : pendingDownstreams) {
|
||||
if (pendingDownstream.first->getId() == ingress.face.getId() &&
|
||||
pendingDownstream.second == ingress.endpoint &&
|
||||
pendingDownstream.first->getLinkType() != ndn::nfd::LINK_TYPE_AD_HOC) {
|
||||
if (pendingDownstream->getId() == ingress.face.getId() &&
|
||||
pendingDownstream->getLinkType() != ndn::nfd::LINK_TYPE_AD_HOC) {
|
||||
continue;
|
||||
}
|
||||
// goto outgoing Data pipeline
|
||||
this->onOutgoingData(data, FaceEndpoint(*pendingDownstream.first, pendingDownstream.second));
|
||||
this->onOutgoingData(data, *pendingDownstream);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -365,38 +388,43 @@ void
|
||||
Forwarder::onDataUnsolicited(const FaceEndpoint& ingress, const Data& data)
|
||||
{
|
||||
// accept to cache?
|
||||
fw::UnsolicitedDataDecision decision = m_unsolicitedDataPolicy->decide(ingress.face, data);
|
||||
auto decision = m_unsolicitedDataPolicy->decide(ingress.face, data);
|
||||
if (decision == fw::UnsolicitedDataDecision::CACHE) {
|
||||
// CS insert
|
||||
m_cs.insert(data, true);
|
||||
}
|
||||
|
||||
NFD_LOG_DEBUG("onDataUnsolicited in=" << ingress << " data=" << data.getName() << " decision=" << decision);
|
||||
NFD_LOG_DEBUG("onDataUnsolicited in=" << ingress << " data=" << data.getName()
|
||||
<< " decision=" << decision);
|
||||
++m_counters.nUnsolicitedData;
|
||||
}
|
||||
|
||||
void
|
||||
Forwarder::onOutgoingData(const Data& data, const FaceEndpoint& egress)
|
||||
bool
|
||||
Forwarder::onOutgoingData(const Data& data, Face& egress)
|
||||
{
|
||||
if (egress.face.getId() == face::INVALID_FACEID) {
|
||||
if (egress.getId() == face::INVALID_FACEID) {
|
||||
NFD_LOG_WARN("onOutgoingData out=(invalid) data=" << data.getName());
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
NFD_LOG_DEBUG("onOutgoingData out=" << egress << " data=" << data.getName());
|
||||
NFD_LOG_DEBUG("onOutgoingData out=" << egress.getId() << " data=" << data.getName());
|
||||
|
||||
// /localhost scope control
|
||||
bool isViolatingLocalhost = egress.face.getScope() == ndn::nfd::FACE_SCOPE_NON_LOCAL &&
|
||||
bool isViolatingLocalhost = egress.getScope() == ndn::nfd::FACE_SCOPE_NON_LOCAL &&
|
||||
scope_prefix::LOCALHOST.isPrefixOf(data.getName());
|
||||
if (isViolatingLocalhost) {
|
||||
NFD_LOG_DEBUG("onOutgoingData out=" << egress << " data=" << data.getName() << " violates /localhost");
|
||||
NFD_LOG_DEBUG("onOutgoingData out=" << egress.getId() << " data=" << data.getName()
|
||||
<< " violates /localhost");
|
||||
// (drop)
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO traffic manager
|
||||
|
||||
// send Data
|
||||
egress.face.sendData(data, egress.endpoint);
|
||||
egress.sendData(data);
|
||||
++m_counters.nOutData;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -456,36 +484,36 @@ Forwarder::onIncomingNack(const FaceEndpoint& ingress, const lp::Nack& nack)
|
||||
[&] (fw::Strategy& strategy) { strategy.afterReceiveNack(ingress, nack, pitEntry); });
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
Forwarder::onOutgoingNack(const shared_ptr<pit::Entry>& pitEntry,
|
||||
const FaceEndpoint& egress, const lp::NackHeader& nack)
|
||||
Face& egress, const lp::NackHeader& nack)
|
||||
{
|
||||
if (egress.face.getId() == face::INVALID_FACEID) {
|
||||
if (egress.getId() == face::INVALID_FACEID) {
|
||||
NFD_LOG_WARN("onOutgoingNack out=(invalid)"
|
||||
<< " nack=" << pitEntry->getInterest().getName() << "~" << nack.getReason());
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// has in-record?
|
||||
auto inRecord = pitEntry->getInRecord(egress.face);
|
||||
auto inRecord = pitEntry->getInRecord(egress);
|
||||
|
||||
// if no in-record found, drop
|
||||
if (inRecord == pitEntry->in_end()) {
|
||||
NFD_LOG_DEBUG("onOutgoingNack out=" << egress
|
||||
NFD_LOG_DEBUG("onOutgoingNack out=" << egress.getId()
|
||||
<< " nack=" << pitEntry->getInterest().getName()
|
||||
<< "~" << nack.getReason() << " no-in-record");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// if multi-access or ad hoc face, drop
|
||||
if (egress.face.getLinkType() != ndn::nfd::LINK_TYPE_POINT_TO_POINT) {
|
||||
NFD_LOG_DEBUG("onOutgoingNack out=" << egress
|
||||
if (egress.getLinkType() != ndn::nfd::LINK_TYPE_POINT_TO_POINT) {
|
||||
NFD_LOG_DEBUG("onOutgoingNack out=" << egress.getId()
|
||||
<< " nack=" << pitEntry->getInterest().getName() << "~" << nack.getReason()
|
||||
<< " link-type=" << egress.face.getLinkType());
|
||||
return;
|
||||
<< " link-type=" << egress.getLinkType());
|
||||
return false;
|
||||
}
|
||||
|
||||
NFD_LOG_DEBUG("onOutgoingNack out=" << egress
|
||||
NFD_LOG_DEBUG("onOutgoingNack out=" << egress.getId()
|
||||
<< " nack=" << pitEntry->getInterest().getName()
|
||||
<< "~" << nack.getReason() << " OK");
|
||||
|
||||
@@ -494,15 +522,17 @@ Forwarder::onOutgoingNack(const shared_ptr<pit::Entry>& pitEntry,
|
||||
nackPkt.setHeader(nack);
|
||||
|
||||
// erase in-record
|
||||
pitEntry->deleteInRecord(egress.face);
|
||||
pitEntry->deleteInRecord(egress);
|
||||
|
||||
// send Nack on face
|
||||
egress.face.sendNack(nackPkt, egress.endpoint);
|
||||
egress.sendNack(nackPkt);
|
||||
++m_counters.nOutNacks;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
Forwarder::onDroppedInterest(const FaceEndpoint& egress, const Interest& interest)
|
||||
Forwarder::onDroppedInterest(const Face& egress, const Interest& interest)
|
||||
{
|
||||
m_strategyChoice.findEffectiveStrategy(interest.getName()).onDroppedInterest(egress, interest);
|
||||
}
|
||||
@@ -551,7 +581,7 @@ void
|
||||
Forwarder::setExpiryTimer(const shared_ptr<pit::Entry>& pitEntry, time::milliseconds duration)
|
||||
{
|
||||
BOOST_ASSERT(pitEntry);
|
||||
BOOST_ASSERT(duration >= 0_ms);
|
||||
duration = std::max(duration, 0_ms);
|
||||
|
||||
pitEntry->expiryTimer.cancel();
|
||||
pitEntry->expiryTimer = getScheduler().schedule(duration, [=] { onInterestFinalize(pitEntry); });
|
||||
|
||||
+11
-8
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -189,10 +189,11 @@ PUBLIC_WITH_TESTS_ELSE_PRIVATE: // pipelines
|
||||
const Interest& interest, const Data& data);
|
||||
|
||||
/** \brief outgoing Interest pipeline
|
||||
* \return A pointer to the out-record created or nullptr if the Interest was dropped
|
||||
*/
|
||||
VIRTUAL_WITH_TESTS void
|
||||
VIRTUAL_WITH_TESTS pit::OutRecord*
|
||||
onOutgoingInterest(const shared_ptr<pit::Entry>& pitEntry,
|
||||
const FaceEndpoint& egress, const Interest& interest);
|
||||
Face& egress, const Interest& interest);
|
||||
|
||||
/** \brief Interest finalize pipeline
|
||||
*/
|
||||
@@ -210,9 +211,10 @@ PUBLIC_WITH_TESTS_ELSE_PRIVATE: // pipelines
|
||||
onDataUnsolicited(const FaceEndpoint& ingress, const Data& data);
|
||||
|
||||
/** \brief outgoing Data pipeline
|
||||
* \return Whether the Data was transmitted (true) or dropped (false)
|
||||
*/
|
||||
VIRTUAL_WITH_TESTS void
|
||||
onOutgoingData(const Data& data, const FaceEndpoint& egress);
|
||||
VIRTUAL_WITH_TESTS bool
|
||||
onOutgoingData(const Data& data, Face& egress);
|
||||
|
||||
/** \brief incoming Nack pipeline
|
||||
*/
|
||||
@@ -220,13 +222,14 @@ PUBLIC_WITH_TESTS_ELSE_PRIVATE: // pipelines
|
||||
onIncomingNack(const FaceEndpoint& ingress, const lp::Nack& nack);
|
||||
|
||||
/** \brief outgoing Nack pipeline
|
||||
* \return Whether the Nack was transmitted (true) or dropped (false)
|
||||
*/
|
||||
VIRTUAL_WITH_TESTS void
|
||||
VIRTUAL_WITH_TESTS bool
|
||||
onOutgoingNack(const shared_ptr<pit::Entry>& pitEntry,
|
||||
const FaceEndpoint& egress, const lp::NackHeader& nack);
|
||||
Face& egress, const lp::NackHeader& nack);
|
||||
|
||||
VIRTUAL_WITH_TESTS void
|
||||
onDroppedInterest(const FaceEndpoint& egress, const Interest& interest);
|
||||
onDroppedInterest(const Face& egress, const Interest& interest);
|
||||
|
||||
VIRTUAL_WITH_TESTS void
|
||||
onNewNextHop(const Name& prefix, const fib::NextHop& nextHop);
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
#ifndef NFD_DAEMON_FW_MT_FORWARDING_INFO_HPP
|
||||
#define NFD_DAEMON_FW_MT_FORWARDING_INFO_HPP
|
||||
|
||||
#include "face/face.hpp"
|
||||
#include "fw/strategy-info.hpp"
|
||||
|
||||
namespace nfd
|
||||
{
|
||||
namespace fw
|
||||
{
|
||||
|
||||
/**
|
||||
* Measurement information that can be saved and retrieved per-name-prefix.
|
||||
*/
|
||||
class MtForwardingInfo : public StrategyInfo
|
||||
{
|
||||
public:
|
||||
static constexpr int
|
||||
getTypeId()
|
||||
{
|
||||
return 1051;
|
||||
}
|
||||
|
||||
MtForwardingInfo()
|
||||
: m_ownPrefix("null")
|
||||
{
|
||||
}
|
||||
|
||||
double
|
||||
getforwPerc(FaceId face)
|
||||
{
|
||||
// if (m_forwPercMap.find(face) == m_forwPercMap.end())
|
||||
// {
|
||||
// std::cout << time::steady_clock::now().time_since_epoch().count() / 1000 * 1000
|
||||
// << " ms, couldn't find face " << face << "\n";
|
||||
// }
|
||||
// assert(m_forwPercMap.find(face) != m_forwPercMap.end());
|
||||
double forwPerc = m_forwPercMap.at(face);
|
||||
// assert(forwPerc >= 0 && forwPerc <= 1);
|
||||
|
||||
return forwPerc;
|
||||
}
|
||||
|
||||
void
|
||||
setforwPerc(FaceId faceId, double perc)
|
||||
{
|
||||
m_forwPercMap[faceId] = perc;
|
||||
}
|
||||
|
||||
void
|
||||
increaseforwPerc(FaceId faceId, double changeRate)
|
||||
{
|
||||
m_forwPercMap[faceId] += changeRate;
|
||||
}
|
||||
|
||||
const std::map<FaceId, double>
|
||||
getForwPercMap() const
|
||||
{
|
||||
return m_forwPercMap;
|
||||
}
|
||||
|
||||
int
|
||||
getFaceCount()
|
||||
{
|
||||
std::vector<FaceId> faceIdList;
|
||||
for (auto faceInfo : m_forwPercMap)
|
||||
{
|
||||
faceIdList.push_back(faceInfo.first);
|
||||
}
|
||||
return faceIdList.size();
|
||||
}
|
||||
|
||||
void
|
||||
setPrefix(std::string prefix)
|
||||
{
|
||||
m_ownPrefix = prefix;
|
||||
}
|
||||
|
||||
std::string
|
||||
getPrefix() const
|
||||
{
|
||||
return m_ownPrefix;
|
||||
}
|
||||
|
||||
private:
|
||||
/** These Functions were used to disable faces in the "highly congested" state:*/
|
||||
// void
|
||||
// enableFace(FaceId faceId)
|
||||
// {
|
||||
// m_disabledFaces.erase(faceId);
|
||||
// }
|
||||
//
|
||||
// void
|
||||
// disableFace(FaceId faceId)
|
||||
// {
|
||||
// m_disabledFaces.emplace(faceId);
|
||||
//// std::cout << "Disabling face " << faceId << "\n";
|
||||
// }
|
||||
//
|
||||
// bool
|
||||
// isFaceEnabled(FaceId faceId)
|
||||
// {
|
||||
// bool disabled = (m_disabledFaces.find(faceId) != m_disabledFaces.end());
|
||||
// return !disabled;
|
||||
// }
|
||||
std::string m_ownPrefix;
|
||||
std::map<FaceId, double> m_forwPercMap;
|
||||
|
||||
std::unordered_set<FaceId> m_disabledFaces;
|
||||
};
|
||||
|
||||
} //fw
|
||||
} //nfd
|
||||
|
||||
#endif
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -69,10 +69,6 @@ MulticastStrategy::afterReceiveInterest(const FaceEndpoint& ingress, const Inter
|
||||
const fib::Entry& fibEntry = this->lookupFib(*pitEntry);
|
||||
const fib::NextHopList& nexthops = fibEntry.getNextHops();
|
||||
|
||||
int nEligibleNextHops = 0;
|
||||
|
||||
bool isSuppressed = false;
|
||||
|
||||
for (const auto& nexthop : nexthops) {
|
||||
Face& outFace = nexthop.getFace();
|
||||
|
||||
@@ -80,30 +76,26 @@ MulticastStrategy::afterReceiveInterest(const FaceEndpoint& ingress, const Inter
|
||||
|
||||
if (suppressResult == RetxSuppressionResult::SUPPRESS) {
|
||||
NFD_LOG_DEBUG(interest << " from=" << ingress << " to=" << outFace.getId() << " suppressed");
|
||||
isSuppressed = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((outFace.getId() == ingress.face.getId() && outFace.getLinkType() != ndn::nfd::LINK_TYPE_AD_HOC) ||
|
||||
wouldViolateScope(ingress.face, interest, outFace)) {
|
||||
if (!isNextHopEligible(ingress.face, interest, nexthop, pitEntry)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
this->sendInterest(pitEntry, FaceEndpoint(outFace, 0), interest);
|
||||
NFD_LOG_DEBUG(interest << " from=" << ingress << " pitEntry-to=" << outFace.getId());
|
||||
|
||||
if (suppressResult == RetxSuppressionResult::FORWARD) {
|
||||
bool wasSent = this->sendInterest(pitEntry, outFace, interest) != nullptr;
|
||||
if (wasSent && suppressResult == RetxSuppressionResult::FORWARD) {
|
||||
m_retxSuppression.incrementIntervalForOutRecord(*pitEntry->getOutRecord(outFace));
|
||||
}
|
||||
++nEligibleNextHops;
|
||||
}
|
||||
|
||||
if (nEligibleNextHops == 0 && !isSuppressed) {
|
||||
NFD_LOG_DEBUG(interest << " from=" << ingress << " noNextHop");
|
||||
if (!hasPendingOutRecords(*pitEntry)) {
|
||||
NFD_LOG_DEBUG(interest << " from=" << ingress << " noNextHop (removing pitEntry)");
|
||||
|
||||
lp::NackHeader nackHeader;
|
||||
nackHeader.setReason(lp::NackReason::NO_ROUTE);
|
||||
this->sendNack(pitEntry, ingress, nackHeader);
|
||||
this->sendNack(pitEntry, ingress.face, nackHeader);
|
||||
|
||||
this->rejectPendingInterest(pitEntry);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -33,9 +33,7 @@
|
||||
namespace nfd {
|
||||
namespace fw {
|
||||
|
||||
/** \brief a forwarding strategy that forwards Interest to all FIB nexthops
|
||||
*
|
||||
* \note This strategy is not EndpointId-aware.
|
||||
/** \brief A forwarding strategy that forwards Interests to all FIB nexthops
|
||||
*/
|
||||
class MulticastStrategy : public Strategy
|
||||
, public ProcessNackTraits<MulticastStrategy>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -90,7 +90,7 @@ NccStrategy::afterReceiveInterest(const FaceEndpoint& ingress, const Interest& i
|
||||
deferFirst = meInfo.prediction;
|
||||
deferRange = time::microseconds((deferFirst.count() + 1) / 2);
|
||||
--nUpstreams;
|
||||
this->sendInterest(pitEntry, FaceEndpoint(*bestFace, 0), interest);
|
||||
this->sendInterest(pitEntry, *bestFace, interest);
|
||||
pitEntryInfo->bestFaceTimeout = getScheduler().schedule(meInfo.prediction,
|
||||
bind(&NccStrategy::timeoutOnBestFace, this, weak_ptr<pit::Entry>(pitEntry)));
|
||||
}
|
||||
@@ -103,7 +103,7 @@ NccStrategy::afterReceiveInterest(const FaceEndpoint& ingress, const Interest& i
|
||||
canForwardToLegacy(*pitEntry, outFace);
|
||||
});
|
||||
if (firstEligibleNexthop != nexthops.end()) {
|
||||
this->sendInterest(pitEntry, FaceEndpoint(firstEligibleNexthop->getFace(), 0), interest);
|
||||
this->sendInterest(pitEntry, firstEligibleNexthop->getFace(), interest);
|
||||
}
|
||||
else {
|
||||
this->rejectPendingInterest(pitEntry);
|
||||
@@ -161,7 +161,7 @@ NccStrategy::doPropagate(FaceId inFaceId, weak_ptr<pit::Entry> pitEntryWeak)
|
||||
if (previousFace != nullptr && fibEntry.hasNextHop(*previousFace) &&
|
||||
!wouldViolateScope(*inFace, interest, *previousFace) &&
|
||||
canForwardToLegacy(*pitEntry, *previousFace)) {
|
||||
this->sendInterest(pitEntry, FaceEndpoint(*previousFace, 0), interest);
|
||||
this->sendInterest(pitEntry, *previousFace, interest);
|
||||
}
|
||||
|
||||
bool isForwarded = false;
|
||||
@@ -170,7 +170,7 @@ NccStrategy::doPropagate(FaceId inFaceId, weak_ptr<pit::Entry> pitEntryWeak)
|
||||
if (!wouldViolateScope(*inFace, interest, face) &&
|
||||
canForwardToLegacy(*pitEntry, face)) {
|
||||
isForwarded = true;
|
||||
this->sendInterest(pitEntry, FaceEndpoint(face, 0), interest);
|
||||
this->sendInterest(pitEntry, face, interest);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -31,9 +31,7 @@
|
||||
namespace nfd {
|
||||
namespace fw {
|
||||
|
||||
/** \brief a forwarding strategy similar to CCNx 0.7.2
|
||||
*
|
||||
* \note This strategy is not EndpointId-aware.
|
||||
/** \brief A forwarding strategy similar to CCNx 0.7.2
|
||||
*/
|
||||
class NccStrategy : public Strategy
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -58,7 +58,7 @@ protected:
|
||||
|
||||
private:
|
||||
virtual void
|
||||
sendNackForProcessNackTraits(const shared_ptr<pit::Entry>& pitEntry, const Face& outFace,
|
||||
sendNackForProcessNackTraits(const shared_ptr<pit::Entry>& pitEntry, Face& outFace,
|
||||
const lp::NackHeader& header) = 0;
|
||||
|
||||
virtual void
|
||||
@@ -78,10 +78,10 @@ protected:
|
||||
|
||||
private:
|
||||
void
|
||||
sendNackForProcessNackTraits(const shared_ptr<pit::Entry>& pitEntry, const Face& outFace,
|
||||
sendNackForProcessNackTraits(const shared_ptr<pit::Entry>& pitEntry, Face& outFace,
|
||||
const lp::NackHeader& header) override
|
||||
{
|
||||
m_strategy->sendNack(pitEntry, FaceEndpoint(outFace, 0), header);
|
||||
m_strategy->sendNack(pitEntry, outFace, header);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -61,24 +61,23 @@ RandomStrategy::afterReceiveInterest(const FaceEndpoint& ingress, const Interest
|
||||
const shared_ptr<pit::Entry>& pitEntry)
|
||||
{
|
||||
const fib::Entry& fibEntry = this->lookupFib(*pitEntry);
|
||||
const Face& inFace = ingress.face;
|
||||
fib::NextHopList nhs;
|
||||
|
||||
std::copy_if(fibEntry.getNextHops().begin(), fibEntry.getNextHops().end(), std::back_inserter(nhs),
|
||||
[&] (const auto& nh) { return isNextHopEligible(inFace, interest, nh, pitEntry); });
|
||||
[&] (const auto& nh) { return isNextHopEligible(ingress.face, interest, nh, pitEntry); });
|
||||
|
||||
if (nhs.empty()) {
|
||||
NFD_LOG_DEBUG(interest << " from=" << ingress << " no nexthop");
|
||||
|
||||
lp::NackHeader nackHeader;
|
||||
nackHeader.setReason(lp::NackReason::NO_ROUTE);
|
||||
this->sendNack(pitEntry, ingress, nackHeader);
|
||||
this->sendNack(pitEntry, ingress.face, nackHeader);
|
||||
this->rejectPendingInterest(pitEntry);
|
||||
return;
|
||||
}
|
||||
|
||||
std::shuffle(nhs.begin(), nhs.end(), ndn::random::getRandomNumberEngine());
|
||||
this->sendInterest(pitEntry, FaceEndpoint(nhs.front().getFace(), 0), interest);
|
||||
this->sendInterest(pitEntry, nhs.front().getFace(), interest);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -32,11 +32,9 @@
|
||||
namespace nfd {
|
||||
namespace fw {
|
||||
|
||||
/** \brief Randomly chooses a nexthop
|
||||
*
|
||||
* Sends an incoming interest to a random outgoing face,
|
||||
* excluding the incoming face.
|
||||
/** \brief A forwarding strategy that randomly chooses a nexthop
|
||||
*
|
||||
* Sends the incoming Interest to a random outgoing face, excluding the incoming face.
|
||||
*/
|
||||
class RandomStrategy : public Strategy
|
||||
, public ProcessNackTraits<RandomStrategy>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -80,7 +80,7 @@ SelfLearningStrategy::afterReceiveInterest(const FaceEndpoint& ingress, const In
|
||||
NFD_LOG_DEBUG("NACK non-discovery Interest=" << interest << " from=" << ingress << " noNextHop");
|
||||
lp::NackHeader nackHeader;
|
||||
nackHeader.setReason(lp::NackReason::NO_ROUTE);
|
||||
this->sendNack(pitEntry, ingress, nackHeader);
|
||||
this->sendNack(pitEntry, ingress.face, nackHeader);
|
||||
this->rejectPendingInterest(pitEntry);
|
||||
}
|
||||
else { // multicast it if matching FIB entry exists
|
||||
@@ -112,7 +112,7 @@ SelfLearningStrategy::afterReceiveData(const shared_ptr<pit::Entry>& pitEntry,
|
||||
OutRecordInfo* outRecordInfo = outRecord->getStrategyInfo<OutRecordInfo>();
|
||||
if (outRecordInfo && outRecordInfo->isNonDiscoveryInterest) { // outgoing Interest was non-discovery
|
||||
if (!needPrefixAnn(pitEntry)) { // no need to attach a PA (common cases)
|
||||
sendDataToAll(pitEntry, ingress, data);
|
||||
sendDataToAll(pitEntry, ingress.face, data);
|
||||
}
|
||||
else { // needs a PA (to respond discovery Interest)
|
||||
asyncProcessData(pitEntry, ingress.face, data);
|
||||
@@ -125,7 +125,7 @@ SelfLearningStrategy::afterReceiveData(const shared_ptr<pit::Entry>& pitEntry,
|
||||
}
|
||||
else { // Data contains no PrefixAnnouncement, upstreams do not support self-learning
|
||||
}
|
||||
sendDataToAll(pitEntry, ingress, data);
|
||||
sendDataToAll(pitEntry, ingress.face, data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,13 +149,17 @@ SelfLearningStrategy::broadcastInterest(const Interest& interest, const Face& in
|
||||
{
|
||||
for (auto& outFace : this->getFaceTable() | boost::adaptors::reversed) {
|
||||
if ((outFace.getId() == inFace.getId() && outFace.getLinkType() != ndn::nfd::LINK_TYPE_AD_HOC) ||
|
||||
wouldViolateScope(inFace, interest, outFace) || outFace.getScope() == ndn::nfd::FACE_SCOPE_LOCAL) {
|
||||
wouldViolateScope(inFace, interest, outFace) ||
|
||||
outFace.getScope() == ndn::nfd::FACE_SCOPE_LOCAL) {
|
||||
continue;
|
||||
}
|
||||
this->sendInterest(pitEntry, FaceEndpoint(outFace, 0), interest);
|
||||
pitEntry->getOutRecord(outFace)->insertStrategyInfo<OutRecordInfo>().first->isNonDiscoveryInterest = false;
|
||||
NFD_LOG_DEBUG("send discovery Interest=" << interest << " from="
|
||||
<< inFace.getId() << " to=" << outFace.getId());
|
||||
|
||||
NFD_LOG_DEBUG("send discovery Interest=" << interest << " from=" << inFace.getId() <<
|
||||
" to=" << outFace.getId());
|
||||
auto outRecord = this->sendInterest(pitEntry, outFace, interest);
|
||||
if (outRecord != nullptr) {
|
||||
outRecord->insertStrategyInfo<OutRecordInfo>().first->isNonDiscoveryInterest = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -165,15 +169,17 @@ SelfLearningStrategy::multicastInterest(const Interest& interest, const Face& in
|
||||
const fib::NextHopList& nexthops)
|
||||
{
|
||||
for (const auto& nexthop : nexthops) {
|
||||
Face& outFace = nexthop.getFace();
|
||||
if ((outFace.getId() == inFace.getId() && outFace.getLinkType() != ndn::nfd::LINK_TYPE_AD_HOC) ||
|
||||
wouldViolateScope(inFace, interest, outFace)) {
|
||||
if (!isNextHopEligible(inFace, interest, nexthop, pitEntry)) {
|
||||
continue;
|
||||
}
|
||||
this->sendInterest(pitEntry, FaceEndpoint(outFace, 0), interest);
|
||||
pitEntry->getOutRecord(outFace)->insertStrategyInfo<OutRecordInfo>().first->isNonDiscoveryInterest = true;
|
||||
NFD_LOG_DEBUG("send non-discovery Interest=" << interest << " from="
|
||||
<< inFace.getId() << " to=" << outFace.getId());
|
||||
|
||||
Face& outFace = nexthop.getFace();
|
||||
NFD_LOG_DEBUG("send non-discovery Interest=" << interest << " from=" << inFace.getId() <<
|
||||
" to=" << outFace.getId());
|
||||
auto outRecord = this->sendInterest(pitEntry, outFace, interest);
|
||||
if (outRecord != nullptr) {
|
||||
outRecord->insertStrategyInfo<OutRecordInfo>().first->isNonDiscoveryInterest = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -195,7 +201,7 @@ SelfLearningStrategy::asyncProcessData(const shared_ptr<pit::Entry>& pitEntry, c
|
||||
if (pitEntry && inFace) {
|
||||
NFD_LOG_DEBUG("found PrefixAnnouncement=" << pa.getAnnouncedName());
|
||||
data.setTag(make_shared<lp::PrefixAnnouncementTag>(lp::PrefixAnnouncementHeader(pa)));
|
||||
this->sendDataToAll(pitEntry, FaceEndpoint(*inFace, 0), data);
|
||||
this->sendDataToAll(pitEntry, *inFace, data);
|
||||
this->setExpiryTimer(pitEntry, 0_ms);
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -33,14 +33,12 @@
|
||||
namespace nfd {
|
||||
namespace fw {
|
||||
|
||||
/** \brief Self-learning strategy
|
||||
/** \brief Self-learning forwarding strategy
|
||||
*
|
||||
* This strategy first broadcasts Interest to learn a single path towards data,
|
||||
* then unicasts subsequent Interests along the learned path
|
||||
* then unicasts subsequent Interests along the learned path.
|
||||
*
|
||||
* \see https://redmine.named-data.net/attachments/864/Self-learning-strategy-v1.pdf
|
||||
*
|
||||
* \note This strategy is not EndpointId-aware
|
||||
*/
|
||||
class SelfLearningStrategy : public Strategy
|
||||
{
|
||||
|
||||
+27
-33
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -165,7 +165,7 @@ Strategy::afterContentStoreHit(const shared_ptr<pit::Entry>& pitEntry,
|
||||
NFD_LOG_DEBUG("afterContentStoreHit pitEntry=" << pitEntry->getName()
|
||||
<< " in=" << ingress << " data=" << data.getName());
|
||||
|
||||
this->sendData(pitEntry, data, ingress);
|
||||
this->sendData(pitEntry, data, ingress.face);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -177,33 +177,31 @@ Strategy::afterReceiveData(const shared_ptr<pit::Entry>& pitEntry,
|
||||
|
||||
this->beforeSatisfyInterest(pitEntry, ingress, data);
|
||||
|
||||
this->sendDataToAll(pitEntry, ingress, data);
|
||||
this->sendDataToAll(pitEntry, ingress.face, data);
|
||||
}
|
||||
|
||||
void
|
||||
Strategy::afterReceiveNack(const FaceEndpoint& ingress, const lp::Nack& nack,
|
||||
Strategy::afterReceiveNack(const FaceEndpoint& ingress, const lp::Nack&,
|
||||
const shared_ptr<pit::Entry>& pitEntry)
|
||||
{
|
||||
NFD_LOG_DEBUG("afterReceiveNack in=" << ingress << " pitEntry=" << pitEntry->getName());
|
||||
}
|
||||
|
||||
void
|
||||
Strategy::onDroppedInterest(const FaceEndpoint& egress, const Interest& interest)
|
||||
Strategy::onDroppedInterest(const Face& egress, const Interest& interest)
|
||||
{
|
||||
NFD_LOG_DEBUG("onDroppedInterest out=" << egress << " name=" << interest.getName());
|
||||
NFD_LOG_DEBUG("onDroppedInterest out=" << egress.getId() << " name=" << interest.getName());
|
||||
}
|
||||
|
||||
void
|
||||
Strategy::sendInterest(const shared_ptr<pit::Entry>& pitEntry,
|
||||
const FaceEndpoint& egress, const Interest& interest)
|
||||
pit::OutRecord*
|
||||
Strategy::sendInterest(const shared_ptr<pit::Entry>& pitEntry, Face& egress, const Interest& interest)
|
||||
{
|
||||
if (interest.getTag<lp::PitToken>() != nullptr) {
|
||||
Interest interest2 = interest; // make a copy to preserve tag on original packet
|
||||
interest2.removeTag<lp::PitToken>();
|
||||
m_forwarder.onOutgoingInterest(pitEntry, egress, interest2);
|
||||
return;
|
||||
return m_forwarder.onOutgoingInterest(pitEntry, egress, interest2);
|
||||
}
|
||||
m_forwarder.onOutgoingInterest(pitEntry, egress, interest);
|
||||
return m_forwarder.onOutgoingInterest(pitEntry, egress, interest);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -213,34 +211,32 @@ Strategy::afterNewNextHop(const fib::NextHop& nextHop, const shared_ptr<pit::Ent
|
||||
<< " nexthop=" << nextHop.getFace().getId());
|
||||
}
|
||||
|
||||
void
|
||||
Strategy::sendData(const shared_ptr<pit::Entry>& pitEntry, const Data& data,
|
||||
const FaceEndpoint& egress)
|
||||
bool
|
||||
Strategy::sendData(const shared_ptr<pit::Entry>& pitEntry, const Data& data, Face& egress)
|
||||
{
|
||||
BOOST_ASSERT(pitEntry->getInterest().matchesData(data));
|
||||
|
||||
shared_ptr<lp::PitToken> pitToken;
|
||||
auto inRecord = pitEntry->getInRecord(egress.face);
|
||||
auto inRecord = pitEntry->getInRecord(egress);
|
||||
if (inRecord != pitEntry->in_end()) {
|
||||
pitToken = inRecord->getInterest().getTag<lp::PitToken>();
|
||||
}
|
||||
|
||||
// delete the PIT entry's in-record based on egress,
|
||||
// since Data is sent to face and endpoint from which the Interest was received
|
||||
pitEntry->deleteInRecord(egress.face);
|
||||
// since the Data is sent to the face from which the Interest was received
|
||||
pitEntry->deleteInRecord(egress);
|
||||
|
||||
if (pitToken != nullptr) {
|
||||
Data data2 = data; // make a copy so each downstream can get a different PIT token
|
||||
data2.setTag(pitToken);
|
||||
m_forwarder.onOutgoingData(data2, egress);
|
||||
return;
|
||||
return m_forwarder.onOutgoingData(data2, egress);
|
||||
}
|
||||
m_forwarder.onOutgoingData(data, egress);
|
||||
return m_forwarder.onOutgoingData(data, egress);
|
||||
}
|
||||
|
||||
void
|
||||
Strategy::sendDataToAll(const shared_ptr<pit::Entry>& pitEntry,
|
||||
const FaceEndpoint& ingress, const Data& data)
|
||||
const Face& inFace, const Data& data)
|
||||
{
|
||||
std::set<Face*> pendingDownstreams;
|
||||
auto now = time::steady_clock::now();
|
||||
@@ -248,7 +244,7 @@ Strategy::sendDataToAll(const shared_ptr<pit::Entry>& pitEntry,
|
||||
// remember pending downstreams
|
||||
for (const pit::InRecord& inRecord : pitEntry->getInRecords()) {
|
||||
if (inRecord.getExpiry() > now) {
|
||||
if (inRecord.getFace().getId() == ingress.face.getId() &&
|
||||
if (inRecord.getFace().getId() == inFace.getId() &&
|
||||
inRecord.getFace().getLinkType() != ndn::nfd::LINK_TYPE_AD_HOC) {
|
||||
continue;
|
||||
}
|
||||
@@ -257,29 +253,27 @@ Strategy::sendDataToAll(const shared_ptr<pit::Entry>& pitEntry,
|
||||
}
|
||||
|
||||
for (const auto& pendingDownstream : pendingDownstreams) {
|
||||
this->sendData(pitEntry, data, FaceEndpoint(*pendingDownstream, 0));
|
||||
this->sendData(pitEntry, data, *pendingDownstream);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Strategy::sendNacks(const shared_ptr<pit::Entry>& pitEntry, const lp::NackHeader& header,
|
||||
std::initializer_list<FaceEndpoint> exceptFaceEndpoints)
|
||||
std::initializer_list<const Face*> exceptFaces)
|
||||
{
|
||||
// populate downstreams with all downstreams faces
|
||||
std::set<Face*> downstreams;
|
||||
std::unordered_set<Face*> downstreams;
|
||||
std::transform(pitEntry->in_begin(), pitEntry->in_end(), std::inserter(downstreams, downstreams.end()),
|
||||
[] (const pit::InRecord& inR) {
|
||||
return &inR.getFace();
|
||||
});
|
||||
[] (const pit::InRecord& inR) { return &inR.getFace(); });
|
||||
|
||||
// delete excluded faces
|
||||
for (const auto& exceptFaceEndpoint : exceptFaceEndpoints) {
|
||||
downstreams.erase(&exceptFaceEndpoint.face);
|
||||
for (auto exceptFace : exceptFaces) {
|
||||
downstreams.erase(const_cast<Face*>(exceptFace));
|
||||
}
|
||||
|
||||
// send Nacks
|
||||
for (const auto& downstream : downstreams) {
|
||||
this->sendNack(pitEntry, FaceEndpoint(*downstream, 0), header);
|
||||
for (auto downstream : downstreams) {
|
||||
this->sendNack(pitEntry, *downstream, header);
|
||||
}
|
||||
// warning: don't loop on pitEntry->getInRecords(), because in-record is deleted when sending Nack
|
||||
}
|
||||
|
||||
+63
-59
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -32,12 +32,12 @@
|
||||
namespace nfd {
|
||||
namespace fw {
|
||||
|
||||
/** \brief represents a forwarding strategy
|
||||
/** \brief Represents a forwarding strategy
|
||||
*/
|
||||
class Strategy : noncopyable
|
||||
{
|
||||
public: // registry
|
||||
/** \brief register a strategy type
|
||||
/** \brief Register a strategy type
|
||||
* \tparam S subclass of Strategy
|
||||
* \param strategyName strategy program name, must contain version
|
||||
* \note It is permitted to register the same strategy type under multiple names,
|
||||
@@ -56,7 +56,7 @@ public: // registry
|
||||
};
|
||||
}
|
||||
|
||||
/** \return whether a strategy instance can be created from \p instanceName
|
||||
/** \return Whether a strategy instance can be created from \p instanceName
|
||||
* \param instanceName strategy instance name, may contain version and parameters
|
||||
* \note This function finds a strategy type using same rules as \p create ,
|
||||
* but does not attempt to construct an instance.
|
||||
@@ -64,7 +64,7 @@ public: // registry
|
||||
static bool
|
||||
canCreate(const Name& instanceName);
|
||||
|
||||
/** \return a strategy instance created from \p instanceName
|
||||
/** \return A strategy instance created from \p instanceName
|
||||
* \retval nullptr if !canCreate(instanceName)
|
||||
* \throw std::invalid_argument strategy type constructor does not accept
|
||||
* specified version or parameters
|
||||
@@ -72,12 +72,12 @@ public: // registry
|
||||
static unique_ptr<Strategy>
|
||||
create(const Name& instanceName, Forwarder& forwarder);
|
||||
|
||||
/** \return whether \p instanceNameA and \p instanceNameA will initiate same strategy type
|
||||
/** \return Whether \p instanceNameA and \p instanceNameA will initiate same strategy type
|
||||
*/
|
||||
static bool
|
||||
areSameType(const Name& instanceNameA, const Name& instanceNameB);
|
||||
|
||||
/** \return registered versioned strategy names
|
||||
/** \return Registered versioned strategy names
|
||||
*/
|
||||
static std::set<Name>
|
||||
listRegistered();
|
||||
@@ -94,7 +94,7 @@ public: // constructor, destructor, strategy info
|
||||
~Strategy();
|
||||
|
||||
#ifdef DOXYGEN
|
||||
/** \return strategy program name
|
||||
/** \return Strategy program name
|
||||
*
|
||||
* The strategy name is defined by the strategy program.
|
||||
* It must end with a version component.
|
||||
@@ -103,7 +103,7 @@ public: // constructor, destructor, strategy info
|
||||
getStrategyName();
|
||||
#endif
|
||||
|
||||
/** \return strategy instance name
|
||||
/** \return Strategy instance name
|
||||
*
|
||||
* The instance name is assigned during instantiation.
|
||||
* It contains a version component, and may have extra parameter components.
|
||||
@@ -114,7 +114,7 @@ public: // constructor, destructor, strategy info
|
||||
return m_name;
|
||||
}
|
||||
|
||||
/** \return whether the afterNewNextHop trigger should be invoked for this strategy.
|
||||
/** \return Whether the afterNewNextHop trigger should be invoked for this strategy.
|
||||
*/
|
||||
bool
|
||||
wantNewNextHopTrigger() const
|
||||
@@ -123,9 +123,10 @@ public: // constructor, destructor, strategy info
|
||||
}
|
||||
|
||||
public: // triggers
|
||||
/** \brief trigger after Interest is received
|
||||
/** \brief Trigger after Interest is received
|
||||
*
|
||||
* The Interest:
|
||||
* - has not exceeded HopLimit
|
||||
* - does not violate Scope
|
||||
* - is not looped
|
||||
* - cannot be satisfied by ContentStore
|
||||
@@ -151,7 +152,7 @@ public: // triggers
|
||||
afterReceiveInterest(const FaceEndpoint& ingress, const Interest& interest,
|
||||
const shared_ptr<pit::Entry>& pitEntry) = 0;
|
||||
|
||||
/** \brief trigger before PIT entry is satisfied
|
||||
/** \brief Trigger before PIT entry is satisfied
|
||||
*
|
||||
* This trigger is invoked when an incoming Data satisfies more than one PIT entry.
|
||||
* The strategy can collect measurements information, but cannot manipulate Data forwarding.
|
||||
@@ -174,7 +175,7 @@ public: // triggers
|
||||
beforeSatisfyInterest(const shared_ptr<pit::Entry>& pitEntry,
|
||||
const FaceEndpoint& ingress, const Data& data);
|
||||
|
||||
/** \brief trigger after a Data is matched in CS
|
||||
/** \brief Trigger after a Data is matched in CS
|
||||
*
|
||||
* In the base class this method sends \p data to \p ingress
|
||||
*/
|
||||
@@ -182,7 +183,7 @@ public: // triggers
|
||||
afterContentStoreHit(const shared_ptr<pit::Entry>& pitEntry,
|
||||
const FaceEndpoint& ingress, const Data& data);
|
||||
|
||||
/** \brief trigger after Data is received
|
||||
/** \brief Trigger after Data is received
|
||||
*
|
||||
* This trigger is invoked when an incoming Data satisfies exactly one PIT entry,
|
||||
* and gives the strategy full control over Data forwarding.
|
||||
@@ -209,7 +210,7 @@ public: // triggers
|
||||
afterReceiveData(const shared_ptr<pit::Entry>& pitEntry,
|
||||
const FaceEndpoint& ingress, const Data& data);
|
||||
|
||||
/** \brief trigger after Nack is received
|
||||
/** \brief Trigger after Nack is received
|
||||
*
|
||||
* This trigger is invoked when an incoming Nack is received in response to
|
||||
* an forwarded Interest.
|
||||
@@ -234,14 +235,14 @@ public: // triggers
|
||||
afterReceiveNack(const FaceEndpoint& ingress, const lp::Nack& nack,
|
||||
const shared_ptr<pit::Entry>& pitEntry);
|
||||
|
||||
/** \brief trigger after Interest dropped for exceeding allowed retransmissions
|
||||
/** \brief Trigger after Interest dropped (e.g., for exceeding allowed retransmissions)
|
||||
*
|
||||
* In the base class this method does nothing.
|
||||
*/
|
||||
virtual void
|
||||
onDroppedInterest(const FaceEndpoint& egress, const Interest& interest);
|
||||
onDroppedInterest(const Face& egress, const Interest& interest);
|
||||
|
||||
/** \brief trigger after new nexthop is added
|
||||
/** \brief Trigger after new nexthop is added
|
||||
*
|
||||
* The strategy should decide whether to send the buffered Interests to the new nexthop.
|
||||
* In the base class, this method does nothing.
|
||||
@@ -250,36 +251,37 @@ public: // triggers
|
||||
afterNewNextHop(const fib::NextHop& nextHop, const shared_ptr<pit::Entry>& pitEntry);
|
||||
|
||||
protected: // actions
|
||||
/** \brief send Interest to egress
|
||||
* \param pitEntry PIT entry
|
||||
* \param egress face through which to send out the Interest and destination endpoint
|
||||
/** \brief Send an Interest packet.
|
||||
* \param pitEntry the PIT entry
|
||||
* \param egress face through which to send out the Interest
|
||||
* \param interest the Interest packet
|
||||
* \return A pointer to the out-record created or nullptr if the Interest was dropped
|
||||
*/
|
||||
VIRTUAL_WITH_TESTS void
|
||||
sendInterest(const shared_ptr<pit::Entry>& pitEntry,
|
||||
const FaceEndpoint& egress, const Interest& interest);
|
||||
VIRTUAL_WITH_TESTS pit::OutRecord*
|
||||
sendInterest(const shared_ptr<pit::Entry>& pitEntry, Face& egress,
|
||||
const Interest& interest);
|
||||
|
||||
/** \brief send \p data to \p egress
|
||||
* \param pitEntry PIT entry
|
||||
/** \brief Send a Data packet.
|
||||
* \param pitEntry the PIT entry
|
||||
* \param data the Data packet
|
||||
* \param egress face through which to send out the Data and destination endpoint
|
||||
* \param egress face through which to send out the Data
|
||||
* \return Whether the Data was sent (true) or dropped (false)
|
||||
*/
|
||||
VIRTUAL_WITH_TESTS void
|
||||
sendData(const shared_ptr<pit::Entry>& pitEntry, const Data& data, const FaceEndpoint& egress);
|
||||
VIRTUAL_WITH_TESTS bool
|
||||
sendData(const shared_ptr<pit::Entry>& pitEntry, const Data& data, Face& egress);
|
||||
|
||||
/** \brief send \p data to all matched and qualified face-endpoint pairs
|
||||
/** \brief Send a Data packet to all matched and qualified faces.
|
||||
*
|
||||
* A matched face is qualified if it is ad-hoc or it is NOT \p ingress
|
||||
* A matched face is qualified if it is ad-hoc or it is NOT \p inFace.
|
||||
*
|
||||
* \param pitEntry PIT entry
|
||||
* \param ingress face through which the Data comes from and endpoint of the sender
|
||||
* \param pitEntry the PIT entry
|
||||
* \param inFace face on which the Data arrived
|
||||
* \param data the Data packet
|
||||
*/
|
||||
VIRTUAL_WITH_TESTS void
|
||||
sendDataToAll(const shared_ptr<pit::Entry>& pitEntry,
|
||||
const FaceEndpoint& ingress, const Data& data);
|
||||
sendDataToAll(const shared_ptr<pit::Entry>& pitEntry, const Face& inFace, const Data& data);
|
||||
|
||||
/** \brief schedule the PIT entry for immediate deletion
|
||||
/** \brief Schedule the PIT entry for immediate deletion.
|
||||
*
|
||||
* This helper function sets the PIT entry expiry time to zero.
|
||||
* The strategy should invoke this function when it concludes that the Interest cannot
|
||||
@@ -291,31 +293,33 @@ protected: // actions
|
||||
this->setExpiryTimer(pitEntry, 0_ms);
|
||||
}
|
||||
|
||||
/** \brief send Nack to egress
|
||||
* \param pitEntry PIT entry
|
||||
* \param egress face through which to send out the Nack and destination endpoint
|
||||
* \param header Nack header
|
||||
/** \brief Send a Nack packet.
|
||||
*
|
||||
* The egress must have a PIT in-record, otherwise this method has no effect.
|
||||
* The egress face must have a PIT in-record, otherwise this method has no effect.
|
||||
*
|
||||
* \param pitEntry the PIT entry
|
||||
* \param egress face through which to send out the Nack
|
||||
* \param header the Nack header
|
||||
* \return Whether the Nack was sent (true) or dropped (false)
|
||||
*/
|
||||
VIRTUAL_WITH_TESTS void
|
||||
sendNack(const shared_ptr<pit::Entry>& pitEntry,
|
||||
const FaceEndpoint& egress, const lp::NackHeader& header)
|
||||
VIRTUAL_WITH_TESTS bool
|
||||
sendNack(const shared_ptr<pit::Entry>& pitEntry, Face& egress,
|
||||
const lp::NackHeader& header)
|
||||
{
|
||||
m_forwarder.onOutgoingNack(pitEntry, egress, header);
|
||||
return m_forwarder.onOutgoingNack(pitEntry, egress, header);
|
||||
}
|
||||
|
||||
/** \brief send Nack to every face-endpoint pair that has an in-record, except those in \p exceptFaceEndpoints
|
||||
* \param pitEntry PIT entry
|
||||
* \param header NACK header
|
||||
* \param exceptFaceEndpoints list of face-endpoint pairs that should be excluded from sending Nacks
|
||||
* \note This is not an action, but a helper that invokes the sendNack action.
|
||||
/** \brief Send Nack to every face that has an in-record, except those in \p exceptFaces
|
||||
* \param pitEntry the PIT entry
|
||||
* \param header the Nack header
|
||||
* \param exceptFaces list of faces that should be excluded from sending Nacks
|
||||
* \note This is not an action, but a helper that invokes the sendNack() action.
|
||||
*/
|
||||
void
|
||||
sendNacks(const shared_ptr<pit::Entry>& pitEntry, const lp::NackHeader& header,
|
||||
std::initializer_list<FaceEndpoint> exceptFaceEndpoints = {});
|
||||
std::initializer_list<const Face*> exceptFaces = {});
|
||||
|
||||
/** \brief Schedule the PIT entry to be erased after \p duration
|
||||
/** \brief Schedule the PIT entry to be erased after \p duration.
|
||||
*/
|
||||
void
|
||||
setExpiryTimer(const shared_ptr<pit::Entry>& pitEntry, time::milliseconds duration)
|
||||
@@ -324,7 +328,7 @@ protected: // actions
|
||||
}
|
||||
|
||||
protected: // accessors
|
||||
/** \brief performs a FIB lookup, considering Link object if present
|
||||
/** \brief Performs a FIB lookup, considering Link object if present.
|
||||
*/
|
||||
const fib::Entry&
|
||||
lookupFib(const pit::Entry& pitEntry) const;
|
||||
@@ -355,14 +359,14 @@ protected: // instance name
|
||||
PartialName parameters; ///< parameter components
|
||||
};
|
||||
|
||||
/** \brief parse a strategy instance name
|
||||
/** \brief Parse a strategy instance name
|
||||
* \param input strategy instance name, may contain version and parameters
|
||||
* \throw std::invalid_argument input format is unacceptable
|
||||
*/
|
||||
static ParsedInstanceName
|
||||
parseInstanceName(const Name& input);
|
||||
|
||||
/** \brief construct a strategy instance name
|
||||
/** \brief Construct a strategy instance name
|
||||
* \param input strategy instance name, may contain version and parameters
|
||||
* \param strategyName strategy name with version but without parameters;
|
||||
* typically this should be \p getStrategyName()
|
||||
@@ -375,7 +379,7 @@ protected: // instance name
|
||||
static Name
|
||||
makeInstanceName(const Name& input, const Name& strategyName);
|
||||
|
||||
/** \brief set strategy instance name
|
||||
/** \brief Set strategy instance name
|
||||
* \note This must be called by strategy subclass constructor.
|
||||
*/
|
||||
void
|
||||
@@ -385,7 +389,7 @@ protected: // instance name
|
||||
}
|
||||
|
||||
PUBLIC_WITH_TESTS_ELSE_PROTECTED: // setter
|
||||
/** \brief set whether the afterNewNextHop trigger should be invoked for this strategy
|
||||
/** \brief Set whether the afterNewNextHop trigger should be invoked for this strategy
|
||||
*/
|
||||
void
|
||||
enableNewNextHopTrigger(bool enabled)
|
||||
@@ -410,7 +414,7 @@ protected: // accessors
|
||||
private: // instance fields
|
||||
Name m_name;
|
||||
|
||||
/** \brief reference to the forwarder
|
||||
/** \brief Reference to the forwarder
|
||||
*
|
||||
* Triggers can access forwarder indirectly via actions.
|
||||
*/
|
||||
@@ -424,7 +428,7 @@ private: // instance fields
|
||||
} // namespace fw
|
||||
} // namespace nfd
|
||||
|
||||
/** \brief registers a strategy
|
||||
/** \brief Registers a strategy
|
||||
*
|
||||
* This macro should appear once in .cpp of each strategy.
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -27,17 +27,17 @@
|
||||
#include "common/logger.hpp"
|
||||
|
||||
#include <ndn-cxx/tag.hpp>
|
||||
#include <ndn-cxx/security/v2/certificate-fetcher-offline.hpp>
|
||||
#include <ndn-cxx/security/v2/certificate-request.hpp>
|
||||
#include <ndn-cxx/security/v2/validation-policy.hpp>
|
||||
#include <ndn-cxx/security/v2/validation-policy-accept-all.hpp>
|
||||
#include <ndn-cxx/security/v2/validation-policy-command-interest.hpp>
|
||||
#include <ndn-cxx/security/v2/validator.hpp>
|
||||
#include <ndn-cxx/security/certificate-fetcher-offline.hpp>
|
||||
#include <ndn-cxx/security/certificate-request.hpp>
|
||||
#include <ndn-cxx/security/validation-policy.hpp>
|
||||
#include <ndn-cxx/security/validation-policy-accept-all.hpp>
|
||||
#include <ndn-cxx/security/validation-policy-command-interest.hpp>
|
||||
#include <ndn-cxx/security/validator.hpp>
|
||||
#include <ndn-cxx/util/io.hpp>
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
namespace sec2 = ndn::security::v2;
|
||||
namespace security = ndn::security;
|
||||
|
||||
namespace nfd {
|
||||
|
||||
@@ -65,11 +65,11 @@ getSignerFromTag(const Interest& interest)
|
||||
|
||||
/** \brief a validation policy that only permits Interest signed by a trust anchor
|
||||
*/
|
||||
class CommandAuthenticatorValidationPolicy : public sec2::ValidationPolicy
|
||||
class CommandAuthenticatorValidationPolicy : public security::ValidationPolicy
|
||||
{
|
||||
public:
|
||||
void
|
||||
checkPolicy(const Interest& interest, const shared_ptr<sec2::ValidationState>& state,
|
||||
checkPolicy(const Interest& interest, const shared_ptr<security::ValidationState>& state,
|
||||
const ValidationContinuation& continueValidation) final
|
||||
{
|
||||
Name klName = getKeyLocatorName(interest, *state);
|
||||
@@ -80,14 +80,14 @@ public:
|
||||
// SignerTag must be placed on the 'original Interest' in ValidationState to be available for
|
||||
// InterestValidationSuccessCallback. The 'interest' parameter refers to a different instance
|
||||
// which is copied into 'original Interest'.
|
||||
auto state1 = dynamic_pointer_cast<sec2::InterestValidationState>(state);
|
||||
auto state1 = dynamic_pointer_cast<security::InterestValidationState>(state);
|
||||
state1->getOriginalInterest().setTag(make_shared<SignerTag>(klName));
|
||||
|
||||
continueValidation(make_shared<sec2::CertificateRequest>(Interest(klName)), state);
|
||||
continueValidation(make_shared<security::CertificateRequest>(Interest(klName)), state);
|
||||
}
|
||||
|
||||
void
|
||||
checkPolicy(const Data& data, const shared_ptr<sec2::ValidationState>& state,
|
||||
checkPolicy(const Data& data, const shared_ptr<security::ValidationState>& state,
|
||||
const ValidationContinuation& continueValidation) final
|
||||
{
|
||||
// Non-certificate Data are not handled by CommandAuthenticator.
|
||||
@@ -117,9 +117,9 @@ CommandAuthenticator::processConfig(const ConfigSection& section, bool isDryRun,
|
||||
if (!isDryRun) {
|
||||
NFD_LOG_INFO("clear-authorizations");
|
||||
for (auto& kv : m_validators) {
|
||||
kv.second = make_shared<sec2::Validator>(
|
||||
make_unique<sec2::ValidationPolicyCommandInterest>(make_unique<CommandAuthenticatorValidationPolicy>()),
|
||||
make_unique<sec2::CertificateFetcherOffline>());
|
||||
kv.second = make_shared<security::Validator>(
|
||||
make_unique<security::ValidationPolicyCommandInterest>(make_unique<CommandAuthenticatorValidationPolicy>()),
|
||||
make_unique<security::CertificateFetcherOffline>());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,7 +144,7 @@ CommandAuthenticator::processConfig(const ConfigSection& section, bool isDryRun,
|
||||
}
|
||||
|
||||
bool isAny = false;
|
||||
shared_ptr<sec2::Certificate> cert;
|
||||
shared_ptr<security::Certificate> cert;
|
||||
if (certfile == "any") {
|
||||
isAny = true;
|
||||
NFD_LOG_WARN("'certfile any' is intended for demo purposes only and "
|
||||
@@ -153,7 +153,7 @@ CommandAuthenticator::processConfig(const ConfigSection& section, bool isDryRun,
|
||||
else {
|
||||
using namespace boost::filesystem;
|
||||
path certfilePath = absolute(certfile, path(filename).parent_path());
|
||||
cert = ndn::io::load<sec2::Certificate>(certfilePath.string());
|
||||
cert = ndn::io::load<security::Certificate>(certfilePath.string());
|
||||
if (cert == nullptr) {
|
||||
NDN_THROW(ConfigFile::Error("cannot load certfile " + certfilePath.string() +
|
||||
" for authorize[" + to_string(authSectionIndex) + "]"));
|
||||
@@ -185,13 +185,13 @@ CommandAuthenticator::processConfig(const ConfigSection& section, bool isDryRun,
|
||||
}
|
||||
|
||||
if (isAny) {
|
||||
found->second = make_shared<sec2::Validator>(make_unique<sec2::ValidationPolicyAcceptAll>(),
|
||||
make_unique<sec2::CertificateFetcherOffline>());
|
||||
found->second = make_shared<security::Validator>(make_unique<security::ValidationPolicyAcceptAll>(),
|
||||
make_unique<security::CertificateFetcherOffline>());
|
||||
NFD_LOG_INFO("authorize module=" << module << " signer=any");
|
||||
}
|
||||
else {
|
||||
const Name& keyName = cert->getKeyName();
|
||||
sec2::Certificate certCopy = *cert;
|
||||
security::Certificate certCopy = *cert;
|
||||
found->second->loadAnchor(certfile, std::move(certCopy));
|
||||
NFD_LOG_INFO("authorize module=" << module << " signer=" << keyName << " certfile=" << certfile);
|
||||
}
|
||||
@@ -215,20 +215,20 @@ CommandAuthenticator::makeAuthorization(const std::string& module, const std::st
|
||||
auto successCb = [accept, validator] (const Interest& interest1) {
|
||||
auto signer1 = getSignerFromTag(interest1);
|
||||
BOOST_ASSERT(signer1 || // signer must be available unless 'certfile any'
|
||||
dynamic_cast<sec2::ValidationPolicyAcceptAll*>(&validator->getPolicy()) != nullptr);
|
||||
dynamic_cast<security::ValidationPolicyAcceptAll*>(&validator->getPolicy()) != nullptr);
|
||||
std::string signer = signer1.value_or("*");
|
||||
NFD_LOG_DEBUG("accept " << interest1.getName() << " signer=" << signer);
|
||||
accept(signer);
|
||||
};
|
||||
auto failureCb = [reject] (const Interest& interest1, const sec2::ValidationError& err) {
|
||||
auto failureCb = [reject] (const Interest& interest1, const security::ValidationError& err) {
|
||||
using ndn::mgmt::RejectReply;
|
||||
RejectReply reply = RejectReply::STATUS403;
|
||||
switch (err.getCode()) {
|
||||
case sec2::ValidationError::NO_SIGNATURE:
|
||||
case sec2::ValidationError::INVALID_KEY_LOCATOR:
|
||||
case security::ValidationError::NO_SIGNATURE:
|
||||
case security::ValidationError::INVALID_KEY_LOCATOR:
|
||||
reply = RejectReply::SILENT;
|
||||
break;
|
||||
case sec2::ValidationError::POLICY_ERROR:
|
||||
case security::ValidationError::POLICY_ERROR:
|
||||
if (interest1.getName().size() < ndn::command_interest::MIN_SIZE) { // "name too short"
|
||||
reply = RejectReply::SILENT;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -29,14 +29,7 @@
|
||||
#include "common/config-file.hpp"
|
||||
|
||||
#include <ndn-cxx/mgmt/dispatcher.hpp>
|
||||
|
||||
namespace ndn {
|
||||
namespace security {
|
||||
namespace v2 {
|
||||
class Validator;
|
||||
} // namespace v2
|
||||
} // namespace security
|
||||
} // namespace ndn
|
||||
#include <ndn-cxx/security/validator.hpp>
|
||||
|
||||
namespace nfd {
|
||||
|
||||
@@ -70,7 +63,7 @@ private:
|
||||
|
||||
private:
|
||||
/// module => validator
|
||||
std::unordered_map<std::string, shared_ptr<ndn::security::v2::Validator>> m_validators;
|
||||
std::unordered_map<std::string, shared_ptr<ndn::security::Validator>> m_validators;
|
||||
};
|
||||
|
||||
} // namespace nfd
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -117,7 +117,8 @@ FaceManager::createFace(const ControlParameters& parameters,
|
||||
faceParams.defaultCongestionThreshold = parameters.getDefaultCongestionThreshold();
|
||||
}
|
||||
if (parameters.hasMtu()) {
|
||||
faceParams.mtu = parameters.getMtu();
|
||||
// The face system limits MTUs to ssize_t, but the management protocol uses uint64_t
|
||||
faceParams.mtu = std::min<uint64_t>(std::numeric_limits<ssize_t>::max(), parameters.getMtu());
|
||||
}
|
||||
faceParams.wantLocalFields = parameters.hasFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED) &&
|
||||
parameters.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED);
|
||||
@@ -152,13 +153,10 @@ template<typename T>
|
||||
static void
|
||||
copyMtu(const Face& face, T& to)
|
||||
{
|
||||
auto transport = face.getTransport();
|
||||
BOOST_ASSERT(transport != nullptr);
|
||||
|
||||
if (transport->getMtu() > 0) {
|
||||
to.setMtu(std::min(static_cast<size_t>(transport->getMtu()), ndn::MAX_NDN_PACKET_SIZE));
|
||||
if (face.getMtu() >= 0) {
|
||||
to.setMtu(std::min<size_t>(face.getMtu(), ndn::MAX_NDN_PACKET_SIZE));
|
||||
}
|
||||
else if (transport->getMtu() == face::MTU_UNLIMITED) {
|
||||
else if (face.getMtu() == face::MTU_UNLIMITED) {
|
||||
to.setMtu(ndn::MAX_NDN_PACKET_SIZE);
|
||||
}
|
||||
}
|
||||
@@ -169,6 +167,7 @@ makeUpdateFaceResponse(const Face& face)
|
||||
ControlParameters params;
|
||||
params.setFaceId(face.getId())
|
||||
.setFacePersistency(face.getPersistency());
|
||||
copyMtu(face, params);
|
||||
|
||||
auto linkService = dynamic_cast<face::GenericLinkService*>(face.getLinkService());
|
||||
if (linkService != nullptr) {
|
||||
@@ -190,8 +189,6 @@ makeCreateFaceResponse(const Face& face)
|
||||
params.setUri(face.getRemoteUri().toString())
|
||||
.setLocalUri(face.getLocalUri().toString());
|
||||
|
||||
copyMtu(face, params);
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
@@ -246,6 +243,11 @@ updateLinkServiceOptions(Face& face, const ControlParameters& parameters)
|
||||
options.defaultCongestionThreshold = parameters.getDefaultCongestionThreshold();
|
||||
}
|
||||
|
||||
if (parameters.hasMtu()) {
|
||||
// The face system limits MTUs to ssize_t, but the management protocol uses uint64_t
|
||||
options.overrideMtu = std::min<uint64_t>(std::numeric_limits<ssize_t>::max(), parameters.getMtu());
|
||||
}
|
||||
|
||||
linkService->setOptions(options);
|
||||
}
|
||||
|
||||
@@ -295,6 +297,19 @@ FaceManager::updateFace(const Interest& interest,
|
||||
}
|
||||
}
|
||||
|
||||
// check whether the requested MTU override is valid (if it's present)
|
||||
if (parameters.hasMtu()) {
|
||||
auto mtu = parameters.getMtu();
|
||||
// The face system limits MTUs to ssize_t, but the management protocol uses uint64_t
|
||||
auto actualMtu = std::min<uint64_t>(std::numeric_limits<ssize_t>::max(), mtu);
|
||||
auto linkService = dynamic_cast<face::GenericLinkService*>(face->getLinkService());
|
||||
if (linkService == nullptr || !linkService->canOverrideMtuTo(actualMtu)) {
|
||||
NFD_LOG_TRACE("cannot override face MTU to " << mtu);
|
||||
areParamsValid = false;
|
||||
response.setMtu(mtu);
|
||||
}
|
||||
}
|
||||
|
||||
if (!areParamsValid) {
|
||||
done(ControlResponse(409, "Invalid properties specified").setBody(response.wireEncode()));
|
||||
return;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -33,7 +33,7 @@
|
||||
#include <ndn-cxx/lp/tags.hpp>
|
||||
#include <ndn-cxx/mgmt/nfd/face-status.hpp>
|
||||
#include <ndn-cxx/mgmt/nfd/rib-entry.hpp>
|
||||
#include <ndn-cxx/security/v2/certificate-fetcher-direct-fetch.hpp>
|
||||
#include <ndn-cxx/security/certificate-fetcher-direct-fetch.hpp>
|
||||
|
||||
namespace nfd {
|
||||
|
||||
@@ -57,8 +57,8 @@ RibManager::RibManager(rib::Rib& rib, ndn::Face& face, ndn::KeyChain& keyChain,
|
||||
, m_dispatcher(dispatcher)
|
||||
, m_faceMonitor(face)
|
||||
, m_localhostValidator(face)
|
||||
, m_localhopValidator(make_unique<ndn::security::v2::CertificateFetcherDirectFetch>(face))
|
||||
, m_paValidator(make_unique<ndn::security::v2::CertificateFetcherDirectFetch>(face))
|
||||
, m_localhopValidator(make_unique<ndn::security::CertificateFetcherDirectFetch>(face))
|
||||
, m_paValidator(make_unique<ndn::security::CertificateFetcherDirectFetch>(face))
|
||||
, m_isLocalhopEnabled(false)
|
||||
{
|
||||
registerCommandHandler<ndn::nfd::RibRegisterCommand>("register",
|
||||
@@ -370,7 +370,7 @@ RibManager::slAnnounce(const ndn::PrefixAnnouncement& pa, uint64_t faceId,
|
||||
cb(res);
|
||||
});
|
||||
},
|
||||
[=] (const Data&, ndn::security::v2::ValidationError err) {
|
||||
[=] (const Data&, ndn::security::ValidationError err) {
|
||||
NFD_LOG_INFO("slAnnounce " << pa.getAnnouncedName() << " " << faceId <<
|
||||
" validation error: " << err);
|
||||
cb(SlAnnounceResult::VALIDATION_FAILURE);
|
||||
|
||||
+11
-3
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -73,7 +73,11 @@ makeLocalNfdTransport(const ConfigSection& config)
|
||||
{
|
||||
if (config.get_child_optional("face_system.unix")) {
|
||||
// default socket path should be the same as in UnixStreamFactory::processConfig
|
||||
#ifdef __linux__
|
||||
auto path = config.get<std::string>("face_system.unix.path", "/run/nfd.sock");
|
||||
#else
|
||||
auto path = config.get<std::string>("face_system.unix.path", "/var/run/nfd.sock");
|
||||
#endif // __linux__
|
||||
return make_shared<ndn::UnixTransport>(path);
|
||||
}
|
||||
else if (config.get_child_optional("face_system.tcp") &&
|
||||
@@ -167,8 +171,12 @@ Service::checkConfig(const ConfigSection& section, const std::string& filename)
|
||||
for (const auto& item : section) {
|
||||
const std::string& key = item.first;
|
||||
const ConfigSection& value = item.second;
|
||||
if (key == CFG_LOCALHOST_SECURITY || key == CFG_LOCALHOP_SECURITY || key == CFG_PA_VALIDATION) {
|
||||
hasLocalhop = key == CFG_LOCALHOP_SECURITY;
|
||||
if (key == CFG_LOCALHOST_SECURITY || key == CFG_PA_VALIDATION) {
|
||||
ndn::ValidatorConfig testValidator(m_face);
|
||||
testValidator.load(value, filename);
|
||||
}
|
||||
else if (key == CFG_LOCALHOP_SECURITY) {
|
||||
hasLocalhop = true;
|
||||
ndn::ValidatorConfig testValidator(m_face);
|
||||
testValidator.load(value, filename);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -87,14 +87,14 @@ DeadNonceList::size() const
|
||||
}
|
||||
|
||||
bool
|
||||
DeadNonceList::has(const Name& name, uint32_t nonce) const
|
||||
DeadNonceList::has(const Name& name, Interest::Nonce nonce) const
|
||||
{
|
||||
Entry entry = DeadNonceList::makeEntry(name, nonce);
|
||||
return m_ht.find(entry) != m_ht.end();
|
||||
}
|
||||
|
||||
void
|
||||
DeadNonceList::add(const Name& name, uint32_t nonce)
|
||||
DeadNonceList::add(const Name& name, Interest::Nonce nonce)
|
||||
{
|
||||
Entry entry = DeadNonceList::makeEntry(name, nonce);
|
||||
m_queue.push_back(entry);
|
||||
@@ -103,11 +103,12 @@ DeadNonceList::add(const Name& name, uint32_t nonce)
|
||||
}
|
||||
|
||||
DeadNonceList::Entry
|
||||
DeadNonceList::makeEntry(const Name& name, uint32_t nonce)
|
||||
DeadNonceList::makeEntry(const Name& name, Interest::Nonce nonce)
|
||||
{
|
||||
Block nameWire = name.wireEncode();
|
||||
return CityHash64WithSeed(reinterpret_cast<const char*>(nameWire.wire()), nameWire.size(),
|
||||
static_cast<uint64_t>(nonce));
|
||||
uint32_t n;
|
||||
std::memcpy(&n, nonce.data(), sizeof(n));
|
||||
return CityHash64WithSeed(reinterpret_cast<const char*>(nameWire.wire()), nameWire.size(), n);
|
||||
}
|
||||
|
||||
size_t
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -67,15 +67,15 @@ public:
|
||||
~DeadNonceList();
|
||||
|
||||
/** \brief Determines if name+nonce exists
|
||||
* \return true if name+nonce exists
|
||||
* \return true if name+nonce exists, false otherwise
|
||||
*/
|
||||
bool
|
||||
has(const Name& name, uint32_t nonce) const;
|
||||
has(const Name& name, Interest::Nonce nonce) const;
|
||||
|
||||
/** \brief Records name+nonce
|
||||
*/
|
||||
void
|
||||
add(const Name& name, uint32_t nonce);
|
||||
add(const Name& name, Interest::Nonce nonce);
|
||||
|
||||
/** \return number of stored Nonces
|
||||
* \note The return value does not contain non-Nonce entries in the index, if any.
|
||||
@@ -95,7 +95,7 @@ private: // Entry and Index
|
||||
typedef uint64_t Entry;
|
||||
|
||||
static Entry
|
||||
makeEntry(const Name& name, uint32_t nonce);
|
||||
makeEntry(const Name& name, Interest::Nonce nonce);
|
||||
|
||||
typedef boost::multi_index_container<
|
||||
Entry,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -28,6 +28,9 @@
|
||||
namespace nfd {
|
||||
namespace pit {
|
||||
|
||||
// Impose a maximum lifetime to prevent integer overflow when calculating m_expiry.
|
||||
static const time::milliseconds MAX_LIFETIME{10_days};
|
||||
|
||||
void
|
||||
FaceRecord::update(const Interest& interest)
|
||||
{
|
||||
@@ -35,9 +38,7 @@ FaceRecord::update(const Interest& interest)
|
||||
m_lastRenewed = time::steady_clock::now();
|
||||
|
||||
auto lifetime = interest.getInterestLifetime();
|
||||
if (lifetime < 0_ms) {
|
||||
lifetime = ndn::DEFAULT_INTEREST_LIFETIME;
|
||||
}
|
||||
lifetime = std::min(lifetime, MAX_LIFETIME);
|
||||
m_expiry = m_lastRenewed + lifetime;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2020, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -51,7 +51,7 @@ public:
|
||||
return m_face;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
Interest::Nonce
|
||||
getLastNonce() const
|
||||
{
|
||||
return m_lastNonce;
|
||||
@@ -79,7 +79,7 @@ public:
|
||||
|
||||
private:
|
||||
Face& m_face;
|
||||
uint32_t m_lastNonce = 0;
|
||||
Interest::Nonce m_lastNonce{0, 0, 0, 0};
|
||||
time::steady_clock::TimePoint m_lastRenewed = time::steady_clock::TimePoint::min();
|
||||
time::steady_clock::TimePoint m_expiry = time::steady_clock::TimePoint::min();
|
||||
};
|
||||
|
||||
+49
-72
@@ -1,41 +1,39 @@
|
||||
FAQ
|
||||
===
|
||||
|
||||
How to change the default paths?
|
||||
--------------------------------
|
||||
How do I change the default installation paths?
|
||||
-----------------------------------------------
|
||||
|
||||
Paths to where NFD is installed can be configured during ``./waf
|
||||
configure``:
|
||||
Paths to where NFD is installed can be configured during ``./waf configure``:
|
||||
|
||||
- Installation prefix (default ``/usr/local``):
|
||||
- Installation prefix (default ``/usr/local``)::
|
||||
|
||||
::
|
||||
./waf configure --prefix=/usr
|
||||
|
||||
./waf configure --prefix=/usr
|
||||
- Location of NFD configuration file (default: ``${prefix}/etc``)::
|
||||
|
||||
- Location of NFD configuration file (default: ``${prefix}/etc``):
|
||||
./waf configure --prefix=/usr --sysconfdir=/etc
|
||||
|
||||
::
|
||||
- Location of manpages (default: ``${prefix}/share/man``)::
|
||||
|
||||
./waf configure --prefix=/usr --sysconfdir=/etc
|
||||
./waf configure --prefix=/usr --sysconfdir=/etc --mandir=/usr/share/man
|
||||
|
||||
- Location of manpages (default: ``${prefix}/share/man``)
|
||||
See ``./waf configure --help`` for the full list of options.
|
||||
|
||||
::
|
||||
How do I use the NDN PPA repository on Ubuntu Linux?
|
||||
----------------------------------------------------
|
||||
|
||||
./waf configure --prefix=/usr --sysconfdir=/etc --mandir=/usr/share/man
|
||||
Please see :ref:`Install NFD on Ubuntu Linux using the NDN PPA repository`.
|
||||
|
||||
How to run NFD as non-root user?
|
||||
--------------------------------
|
||||
How do I run NFD as a non-root user?
|
||||
------------------------------------
|
||||
|
||||
How to configure automatic dropping of privileges?
|
||||
++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
How do I configure automatic privilege dropping?
|
||||
++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
NFD can be configured to drop privileges whenever possible. You can specify a user and/or
|
||||
group for NFD to change its *effective* user/group ID to in the ``general`` section of the
|
||||
configuration file. For example:
|
||||
|
||||
::
|
||||
configuration file. For example::
|
||||
|
||||
general
|
||||
{
|
||||
@@ -54,71 +52,58 @@ respectively.
|
||||
root). However, reducing privileges may limit any damage caused by well intentioned,
|
||||
but buggy, code.
|
||||
|
||||
How to enable Ethernet Face Support?
|
||||
++++++++++++++++++++++++++++++++++++
|
||||
How do I enable Ethernet face support?
|
||||
++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
The ``ether`` configuration file section contains settings for Ethernet faces and
|
||||
channels. These settings will **NOT** work without root or setting the appropriate
|
||||
permissions:
|
||||
channels. These settings will **NOT** work without root or without setting the
|
||||
appropriate permissions.
|
||||
|
||||
::
|
||||
- On **Ubuntu**::
|
||||
|
||||
sudo setcap cap_net_raw,cap_net_admin=eip /full/path/nfd
|
||||
sudo apt install libcap2-bin
|
||||
sudo setcap cap_net_raw,cap_net_admin=eip /path/to/nfd
|
||||
|
||||
You may need to install a package to use setcap:
|
||||
|
||||
**Ubuntu:**
|
||||
|
||||
::
|
||||
|
||||
sudo apt-get install libcap2-bin
|
||||
|
||||
**Mac OS X:**
|
||||
|
||||
::
|
||||
- On **macOS**::
|
||||
|
||||
curl https://bugs.wireshark.org/bugzilla/attachment.cgi?id=3373 -o ChmodBPF.tar.gz
|
||||
tar zxvf ChmodBPF.tar.gz
|
||||
open ChmodBPF/Install\ ChmodBPF.app
|
||||
|
||||
or manually:
|
||||
|
||||
::
|
||||
or manually::
|
||||
|
||||
sudo chgrp admin /dev/bpf*
|
||||
sudo chmod g+rw /dev/bpf*
|
||||
|
||||
How to enable UDP multicast support in multi-homed Linux machines
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
How do I enable UDP multicast support in multi-homed Linux machines?
|
||||
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
The UDP configuration file section contains settings for unicast and multicast UDP
|
||||
faces. If the Linux box is equipped with multiple network interfaces with multicast
|
||||
capabilities, the settings for multicast faces will **NOT** work without root
|
||||
or setting the appropriate permissions:
|
||||
The ``udp`` configuration file section contains settings for unicast and multicast UDP
|
||||
faces. If the Linux machine is equipped with multiple network interfaces with multicast
|
||||
capabilities, the settings for multicast faces will **NOT** work without root or without
|
||||
setting the appropriate permissions::
|
||||
|
||||
::
|
||||
sudo setcap cap_net_raw=eip /path/to/nfd
|
||||
|
||||
sudo setcap cap_net_raw=eip /full/path/nfd
|
||||
.. _How do I configure NFD security:
|
||||
|
||||
.. _How to configure NFD security:
|
||||
How do I configure NFD security?
|
||||
--------------------------------
|
||||
|
||||
How to configure NFD security?
|
||||
------------------------------
|
||||
.. note:: The sample configuration file for NFD allows any user to manage faces, FIB, RIB,
|
||||
CS, and strategy choices of the local NFD instance. The following procedure can be used
|
||||
to restrict certain operations to certain users.
|
||||
|
||||
.. note:: The sample configuration file of NFD allow any user to manage faces, FIB, RIB, and
|
||||
StrategyChoice of the local NFD. The following description can be used to restrict certain
|
||||
operations to certain users.
|
||||
More extensive documentation on the security mechanisms in NFD, as well as the available
|
||||
options to configure its trust model, is currently in preparation.
|
||||
|
||||
More extensive documentation about NFD's security and options to configure trust model for
|
||||
NFD is currently in preparation.
|
||||
|
||||
Many NFD management protocols use commands Interests (e.g., FIB modification, Face
|
||||
creation/destructions, etc.), which require an NDN certificate (either self-signed for local
|
||||
Many management components in NFD use *Command Interests* (e.g., FIB modification, face
|
||||
creation/destruction, etc.), which require an NDN certificate (either self-signed for local
|
||||
trust or delegated from a trusted authority).
|
||||
|
||||
If you do not already have NDN certificate, you can generate one with the following commands:
|
||||
If you do not already have an NDN certificate, you can generate one using the following procedure.
|
||||
|
||||
**Generate and install a self-signed identity certificate**:
|
||||
**Generating and installing a self-signed identity certificate**:
|
||||
|
||||
::
|
||||
|
||||
@@ -128,21 +113,13 @@ Note that the argument to ndnsec-key will be the identity name of the new key (i
|
||||
``/your-username``). Identity names are hierarchical NDN names and may have multiple components
|
||||
(e.g. ``/ndn/ucla/edu/alice``). You may create additional keys and identities as you see fit.
|
||||
|
||||
**Dump the NDN certificate to a file**:
|
||||
**Exporting the NDN certificate to a file**:
|
||||
|
||||
The following commands assume that you have not modified ``PREFIX`` or ``SYSCONFDIR`` If you
|
||||
have, please substitute ``/usr/local/etc`` for the appropriate value (the overriden
|
||||
``SYSCONFDIR`` or ``PREFIX/etc`` if you changed ``PREFIX``).
|
||||
The following commands assume that you have not modified ``PREFIX`` or ``SYSCONFDIR``.
|
||||
If you have, please substitute the appropriate path in place of ``/usr/local/etc``.
|
||||
|
||||
::
|
||||
|
||||
sudo mkdir -p /usr/local/etc/ndn/keys
|
||||
ndnsec-cert-dump -i /`whoami` > default.ndncert
|
||||
sudo mv default.ndncert /usr/local/etc/ndn/keys/default.ndncert
|
||||
|
||||
.. _How to start using NDN PPA repository on Ubuntu Linux:
|
||||
|
||||
How to start using NDN PPA repository on Ubuntu Linux?
|
||||
------------------------------------------------------
|
||||
|
||||
Please see :ref:`Install NFD Using the NDN PPA Repository on Ubuntu Linux`.
|
||||
+148
-163
@@ -1,209 +1,211 @@
|
||||
Getting Started with NFD
|
||||
Getting started with NFD
|
||||
========================
|
||||
|
||||
.. _Install NFD Using the NDN PPA Repository on Ubuntu Linux:
|
||||
Supported platforms
|
||||
-------------------
|
||||
|
||||
Install NFD Using the NDN PPA Repository on Ubuntu Linux
|
||||
NFD is built against a continuous integration system and has been tested on the
|
||||
following platforms:
|
||||
|
||||
- Ubuntu 18.04 (amd64, armhf, i386)
|
||||
- Ubuntu 20.04 (amd64)
|
||||
- macOS 10.13
|
||||
- macOS 10.14
|
||||
- macOS 10.15
|
||||
- CentOS 8
|
||||
|
||||
NFD is known to work on the following platforms, although they are not officially
|
||||
supported:
|
||||
|
||||
- Debian 10 (Buster)
|
||||
- Fedora >= 29
|
||||
- Gentoo Linux
|
||||
- Raspbian >= 2019-06-20 (Buster)
|
||||
|
||||
.. _Install NFD on Ubuntu Linux using the NDN PPA repository:
|
||||
|
||||
Install NFD on Ubuntu Linux using the NDN PPA repository
|
||||
--------------------------------------------------------
|
||||
|
||||
NFD binaries and related tools for the latest versions of Ubuntu Linux can be installed using PPA
|
||||
packages from named-data repository. First, you will need to add ``named-data/ppa``
|
||||
repository to binary package sources and update list of available packages.
|
||||
NFD binaries and related tools for supported versions of Ubuntu can be installed using
|
||||
PPA packages from the **named-data** repository. First, you will need to add the
|
||||
``named-data/ppa`` repository to the binary package sources and update the list of
|
||||
available packages.
|
||||
|
||||
Preliminary steps if you have not used PPA packages before
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
To simplify adding new PPA repositories, Ubuntu provides ``add-apt-repository`` tool,
|
||||
To simplify adding new PPA repositories, Ubuntu provides the ``add-apt-repository`` tool,
|
||||
which is not installed by default on some systems.
|
||||
|
||||
::
|
||||
|
||||
sudo apt-get install software-properties-common
|
||||
sudo apt install software-properties-common
|
||||
|
||||
Adding NDN PPA
|
||||
~~~~~~~~~~~~~~
|
||||
Adding the NDN PPA
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
After installing ``add-apt-repository``, run the following command to add `NDN PPA
|
||||
repository`_.
|
||||
|
||||
::
|
||||
After installing ``add-apt-repository``, run the following commands to add the `NDN PPA
|
||||
repository`_::
|
||||
|
||||
sudo add-apt-repository ppa:named-data/ppa
|
||||
sudo apt-get update
|
||||
sudo apt update
|
||||
|
||||
Installing NFD and other NDN packages
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
After you have added `NDN PPA repository`_, NFD and other NDN packages can be easily
|
||||
installed in a standard way, i.e., either using ``apt-get`` as shown below or using any
|
||||
other package manager, such as Synaptic Package Manager:
|
||||
After you have added the `NDN PPA repository`_, NFD and other NDN packages can be easily
|
||||
installed either using ``apt``, as shown below, or any other compatible package manager.
|
||||
|
||||
::
|
||||
|
||||
sudo apt-get install nfd
|
||||
sudo apt install nfd
|
||||
|
||||
For the list of available packages, refer to `NDN PPA repository`_ homepage.
|
||||
For the list of available packages, refer to the `NDN PPA repository`_ page.
|
||||
|
||||
.. _NDN PPA repository: https://launchpad.net/~named-data/+archive/ppa
|
||||
|
||||
Building from Source
|
||||
Building from source
|
||||
--------------------
|
||||
|
||||
Downloading from Git
|
||||
Downloading from git
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The first step is to obtain the source code for ``NFD`` and, its main dependency, the
|
||||
``ndn-cxx`` library. If you are not planning to work with the bleeding edge code, make
|
||||
sure you checkout the correct release tag (e.g., ``*-0.7.0``) for both repositories:
|
||||
The first step is to obtain the source code for NFD and its main dependency, the
|
||||
*ndn-cxx* library. If you do not want a development version of NFD, make sure you
|
||||
checkout the correct release tag (e.g., ``*-0.7.1``) from both repositories.
|
||||
|
||||
::
|
||||
.. code-block:: sh
|
||||
|
||||
# Download ndn-cxx
|
||||
git clone https://github.com/named-data/ndn-cxx
|
||||
git clone https://github.com/named-data/ndn-cxx.git
|
||||
|
||||
# Download NFD
|
||||
git clone --recursive https://github.com/named-data/NFD
|
||||
git clone --recursive https://github.com/named-data/NFD.git
|
||||
|
||||
.. note::
|
||||
While we strive to ensure that the latest version (master branch) of NFD and ndn-cxx
|
||||
always properly compiles and works, sometimes there could be problems. In these cases, use
|
||||
the latest released version.
|
||||
While we strive to ensure that the latest version (git master branch) of NFD and ndn-cxx
|
||||
always compiles and works properly, we cannot guarantee that there will be no issues.
|
||||
If this is discovered to be the case, please use matching released versions (git tag or
|
||||
tarball) of NFD and ndn-cxx instead.
|
||||
|
||||
Prerequisites
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
Install the `ndn-cxx library <https://named-data.net/doc/ndn-cxx/current/INSTALL.html>`__ and its requirements
|
||||
Install the `ndn-cxx library <https://named-data.net/doc/ndn-cxx/current/INSTALL.html>`__
|
||||
and its prerequisites.
|
||||
|
||||
- On macOS with Homebrew:
|
||||
On Linux, NFD needs the following dependencies to enable optional features:
|
||||
|
||||
::
|
||||
- On **Ubuntu**:
|
||||
|
||||
brew install boost openssl pkg-config
|
||||
.. code-block:: sh
|
||||
|
||||
- On Ubuntu:
|
||||
sudo apt install libpcap-dev libsystemd-dev
|
||||
|
||||
::
|
||||
- On **CentOS** and **Fedora**:
|
||||
|
||||
sudo apt-get install build-essential pkg-config libboost-all-dev \
|
||||
libsqlite3-dev libssl-dev libpcap-dev
|
||||
.. code-block:: sh
|
||||
|
||||
To build manpages and API documentation:
|
||||
|
||||
- On macOS with Homebrew:
|
||||
|
||||
::
|
||||
|
||||
brew install doxygen graphviz
|
||||
sudo easy_install pip
|
||||
sudo pip Sphinx
|
||||
|
||||
- On Ubuntu:
|
||||
|
||||
::
|
||||
|
||||
sudo apt-get install doxygen graphviz python-sphinx
|
||||
sudo dnf config-manager --enable PowerTools # on CentOS only
|
||||
sudo dnf install libpcap-devel systemd-devel
|
||||
|
||||
Build
|
||||
~~~~~
|
||||
|
||||
The following basic commands should be used to build NFD on Ubuntu and macOS with Homebrew:
|
||||
The following commands can be used to build and install NFD from source:
|
||||
|
||||
::
|
||||
.. code-block:: sh
|
||||
|
||||
./waf configure # on CentOS, add --without-pch
|
||||
./waf
|
||||
sudo ./waf install
|
||||
|
||||
If you have installed ndn-cxx and/or any other dependencies into a non-standard path,
|
||||
you may need to modify the ``PKG_CONFIG_PATH`` environment variable before running
|
||||
``./waf configure``. For example:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
export PKG_CONFIG_PATH="/custom/lib/pkgconfig:$PKG_CONFIG_PATH"
|
||||
./waf configure
|
||||
./waf
|
||||
sudo ./waf install
|
||||
|
||||
If you have installed ``ndn-cxx`` library and/or other dependencies into a non-standard path, you
|
||||
may need to modify ``PKG_CONFIG_PATH`` environment variable before running ``./waf configure``.
|
||||
For example,
|
||||
|
||||
::
|
||||
|
||||
export PKG_CONFIG_PATH=/custom/lib/pkgconfig:$PKG_CONFIG_PATH
|
||||
./waf configure
|
||||
./waf
|
||||
sudo ./waf install
|
||||
|
||||
Refer to ``./waf --help`` for more options that can be used during ``configure`` stage and
|
||||
how to properly configure and run NFD.
|
||||
Refer to ``./waf --help`` for more options that can be used during the ``configure`` stage.
|
||||
|
||||
.. note::
|
||||
If you are working on a source repository that has been compiled before, and you have
|
||||
upgraded one of the dependencies, please execute ``./waf distclean`` to clear object files
|
||||
and start over.
|
||||
If you are working on a source repository that has been compiled before, and you have
|
||||
upgraded one of the dependencies, please execute ``./waf distclean`` to clear object files
|
||||
and start over.
|
||||
|
||||
Debug symbols
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
The default compiler flags enable debug symbols to be included in binaries. This
|
||||
potentially allows more meaningful debugging if NFD or other tools happen to crash.
|
||||
The default compiler flags include debug symbols in binaries. This should provide
|
||||
more meaningful debugging information if NFD or other tools happen to crash.
|
||||
|
||||
If it is undesirable, default flags can be easily overridden. The following example shows
|
||||
how to completely disable debug symbols and configure NFD to be installed into ``/usr``
|
||||
with configuration in ``/etc`` folder.
|
||||
If this is not desired, the default flags can be overridden to disable debug symbols.
|
||||
The following example shows how to completely disable debug symbols and configure
|
||||
NFD to be installed into ``/usr`` with configuration in the ``/etc`` directory.
|
||||
|
||||
::
|
||||
.. code-block:: sh
|
||||
|
||||
CXXFLAGS="-O2" ./waf configure --prefix=/usr --sysconfdir=/etc
|
||||
./waf
|
||||
sudo ./waf install
|
||||
|
||||
.. note::
|
||||
For Ubuntu PPA packages debug symbols are available in ``*-dbg`` packages.
|
||||
For Ubuntu PPA packages, debug symbols are available in ``*-dbg`` packages.
|
||||
|
||||
Customize Compiler
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
Customizing the compiler
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
To choose a custom C++ compiler for building NFD, set the ``CXX`` environment variable
|
||||
to point to the compiler binary. For example, to select the clang compiler on a Linux
|
||||
system, use the following:
|
||||
To build NFD with a different compiler (rather than the platform default), set the
|
||||
``CXX`` environment variable to point to the compiler binary. For example, to build
|
||||
with clang on Linux, use the following:
|
||||
|
||||
::
|
||||
.. code-block:: sh
|
||||
|
||||
CXX=clang++ ./waf configure
|
||||
|
||||
Building documentation
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
Building the documentation
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
NFD tutorials and API documentation can be built using the following commands:
|
||||
Tutorials and API documentation can be built using the following commands:
|
||||
|
||||
::
|
||||
.. code-block:: sh
|
||||
|
||||
# Full set of documentation (tutorials + API) in build/docs
|
||||
./waf docs
|
||||
|
||||
# Only tutorials in `build/docs`
|
||||
# Only tutorials in build/docs
|
||||
./waf sphinx
|
||||
|
||||
# Only API docs in `build/docs/doxygen`
|
||||
./waf doxgyen
|
||||
# Only API docs in build/docs/doxygen
|
||||
./waf doxygen
|
||||
|
||||
If ``sphinx-build`` is detected during ``./waf configure``, manpages will automatically
|
||||
be built and installed during the normal build process (i.e., during ``./waf`` and
|
||||
``./waf install``). By default, manpages will be installed into ``${PREFIX}/share/man``
|
||||
(the default value for ``PREFIX`` is ``/usr/local``). This location can be changed
|
||||
during the ``./waf configure`` stage using the ``--prefix``, ``--datarootdir``, or
|
||||
``--mandir`` options.
|
||||
|
||||
Manpages are automatically created and installed during the normal build process (e.g.,
|
||||
during ``./waf`` and ``./waf install``), if ``python-sphinx`` module is detected during
|
||||
``./waf configure`` stage. By default, manpages are installed into
|
||||
``${PREFIX}/share/man`` (where default value for ``PREFIX`` is ``/usr/local``). This
|
||||
location can be changed during ``./waf configure`` stage using ``--prefix``,
|
||||
``--datarootdir``, or ``--mandir`` options.
|
||||
|
||||
For more details, refer to ``./waf --help``.
|
||||
For further details, please refer to ``./waf --help``.
|
||||
|
||||
Initial configuration
|
||||
---------------------
|
||||
|
||||
.. note::
|
||||
If you have installed NFD from binary packages, the package manager has already
|
||||
installed initial configuration and you can safely skip this section.
|
||||
installed a working configuration and you can safely skip this section.
|
||||
|
||||
General
|
||||
~~~~~~~
|
||||
|
||||
After installing NFD from source, you need to create a proper config file. If default
|
||||
location for ``./waf configure`` was used, this can be accomplished by simply copying the
|
||||
sample configuration file:
|
||||
|
||||
::
|
||||
After installing NFD from source, you need to create a proper configuration file.
|
||||
If the default installation directories were used with ``./waf configure``, this
|
||||
can be accomplished by simply copying the sample configuration file as follows::
|
||||
|
||||
sudo cp /usr/local/etc/ndn/nfd.conf.sample /usr/local/etc/ndn/nfd.conf
|
||||
|
||||
@@ -211,15 +213,17 @@ NFD Security
|
||||
~~~~~~~~~~~~
|
||||
|
||||
NFD provides mechanisms to enable strict authorization for all management commands. In
|
||||
particular, one can authorize only specific public keys to create new Faces or change the
|
||||
particular, one can authorize only specific public keys to create new faces or change the
|
||||
forwarding strategy for specific namespaces. For more information about how to generate
|
||||
private/public key pair, generate self-signed certificate, and use this self-signed
|
||||
certificate to authorize NFD management commands, refer to :ref:`How to configure NFD
|
||||
security` FAQ question.
|
||||
public/private key pairs, generate self-signed certificates, and use them to authorize
|
||||
NFD management commands, refer to the :ref:`How do I configure NFD security` FAQ question.
|
||||
|
||||
In the sample configuration file, all authorizations are disabled, effectively allowing
|
||||
anybody on the local machine to issue NFD management commands. **The sample file is
|
||||
intended only for demo purposes and MUST NOT be used in a production environment.**
|
||||
In the sample configuration file, all security mechanisms are disabled for local clients,
|
||||
effectively allowing anybody on the local machine to issue NFD management commands.
|
||||
|
||||
.. note::
|
||||
The sample configuration file is intended only for demo purposes and should NOT be
|
||||
used in production environments.
|
||||
|
||||
Running
|
||||
-------
|
||||
@@ -227,81 +231,62 @@ Running
|
||||
Starting
|
||||
~~~~~~~~
|
||||
|
||||
If you have installed NFD from source code, it is recommended to start NFD with the
|
||||
``nfd-start`` script:
|
||||
|
||||
::
|
||||
If you have installed NFD from source, it is recommended to start NFD with the
|
||||
``nfd-start`` script::
|
||||
|
||||
nfd-start
|
||||
|
||||
On macOS it may ask for your keychain password or ask ``nfd wants to sign using key in
|
||||
your keychain``. Enter your keychain password and click "Always Allow".
|
||||
On macOS, this command may ask for your keychain password or ask "nfd wants to sign using
|
||||
key [xyz] in your keychain". Enter your keychain password and click "Always Allow".
|
||||
|
||||
Later, you can stop NFD with ``nfd-stop`` or by simply killing the ``nfd`` process.
|
||||
|
||||
If you have installed NFD using a package manager, you can start and stop NFD using the
|
||||
operating system's service manager (such as systemd or launchd) or using
|
||||
"Automatically start NFD" option in NDN Control Center app.
|
||||
operating system's service manager, such as ``systemctl`` or ``launchctl``.
|
||||
|
||||
Connecting to remote NFDs
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Connecting to remote forwarders
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
To create a UDP tunnel to a remote NFD, execute the following command in terminal:
|
||||
To create a UDP tunnel to a remote instance of NFD, execute the following command
|
||||
in a terminal::
|
||||
|
||||
::
|
||||
nfdc face create udp://<other-host>
|
||||
|
||||
nfdc face create udp://<other host>
|
||||
|
||||
where ``<other host>`` is the name or IP address of the other host (e.g.,
|
||||
``udp://spurs.cs.ucla.edu``). This outputs:
|
||||
|
||||
::
|
||||
where ``<other-host>`` is the name or IP address of the other host (e.g.,
|
||||
``udp://ndn.example.net``). If successful, this will print something like::
|
||||
|
||||
face-created id=308 local=udp4://10.0.2.15:6363 remote=udp4://131.179.196.46:6363 persistency=persistent
|
||||
|
||||
To add a route ``/ndn`` toward the remote NFD, execute the following command in terminal:
|
||||
To add a route ``/ndn`` toward this remote forwarder, execute the following command
|
||||
in a terminal::
|
||||
|
||||
::
|
||||
nfdc route add /ndn udp://<other-host>
|
||||
|
||||
nfdc route add /ndn udp://<other host>
|
||||
|
||||
This outputs:
|
||||
|
||||
::
|
||||
This will print::
|
||||
|
||||
route-add-accepted prefix=/ndn nexthop=308 origin=static cost=0 flags=child-inherit expires=never
|
||||
|
||||
The ``/ndn`` means that NFD will forward all Interests that start with ``/ndn`` through the
|
||||
face to the other host. If you only want to forward Interests with a certain prefix, use it
|
||||
instead of ``/ndn``. This only forwards Interests to the other host, but there is no "back
|
||||
route" for the other host to forward Interests to you. For that, you can rely on automatic
|
||||
prefix propagation feature of NFD or go to the other host and use ``nfdc`` to add the route.
|
||||
This indicates that NFD will forward all Interests that start with ``/ndn`` through the
|
||||
face to the other host. This forwards Interests to the other host, but does not provide
|
||||
a "back route" for the other host to forward Interests to you. For this, you can rely on
|
||||
the "automatic prefix propagation" feature of NFD or use the ``nfdc`` command on the other
|
||||
host to add the route.
|
||||
|
||||
Playing with NFD
|
||||
----------------
|
||||
|
||||
After you haved installed, configured, and started NFD, you can try to install and play
|
||||
with the following:
|
||||
After you have installed, configured, and started NFD, you can demonstrate the features
|
||||
of NDN using the following applications and libraries.
|
||||
|
||||
Sample applications:
|
||||
|
||||
- `Simple examples in ndn-cxx library <https://named-data.net/doc/ndn-cxx/current/examples.html>`_
|
||||
|
||||
If you have installed ndn-cxx from source, you already have compiled these:
|
||||
|
||||
+ examples/producer
|
||||
+ examples/consumer
|
||||
+ examples/consumer-with-timer
|
||||
|
||||
- `Introductory examples of NDN-CCL
|
||||
<https://redmine.named-data.net/projects/application-development-documentation-guides/wiki/Step-By-Step_-_Common_Client_Libraries>`_
|
||||
+ `Simple examples using the ndn-cxx library <https://named-data.net/doc/ndn-cxx/current/examples.html>`__
|
||||
+ `Introductory examples of NDN-CCL
|
||||
<https://redmine.named-data.net/projects/application-development-documentation-guides/wiki/Step-By-Step_-_Common_Client_Libraries>`__
|
||||
|
||||
Real applications and libraries:
|
||||
|
||||
+ `ndn-tools - NDN Essential Tools <https://github.com/named-data/ndn-tools>`_
|
||||
+ `ndn-traffic-generator - Traffic Generator For NDN
|
||||
<https://github.com/named-data/ndn-traffic-generator>`_
|
||||
+ `repo-ng - Next generation of NDN repository <https://github.com/named-data/repo-ng>`_
|
||||
+ `ChronoChat - Multi-user NDN chat application <https://github.com/named-data/ChronoChat>`_
|
||||
+ `ChronoSync - Sync library for multiuser realtime applications for NDN
|
||||
<https://github.com/named-data/ChronoSync>`_
|
||||
+ `ndn-tools - Essential NDN command-line tools <https://github.com/named-data/ndn-tools>`__
|
||||
+ `ndn-traffic-generator - Traffic generator for NDN <https://github.com/named-data/ndn-traffic-generator>`__
|
||||
+ `ChronoSync - Sync library for multi-user real-time applications <https://github.com/named-data/ChronoSync>`__
|
||||
+ `PSync - Partial and full synchronization library <https://github.com/named-data/PSync>`__
|
||||
+13
-18
@@ -1,10 +1,8 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Configuration file for the Sphinx documentation builder.
|
||||
#
|
||||
# This file only contains a selection of the most common options. For a full
|
||||
# list see the documentation:
|
||||
# http://www.sphinx-doc.org/en/master/config
|
||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html
|
||||
|
||||
# -- Path setup --------------------------------------------------------------
|
||||
|
||||
@@ -12,7 +10,7 @@
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
#
|
||||
import os
|
||||
# import os
|
||||
import sys
|
||||
# sys.path.insert(0, os.path.abspath('.'))
|
||||
|
||||
@@ -20,13 +18,13 @@ import sys
|
||||
# -- Project information -----------------------------------------------------
|
||||
|
||||
project = u'Named Data Networking Forwarding Daemon (NFD)'
|
||||
copyright = u'Copyright © 2014-2019 Named Data Networking Project.'
|
||||
copyright = u'Copyright © 2014-2020 Named Data Networking Project.'
|
||||
author = u'Named Data Networking Project'
|
||||
|
||||
# The short X.Y version
|
||||
# The short X.Y version.
|
||||
#version = ''
|
||||
|
||||
# The full version, including alpha/beta/rc tags
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
#release = ''
|
||||
|
||||
# There are two options for replacing |today|: either, you set today to some
|
||||
@@ -40,7 +38,7 @@ today_fmt = '%Y-%m-%d'
|
||||
|
||||
# If your documentation needs a minimal Sphinx version, state it here.
|
||||
#
|
||||
needs_sphinx = '1.1'
|
||||
needs_sphinx = '1.3'
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
@@ -58,12 +56,7 @@ def addExtensionIfExists(extension):
|
||||
sys.stderr.write("Extension '%s' not found. "
|
||||
"Some documentation may not build correctly.\n" % extension)
|
||||
|
||||
if sys.version_info[0] >= 3:
|
||||
addExtensionIfExists('sphinxcontrib.doxylink')
|
||||
|
||||
# sphinxcontrib.googleanalytics is currently not working with the latest version of Sphinx
|
||||
# if os.getenv('GOOGLE_ANALYTICS', None):
|
||||
# addExtensionIfExists('sphinxcontrib.googleanalytics')
|
||||
addExtensionIfExists('sphinxcontrib.doxylink')
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'index'
|
||||
@@ -92,6 +85,12 @@ html_theme_path = ['.']
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['_static']
|
||||
|
||||
html_copy_source = False
|
||||
html_show_sourcelink = False
|
||||
|
||||
# Disable syntax highlighting of code blocks by default.
|
||||
highlight_language = 'none'
|
||||
|
||||
|
||||
# -- Options for LaTeX output ------------------------------------------------
|
||||
|
||||
@@ -156,7 +155,3 @@ doxylink = {
|
||||
extlinks = {
|
||||
'issue': ('https://redmine.named-data.net/issues/%s', 'issue #'),
|
||||
}
|
||||
|
||||
if os.getenv('GOOGLE_ANALYTICS', None):
|
||||
googleanalytics_id = os.environ['GOOGLE_ANALYTICS']
|
||||
googleanalytics_enabled = True
|
||||
@@ -2129,12 +2129,6 @@ EXTERNAL_GROUPS = YES
|
||||
|
||||
EXTERNAL_PAGES = YES
|
||||
|
||||
# The PERL_PATH should be the absolute path and name of the perl script
|
||||
# interpreter (i.e. the result of 'which perl').
|
||||
# The default file (with absolute path) is: /usr/bin/perl.
|
||||
|
||||
PERL_PATH = /usr/bin/perl
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the dot tool
|
||||
#---------------------------------------------------------------------------
|
||||
@@ -2148,15 +2142,6 @@ PERL_PATH = /usr/bin/perl
|
||||
|
||||
CLASS_DIAGRAMS = YES
|
||||
|
||||
# You can define message sequence charts within doxygen comments using the \msc
|
||||
# command. Doxygen will then run the mscgen tool (see:
|
||||
# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
|
||||
# documentation. The MSCGEN_PATH tag allows you to specify the directory where
|
||||
# the mscgen tool resides. If left empty the tool is assumed to be found in the
|
||||
# default search path.
|
||||
|
||||
MSCGEN_PATH =
|
||||
|
||||
# You can include diagrams made with dia in doxygen documentation. Doxygen will
|
||||
# then run dia to produce the diagram and insert it in the documentation. The
|
||||
# DIA_PATH tag allows you to specify the directory where the dia binary resides.
|
||||
|
||||
+18
-18
@@ -1,9 +1,9 @@
|
||||
NFD - Named Data Networking Forwarding Daemon
|
||||
=============================================
|
||||
NFD: Named Data Networking Forwarding Daemon
|
||||
============================================
|
||||
|
||||
NFD is a network forwarder that implements and evolves together with the Named Data
|
||||
Networking (NDN) `protocol <https://named-data.net/doc/ndn-tlv/>`__. NFD is a core
|
||||
component of the `NDN Platform <https://named-data.net/codebase/platform/>`__.
|
||||
**NFD** is a network forwarder that implements and evolves together with the Named Data
|
||||
Networking (NDN) `protocol <https://named-data.net/doc/NDN-packet-spec/current/>`__.
|
||||
NFD is a core component of the `NDN Platform <https://named-data.net/codebase/platform/>`__.
|
||||
|
||||
NFD Documentation
|
||||
-----------------
|
||||
@@ -38,26 +38,26 @@ NFD Documentation
|
||||
|
||||
* :doc:`manpages`
|
||||
|
||||
**Additional documentation**
|
||||
Additional Documentation
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
* `NFD Developer's Guide <https://named-data.net/wp-content/uploads/2016/10/ndn-0021-7-nfd-developer-guide.pdf>`_
|
||||
* `NFD Developer's Guide <https://named-data.net/publications/techreports/ndn-0021-10-nfd-developer-guide/>`__
|
||||
|
||||
A comprehensive guide to the design and implementation of NFD. The developer's guide also contains
|
||||
suggestions and hints for anyone wanting to modify or extend NFD.
|
||||
|
||||
* `NDN Software Contributor's Guide
|
||||
<https://github.com/named-data/NFD/blob/master/CONTRIBUTING.md>`__
|
||||
* `NDN Software Contributor's Guide <https://github.com/named-data/.github/blob/master/CONTRIBUTING.md>`__
|
||||
(guide for newcomers to the NDN community of software)
|
||||
|
||||
* `NFD Wiki <https://redmine.named-data.net/projects/nfd/wiki>`_
|
||||
|
||||
+ `NFD Management protocol <https://redmine.named-data.net/projects/nfd/wiki/Management>`_
|
||||
+ `NFD Configuration file format <https://redmine.named-data.net/projects/nfd/wiki/ConfigFileFormat>`_
|
||||
* `NFD Wiki <https://redmine.named-data.net/projects/nfd/wiki>`__
|
||||
|
||||
The NFD Wiki contains detailed protocol specifications and
|
||||
information for building on unsupported platforms.
|
||||
|
||||
* `API Documentation (doxygen) <doxygen/annotated.html>`_
|
||||
+ `NFD Management protocol <https://redmine.named-data.net/projects/nfd/wiki/Management>`__
|
||||
+ `NFD configuration file format <https://redmine.named-data.net/projects/nfd/wiki/ConfigFileFormat>`__
|
||||
|
||||
* `API Documentation (doxygen) <doxygen/annotated.html>`__
|
||||
|
||||
* :doc:`RELEASE_NOTES`
|
||||
|
||||
@@ -66,7 +66,7 @@ NFD Documentation
|
||||
License
|
||||
-------
|
||||
|
||||
NFD is an open and free software package licensed under GPL 3.0 license and is the
|
||||
centerpiece of our committement to making NDN's core technology open and free to all
|
||||
Internet users and developers. For more information about the licensing details and
|
||||
limitation, refer to `COPYING.md <https://github.com/named-data/NFD/blob/master/COPYING.md>`_.
|
||||
NFD is a free and open-source software package licensed under the GPL version 3 and
|
||||
is the centerpiece of our committement to making NDN's core technology free and open
|
||||
to all Internet users and developers. For more information about licensing, refer to
|
||||
`COPYING.md <https://github.com/named-data/NFD/blob/master/COPYING.md>`__.
|
||||
@@ -3,30 +3,25 @@
|
||||
Local hub prefix discovery
|
||||
==========================
|
||||
|
||||
Some applications need to discover the prefix(es) under which they can publish data
|
||||
/ which Interests the local hub will be able to forward down to the application.
|
||||
In order to discover that, applications need to send an Interest for
|
||||
``/localhop/nfd/rib/routable-prefixes`` prefix. Response data to the
|
||||
Interest contains a list of prefixes and should be encoded as follows:
|
||||
Some applications need to discover the prefix(es) under which they can publish
|
||||
data / which Interests the local hub will be able to forward down to the
|
||||
application. In order to discover that, an application can send an Interest for
|
||||
``/localhop/nfd/rib/routable-prefixes``. The data in response to this Interest
|
||||
will contain a list of prefixes and should be encoded as follows:
|
||||
|
||||
::
|
||||
.. code-block:: abnf
|
||||
|
||||
Response ::= DATA-TYPE TLV-LENGTH
|
||||
Name (= /localhop/nfd/rib/routable-prefixes/[version]/[segment])
|
||||
MetaInfo (= ResponseMetaInfo)
|
||||
Content (= ResponseContent)
|
||||
Signature
|
||||
Response = DATA-TYPE TLV-LENGTH
|
||||
Name ; /localhop/nfd/rib/routable-prefixes/[version]/[segment]
|
||||
MetaInfo ; ContentType == BLOB, FreshnessPeriod == 5000
|
||||
ResponseContent
|
||||
DataSignature
|
||||
|
||||
ResponseMetaInfo ::= META-INFO-TYPE TLV-LENGTH
|
||||
ContentType (= BLOB)
|
||||
FreshnessPeriod (= 5000)
|
||||
ResponseContent = 1*Name
|
||||
|
||||
ResponseContent ::= Name+
|
||||
|
||||
.. note::
|
||||
ResponseContent should contain at least one ``Name``, which should be routable
|
||||
towards the face from which the request has been received. The requester may
|
||||
process the list of returned names and pick whichever it wants to use.
|
||||
``ResponseContent`` should contain at least one ``Name``, which should be routable
|
||||
towards the face from which the request was received. The requester may process
|
||||
the list of returned names and pick whichever it wants to use.
|
||||
|
||||
For now, the ``/localhop/nfd/rib/routable-prefixes`` data is served by
|
||||
:ref:`ndn-autoconfig-server`.
|
||||
@@ -3,12 +3,10 @@
|
||||
ndn-autoconfig-server
|
||||
=====================
|
||||
|
||||
Usage
|
||||
-----
|
||||
Synopsis
|
||||
--------
|
||||
|
||||
::
|
||||
|
||||
ndn-autoconfig-server [-h] [-p <PREFIX>] [-p <PREFIX>] ... <FACEURI>
|
||||
**ndn-autoconfig-server** [**-h**] [**-V**] [**-p** *PREFIX*]... *FACEURI*
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
@@ -3,12 +3,10 @@
|
||||
ndn-autoconfig
|
||||
==============
|
||||
|
||||
Usage
|
||||
-----
|
||||
Synopsis
|
||||
--------
|
||||
|
||||
::
|
||||
|
||||
ndn-autoconfig [options]
|
||||
**ndn-autoconfig** [**-h**] [**-V**] [**-c** *file*] [**-d**]
|
||||
|
||||
Description
|
||||
-----------
|
||||
@@ -24,11 +22,11 @@ Options
|
||||
|
||||
NOTE: if connection to NFD fails, the daemon will be terminated.
|
||||
|
||||
``-c [FILE]`` or ``--config=[FILE]``
|
||||
``-c FILE`` or ``--config=FILE``
|
||||
Use the specified configuration file. If `enabled = true` is not specified in the
|
||||
configuration file, no actions will be performed.
|
||||
|
||||
``--ndn-fch-url=[URL]``
|
||||
``--ndn-fch-url=URL``
|
||||
Use the specified URL to find the closest hub (NDN-FCH protocol). If not specified,
|
||||
``http://ndn-fch.named-data.net/`` will be used. Only ``http://`` URLs are supported.
|
||||
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
nfd-autoreg
|
||||
===========
|
||||
|
||||
Usage
|
||||
-----
|
||||
Synopsis
|
||||
--------
|
||||
|
||||
::
|
||||
|
||||
nfd-autoreg --prefix=</autoreg/prefix> [--prefix=</another/prefix>] ...
|
||||
**nfd-autoreg** --prefix=</autoreg/prefix> [--prefix=</another/prefix>]...
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
Loaded 100 of 203 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user