Compare commits

...
44 Commits
Author SHA1 Message Date
baihe 8bb9a2772a feat(pcon): Support PCONStrategy 2024-01-01 06:23:41 +00:00
Eric Newberry 3dc9fd0b82 Prepare release 0.7.1
refs #5129

Change-Id: Iba2703bdc5153024dbdfcb7e4c043f52964736f9
2020-10-08 16:41:45 -07:00
Davide Pesavento c0c089314b docs: refresh and improve the "named data" sphinx theme
Change-Id: I196c30f84ce4edd5cd10dfe3cab6ea2dc6947815
2020-10-07 13:19:14 -04:00
Davide Pesavento 9f6a7d97bc docs: fix syntax highlighting of code blocks
And various other cleanups

Change-Id: I240badc5358c09f006c2a22d4706ce373f2dd188
2020-10-07 13:18:44 -04:00
Davide Pesavento 0bba81df36 fw: delete spurious assertion in AccessStrategy
Refs: #5127
Change-Id: Ic6d8b098dc29735f800d4c6b1dc40316d4755172
2020-10-06 13:15:34 -04:00
Eric Newberry 2377ada11a fw: handle dropped packets in strategies
refs #5128

Change-Id: Ic7f7e61b2dde66004d0291bb41e008961fc7b252
2020-10-04 21:06:43 -04:00
Davide Pesavento b7e72c3a0a tests: use NullSignature
Change-Id: Icb8ff95905cfa2ba9d9a493d7a60b30a61a8d671
2020-10-02 20:00:03 -04:00
Ashlesh Gawande c1d4837b6f fw: fix PIT entry rejection in MulticastStrategy on receiving same Interest
refs: #5123

Change-Id: Ie0e1ff798313b190618a42b2a78f8b0cc4184097
2020-08-10 18:52:09 -07:00
Davide Pesavento bc0e617e48 ci: disable frames in lcov HTML coverage report
Change-Id: I5dea51551f8011277d49ce78c80d9064580399a1
2020-08-07 21:05:34 -04:00
Davide Pesavento 5bafd2c7c4 tests: fix Face/TestLpFragmenter after Data encoding changes in ndn-cxx
Change-Id: I6f01ca36ba6f5833a9d73ddc777c5fcdadcd7334
2020-07-28 16:16:27 -04:00
Teng Liang 13d582abec face: remove EndpointId from egress APIs in transport
refs: #4973
Change-Id: I43ca0c0826ec132413c584a1daa2d4687a4965fd
2020-07-22 06:18:21 -07:00
Davide Pesavento d82134b850 ci: add Xcode 11.6 and 12 to Travis CI build matrix
Change-Id: I37add5d807b36dbd8dc8e9f3248488ca5d8a46e5
2020-07-01 22:40:16 -04:00
Teng Liang ebc20f6000 fw: remove EndpointId from egress APIs
This commit partially reverts c707948105

refs: #4849, #4973
Change-Id: I1063e5de2c0e3c90971c4ae006ce46de386c2ed0
2020-07-01 21:34:13 -04:00
Eric Newberry fdc0645d77 fw: add test for received Interest with no nonce
refs #4685

Change-Id: I4f81890b34f4453825f7426e5e55c58b234258cd
2020-06-24 12:46:18 -07:00
Junxiao Shi e1cf4ba46a table: prevent integer overflow in pit::FaceRecord
refs #4979

Change-Id: Iacd5abdfc8ae4530364e3fa590778a234140b7ed
2020-06-19 16:40:53 -06:00
Alex Lane 6bead9b6de fw: Add unsolicited data forwarder counter
Change-Id: I47650e270f0305e34fb4ec9713802671ac96a4cb
2020-06-16 13:37:38 -04:00
Teng Liang f3bc3ae906 face: remove EndpointId from egress APIs
This commit partially reverts 075bb7dac4

refs: #4843, #4973

Change-Id: Iab92addff2bd0fa1e24100d43f9f7076ee84a3f8
2020-06-08 22:06:23 -07:00
Alexander Afanasyev a158370ecb Adjust includes for the updated locations of ndn-cxx security headers
Change-Id: I5a94879966de2c166fed8dedda0ed1d65c33c300
2020-06-06 16:30:06 -04:00
Alexander Afanasyev 34b2b57831 Rename VERSION to VERSION.info to avoid conflicts with modern STL
On case-insensitive file systems (e.g., macOS), inclusion of the new
standard <version> header resulted in unexpected inclusion of VERSION
file.

Change-Id: I5be60b42305856f7b45f3a7116c7bf0cb9082ecf
2020-05-30 18:32:34 -04:00
Eric Newberry 1f237abbf1 tests: avoid use of deprecated default SigningInfo
refs #4804

Change-Id: I32db316bbaca89fb92ec4b70568d0ff7fcd3423b
2020-05-29 10:47:47 -07:00
Alexander Afanasyev 3a2339a1b4 face: Connect faces to the parent (unicast) or associated (multicast) channels
Change-Id: Ie7b2e8fb60050a2bc6e4f5ad053c26e121f3c3d5
Refs: #4973
2020-05-29 10:51:02 -04:00
Davide Pesavento 1752159ae0 build: align minimum build dependencies with ndn-cxx
* Recommend boost >= 1.65.1 and gcc >= 7.4.0
 * Require clang >= 4.0, or Xcode >= 9.0 on macOS
 * Silence an ABI-related diagnostic message from gcc on armv7
 * Fix redundant-tags warning with gcc 10
 * Add CentOS-specific instructions to docs/INSTALL.rst
 * Add Xcode 11.5 to Travis CI

Refs: #5087, #5106
Change-Id: I70746729a132ecb07d4788934385bb403039dba9
2020-05-15 14:25:26 -04:00
Eric Newberry 4995bf960d tools: erase all requested entries from CS in nfdc
This change modifies the behavior of nfdc cs
erase to erase up to the requested count of CS
entries, instead of requiring the user to
continually rerun the command to reach the
desired count of erases.

refs #4744

Change-Id: Ia9b6fa2b4f97769fe6fa911a7b0b5c641ce215dc
2020-04-21 15:31:53 -07:00
Eric Newberry c68b2e8a46 fw: add HopLimit to strategy documentation
refs #4806

Change-Id: I4299c17cb3974efccdd908bcd2aea58ab75c12b4
2020-04-16 13:19:17 -07:00
Junxiao Shi c29eb7f50e fw: attach PIT token upon CS hit
refs #5090

Change-Id: I496ec0865dc4b8dfb35efe2be8453eda96a2ea9b
2020-04-14 13:39:15 -07:00
Eric Newberry 9d283adac4 fw: process HopLimit
refs #4806

Change-Id: I20682570409a576a6f35784f34d33ef27bf801cd
2020-04-14 13:29:30 -07:00
Davide Pesavento b93fb6c831 ci: set ASan's detect_invalid_pointer_pairs to 2
Change-Id: Ibc9a4bd447a8ccebbf864c2da6c279ef5e272739
2020-04-13 20:54:43 -04:00
Davide Pesavento 8f290fc884 ci: add CentOS 8 support; drop CentOS 7
Refs: #5040, #5087
Change-Id: I8a52e02801b8e313d1a7531228616526b0f3cc94
2020-04-12 13:20:07 -04:00
Eric Newberry cb27d91658 common: handle negative unsigneds in config
refs #4489

Change-Id: Ibeab0aad9ac95bef1ef2f17178b795cde4a79fea
2020-04-09 21:23:29 -07:00
Alex Lane 9cec699867 fw: Minor bug fixes for timeout sensitivity and ignored probes in ASF
refs #4983, #4193

Change-Id: I2cf9ac9b51be83e8b03dca40221c7e550c4878a1
2020-04-09 20:12:22 -04:00
Eric Newberry d656aff913 tools: create face during nfdc route add
refs #4332

Change-Id: I1a30bf87abd57bab08a2c027870e779392de0104
2020-04-08 20:55:11 -07:00
Eric Newberry 22974904d3 face: use /run/nfd.sock on Linux
refs #5039

Change-Id: I10902725912a8f194ce6da6590378c1029955f80
2020-04-07 19:33:57 -07:00
Davide Pesavento 69857c37c2 build+docs: switch to python3, refresh FAQ and INSTALL documents
Refs: #5095
Change-Id: Icdc0e9463b28c07783edbe392a9bc47136947e3b
2020-04-06 15:32:21 -04:00
Eric Newberry feeb918ea8 face: handle initially non-running Ethernet interfaces
refs #5096

Change-Id: I27cc913cc2478baa8dfaad08e67bd1b9703c43f4
2020-04-01 16:35:24 -07:00
Eric Newberry 13ff259ec8 mgmt+tools: allow MTU overrides on existing faces
refs #5056

Change-Id: I464a0c68773290bf1cfd0bf2afc4344e79fbb614
2020-03-31 17:50:55 -07:00
Eric Newberry cb6551e96f face: allow GenericLinkService to override MTU
refs #5056

Change-Id: I8eb2dd732b1431e0e809deb53792a14be1698ff1
2020-03-29 16:08:06 -07:00
Davide Pesavento 56c68a364a ci: update Travis configuration
* Drop all versions of gcc < 7 and clang < 5
 * Add clang 11 (development branch)
 * Reenable ASan on Linux with clang 7, the upstream bug has been fixed
 * Drop Xcode 9.2 (macOS 10.12 is no longer supported)
 * Upgrade Xcode 11 to 11.3
 * Workaround issue with missing /usr/local/opt/openssl on macOS
 * Various cleanups

Change-Id: Iee54c0d0480b6ff15bb112a49b3a5c49586ac976
2020-03-29 16:45:43 -04:00
Davide Pesavento 51cf75c8f0 fw+table: use Interest::Nonce instead of uint32_t
Change-Id: I2a4b83696db80d2d0b675121da53a73c309e059c
2020-03-11 22:21:13 -04:00
Jongseok Lee 854866f424 rib: fix logic bug in config file validation
Closes: https://github.com/named-data/NFD/pull/9
Change-Id: I3b7c53c475098ec83fd469ceb40a306dfcd80cf3
2020-03-10 20:23:02 -04:00
Eric Newberry 32f7eac7cd face: deduplicate received LpPackets with reliability
refs #5079

Change-Id: I19ad959ba736253a750997fa468d419c93425686
2020-02-20 15:23:25 -08:00
Eric Newberry 5ab4cf83d9 face: add logging to LpReliability
refs #5080

Change-Id: I2dce3f9d933273cb65603c7cd2177c5d142f4487
2020-02-09 22:06:58 -08:00
Eric Newberry f3ee808927 face: support runtime MTU changes on Ethernet faces
refs #3257

Change-Id: I160fe444b889b8f7be19022a2bd52bbc9f7a21aa
2020-02-09 14:34:00 -08:00
Eric Newberry 97f26a2618 docs: restructure and update AUTHORS.md
refs #5078

Change-Id: Iefa1c730cd83e2965bf92ef6598eb092c4de48f7
2020-01-30 17:13:10 -08:00
Davide Pesavento e89118e8be build: upgrade waf to version 2.0.19
Change-Id: I513db4ba8a12a269deca378e0ab77c7946b3dd63
2020-01-13 21:52:03 -05:00
203 changed files with 4849 additions and 3900 deletions

No files matched your search

+1 -1
View File
@@ -26,4 +26,4 @@ __pycache__/
*.py[cod]
# Other
/VERSION
/VERSION.info
+6 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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 -7
View File
@@ -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
View File
@@ -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.
+2
View File
@@ -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
View File
@@ -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
-30
View File
@@ -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
+34 -23
View File
@@ -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
View File
@@ -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
View File
@@ -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).
+6 -5
View File
@@ -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
View File
@@ -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 {
+4 -2
View File
@@ -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>() +
+13 -17
View File
@@ -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()) {
+2 -2
View File
@@ -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
+3 -3
View File
@@ -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__);
+6 -3
View File
@@ -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] {
+7 -4
View File
@@ -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;
}
+12 -4
View File
@@ -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__);
+4 -3
View File
@@ -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
+7 -1
View File
@@ -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.
+2 -2
View File
@@ -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)
+10 -3
View File
@@ -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
View File
@@ -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
{
+55 -34
View File
@@ -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>()) {
+40 -31
View File
@@ -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;
+2 -2
View File
@@ -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);
+2 -2
View File
@@ -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();
+8 -8
View File
@@ -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);
}
+27 -18
View File
@@ -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&
+89 -17
View File
@@ -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
+10 -4
View File
@@ -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
+2 -2
View File
@@ -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__);
+2 -2
View File
@@ -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;
+4 -4
View File
@@ -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
{
}
+2 -2
View File
@@ -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
{
}
};
+3 -3
View File
@@ -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__);
+2 -1
View File
@@ -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); });
+19 -5
View File
@@ -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
{
+3 -19
View File
@@ -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
{
+7 -2
View File
@@ -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); });
+11 -4
View File
@@ -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;
}
+3 -10
View File
@@ -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");
+2 -3
View File
@@ -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
+3 -11
View File
@@ -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");
+2 -3
View File
@@ -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
+2 -1
View File
@@ -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; });
+7 -2
View File
@@ -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;
+2 -1
View File
@@ -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;
+2 -2
View File
@@ -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__);
+2 -2
View File
@@ -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();
+174
View File
@@ -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);
}
}
}
}
+150
View File
@@ -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
+15 -13
View File
@@ -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);
}
+2 -4
View File
@@ -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
+2 -2
View File
@@ -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;
+5 -5
View File
@@ -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
View File
@@ -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);
}
+4 -6
View File
@@ -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;
+2 -2
View File
@@ -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 -3
View File
@@ -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
{
+15 -14
View File
@@ -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 -3
View File
@@ -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>
+4 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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);
+115
View File
@@ -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
+7 -15
View File
@@ -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);
}
+2 -4
View File
@@ -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>
+5 -5
View File
@@ -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;
}
}
+2 -4
View File
@@ -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
{
+4 -4
View File
@@ -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
+4 -5
View File
@@ -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
+3 -5
View File
@@ -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>
+23 -17
View File
@@ -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 {
+3 -5
View File
@@ -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
View File
@@ -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
View File
@@ -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.
*/
+26 -26
View File
@@ -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;
}
+3 -10
View File
@@ -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
+25 -10
View File
@@ -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;
+5 -5
View File
@@ -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
View File
@@ -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);
}
+7 -6
View File
@@ -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
+5 -5
View File
@@ -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,
+5 -4
View File
@@ -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;
}
+3 -3
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
-15
View File
@@ -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
View File
@@ -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>`__.
+15 -20
View File
@@ -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 -5
View File
@@ -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
-----------
+5 -7
View File
@@ -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.
+3 -5
View File
@@ -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