Compare commits

..
4 Commits
Author SHA1 Message Date
baihe a4eb0fb1b6 fix: Disable rate limit in compare scenario 2024-01-20 07:04:42 +00:00
root 1a792daaa3 feat(qsccp): Add QSCCP strategy 2023-12-18 12:49:43 +08:00
SunnyQjm 34e13e9802 fix: Do calculateRate by trigger not by scheduler 2023-12-15 14:55:20 +00:00
SunnyQjm 3813f1c9ee feat: Add qsccp sched 2023-12-03 21:08:06 +08:00
526 changed files with 12507 additions and 8710 deletions

No files matched your search

-69
View File
@@ -1,69 +0,0 @@
name: CI
on:
push:
paths-ignore:
- 'docs/**'
- '*.md'
- '.mailmap'
workflow_dispatch:
permissions:
contents: read
jobs:
linux:
name: ${{ matrix.compiler }} on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-20.04]
compiler: [g++-7, g++-8, g++-9, g++-10,
clang++-7, clang++-8, clang++-9, clang++-10, clang++-11, clang++-12]
include:
- os: ubuntu-22.04
compiler: g++-11
- os: ubuntu-22.04
compiler: g++-12
- os: ubuntu-22.04
compiler: clang++-13
- os: ubuntu-22.04
compiler: clang++-14
env:
CXX: ${{ matrix.compiler }}
steps:
- name: Install C++ compiler
run: |
sudo apt-get -qy install ${CXX/clang++/clang}
${CXX} --version
- name: Checkout
uses: actions/checkout@v3
with:
submodules: true
- name: Build and test
run: ./.jenkins
macos:
name: Xcode ${{ matrix.xcode }} on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [macos-11]
xcode: ['12.4', '12.5', '13.2']
include:
- os: macos-12
xcode: '13.4'
- os: macos-12
xcode: '14.2'
steps:
- name: Set up Xcode
uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: ${{ matrix.xcode }}
- name: Checkout
uses: actions/checkout@v3
with:
submodules: true
- name: Build and test
run: ./.jenkins
-37
View File
@@ -1,37 +0,0 @@
name: Docs
on:
push:
paths-ignore:
- '*.md'
- '.mailmap'
workflow_dispatch:
permissions:
contents: read
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [macos-latest, ubuntu-latest]
env:
JOB_NAME: Docs
steps:
- name: Checkout
uses: actions/checkout@v3
with:
submodules: true
- name: Install dependencies
run: |
find .jenkins.d/ -type f -name '[1-9]*.sh' -exec chmod -x '{}' +
./.jenkins
- name: Build documentation
run: |
pybindir=$(python3 -c 'import sysconfig; print(sysconfig.get_path("scripts", "posix_user"))')
export PATH="${pybindir}${PATH:+:}${PATH}"
./waf --color=yes configure
./waf --color=yes build --targets=version.hpp
./waf --color=yes build --targets=manpages
./waf --color=yes docs
+16 -33
View File
@@ -1,49 +1,32 @@
#!/usr/bin/env bash
set -eo pipefail
case $(uname) in
Linux)
if [[ -e /etc/os-release ]]; then
source /etc/os-release
else
source /usr/lib/os-release
fi
export ID VERSION_ID
export ID_LIKE="${ID} ${ID_LIKE} linux"
export PATH="${HOME}/.local/bin${PATH:+:}${PATH}"
;;
Darwin)
# Emulate a subset of os-release(5)
export ID=macos
export VERSION_ID=$(sw_vers -productVersion)
export PATH="/usr/local/bin${PATH:+:}${PATH}"
if [[ -x /opt/homebrew/bin/brew ]]; then
eval "$(/opt/homebrew/bin/brew shellenv)"
elif [[ -x /usr/local/bin/brew ]]; then
eval "$(/usr/local/bin/brew shellenv)"
fi
;;
esac
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
if [[ $JOB_NAME == *"code-coverage" ]]; then
export DISABLE_ASAN=yes
export DISABLE_HEADERS_CHECK=yes
fi
nanos() {
# Cannot use date(1) because macOS does not support %N format specifier
python3 -c 'import time; print(int(time.time() * 1e9))'
}
for file in .jenkins.d/*; do
[[ -f $file && -x $file ]] || continue
if [[ -n $GITHUB_ACTIONS ]]; then
if [[ -n $TRAVIS ]]; then
label=$(basename "$file" | sed -E 's/[[:digit:]]+-(.*)\..*/\1/')
echo "::group::${label}"
echo -ne "travis_fold:start:${label}\r"
echo -ne "travis_time:start:${label}\r"
start=$(nanos)
fi
echo "\$ $file"
"$file"
if [[ -n $GITHUB_ACTIONS ]]; then
echo "::endgroup::"
if [[ -n $TRAVIS ]]; then
finish=$(nanos)
echo -ne "travis_time:end:${label}:start=${start},finish=${finish},duration=$((finish-start)),event=${label}\r"
echo -ne "travis_fold:end:${label}\r"
fi
done
+34 -33
View File
@@ -1,40 +1,41 @@
#!/usr/bin/env bash
set -eo pipefail
set -ex
APT_PKGS=(build-essential pkg-config python3-minimal
libboost-all-dev libssl-dev libsqlite3-dev
libpcap-dev libsystemd-dev)
FORMULAE=(boost openssl pkg-config)
PIP_PKGS=()
case $JOB_NAME in
*code-coverage)
APT_PKGS+=(lcov python3-pip)
PIP_PKGS+=('gcovr~=5.2')
;;
*Docs)
APT_PKGS+=(doxygen graphviz python3-pip)
FORMULAE+=(doxygen graphviz)
PIP_PKGS+=(sphinx sphinxcontrib-doxylink)
;;
esac
set -x
if [[ $ID == macos ]]; then
if [[ -n $GITHUB_ACTIONS ]]; then
export HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1
if has OSX $NODE_LABELS; then
FORMULAE=(boost openssl pkg-config)
if has OSX-10.13 $NODE_LABELS || has OSX-10.14 $NODE_LABELS; then
FORMULAE+=(python)
fi
brew update
brew install --formula "${FORMULAE[@]}"
elif [[ $ID_LIKE == *debian* ]]; 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 "${APT_PKGS[@]}"
elif [[ $ID_LIKE == *fedora* ]]; then
sudo dnf -y install gcc-c++ libasan lld pkgconf-pkg-config python3 \
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
fi
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
if (( ${#PIP_PKGS[@]} )); then
pip3 install --user --upgrade --upgrade-strategy=eager "${PIP_PKGS[@]}"
fi
+13 -8
View File
@@ -1,11 +1,11 @@
#!/usr/bin/env bash
set -exo pipefail
set -ex
pushd "$CACHE_DIR" >/dev/null
INSTALLED_VERSION=
if [[ $ID == macos ]]; then
BOOST=$(brew list --formula --versions boost)
if has OSX $NODE_LABELS; then
BOOST=$(brew ls --versions boost)
OLD_BOOST=$(cat boost.txt || :)
if [[ $OLD_BOOST != $BOOST ]]; then
echo "$BOOST" > boost.txt
@@ -35,16 +35,21 @@ sudo rm -f /usr/local/lib{,64}/pkgconfig/libndn-cxx.pc
pushd ndn-cxx >/dev/null
./waf --color=yes configure --without-osx-keychain
./waf --color=yes build
sudo ./waf --color=yes install
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 [[ $ID_LIKE == *fedora* ]]; then
if has CentOS-8 $NODE_LABELS; then
sudo tee /etc/ld.so.conf.d/ndn.conf >/dev/null <<< /usr/local/lib64
fi
if [[ $ID_LIKE == *linux* ]]; then
if has Linux $NODE_LABELS; then
sudo ldconfig
fi
+10 -8
View File
@@ -1,5 +1,8 @@
#!/usr/bin/env bash
set -eo pipefail
set -ex
git submodule sync
git submodule update --init
if [[ -z $DISABLE_ASAN ]]; then
ASAN="--with-sanitizer=address"
@@ -7,23 +10,22 @@ fi
if [[ $JOB_NAME == *"code-coverage" ]]; then
COVERAGE="--with-coverage"
fi
if [[ -n $DISABLE_PCH ]]; then
if has CentOS-8 $NODE_LABELS; then
# https://bugzilla.redhat.com/show_bug.cgi?id=1721553
PCH="--without-pch"
fi
set -x
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
./waf --color=yes build -j$WAF_JOBS
# 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
./waf --color=yes build -j$WAF_JOBS
# Cleanup
./waf --color=yes distclean
@@ -31,9 +33,9 @@ fi
# Build in debug mode with tests
./waf --color=yes configure --debug --with-tests $ASAN $COVERAGE $PCH
./waf --color=yes build
./waf --color=yes build -j$WAF_JOBS
# (tests will be run against the debug version)
# Install
sudo ./waf --color=yes install
sudo_preserve_env PATH -- ./waf --color=yes install
+13 -10
View File
@@ -1,5 +1,14 @@
#!/usr/bin/env bash
set -eo pipefail
set -ex
# Prepare environment
rm -rf ~/.ndn
if has OSX $NODE_LABELS; then
security unlock-keychain -p named-data
fi
ndnsec-keygen "/tmp/jenkins/$NODE_NAME" | ndnsec-install-cert -
# https://github.com/google/sanitizers/wiki/AddressSanitizerFlags
ASAN_OPTIONS="color=always"
@@ -13,7 +22,6 @@ ASAN_OPTIONS+=":detect_leaks=0"
ASAN_OPTIONS+=":strip_path_prefix=${PWD}/"
export ASAN_OPTIONS
# https://www.boost.org/doc/libs/release/libs/test/doc/html/boost_test/runtime_config/summary.html
export BOOST_TEST_BUILD_INFO=1
export BOOST_TEST_COLOR_OUTPUT=1
export BOOST_TEST_DETECT_MEMORY_LEAK=0
@@ -22,11 +30,6 @@ ut_log_args() {
echo --logger=HRF,test_suite,stdout:XML,all,build/xunit-log${1:+-$1}.xml
}
set -x
# Prepare environment
rm -rf ~/.ndn
# First run all tests as unprivileged user
./build/unit-tests-core $(ut_log_args core)
./build/unit-tests-daemon $(ut_log_args daemon)
@@ -34,9 +37,9 @@ rm -rf ~/.ndn
./build/unit-tests-tools $(ut_log_args tools)
# Then use sudo to run those tests that need superuser powers
sudo --preserve-env=ASAN_OPTIONS,BOOST_TEST_COLOR_OUTPUT \
sudo_preserve_env ASAN_OPTIONS BOOST_TEST_COLOR_OUTPUT -- \
./build/unit-tests-daemon -t TestPrivilegeHelper $(ut_log_args daemon-privilege-helper)
sudo --preserve-env=ASAN_OPTIONS,BOOST_TEST_COLOR_OUTPUT \
sudo_preserve_env ASAN_OPTIONS BOOST_TEST_COLOR_OUTPUT -- \
./build/unit-tests-daemon -t Face/*Ethernet* $(ut_log_args daemon-ethernet)
sudo --preserve-env=ASAN_OPTIONS,BOOST_TEST_COLOR_OUTPUT \
sudo_preserve_env ASAN_OPTIONS BOOST_TEST_COLOR_OUTPUT -- \
./build/unit-tests-daemon -t Face/TestUdpFactory $(ut_log_args daemon-udp)
+18 -15
View File
@@ -1,32 +1,35 @@
#!/usr/bin/env bash
set -exo pipefail
set -ex
if [[ $JOB_NAME == *"code-coverage" ]]; then
# Generate an XML report (Cobertura format) and a detailed HTML report using gcovr
# Note: trailing slashes are important in the paths below. Do not remove them!
gcovr --object-directory build \
--exclude tests/ \
--exclude websocketpp/ \
--exclude-throw-branches \
--exclude-unreachable-branches \
--cobertura build/coverage.xml \
--html-details build/gcovr/ \
--print-summary
gcovr --object-directory=build \
--output=build/coverage.xml \
--exclude="$PWD/(tests|websocketpp)" \
--root=. \
--xml
# Generate a detailed HTML report using lcov
# Generate also a detailed HTML output, but using lcov (better results)
lcov --quiet \
--capture \
--directory . \
--exclude "$PWD/tests/*" \
--exclude "$PWD/websocketpp/*" \
--no-external \
--rc lcov_branch_coverage=1 \
--output-file build/coverage-with-tests-and-websocketpp.info
lcov --quiet \
--remove build/coverage-with-tests-and-websocketpp.info "$PWD/websocketpp/*" \
--rc lcov_branch_coverage=1 \
--output-file build/coverage-with-tests.info
lcov --quiet \
--remove build/coverage-with-tests.info "$PWD/tests/*" \
--rc lcov_branch_coverage=1 \
--output-file build/coverage.info
genhtml --branch-coverage \
--demangle-cpp \
--legend \
--output-directory build/lcov \
--output-directory build/coverage \
--title "NFD unit tests" \
build/coverage.info
fi
+16 -24
View File
@@ -1,36 +1,28 @@
# Continuous Integration Scripts
# CONTINUOUS INTEGRATION SCRIPTS
## Environment Variables
## Environment Variables Used in Build Scripts
- `ID`: lower-case string that identifies the operating system, for example: `ID=ubuntu`,
`ID=centos`. See [os-release(5)] for more information. On macOS, where `os-release` is
not available, we emulate it by setting `ID=macos`.
- `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.
- `ID_LIKE`: space-separated list of operating system identifiers that are closely related
to the running OS. See [os-release(5)] for more information. The listed values are used
by the CI scripts to select the proper behavior for different platforms and OS flavors.
The list should normally contain `[OS_TYPE]`, `[DISTRO_TYPE]`, and `[DISTRO_VERSION]`.
Examples:
Example values:
- On CentOS, `ID_LIKE="centos rhel fedora linux"`
- On Ubuntu, `ID_LIKE="ubuntu debian linux"`
- `[OS_TYPE]`: `Linux`, `OSX`
- `[DISTRO_TYPE]`: `Ubuntu`, `CentOS`
- `[DISTRO_VERSION]`: `Ubuntu-16.04`, `Ubuntu-18.04`, `CentOS-8`, `OSX-10.14`, `OSX-10.15`
- `VERSION_ID`: identifies the operating system version, excluding any release code names.
See [os-release(5)] for more information. Examples: `VERSION_ID=42`, `VERSION_ID=22.04`.
- `JOB_NAME`: optional variable that defines the type of build job. Depending on the job type,
the build scripts can perform different tasks.
- `JOB_NAME`: defines the type of the current CI job. Depending on the job type, the CI
scripts can perform different tasks.
Supported values:
Possible values:
- empty: default build task
- `code-coverage`: debug build with tests and code coverage analysis
- `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`: directory containing cached files from previous builds, e.g., a compiled
version of ndn-cxx. 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.
- `DISABLE_ASAN`: disable building with AddressSanitizer. This is automatically set for
the `code-coverage` job type.
[os-release(5)]: https://www.freedesktop.org/software/systemd/man/os-release.html
- `WAF_JOBS`: number of parallel build threads used by waf, defaults to 1.
+39
View File
@@ -0,0 +1,39 @@
has() {
local saved_xtrace
[[ $- == *x* ]] && saved_xtrace=-x || saved_xtrace=+x
set +x
local p=$1
shift
local i ret=1
for i in "$@"; do
if [[ "${i}" == "${p}" ]]; then
ret=0
break
fi
done
set ${saved_xtrace}
return ${ret}
}
export -f has
sudo_preserve_env() {
local saved_xtrace
[[ $- == *x* ]] && saved_xtrace=-x || saved_xtrace=+x
set +x
local vars=()
while [[ $# -gt 0 ]]; do
local arg=$1
shift
case ${arg} in
--) break ;;
*) vars+=("${arg}=${!arg}") ;;
esac
done
set ${saved_xtrace}
sudo env "${vars[@]}" "$@"
}
export -f sudo_preserve_env
+115
View File
@@ -0,0 +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:
- COMPILER=g++-7
- COMPILER=g++-9
- COMPILER=clang++-6.0
- COMPILER=clang++-9
jobs:
include:
# 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
# macOS
- os: osx
osx_image: xcode9.4
env: # default compiler
- os: osx
osx_image: xcode10.1
env: # default compiler
- os: osx
osx_image: xcode10.3
env: # default compiler
- os: osx
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=g++-5
- env: COMPILER=g++-6
- env: COMPILER=clang++-4.0
- env: COMPILER=clang++-12
fast_finish: true
before_install:
- |
: Adding apt repositories
case ${COMPILER} in
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++-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%-12} main"
travis_retry sudo apt-get -qq update
;;
esac
install:
- |
: Installing C++ compiler
if [[ -n ${COMPILER} ]]; then
travis_retry sudo apt-get -qy install ${COMPILER/clang++/clang}
fi
before_script:
- |
: 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
script:
- ./.jenkins
+2 -2
View File
@@ -54,8 +54,8 @@ from waflib import Utils, Logs, Errors
from waflib.Configure import conf
from waflib.TaskGen import feature, after_method
BOOST_LIBS = ['/usr/lib', '/usr/local/lib', '/opt/homebrew/lib', '/opt/local/lib', '/sw/lib', '/lib']
BOOST_INCLUDES = ['/usr/include', '/usr/local/include', '/opt/homebrew/include', '/opt/local/include', '/sw/include']
BOOST_LIBS = ['/usr/lib', '/usr/local/lib', '/opt/local/lib', '/sw/lib', '/lib']
BOOST_INCLUDES = ['/usr/include', '/usr/local/include', '/opt/local/include', '/sw/include']
BOOST_VERSION_FILE = 'boost/version.hpp'
BOOST_VERSION_CODE = '''
+24 -20
View File
@@ -16,24 +16,23 @@ def configure(conf):
errmsg = ''
warnmsg = ''
if cxx == 'gcc':
if ccver < (7, 4, 0):
if ccver < (5, 3, 0):
errmsg = ('The version of gcc you are using is too old.\n'
'The minimum supported gcc version is 7.4.')
'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 Utils.unversioned_sys_platform() == 'darwin':
if ccver < (10, 0, 0):
errmsg = ('The version of Xcode you are using is too old.\n'
'The minimum supported Xcode version is 11.3.')
elif ccver < (11, 0, 0):
warnmsg = ('Using a version of Xcode older than 11.3 is not '
'officially supported and may result in build failures.')
elif ccver < (6, 0, 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 6.0.')
'The minimum supported clang version is 4.0.')
conf.flags = ClangFlags()
else:
warnmsg = f'{cxx} compiler is unsupported'
warnmsg = '%s compiler is unsupported' % cxx
conf.flags = CompilerFlags()
if errmsg:
@@ -136,8 +135,10 @@ class GccBasicFlags(CompilerFlags):
"""
def getGeneralFlags(self, conf):
flags = super(GccBasicFlags, self).getGeneralFlags(conf)
flags['CXXFLAGS'] += ['-std=c++17']
if Utils.unversioned_sys_platform() != 'darwin':
flags['CXXFLAGS'] += ['-std=c++14']
if Utils.unversioned_sys_platform() == 'linux':
flags['LINKFLAGS'] += ['-fuse-ld=gold']
elif Utils.unversioned_sys_platform() == 'freebsd':
flags['LINKFLAGS'] += ['-fuse-ld=lld']
return flags
@@ -145,9 +146,9 @@ class GccBasicFlags(CompilerFlags):
flags = super(GccBasicFlags, self).getDebugFlags(conf)
flags['CXXFLAGS'] += ['-Og',
'-g3',
'-pedantic',
'-Wall',
'-Wextra',
'-Wpedantic',
'-Werror',
'-Wcatch-value=2',
'-Wextra-semi',
@@ -163,9 +164,9 @@ class GccBasicFlags(CompilerFlags):
flags = super(GccBasicFlags, self).getOptimizedFlags(conf)
flags['CXXFLAGS'] += ['-O2',
'-g',
'-pedantic',
'-Wall',
'-Wextra',
'-Wpedantic',
'-Wcatch-value=2',
'-Wextra-semi',
'-Wnon-virtual-dtor',
@@ -180,7 +181,7 @@ class GccFlags(GccBasicFlags):
flags['CXXFLAGS'] += ['-fdiagnostics-color',
'-Wredundant-tags',
]
if platform.machine() == 'armv7l':
if platform.machine() == 'armv7l' and self.getCompilerVersion(conf) >= (7, 1, 0):
flags['CXXFLAGS'] += ['-Wno-psabi'] # Bug #5106
return flags
@@ -189,7 +190,7 @@ class GccFlags(GccBasicFlags):
flags['CXXFLAGS'] += ['-fdiagnostics-color',
'-Wredundant-tags',
]
if platform.machine() == 'armv7l':
if platform.machine() == 'armv7l' and self.getCompilerVersion(conf) >= (7, 1, 0):
flags['CXXFLAGS'] += ['-Wno-psabi'] # Bug #5106
return flags
@@ -198,8 +199,7 @@ class ClangFlags(GccBasicFlags):
flags = super(ClangFlags, self).getGeneralFlags(conf)
if Utils.unversioned_sys_platform() == 'darwin':
# Bug #4296
brewdir = '/opt/homebrew' if platform.machine() == 'arm64' else '/usr/local'
flags['CXXFLAGS'] += [['-isystem', f'{brewdir}/include'], # for Homebrew
flags['CXXFLAGS'] += [['-isystem', '/usr/local/include'], # for Homebrew
['-isystem', '/opt/local/include']] # for MacPorts
elif Utils.unversioned_sys_platform() == 'freebsd':
# Bug #4790
@@ -212,6 +212,8 @@ class ClangFlags(GccBasicFlags):
'-Wundefined-func-template',
'-Wno-unused-local-typedef', # Bugs #2657 and #3209
]
if self.getCompilerVersion(conf) < (6, 0, 0):
flags['CXXFLAGS'] += ['-Wno-missing-braces'] # Bug #4721
return flags
def getOptimizedFlags(self, conf):
@@ -220,4 +222,6 @@ class ClangFlags(GccBasicFlags):
'-Wundefined-func-template',
'-Wno-unused-local-typedef', # Bugs #2657 and #3209
]
if self.getCompilerVersion(conf) < (6, 0, 0):
flags['CXXFLAGS'] += ['-Wno-missing-braces'] # Bug #4721
return flags
+1 -1
View File
@@ -53,10 +53,10 @@ def checkWebsocket(self, **kw):
self.end_msg('.'.join(self.env.WEBSOCKET_VERSION))
self.env.append_unique('DEFINES', ['_WEBSOCKETPP_CPP11_STL_'])
self.env.INCLUDES_WEBSOCKET = websocketDir.parent.abspath()
self.env.HAVE_WEBSOCKET = True
self.define('HAVE_WEBSOCKET', 1)
self.define('_WEBSOCKETPP_CPP11_STL_', 1)
except Errors.WafError as error:
if isMandatory:
+5 -5
View File
@@ -1,12 +1,12 @@
# NFD Authors
The following lists maintainers, primary developers, and all much-appreciated contributors to NFD in alphabetical order.
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>.
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 Obaid Amin <http://obaidamin.weebly.com>
* 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>
@@ -31,7 +31,7 @@ If you would like to become a contributor to the official repository, please fol
* Eric Newberry <https://ericnewberry.com>
* Ju Pan <https://cs-jupan.com>
* João Pereira <http://website.jpereira.co.uk>
* ***(Maintainer)*** Davide Pesavento <https://github.com/Pesa>
* 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>
@@ -55,7 +55,7 @@ If you would like to become a contributor to the official repository, please fol
* Patrick Crowley <https://www.arl.wustl.edu/~pcrowley>
* Christos Papadopoulos <https://www.cs.colostate.edu/~christos>
* Giovanni Pau <https://www.unibo.it/sitoweb/giovanni.pau/en>
* 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>
-17
View File
@@ -1,17 +0,0 @@
cff-version: 1.2.0
message: If you use NFD in your research, please cite it as below.
license: GPL-3.0-or-later
repository-code: "https://github.com/named-data/NFD"
title: Named Data Networking Forwarding Daemon
url: "https://named-data.net/doc/NFD/"
preferred-citation:
authors:
- name: Named Data Networking Project Team
date-published: "2021-07-30"
journal: NDN Technical Report NDN-0021
month: 7
title: NFD Developer's Guide
type: generic
url: "https://named-data.net/publications/techreports/ndn-0021-11-nfd-guide/"
version: 11
year: 2021
+81
View File
@@ -0,0 +1,81 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our
project and our community a harassment-free experience for everyone,
regardless of age, body size, disability, ethnicity, gender identity
and expression, level of experience, nationality, personal appearance,
race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive
environment include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual
attention or advances
* Trolling, insulting/derogatory comments, and personal or political
attacks
* Public or private harassment
* Publishing others' private information, such as a physical or
electronic address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in
a professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of
acceptable behavior and are expected to take appropriate and fair
corrective action in response to any instances of unacceptable
behavior.
Project maintainers have the right and responsibility to remove, edit,
or reject comments, commits, code, wiki edits, issues, and other
contributions that are not aligned to this Code of Conduct, or to ban
temporarily or permanently any contributor for other behaviors that
they deem inappropriate, threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public
spaces when an individual is representing the project or its
community. Examples of representing a project or community include
using an official project e-mail address, posting via an official
social media account, or acting as an appointed representative at an
online or offline event. Representation of a project may be further
defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior
may be reported by contacting the project leaders Lixia Zhang,
Beichuan Zhang, or Alex Afanasyev
at
[lixia@cs.ucla.edu](mailto:lixia@cs.ucla.edu),
[bzhang@cs.arizona.edu](mailto:bzhang@cs.arizona.edu),
and [aa@cs.ucla.edu](mailto:aa@cs.ucla.edu). All complaints will be
reviewed and investigated and will result in a response that is deemed
necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of
an incident. Further details of specific enforcement policies may be
posted separately.
Project maintainers who do not follow or enforce the Code of Conduct
in good faith may face temporary or permanent repercussions as
determined by other members of the project's leadership.
## Attribution
This Code of Conduct is adapted from
the [Contributor Covenant](http://contributor-covenant.org), version 1.4, available
at [http://contributor-covenant.org/version/1/4](http://contributor-covenant.org/version/1/4/)
+489
View File
@@ -0,0 +1,489 @@
# Contributing to the NDN Codebase
## Getting Started
The NDN team is very glad you are interested in contributing! The NDN
(Named Data Networking) codebase is composed of many projects, with
multiple universities across the world contributing. This
documentation will help you understand how we work and what we expect
from contributors.
### Code of Conduct
NDN codebase development adheres to the Contributor Covenant, located
in `CODE_OF_CONDUCT.md`. By contributing, you are expected to also
adhere to this code. If you feel someone has breached this code of
conduct,
please
[email us](mailto:lixia@cs.ucla.edu,bzhang@cs.arizona.edu,aa@cs.ucla.edu).
### What can I do?
The NDN codebase continually needs help with, among other
things:
1. Implementing new features
2. Writing fixes for bugs
3. Writing documentation for features that have recently changed or
that change quickly. Sometimes people forget to update
documentation!
4. Code review
## Finding Documentation
The NDN team maintains a community
([Redmine site](https://redmine.named-data.net/projects/nfd)) for
issue tracking and documentation hosting. Redmine is the hub for
design activity. In particular, all design discussion and decisions
will either occur or be copied there.
**Why did they do it *this* way?** When writing code, if you ever have
questions about why some design decision was made, the best approach
is to use `git blame` on a file to inspect the last commit for some
line of code. In this view there will be a commit hash in hex
(e.g. `0ab12e3a`) in the first column. Using our example, `git show
0ab12e3a` would show the commit made for that line. In the commit view
there should be a reference number (e.g. `refs: #1234`). Using this
number, you can find a pertaining issue on the Redmine
(e.g., `https://redmine.named-data.net/issues/1234`).
Additionally, in some cases there are published papers you can read in
order to gain a better understanding of the project. Searching for
these papers is not difficult; in many cases you can find a pertaining
paper or technical report listed on
[the main NDN website](https://named-data.net/publications).
Usually the title of a project will be a good keyword.
If you cannot find an answer to your question, the best place to go is
the
[mailing lists](https://named-data.net/codebase/platform/support/mailing-lists/).
There are multiple different lists for different interests, so be sure you
are mailing the right list for a quick response.
## Tracking work on Redmine ##
As mentioned above, Redmine is the organizational hub of the NDN
projects. As such, extensive use of it is made, and learning how it
works will help you. In particular, there is a workflow associated
with Redmine. Generally it is:
1. An issue is reported by someone. At this point they should
describe the issue, including relationships to other
issues. Unless they know what they're doing, they should leave
particulars blank. Such particulars are priority, target version,
assignees, and categories.
2. Design discussion about the issue occurs, and the issue is either
accepted or rejected.
3. Someone either is assigned to, or assigns themselves to work on the
issue, setting the status to "In progress."
**Note:** You must be a "Developer" of the project before you are
able to toggle the Status field. A user should contact a project
manager to be granted Developer privilege. Project managers can be
found on "Overview" page of the project.
4. After every useful chunk of progress, notes are made on the issue
and the progress percentage is updated to reflect this. Remember
that notes are actually Markdown, so it is advised to use the
'preview' button to ensure your note looks right.
5. The changes are uploaded to Gerrit for review. Once all changes
pertaining to an issue are on Gerrit, an issues status should
change to "Code review."
6. Once all changes are cleared for merging, they either can be
merged, or held for feedback, at which point the issue status
should become "Feedback."
7. After all changes have been merged, the issue should be set to
"Closed."
Redmine provides other facilities for managing your work on NDN
projects, too, such as time logging and time estimation.
## Contributing Guidelines
### Repositories ###
All NDN projects are hosted on GitHub, at various organizations, using git
for version control:
- [Main NDN codebase](https://github.com/named-data)
- [NDN codebase for mobile platforms](https://github.com/named-data-mobile)
- [NDN codebase for IoT](https://github.com/named-data-iot)
- [ndnSIM codebase](https://github.com/named-data-ndnSIM)
- [Other NDN codebase (REMAP)](https://github.com/remap)
If you are unfamiliar with git, some kind
of [tutorial on git](https://git-scm.com/book/en/v1/Getting-Started)
should be your first step.
There is also a [Git game](http://learngitbranching.js.org/index.html)
you can play. Finally, there is a
[wiki page](https://redmine.named-data.net/projects/nfd/wiki#Development-process)
on NFD's Redmine that has more useful links.
There are a lot of different projects, so take some time to look
through them for ones that pertain to your interests. NDN projects
use [Gerrit](https://gerrit.named-data.net/) for code review purposes.
Occasionally there will be other repositories used privately to test
changes, but this is uncommon. In general, you will not need to refer
to these repositories.
### Style ###
Most NDN projects are written in C++, and there is a
[style guide](https://named-data.net/doc/ndn-cxx/current/code-style.html).
In general the NDN style is similar to the GNU style, but there are
some significant changes. This style guide is not exhaustive, and in
all cases not covered by the guide you should emulate the current
style of the project.
There is a
[partial styleguide](https://redmine.named-data.net/projects/nfd/wiki/CodeStyle)
for Python. It applies many of the provisions from the C++ guide, in
addition to some other Python-specific things.
Some NDN projects are written in JavaScript, and there is a [style guide](https://named-data.net/codebase/platform/documentation/ndn-platform-development-guidelines/cpp-code-guidelines/) for that language, too.
#### Commit Messages ####
Commit messages are very important, as they are usually the first
thing (besides the changelog file) a developer looks at when trying to
understand the timeline of a project. Commit messages should:
- Have a short, descriptive first line, starting with the module
they change. A good rule of thumb is a maximum length of 65
characters.
- If including a body, leave a blank line between the first line and
the rest, and ensure that each line is no longer than 72 characters.
- Include Redmine issue numbers. The exact syntax is given below.
- Be written in an imperative mood. E.g. `"Make foo a bar"` and not
`"Foo is now a bar"`
- Use the present tense. E.g. `"Make foo a bar"` and not `"Made foo a
bar"`
To explain, the anatomy of a typical commit message is like this:
docs: write contributing guide and code of conduct
This commit adds a guide that may be useful for new-comers to NDN in
becoming productive contributors. This commit also adds a code of
conduct.
refs: #3898
Change-Id: Ife89360305027dba9020f0b298793c1121ae1fd6c
Explaining this:
- `docs` is the module that the commit affects. We want this because
it lets someone know at a glance what part of the project it
changes. For some projects, there will be only one module or only
very small other modules. This practice should be observed in
those cases, too.
- `#3898` is the Redmine issue number. Gerrit transforms these into
clickable links, and it is useful to reviewers to gain background
understanding of the issue. You can have multiple by separating
them with commas.
- `Change-Id` should be filled automatically. It is used by Gerrit
to track changes.
### Unit Tests ###
With a few exceptions, every patch needs to have unit tests that
accompany them. For C++, we use
the [Boost unit test framework](http://www.boost.org/libs/test) to
help us out. Note that this link points to the newest version of the
Boost Test library documentation, and you may need to refer to older
documentation if you are using an older version of Boost. More
information on this is available in
the
[NFD Dev Guide](https://named-data.net/publications/techreports/ndn-0021-7-nfd-developer-guide/)
When designing and writing tests, a few things need to be kept in mind:
1. Unit tests are **design** tools, *not* debug tools. Just because
your code passes some unit tests does not mean it is
bug-free. Unit tests are tools to convince you that your code does
what you think it does.
2. It can be difficult to know when you should test something. If
you find that you are having a hard time designing a test for
something, ask yourself whether it is because it doesn't make
sense to test what you've just written, or if it's because the way
you designed it makes it difficult to test. Consider a second look
at your design if you think it's the second one.
3. The method that gave the world unit tests says that unit tests
should be written *before* the code they test. This is
a contentious issue, so writing them either before or after is
acceptable. If writing them later, keep the tests in mind when
writing the code, and it will help design good interfaces.
4. At the very least, write the test for a completed module/unit of
code before moving on. Doing this will ensure that the test gets
written, and will help you think about the interface that you need
to examine. If you don't, you may forget exactly what each piece
is responsible for when you're looking at the whole system
afterward.
5. Separate your I/O, as it is very hard to test, so I/O should be
isolated if possible. Consider something like separating a
function that invokes I/O into two functions: one that does the
I/O and calls the other one, which takes that I/O result. This
will make it easier to test that second function than if they were
combined.
Writing unit tests using the Boost framework is quite simple, and you
can refer to existing unit tests for examples.
([This is a good example.](https://github.com/named-data/NFD/blob/master/tests/rib/rib.t.cpp))
#### Building and running unit tests ####
This is mentioned in greater depth in
the [developer's readme](README-dev.md), but the basic procedure is:
1. In the base directory of the project, run `./waf distclean`. This
removes all prior build files.
2. Run `./waf configure --with-tests`. This configures the next build
to also build the tests.
3. Run `./waf`. This will build the tests.
4. Then, the unit tests will be in the `build` directory, and will be
named `unit-tests-<module name`, e.g. `unit-tests-nlsr` or
`unit-tests-rib`. To run just one test suite, run
`./unit-tests-exampleModule -t ExampleTestSuite`. To run a
specific test in a suite, use `./unit-tests-exampleModule -t
ExampleTestSuite/ExampleTestCase`.
## Gerrit: Uploading Patches and Code Review ##
As mentioned above, NDN projects
use [Gerrit](https://gerrit.named-data.net/) for code review. This is
a web-hosted, open code review platform that allows for interactive
code review, rebasing, and cross-linking with the Redmine, and a
developer interacts with it using the familiar git. For issues that
require a tracker reference, a particularly useful feature is that
the `refs: #...` becomes a clickable link to the issue for design
discussion.
### First-time Setup ###
The first-time Gerrit setup goes like this:
1. Log in to Gerrit. You can authenticate using many different
methods, including GitHub OAuth. You need to ensure that you have a Gerrit username:
1. Log in.
2. Click on your name in the top right corner and click "Settings" in the pop-up box.
3. In the `Username` box, check for a name. If there's already one there, great.
4. If not, type one in, and this will be used in later steps.
2. Set up your Gerrit credentials. This will depend on how you
configured your Gerrit remote in step 1. Among other things, you
need to set up identities so that the email on your Gerrit profile
matches whatever email you will be committing with on your git
repo.
**Note:** We only support using
[SSH access to Gerrit](https://gerrit.named-data.net/Documentation/user-upload.html#ssh).
This shows what the identities panel looks like. If you do
not see the email here that you have configured git to use, you
cannot upload to Gerrit.
![Web page showing what the "identities" panel looks like](./docs/images/gerrit-credentials-blurred.png)
In that case, add it under contact information panel.
![Web page showing what the "contact information" panel looks like](./docs/images/gerrit-email.png).
Gerrit itself has
[extensive documentation](https://gerrit.named-data.net/Documentation/error-messages.html)
regarding error messages, and this identity-based one is by far the most
common. This is the
[documentation for an identity error.](https://gerrit.named-data.net/Documentation/error-invalid-author.html)
3. Clone the source for a project from Gerrit.
1. While logged in to Gerrit, there will be a link in the top-left
area, `Projects`.
2. From this project view, click on the `Clone with commit-msg
hook` tab.
3. Click on the `ssh` tab to select cloning over SSH. **Note:**
This will require setting up SSH access to Gerrit first.
4. Copy-and-paste the `git clone ...` command into your terminal
to fetch the project source.
After this, your remotes will be set up correctly, and pushing to
Gerrit will only require `git push origin HEAD:refs/for/master` after
committing work. This section has some
[git tips and tricks to type less][type-less].
### Uploading patches ###
Most patches should have a corresponding Redmine issue that they can
reference. If you search the Redmine and notice there is no relevant
issue for a patch you are writing, please create an issue first. You
will need a Redmine account, which can be created there.
After writing some changes, commit them locally as normal. After
saving and exiting your editor, the commit hook will insert a unique
`Change-Id` to the message.
Once you have a commit message you are happy with, simply run `git
push HEAD:refs/for/master`.
**Note:** Gerrit separates commits into patch sets by the unique
`Change-Id`s. As a result, you must either:
* Squash your various commits into one with `git rebase -i
<initial commit>`, ensuring that the ultimate `Change-Id` in the
commit is the one on the patch set on Gerrit. This workflow is
generally preferred.
* Amend your commit with any new changes using `git commit --amend`.
If you do not do this, what will happen is that each commit will be
interpreted by Gerrit as a separate patch set. This is probably not
what you want.
### Code Review ###
#### Dealing with Code Review ####
It is important to remember that code review is about improving
the quality of code contributed, and nothing else. Further, code
review is highly important, as every line of code that's
committed comes with a burden of maintenance. Code review helps
minimize the burden of that maintenance. Consider that when you
are receiving comments, those comments are influenced by two
things:
- How the reviewer personally feels about the change ("Would I
be happy to see this code in a year?" or "Would I be happy if
I wrote this?") and
- How the reviewer feels the change abides by style and usage
requirements ("I may not personally mind, but we have to do it
this way.")
Remembering these things when reading comments helps to separate
what can feel like needless negativity.
#### Doing Code Review and Writing Comments ####
**Code review is *extremely* important!** We need every bit of code
review you can give. In many cases this is the bottleneck for
new contributors who do not fully understand how certain
language constructs should be used, what best practices are,
etc. In these cases it is important to give constructive
feedback.
Writing comments is somewhat counter-intuitive on Gerrit. If you are
signed in through a modern browser, you can leave a comment in a file
either by clicking on the line number, by selecting some text you want
to comment and pressing 'c', or by clicking on someone else's
comment. After typing, click the `Save` button there. After navigating
through the patch set with the arrows at the top-right of the Gerrit
UI, you then must click the up-arrow to get back to the Change
screen. **At this point your comments have *not* been made yet!** You
must then click the `Reply...` button, and assign a score. If you
correctly saved your comments, they will be shown at the bottom of
that box. Once you click post, the comments will be made public to
others.
Minimally, a review *must* include:
- A score (usually -1, 0, or +1)
- An "itemized" commentary on each objection you have, or a
justification for a whole-change objection.
Optimally, a review should include:
- A useful explanation of *why* you object to some item. This is
more important than it first appears. Consider that although
you may have been writing code since before you could count,
not everyone has. Some things may not be obvious to others,
and sharing your knowledge is key to making an open-source
project work.
- Comments about good design decisions. These help motivate
developers when otherwise a review is entirely negative
comments.
#### Expediting the Code Review Process ####
If you observe that code review takes a long time, there are a
few things that you can do to to expedite the process:
1. **Think about language best practices.**
2. **Ask yourself how you would feel about this code, if you saw it "in the wild."**
3. **When making code decisions, ask yourself "why *shouldn't* I do it this way?"**
#### Responding to Code Review ####
There are a few things to remember when responding to code review, including:
- **Don't** click "Done" on a comment if you agree with a comment and
are updating the code accordingly. These comments are essentially
useless and only clutter the discussion. Gerrit has a convenient
mechanism to check the differences between two patch sets, so
reviewers are expected to check that their comments have been
addressed.
- **Don't** blindly follow what is suggested. Review is just that: a
review. Sometimes what is suggested is functionally equivalent to
what you have implemented. Other times, the reviewer has not
considered something when writing their review, and their
suggestion will not work. Lastly, if you disagree with a suggestion
for some other reason, feel free to object, but you may be asked to
provide an explanation.
- **How** to reply. To reply to a comment, click on the comment in
the Gerrit interface, type your reply, and then press save. After
replying, you **must remember** to go to the main patch set change
screen, and press `Reply...`. Your comments will be shown as
drafts, and you must click `Post` to make them visible to others.
### Jenkins ###
As a supplement to the code review process, every patch set is automatically
compiled and tested on multiple platforms
using [our instance of Jenkins](http://jenkins.named-data.net/), the
continuous integration system. Interacting with Jenkins is not usually
necessary, as Jenkins automatically picks up new patch sets and posts
the results. Typically the only interaction needed with Jenkins is
when some kind of glitch occurs and a build needs to be retriggered.
It is expected that code is checked locally. Reviewers may wait until
Jenkins checks the code before doing a more functional review of the
code. Since Jenkins checks can take a while, you can save some time by
checking yourself first.
### Gerrit Change-Id Commit Hook ###
If you encounter an error like this when trying to push work:
remote: ERROR: [4311462] missing Change-Id in commit message footer
remote:
remote: Hint: To automatically insert Change-Id, install the hook:
remote: gitdir=$(git rev-parse --git-dir); scp -p -P 29418 someuser@gerrit.named-data.net:hooks/commit-msg ${gitdir}/hooks/
remote: And then amend the commit:
remote: git commit --amend
Then your commit hook has not been set up correctly, somehow. Follow
the instructions in the terminal to resolve this.
### Code Style Robot ###
As part of CI, there is a script that checks every patch uploaded to
Gerrit for code style consistency. Checking these kinds of things is
notoriously difficult, and while the robot is very good in general, it
will occasionally report false positives and miss things. So all
issues it raises should be inspected manually to ensure they really
are style problems. Further, since this automated check is not
perfect, you should take steps (e.g., configure your editor or run a
linter before you commit) to ensure you adhere to code style rules.
### <a name="type-less"></a> Typing Less to Upload Patches to Gerrit ###
If typing `HEAD:refs/for/master` feels
repetitive, you have a few options:
* You can configure git to do the work for you, as described
in [this blog post](https://yoursunny.com/t/2017/NFD-devbox/#Uploading-to-Gerrit)
* Git has an alias system that you can use to specify certain
commands. For example, you can use `git config --global alias.pg
"push origin HEAD:refs/for/master"` to make `git pg` push to
Gerrit. [Learn about git aliases here.](https://githowto.com/aliases)
* If using Linux or macOS, it is relatively simple to create a shell
alias: `alias gs="git status"` for example, or `alias gitpush="git
push origin HEAD:refs/for/master`. The alias itself must be one
word, but it can represent multiple words. To persist your
aliases, they need to go in your environment file, which is
generally at `~/.bashrc` or `~/.zshrc` or `~/.profile`. The exact
syntax of aliases and the environment variables file will vary by
shell. You should be careful not to overuse aliases, however.
[type-less]: #type-less
+6 -5
View File
@@ -9,10 +9,10 @@ NFD relies on third-party software, licensed under the following licenses:
- The Boost libraries are licensed under the
[Boost Software License 1.0](https://www.boost.org/users/license.html)
- CityHash is licensed under the
- CityHash is licensed under a
[MIT license](https://github.com/google/cityhash/blob/master/COPYING)
- Libpcap is licensed under the
- Libpcap is licensed under a
[3-clause BSD license](https://github.com/the-tcpdump-group/libpcap/blob/master/LICENSE)
- The WebSocket++ library is licensed under the terms of the
@@ -21,10 +21,11 @@ NFD relies on third-party software, licensed under the following licenses:
- The waf build system is licensed under the terms of the
[BSD license](https://github.com/named-data/NFD/blob/master/waf)
The GPL license is provided below in this file. For more information about
these licenses, see <https://www.gnu.org/licenses/>
--------------------------------------------------------------------------------
The GPL license is provided below in this file. For more information about
these licenses, see https://www.gnu.org/licenses/
----------------------------------------------------------------------------------
### GNU GENERAL PUBLIC LICENSE
+4 -11
View File
@@ -1,15 +1,8 @@
<div align="center">
# NFD - Named Data Networking Forwarding Daemon
[<img alt height="70" src="docs/named_data_theme/static/ndn-logo.svg"/>](https://named-data.net/)
# NFD: Named Data Networking Forwarding Daemon
</div>
[![CI](https://github.com/named-data/NFD/actions/workflows/ci.yml/badge.svg)](https://github.com/named-data/NFD/actions/workflows/ci.yml)
[![Docs](https://github.com/named-data/NFD/actions/workflows/docs.yml/badge.svg)](https://github.com/named-data/NFD/actions/workflows/docs.yml)
![Language](https://img.shields.io/badge/C%2B%2B-17-blue)
![Latest version](https://img.shields.io/github/v/tag/named-data/NFD?label=Latest%20version)
![Language](https://img.shields.io/badge/C%2B%2B-14-blue.svg)
[![Build Status](https://travis-ci.org/named-data/NFD.svg?branch=master)](https://travis-ci.org/named-data/NFD)
![Latest Version](https://img.shields.io/github/tag/named-data/NFD.svg?color=darkkhaki&label=latest%20version)
## Overview
+1
View File
@@ -0,0 +1 @@
docs/release-notes-latest.rst
+58
View File
@@ -0,0 +1,58 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2014-2015, 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/>.
*/
#ifndef NFD_CORE_ALGORITHM_HPP
#define NFD_CORE_ALGORITHM_HPP
#include "common.hpp"
#include <boost/concept/requires.hpp>
namespace nfd {
/** \brief finds the last element satisfying a predicate
* \tparam It BidirectionalIterator
* \tparam Pred UnaryPredicate
*
* \return Iterator to the last element satisfying the condition,
* or \p last if no such element is found.
*
* Complexity: at most \p last-first invocations of \p p
*/
template<typename It, typename Pred>
BOOST_CONCEPT_REQUIRES(
((boost::BidirectionalIterator<It>))
((boost::UnaryPredicate<Pred, typename std::iterator_traits<It>::value_type>)),
(It)
)
find_last_if(It first, It last, Pred p)
{
std::reverse_iterator<It> firstR(first), lastR(last);
auto found = std::find_if(lastR, firstR, p);
return found == firstR ? last : std::prev(found.base());
}
} // namespace nfd
#endif // NFD_CORE_ALGORITHM_HPP
+28 -20
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, 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,20 +28,20 @@
#include "core/config.hpp"
#ifdef NFD_WITH_TESTS
#define NFD_VIRTUAL_WITH_TESTS virtual
#define NFD_PUBLIC_WITH_TESTS_ELSE_PROTECTED public
#define NFD_PUBLIC_WITH_TESTS_ELSE_PRIVATE public
#define NFD_PROTECTED_WITH_TESTS_ELSE_PRIVATE protected
#define NFD_OVERRIDE_WITH_TESTS_ELSE_FINAL override
#define NFD_FINAL_UNLESS_WITH_TESTS
#ifdef WITH_TESTS
#define VIRTUAL_WITH_TESTS virtual
#define PUBLIC_WITH_TESTS_ELSE_PROTECTED public
#define PUBLIC_WITH_TESTS_ELSE_PRIVATE public
#define PROTECTED_WITH_TESTS_ELSE_PRIVATE protected
#define OVERRIDE_WITH_TESTS_ELSE_FINAL override
#define FINAL_UNLESS_WITH_TESTS
#else
#define NFD_VIRTUAL_WITH_TESTS
#define NFD_PUBLIC_WITH_TESTS_ELSE_PROTECTED protected
#define NFD_PUBLIC_WITH_TESTS_ELSE_PRIVATE private
#define NFD_PROTECTED_WITH_TESTS_ELSE_PRIVATE private
#define NFD_OVERRIDE_WITH_TESTS_ELSE_FINAL final
#define NFD_FINAL_UNLESS_WITH_TESTS final
#define VIRTUAL_WITH_TESTS
#define PUBLIC_WITH_TESTS_ELSE_PROTECTED protected
#define PUBLIC_WITH_TESTS_ELSE_PRIVATE private
#define PROTECTED_WITH_TESTS_ELSE_PRIVATE private
#define OVERRIDE_WITH_TESTS_ELSE_FINAL final
#define FINAL_UNLESS_WITH_TESTS final
#endif
#include <cstddef>
@@ -50,15 +50,17 @@
#include <limits>
#include <map>
#include <memory>
#include <optional>
#include <set>
#include <stdexcept>
#include <string>
#include <string_view>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
#include <ndn-cxx/data.hpp>
#include <ndn-cxx/delegation.hpp>
#include <ndn-cxx/delegation-list.hpp>
#include <ndn-cxx/interest.hpp>
#include <ndn-cxx/name.hpp>
#include <ndn-cxx/encoding/block.hpp>
@@ -68,11 +70,13 @@
#include <ndn-cxx/util/exception.hpp>
#include <ndn-cxx/util/scheduler.hpp>
#include <ndn-cxx/util/signal.hpp>
#include <ndn-cxx/util/span.hpp>
#include <ndn-cxx/util/time.hpp>
#include <boost/asio.hpp>
#include <boost/assert.hpp>
#include <boost/core/noncopyable.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/property_tree/ptree.hpp>
namespace nfd {
@@ -90,14 +94,18 @@ using std::static_pointer_cast;
using std::dynamic_pointer_cast;
using std::const_pointer_cast;
using namespace std::string_literals;
using namespace std::string_view_literals;
using std::bind;
using ndn::span;
using namespace std::string_literals;
using ndn::optional;
using ndn::nullopt;
using ndn::to_string;
using ndn::Block;
using ndn::Data;
using ndn::Delegation;
using ndn::DelegationList;
using ndn::FaceUri;
using ndn::Interest;
using ndn::Name;
+2 -6
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, Regents of the University of California,
* Copyright (c) 2014-2018, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -25,13 +25,9 @@
#include "network.hpp"
#include <boost/lexical_cast.hpp>
#include <boost/utility/value_init.hpp>
#include <algorithm>
#include <cctype>
#include <istream>
#include <ostream>
namespace nfd {
@@ -63,7 +59,7 @@ Network::getMaxRangeV6()
}
bool
Network::isValidCidr(std::string_view cidr)
Network::isValidCidr(const std::string& cidr)
{
auto pos = cidr.find('/');
if (pos == std::string::npos) {
+4 -5
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, Regents of the University of California,
/**
* Copyright (c) 2014-2016, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -26,8 +26,7 @@
#ifndef NFD_CORE_NETWORK_HPP
#define NFD_CORE_NETWORK_HPP
#include <boost/asio/ip/address.hpp>
#include <string_view>
#include "common.hpp"
namespace nfd {
@@ -52,7 +51,7 @@ public:
getMaxRangeV6();
static bool
isValidCidr(std::string_view cidr);
isValidCidr(const std::string& cidr);
bool
operator==(const Network& rhs) const
+12 -16
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, Regents of the University of California,
* Copyright (c) 2014-2019, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -26,16 +26,14 @@
#ifndef NFD_CORE_VERSION_HPP
#define NFD_CORE_VERSION_HPP
// The NFD version follows the approach of Calendar Versioning (https://calver.org/)
// based on the year and month of the release, followed by an optional "patch" number,
// i.e., `YY.0M[.MICRO]` using CalVer notation.
// NFD version follows Semantic Versioning 2.0.0
// https://semver.org/spec/v2.0.0.html
//
// To change version number, modify the VERSION variable in the top-level wscript.
// To change version number, modify VERSION variable in top-level wscript.
/**
* \brief NFD version represented as an integer.
/** \brief NFD version represented as an integer.
*
* Equivalent to: #NFD_VERSION_MAJOR*1000000 + #NFD_VERSION_MINOR*1000 + #NFD_VERSION_PATCH
* Equivalent to: `#NFD_VERSION_MAJOR*1000000 + #NFD_VERSION_MINOR*1000 + #NFD_VERSION_PATCH`
*/
#define NFD_VERSION @VERSION@
@@ -46,8 +44,7 @@
/// The patch version of NFD
#define NFD_VERSION_PATCH @VERSION_PATCH@
/**
* \brief NFD version represented as a string.
/** \brief NFD version represented as a string.
*
* Format:
* @code
@@ -56,21 +53,20 @@
*/
extern const char NFD_VERSION_STRING[];
/**
* \brief NFD version string, including git commit information if NFD is build from a
* specific git commit.
/** \brief NFD version string, including git commit information, if NFD is build from
* specific git commit.
*
* #NFD_VERSION_BUILD_STRING is obtained using the following command (`NFD-` prefix is
* afterwards removed): ``git describe --match 'NFD-*'``
* afterwards removed): `git describe --match 'NFD-*'`
*
* When NFD is not built from git, #NFD_VERSION_BUILD_STRING equals #NFD_VERSION_STRING.
*
* Format:
* @code
* MAJOR.MINOR(.PATCH)(-release-candidate-tag)(-(number-of-commits-since-tag)-COMMIT-HASH)
* MAJOR.MINOR.PATCH(-release-candidate-tag)(-(number-of-commits-since-tag)-COMMIT-HASH)
* @endcode
*
* Example: 2022.02-1-g5c86570
* Example: 0.1.0-rc1-1-g5c86570
*/
extern const char NFD_VERSION_BUILD_STRING[];
+4 -4
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, Regents of the University of California,
* Copyright (c) 2014-2019, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -32,8 +32,8 @@
namespace nfd {
ConfigFile::ConfigFile(UnknownConfigSectionHandler callback)
: m_unknownSectionCallback(std::move(callback))
ConfigFile::ConfigFile(UnknownConfigSectionHandler unknownSectionCallback)
: m_unknownSectionCallback(unknownSectionCallback)
{
}
@@ -77,7 +77,7 @@ void
ConfigFile::addSectionHandler(const std::string& sectionName,
ConfigSectionHandler subscriber)
{
m_subscriptions[sectionName] = std::move(subscriber);
m_subscriptions[sectionName] = subscriber;
}
void
+12 -34
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, 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,32 +32,27 @@
namespace nfd {
/**
* \brief A configuration file section.
/** \brief a config file section
*/
using ConfigSection = boost::property_tree::ptree;
/**
* \brief An optional configuration file section.
/** \brief an optional config file section
*/
using OptionalConfigSection = boost::optional<const ConfigSection&>;
/**
* \brief Callback to process a configuration file section.
/** \brief callback to process a config file section
*/
using ConfigSectionHandler = std::function<void(const ConfigSection& section, bool isDryRun,
const std::string& filename)>;
/**
* \brief Callback to process a configuration file section without a #ConfigSectionHandler.
/** \brief callback to process a config file section without a \p ConfigSectionHandler
*/
using UnknownConfigSectionHandler = std::function<void(const std::string& filename,
const std::string& sectionName,
const ConfigSection& section,
bool isDryRun)>;
/**
* \brief Configuration file parsing utility.
/** \brief configuration file parsing utility
*/
class ConfigFile : noncopyable
{
@@ -85,7 +80,7 @@ public: // unknown section handlers
bool isDryRun);
public: // parse helpers
/** \brief Parse a config option that can be either "yes" or "no".
/** \brief parse a config option that can be either "yes" or "no"
* \retval true "yes"
* \retval false "no"
* \throw Error the value is neither "yes" nor "no"
@@ -100,7 +95,7 @@ public: // parse helpers
}
/**
* \brief Parse a numeric (integral or floating point) config option.
* \brief parse a numeric (integral or floating point) config option
* \tparam T an arithmetic type
*
* \return the numeric value of the parsed option
@@ -110,9 +105,9 @@ public: // parse helpers
static T
parseNumber(const ConfigSection& node, const std::string& key, const std::string& sectionName)
{
static_assert(std::is_arithmetic_v<T>);
static_assert(std::is_arithmetic<T>::value, "T must be an arithmetic type");
auto value = node.get_value_optional<T>();
boost::optional<T> value = node.get_value_optional<T>();
// 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)) {
@@ -122,32 +117,15 @@ public: // parse helpers
"' for option '" + key + "' in section '" + sectionName + "'"));
}
template<typename T>
template <typename T>
static T
parseNumber(const ConfigSection::value_type& option, const std::string& sectionName)
{
return parseNumber<T>(option.second, option.first, sectionName);
}
/**
* \brief Check that a value is within the inclusive range [min, max].
* \throw Error the value is out of the acceptable range
*/
template<typename T>
static void
checkRange(T value, T min, T max, const std::string& key, const std::string& sectionName)
{
static_assert(std::is_integral_v<T>);
if (value < min || value > max) {
NDN_THROW(Error("Invalid value '" + to_string(value) + "' for option '" + key +
"' in section '" + sectionName + "': out of acceptable range [" +
to_string(min) + ", " + to_string(max) + "]"));
}
}
public: // setup and parsing
/// \brief Setup notification of configuration file sections.
/// \brief setup notification of configuration file sections
void
addSectionHandler(const std::string& sectionName,
ConfigSectionHandler subscriber);
+12 -15
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, Regents of the University of California,
* Copyright (c) 2014-2019, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -30,27 +30,24 @@
namespace nfd {
/**
* \brief Represents a counter that encloses an integer value.
/** \brief represents a counter that encloses an integer value
*
* SimpleCounter is noncopyable, because increment should be called on the counter,
* not a copy of it; it's implicitly convertible to an integral type to be observed.
* SimpleCounter is noncopyable, because increment should be called on the counter,
* not a copy of it; it's implicitly convertible to an integral type to be observed
*/
class SimpleCounter : noncopyable
{
public:
typedef uint64_t rep;
/**
* \brief Observe the counter's value.
/** \brief observe the counter
*/
operator rep() const noexcept
{
return m_value;
}
/**
* \brief Replace the counter's value.
/** \brief replace the counter value
*/
void
set(rep value) noexcept
@@ -62,14 +59,14 @@ protected:
rep m_value = 0;
};
/** \brief Represents a counter of number of packets.
/** \brief represents a counter of number of packets
*
* \warning The counter value may wrap after exceeding the range of underlying integer type.
*/
class PacketCounter : public SimpleCounter
{
public:
/** \brief Increment the counter by one.
/** \brief increment the counter by one
*/
PacketCounter&
operator++() noexcept
@@ -80,14 +77,14 @@ public:
// postfix ++ operator is not provided because it's not needed
};
/** \brief Represents a counter of number of bytes.
/** \brief represents a counter of number of bytes
*
* \warning The counter value may wrap after exceeding the range of underlying integer type.
*/
class ByteCounter : public SimpleCounter
{
public:
/** \brief Increase the counter.
/** \brief increase the counter
*/
ByteCounter&
operator+=(rep n) noexcept
@@ -97,7 +94,7 @@ public:
}
};
/** \brief Provides a counter that observes the size of a table.
/** \brief provides a counter that observes the size of a table
* \tparam T a type that provides a size() const member function
*
* if table not specified in constructor, it can be added later by invoking observe()
@@ -120,7 +117,7 @@ public:
m_table = table;
}
/** \brief Observe the counter.
/** \brief observe the counter
*/
operator Rep() const
{
+2 -2
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2021, Regents of the University of California,
* Copyright (c) 2014-2019, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -50,7 +50,7 @@ getScheduler()
return *g_scheduler;
}
#ifdef NFD_WITH_TESTS
#ifdef WITH_TESTS
void
resetGlobalIoService()
{
+2 -4
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022 Regents of the University of California,
* Copyright (c) 2014-2019 Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -27,8 +27,6 @@
#include "core/common.hpp"
#include <boost/asio/io_service.hpp>
namespace nfd {
/** \brief Returns the global io_service instance for the calling thread.
@@ -63,7 +61,7 @@ runOnMainIoService(const std::function<void()>& f);
void
runOnRibIoService(const std::function<void()>& f);
#ifdef NFD_WITH_TESTS
#ifdef WITH_TESTS
/** \brief Destroy the global io_service instance.
*
* It will be recreated at the next invocation of getGlobalIoService().
+9 -9
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2021, 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,18 +33,18 @@ namespace nfd {
NFD_LOG_INIT(PrivilegeHelper);
#ifdef NFD_HAVE_PRIVILEGE_DROP_AND_ELEVATE
#ifdef HAVE_PRIVILEGE_DROP_AND_ELEVATE
uid_t PrivilegeHelper::s_normalUid = ::geteuid();
gid_t PrivilegeHelper::s_normalGid = ::getegid();
uid_t PrivilegeHelper::s_privilegedUid = ::geteuid();
gid_t PrivilegeHelper::s_privilegedGid = ::getegid();
#endif // NFD_HAVE_PRIVILEGE_DROP_AND_ELEVATE
#endif // HAVE_PRIVILEGE_DROP_AND_ELEVATE
void
PrivilegeHelper::initialize(const std::string& userName, const std::string& groupName)
{
#ifdef NFD_HAVE_PRIVILEGE_DROP_AND_ELEVATE
#ifdef HAVE_PRIVILEGE_DROP_AND_ELEVATE
static const size_t MAX_GROUP_BUFFER_SIZE = 16384; // 16 KiB
static const size_t MAX_PASSWD_BUFFER_SIZE = 16384;
@@ -111,13 +111,13 @@ PrivilegeHelper::initialize(const std::string& userName, const std::string& grou
if (!userName.empty() || !groupName.empty()) {
throw Error("Dropping and raising privileges is not supported on this platform");
}
#endif // NFD_HAVE_PRIVILEGE_DROP_AND_ELEVATE
#endif // HAVE_PRIVILEGE_DROP_AND_ELEVATE
}
void
PrivilegeHelper::drop()
{
#ifdef NFD_HAVE_PRIVILEGE_DROP_AND_ELEVATE
#ifdef HAVE_PRIVILEGE_DROP_AND_ELEVATE
if (::geteuid() == s_normalUid && ::getegid() == s_normalGid)
return;
@@ -132,13 +132,13 @@ PrivilegeHelper::drop()
NFD_LOG_INFO("dropped to effective uid=" << ::geteuid() << " gid=" << ::getegid());
#else
NFD_LOG_WARN("Dropping privileges is not supported on this platform");
#endif // NFD_HAVE_PRIVILEGE_DROP_AND_ELEVATE
#endif // HAVE_PRIVILEGE_DROP_AND_ELEVATE
}
void
PrivilegeHelper::raise()
{
#ifdef NFD_HAVE_PRIVILEGE_DROP_AND_ELEVATE
#ifdef HAVE_PRIVILEGE_DROP_AND_ELEVATE
if (::geteuid() == s_privilegedUid && ::getegid() == s_privilegedGid)
return;
@@ -153,7 +153,7 @@ PrivilegeHelper::raise()
NFD_LOG_INFO("elevated to effective uid=" << ::geteuid() << " gid=" << ::getegid());
#else
NFD_LOG_WARN("Elevating privileges is not supported on this platform");
#endif // NFD_HAVE_PRIVILEGE_DROP_AND_ELEVATE
#endif // HAVE_PRIVILEGE_DROP_AND_ELEVATE
}
} // namespace nfd
+9 -11
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, Regents of the University of California,
* Copyright (c) 2014-2019, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -35,12 +35,10 @@ namespace nfd {
class PrivilegeHelper
{
public:
/**
* \brief Indicates a serious seteuid/setegid failure.
/** \brief represents a serious seteuid/gid failure
*
* This should only be caught by main as part of a graceful program termination.
*
* \note This is not an std::exception and NDN_THROW should not be used.
* This should only be caught by main as part of a graceful program termination.
* \note This is not an std::exception and NDN_THROW should not be used.
*/
class Error
{
@@ -73,7 +71,7 @@ public:
{
raise();
try {
std::invoke(std::forward<F>(f));
f();
}
catch (...) {
drop();
@@ -82,18 +80,18 @@ public:
drop();
}
NFD_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
PUBLIC_WITH_TESTS_ELSE_PRIVATE:
static void
raise();
NFD_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
#ifdef NFD_HAVE_PRIVILEGE_DROP_AND_ELEVATE
PUBLIC_WITH_TESTS_ELSE_PRIVATE:
#ifdef HAVE_PRIVILEGE_DROP_AND_ELEVATE
static uid_t s_normalUid;
static gid_t s_normalGid;
static uid_t s_privilegedUid;
static gid_t s_privilegedGid;
#endif // NFD_HAVE_PRIVILEGE_DROP_AND_ELEVATE
#endif // HAVE_PRIVILEGE_DROP_AND_ELEVATE
};
} // namespace nfd
+62
View File
@@ -0,0 +1,62 @@
#include "TokenBucket.hpp"
#include "common/global.hpp"
#include "common/logger.hpp"
#include <iostream>
#include <functional>
namespace nfd {
namespace face {
NFD_LOG_INIT(QSCCPTokenBucket);
TokenBucket::TokenBucket(uint64_t rateLimit, uint64_t bucketSize, const std::string& name): rateLimit(rateLimit), bucketSize(bucketSize), name(name) {
this->eachStep = this->rateLimit / 250.0;
this->currentTokenSize = 0;
this->isStart = false;
// NFD_LOG_DEBUG("Create tokenBucket: " << name << ", eachStep: " << this->eachStep << ", rateLimit: " << this->rateLimit);
}
void TokenBucket::start() {
if (this->isStart) {
return;
}
// 每 4ms 增加一次令牌
getScheduler().schedule(time::milliseconds(4), std::bind(&TokenBucket::generateToken, this));
}
void TokenBucket::generateToken() {
// NFD_LOG_DEBUG(this->name << "=> do generateToken => " << this->currentTokenSize);
if (this->currentTokenSize + this->eachStep > this->bucketSize) {
this->currentTokenSize = this->bucketSize;
} else {
this->currentTokenSize += this->eachStep;
}
getScheduler().schedule(time::milliseconds(4), std::bind(&TokenBucket::generateToken, this));
}
void TokenBucket::generateTokenByCurrentTime(long currentTime) {
if (this->lastGenerateTokenTime == -1) {
this->lastGenerateTokenTime = currentTime;
return;
}
if (currentTime - this->lastGenerateTokenTime < 1) {
return;
}
long currentStep = (currentTime - this->lastGenerateTokenTime) * this->rateLimit / 1000.0;
// std::cout << "currentStep: " << currentStep << "currentTime: " << currentTime << "lastGenerateTokenTime: " << this->lastGenerateTokenTime << std::endl;
// NFD_LOG_DEBUG(this->name << "=> do generateToken => " << this->currentTokenSize);
this->lastGenerateTokenTime = currentTime;
if (this->currentTokenSize + currentStep > this->bucketSize) {
this->currentTokenSize = this->bucketSize;
} else {
this->currentTokenSize += currentStep;
}
}
bool TokenBucket::use(uint64_t tokenNum) {
if(this->currentTokenSize > tokenNum) {
this->currentTokenSize -= tokenNum;
// NFD_LOG_DEBUG(this->name << "=> use success => " << this->currentTokenSize);
return true;
} else {
// NFD_LOG_DEBUG(this->name << "=> use failed => " << this->currentTokenSize);
return false;
}
}
}
}
+41
View File
@@ -0,0 +1,41 @@
//
// Created by gdcni21 on 3/25/22.
//
#ifndef NS_TOKENBUCKET_H
#define NS_TOKENBUCKET_H
#include <memory>
#include <string>
namespace nfd {
namespace face {
class TokenBucket {
public:
explicit TokenBucket(uint64_t rateLimit, uint64_t bucketSize, const std::string& name);
void start();
/**
* 周期性增加token
**/
void generateToken();
/**
* 根据当前时间生成token
*/
void generateTokenByCurrentTime(long currentTime);
/**
* 尝试消费n个token
* @param tokenNum
* @return
*/
bool use(uint64_t tokenNum);
public:
double eachStep; // 每个周期增加的令牌
double currentTokenSize; // 当前令牌数
uint64_t rateLimit; // 令牌生成速率
uint64_t bucketSize; // 令牌桶容量
std::string name;
bool isStart; // 标识是否启动
long lastGenerateTokenTime = -1;
};
}
}
#endif //NS_TOKENBUCKET_H
+6 -10
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, Regents of the University of California,
* Copyright (c) 2014-2019, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -26,22 +26,17 @@
#include "channel.hpp"
#include "face.hpp"
namespace nfd::face {
namespace nfd {
namespace face {
Channel::~Channel() = default;
void
Channel::setUri(const FaceUri& uri) noexcept
Channel::setUri(const FaceUri& uri)
{
m_uri = uri;
}
void
Channel::setDefaultMtu(size_t mtu) noexcept
{
m_defaultMtu = mtu;
}
void
connectFaceClosedSignal(Face& face, std::function<void()> f)
{
@@ -52,4 +47,5 @@ connectFaceClosedSignal(Face& face, std::function<void()> f)
});
}
} // namespace nfd::face
} // namespace face
} // namespace nfd
+9 -22
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, 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,7 +29,8 @@
#include "channel-log.hpp"
#include "face-common.hpp"
namespace nfd::face {
namespace nfd {
namespace face {
/** \brief Represents a channel that listens on a local endpoint.
* \sa FaceSystem
@@ -44,42 +45,27 @@ public:
~Channel();
const FaceUri&
getUri() const noexcept
getUri() const
{
return m_uri;
}
/**
* \brief Returns the default MTU for all faces created by this channel.
*/
size_t
getDefaultMtu() const noexcept
{
return m_defaultMtu;
}
/**
* \brief Returns whether the channel is listening.
/** \brief Returns whether the channel is listening
*/
virtual bool
isListening() const = 0;
/**
* \brief Returns the number of faces in the channel.
/** \brief Returns the number of faces in the channel
*/
virtual size_t
size() const = 0;
protected:
void
setUri(const FaceUri& uri) noexcept;
void
setDefaultMtu(size_t mtu) noexcept;
setUri(const FaceUri& uri);
private:
FaceUri m_uri;
size_t m_defaultMtu = ndn::MAX_NDN_PACKET_SIZE;
};
/** \brief Prototype for the callback that is invoked when a face is created
@@ -101,6 +87,7 @@ using FaceCreationFailedCallback = std::function<void(uint32_t status, const std
void
connectFaceClosedSignal(Face& face, std::function<void()> f);
} // namespace nfd::face
} // namespace face
} // namespace nfd
#endif // NFD_DAEMON_FACE_CHANNEL_HPP
+30 -22
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, 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,23 +32,21 @@
#include <array>
namespace nfd::face {
namespace nfd {
namespace face {
struct Unicast {};
struct Multicast {};
/**
* \brief Implements Transport for datagram-based protocols.
/** \brief Implements Transport for datagram-based protocols.
*
* \tparam Protocol A datagram-based protocol in Boost.Asio
* \tparam Addressing The addressing mode, either Unicast or Multicast
* \tparam Protocol a datagram-based protocol in Boost.Asio
*/
template<class Protocol, class Addressing>
template<class Protocol, class Addressing = Unicast>
class DatagramTransport : public Transport
{
public:
using protocol = Protocol;
using addressing = Addressing;
typedef Protocol protocol;
/** \brief Construct datagram transport.
*
@@ -60,11 +58,11 @@ public:
ssize_t
getSendQueueLength() override;
/**
* \brief Receive datagram, translate buffer into packet, deliver to parent class.
/** \brief Receive datagram, translate buffer into packet, deliver to parent class.
*/
void
receiveDatagram(span<const uint8_t> buffer, const boost::system::error_code& error);
receiveDatagram(const uint8_t* buffer, size_t nBytesReceived,
const boost::system::error_code& error);
protected:
void
@@ -88,6 +86,9 @@ protected:
void
resetRecentlyReceived();
static EndpointId
makeEndpointId(const typename protocol::endpoint& ep);
protected:
typename protocol::socket m_socket;
typename protocol::endpoint m_sender;
@@ -169,38 +170,37 @@ DatagramTransport<T, U>::doSend(const Block& packet)
template<class T, class U>
void
DatagramTransport<T, U>::receiveDatagram(span<const uint8_t> buffer,
DatagramTransport<T, U>::receiveDatagram(const uint8_t* buffer, size_t nBytesReceived,
const boost::system::error_code& error)
{
if (error)
return processErrorCode(error);
NFD_LOG_FACE_TRACE("Received: " << buffer.size() << " bytes from " << m_sender);
NFD_LOG_FACE_TRACE("Received: " << nBytesReceived << " bytes from " << m_sender);
auto [isOk, element] = Block::fromBuffer(buffer);
bool isOk = false;
Block element;
std::tie(isOk, element) = Block::fromBuffer(buffer, nBytesReceived);
if (!isOk) {
NFD_LOG_FACE_WARN("Failed to parse incoming packet from " << m_sender);
// This packet won't extend the face lifetime
return;
}
if (element.size() != buffer.size()) {
if (element.size() != nBytesReceived) {
NFD_LOG_FACE_WARN("Received datagram size and decoded element size don't match");
// This packet won't extend the face lifetime
return;
}
m_hasRecentlyReceived = true;
if constexpr (std::is_same_v<addressing, Multicast>)
this->receive(element, m_sender);
else
this->receive(element);
this->receive(element, makeEndpointId(m_sender));
}
template<class T, class U>
void
DatagramTransport<T, U>::handleReceive(const boost::system::error_code& error, size_t nBytesReceived)
{
receiveDatagram(ndn::make_span(m_receiveBuffer).first(nBytesReceived), error);
receiveDatagram(m_receiveBuffer.data(), nBytesReceived, error);
if (m_socket.is_open())
m_socket.async_receive_from(boost::asio::buffer(m_receiveBuffer), m_sender,
@@ -257,6 +257,14 @@ DatagramTransport<T, U>::resetRecentlyReceived()
m_hasRecentlyReceived = false;
}
} // namespace nfd::face
template<class T, class U>
EndpointId
DatagramTransport<T, U>::makeEndpointId(const typename protocol::endpoint&)
{
return 0;
}
} // namespace face
} // namespace nfd
#endif // NFD_DAEMON_FACE_DATAGRAM_TRANSPORT_HPP
+25 -14
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, 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,8 @@
#include <boost/range/adaptor/map.hpp>
#include <pcap/pcap.h>
namespace nfd::face {
namespace nfd {
namespace face {
NFD_LOG_INIT(EthernetChannel);
@@ -119,20 +120,26 @@ EthernetChannel::handleRead(const boost::system::error_code& error,
return;
}
auto [pkt, readErr] = m_pcap.readNextPacket();
if (pkt.empty()) {
NFD_LOG_CHAN_WARN("Read error: " << readErr);
const uint8_t* pkt;
size_t len;
std::string err;
std::tie(pkt, len, err) = m_pcap.readNextPacket();
if (pkt == nullptr) {
NFD_LOG_CHAN_WARN("Read error: " << err);
}
else {
auto [eh, frameErr] = ethernet::checkFrameHeader(pkt, m_localEndpoint->getEthernetAddress(),
m_localEndpoint->getEthernetAddress());
const ether_header* eh;
std::tie(eh, err) = ethernet::checkFrameHeader(pkt, len, m_localEndpoint->getEthernetAddress(),
m_localEndpoint->getEthernetAddress());
if (eh == nullptr) {
NFD_LOG_CHAN_DEBUG(frameErr);
NFD_LOG_CHAN_DEBUG(err);
}
else {
ethernet::Address sender(eh->ether_shost);
pkt = pkt.subspan(ethernet::HDR_LEN);
processIncomingPacket(pkt, sender, onFaceCreated, onReceiveFailed);
pkt += ethernet::HDR_LEN;
len -= ethernet::HDR_LEN;
processIncomingPacket(pkt, len, sender, onFaceCreated, onReceiveFailed);
}
}
@@ -147,7 +154,7 @@ EthernetChannel::handleRead(const boost::system::error_code& error,
}
void
EthernetChannel::processIncomingPacket(span<const uint8_t> packet,
EthernetChannel::processIncomingPacket(const uint8_t* packet, size_t length,
const ethernet::Address& sender,
const FaceCreatedCallback& onFaceCreated,
const FaceCreationFailedCallback& onReceiveFailed)
@@ -175,7 +182,7 @@ EthernetChannel::processIncomingPacket(span<const uint8_t> packet,
// dispatch the packet to the face for processing
auto* transport = static_cast<UnicastEthernetTransport*>(face->getTransport());
transport->receivePayload(packet, sender);
transport->receivePayload(packet, length, sender);
}
std::pair<bool, shared_ptr<Face>>
@@ -197,12 +204,15 @@ EthernetChannel::createFace(const ethernet::Address& remoteEndpoint,
if (params.mtu) {
options.overrideMtu = *params.mtu;
}
if (params.bandwidth) {
options.C = *params.bandwidth;
}
auto linkService = make_unique<GenericLinkService>(options);
auto transport = make_unique<UnicastEthernetTransport>(*m_localEndpoint, remoteEndpoint,
params.persistency, m_idleFaceTimeout);
auto face = make_shared<Face>(std::move(linkService), std::move(transport));
face->setChannel(weak_from_this());
face->setChannel(shared_from_this()); // use weak_from_this() in C++17
m_channelFaces[remoteEndpoint] = face;
connectFaceClosedSignal(*face, [this, remoteEndpoint] {
@@ -233,4 +243,5 @@ EthernetChannel::updateFilter()
m_pcap.setPacketFilter(filter.data());
}
} // namespace nfd::face
} // namespace face
} // namespace nfd
+14 -10
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, Regents of the University of California,
* Copyright (c) 2014-2018, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -29,16 +29,15 @@
#include "channel.hpp"
#include "ethernet-protocol.hpp"
#include "pcap-helper.hpp"
#include <boost/asio/posix/stream_descriptor.hpp>
#include <ndn-cxx/net/network-interface.hpp>
namespace nfd::face {
namespace nfd {
namespace face {
/**
* \brief Class implementing Ethernet-based channel to create faces
*/
class EthernetChannel final : public Channel
class EthernetChannel : public Channel
{
public:
/**
@@ -47,7 +46,11 @@ public:
class Error : public std::runtime_error
{
public:
using std::runtime_error::runtime_error;
explicit
Error(const std::string& what)
: std::runtime_error(what)
{
}
};
/**
@@ -60,13 +63,13 @@ public:
time::nanoseconds idleTimeout);
bool
isListening() const final
isListening() const override
{
return m_isListening;
}
size_t
size() const final
size() const override
{
return m_channelFaces.size();
}
@@ -107,7 +110,7 @@ private:
const FaceCreationFailedCallback& onReceiveFailed);
void
processIncomingPacket(span<const uint8_t> packet,
processIncomingPacket(const uint8_t* packet, size_t length,
const ethernet::Address& sender,
const FaceCreatedCallback& onFaceCreated,
const FaceCreationFailedCallback& onReceiveFailed);
@@ -133,6 +136,7 @@ private:
#endif
};
} // namespace nfd::face
} // namespace face
} // namespace nfd
#endif // NFD_DAEMON_FACE_ETHERNET_CHANNEL_HPP
+7 -5
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, 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,8 @@
#include <boost/range/adaptors.hpp>
#include <boost/range/algorithm/copy.hpp>
namespace nfd::face {
namespace nfd {
namespace face {
NFD_LOG_INIT(EthernetFactory);
NFD_REGISTER_PROTOCOL_FACTORY(EthernetFactory);
@@ -239,7 +240,7 @@ EthernetFactory::createMulticastFace(const ndn::net::NetworkInterface& netif,
{
BOOST_ASSERT(address.isMulticast());
std::pair key(netif.getName(), address);
auto key = std::make_pair(netif.getName(), address);
auto found = m_mcastFaces.find(key);
if (found != m_mcastFaces.end()) {
return found->second;
@@ -338,7 +339,7 @@ EthernetFactory::applyMcastConfigToNetif(const ndn::net::NetworkInterface& netif
return nullptr;
}
if (face->getId() == INVALID_FACEID) {
if (face->getId() == face::INVALID_FACEID) {
// new face: register with forwarding
this->addFace(face);
}
@@ -376,4 +377,5 @@ EthernetFactory::applyConfig(const FaceSystem::ConfigContext&)
}
}
} // namespace nfd::face
} // namespace face
} // namespace nfd
+15 -11
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, Regents of the University of California,
* Copyright (c) 2014-2018, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -29,11 +29,12 @@
#include "protocol-factory.hpp"
#include "ethernet-channel.hpp"
namespace nfd::face {
namespace nfd {
namespace face {
/** \brief Protocol factory for Ethernet.
/** \brief Protocol factory for Ethernet
*/
class EthernetFactory final : public ProtocolFactory
class EthernetFactory : public ProtocolFactory
{
public:
static const std::string&
@@ -43,7 +44,7 @@ public:
EthernetFactory(const CtorParams& params);
/**
* \brief Create Ethernet-based channel on the specified network interface.
* \brief Create Ethernet-based channel on the specified network interface
*
* If this method is called twice with the same endpoint, only one channel
* will be created. The second call will just return the existing channel.
@@ -57,7 +58,7 @@ public:
time::nanoseconds idleTimeout);
/**
* \brief Create a face to communicate on the given Ethernet multicast group.
* \brief Create a face to communicate on the given Ethernet multicast group
*
* If this method is called twice with the same arguments, only one face
* will be created. The second call will just return the existing face.
@@ -72,17 +73,19 @@ public:
const ethernet::Address& group);
private:
/** \brief process face_system.ether config section
*/
void
doProcessConfig(OptionalConfigSection configSection,
FaceSystem::ConfigContext& context) final;
FaceSystem::ConfigContext& context) override;
void
doCreateFace(const CreateFaceRequest& req,
const FaceCreatedCallback& onCreated,
const FaceCreationFailedCallback& onFailure) final;
const FaceCreationFailedCallback& onFailure) override;
std::vector<shared_ptr<const Channel>>
doGetChannels() const final;
doGetChannels() const override;
/** \brief Create EthernetChannel on \p netif if requested by \p m_unicastConfig.
* \return new or existing channel, or nullptr if no channel should be created
@@ -119,12 +122,13 @@ private:
};
MulticastConfig m_mcastConfig;
// [ifname, group] => face
/// (ifname, group) => face
std::map<std::pair<std::string, ethernet::Address>, shared_ptr<Face>> m_mcastFaces;
signal::ScopedConnection m_netifAddConn;
};
} // namespace nfd::face
} // namespace face
} // namespace nfd
#endif // NFD_DAEMON_FACE_ETHERNET_FACTORY_HPP
+11 -8
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, Regents of the University of California,
* Copyright (c) 2014-2018, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -27,15 +27,17 @@
#include <boost/endian/conversion.hpp>
namespace nfd::ethernet {
namespace nfd {
namespace ethernet {
std::tuple<const ether_header*, std::string>
checkFrameHeader(span<const uint8_t> packet, const Address& localAddr, const Address& destAddr)
std::pair<const ether_header*, std::string>
checkFrameHeader(const uint8_t* packet, size_t length,
const Address& localAddr, const Address& destAddr)
{
if (packet.size() < HDR_LEN + MIN_DATA_LEN)
return {nullptr, "Received frame too short: " + to_string(packet.size()) + " bytes"};
if (length < HDR_LEN + MIN_DATA_LEN)
return {nullptr, "Received frame too short: " + to_string(length) + " bytes"};
const ether_header* eh = reinterpret_cast<const ether_header*>(packet.data());
const ether_header* eh = reinterpret_cast<const ether_header*>(packet);
// in some cases VLAN-tagged frames may survive the BPF filter,
// make sure we do not process those frames (see #3348)
@@ -56,4 +58,5 @@ checkFrameHeader(span<const uint8_t> packet, const Address& localAddr, const Add
return {eh, ""};
}
} // namespace nfd::ethernet
} // namespace ethernet
} // namespace nfd
+8 -6
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, Regents of the University of California,
* Copyright (c) 2014-2017, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -27,17 +27,19 @@
#define NFD_DAEMON_FACE_ETHERNET_PROTOCOL_HPP
#include "core/common.hpp"
#include <ndn-cxx/net/ethernet.hpp>
#include <net/ethernet.h>
namespace nfd::ethernet {
namespace nfd {
namespace ethernet {
using namespace ndn::ethernet;
std::tuple<const ether_header*, std::string>
checkFrameHeader(span<const uint8_t> packet, const Address& localAddr, const Address& destAddr);
std::pair<const ether_header*, std::string>
checkFrameHeader(const uint8_t* packet, size_t length,
const Address& localAddr, const Address& destAddr);
} // namespace nfd::ethernet
} // namespace ethernet
} // namespace nfd
#endif // NFD_DAEMON_FACE_ETHERNET_PROTOCOL_HPP
+39 -20
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, 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,9 +29,12 @@
#include <pcap/pcap.h>
#include <cstring> // for memcpy()
#include <boost/endian/conversion.hpp>
namespace nfd::face {
namespace nfd {
namespace face {
NFD_LOG_INIT(EthernetTransport);
@@ -122,17 +125,17 @@ EthernetTransport::sendPacket(const ndn::Block& block)
// pad with zeroes if the payload is too short
if (block.size() < ethernet::MIN_DATA_LEN) {
static const uint8_t padding[ethernet::MIN_DATA_LEN] = {};
buffer.appendBytes(ndn::make_span(padding).subspan(block.size()));
buffer.appendByteArray(padding, ethernet::MIN_DATA_LEN - block.size());
}
// construct and prepend the ethernet header
uint16_t ethertype = boost::endian::native_to_big(ethernet::ETHERTYPE_NDN);
buffer.prependBytes({reinterpret_cast<const uint8_t*>(&ethertype), ethernet::TYPE_LEN});
buffer.prependBytes(m_srcAddress);
buffer.prependBytes(m_destAddress);
buffer.prependByteArray(reinterpret_cast<const uint8_t*>(&ethertype), ethernet::TYPE_LEN);
buffer.prependByteArray(m_srcAddress.data(), m_srcAddress.size());
buffer.prependByteArray(m_destAddress.data(), m_destAddress.size());
// send the frame
int sent = pcap_inject(m_pcap, buffer.data(), buffer.size());
int sent = pcap_inject(m_pcap, buffer.buf(), buffer.size());
if (sent < 0)
handleError("Send operation failed: " + m_pcap.getLastError());
else if (static_cast<size_t>(sent) < buffer.size())
@@ -165,20 +168,26 @@ EthernetTransport::handleRead(const boost::system::error_code& error)
return;
}
auto [pkt, readErr] = m_pcap.readNextPacket();
if (pkt.empty()) {
NFD_LOG_FACE_DEBUG("Read error: " << readErr);
const uint8_t* pkt;
size_t len;
std::string err;
std::tie(pkt, len, err) = m_pcap.readNextPacket();
if (pkt == nullptr) {
NFD_LOG_FACE_WARN("Read error: " << err);
}
else {
auto [eh, frameErr] = ethernet::checkFrameHeader(pkt, m_srcAddress,
m_destAddress.isMulticast() ? m_destAddress : m_srcAddress);
const ether_header* eh;
std::tie(eh, err) = ethernet::checkFrameHeader(pkt, len, m_srcAddress,
m_destAddress.isMulticast() ? m_destAddress : m_srcAddress);
if (eh == nullptr) {
NFD_LOG_FACE_WARN(frameErr);
NFD_LOG_FACE_WARN(err);
}
else {
ethernet::Address sender(eh->ether_shost);
pkt = pkt.subspan(ethernet::HDR_LEN);
receivePayload(pkt, sender);
pkt += ethernet::HDR_LEN;
len -= ethernet::HDR_LEN;
receivePayload(pkt, len, sender);
}
}
@@ -193,11 +202,14 @@ EthernetTransport::handleRead(const boost::system::error_code& error)
}
void
EthernetTransport::receivePayload(span<const uint8_t> payload, const ethernet::Address& sender)
EthernetTransport::receivePayload(const uint8_t* payload, size_t length,
const ethernet::Address& sender)
{
NFD_LOG_FACE_TRACE("Received: " << payload.size() << " bytes from " << sender);
NFD_LOG_FACE_TRACE("Received: " << length << " bytes from " << sender);
auto [isOk, element] = Block::fromBuffer(payload);
bool isOk = false;
Block element;
std::tie(isOk, element) = Block::fromBuffer(payload, length);
if (!isOk) {
NFD_LOG_FACE_WARN("Failed to parse incoming packet from " << sender);
// This packet won't extend the face lifetime
@@ -205,7 +217,13 @@ EthernetTransport::receivePayload(span<const uint8_t> payload, const ethernet::A
}
m_hasRecentlyReceived = true;
this->receive(element, m_destAddress.isMulticast() ? sender : EndpointId{});
static_assert(sizeof(EndpointId) >= ethernet::ADDR_LEN, "EndpointId is too small");
EndpointId endpoint = 0;
if (m_destAddress.isMulticast()) {
std::memcpy(&endpoint, sender.data(), sender.size());
}
this->receive(element, endpoint);
}
void
@@ -221,4 +239,5 @@ EthernetTransport::handleError(const std::string& errorMessage)
doClose();
}
} // namespace nfd::face
} // namespace face
} // namespace nfd
+9 -6
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, 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,10 +30,10 @@
#include "pcap-helper.hpp"
#include "transport.hpp"
#include <boost/asio/posix/stream_descriptor.hpp>
#include <ndn-cxx/net/network-interface.hpp>
namespace nfd::face {
namespace nfd {
namespace face {
/**
* @brief Base class for Ethernet-based Transports
@@ -49,11 +49,13 @@ public:
/**
* @brief Processes the payload of an incoming frame
* @param payload Payload bytes, starting from the first byte after the Ethernet header
* @param payload Pointer to the first byte of data after the Ethernet header
* @param length Payload length
* @param sender Sender address
*/
void
receivePayload(span<const uint8_t> payload, const ethernet::Address& sender);
receivePayload(const uint8_t* payload, size_t length,
const ethernet::Address& sender);
protected:
EthernetTransport(const ndn::net::NetworkInterface& localEndpoint,
@@ -113,6 +115,7 @@ private:
#endif
};
} // namespace nfd::face
} // namespace face
} // namespace nfd
#endif // NFD_DAEMON_FACE_ETHERNET_TRANSPORT_HPP
+29 -32
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, 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,14 +26,12 @@
#ifndef NFD_DAEMON_FACE_FACE_COMMON_HPP
#define NFD_DAEMON_FACE_FACE_COMMON_HPP
#include "ethernet-protocol.hpp"
#include "udp-protocol.hpp"
#include "core/common.hpp"
#include "common/logger.hpp"
#include <ndn-cxx/encoding/nfd-constants.hpp>
#include <boost/logic/tribool.hpp>
#include <variant>
namespace nfd {
namespace face {
@@ -41,40 +39,36 @@ namespace face {
class Face;
class LinkService;
/**
* \brief Identifies a face.
/** \brief Identifies a face.
*/
using FaceId = uint64_t;
/// Indicates an invalid FaceId
inline constexpr FaceId INVALID_FACEID = ndn::nfd::INVALID_FACE_ID;
/// Identifies the InternalFace used in management
inline constexpr FaceId FACEID_INTERNAL_FACE = 1;
/// Identifies a packet comes from the ContentStore
inline constexpr FaceId FACEID_CONTENT_STORE = 254;
/// Identifies the NullFace that drops every packet
inline constexpr FaceId FACEID_NULL = 255;
/// Upper bound of reserved FaceIds
inline constexpr FaceId FACEID_RESERVED_MAX = 255;
/// indicates an invalid FaceId
const FaceId INVALID_FACEID = ndn::nfd::INVALID_FACE_ID;
/// identifies the InternalFace used in management
const FaceId FACEID_INTERNAL_FACE = 1;
/// identifies a packet comes from the ContentStore
const FaceId FACEID_CONTENT_STORE = 254;
/// identifies the NullFace that drops every packet
const FaceId FACEID_NULL = 255;
/// upper bound of reserved FaceIds
const FaceId FACEID_RESERVED_MAX = 255;
/**
* \brief Minimum MTU that may be set.
/** \brief Minimum MTU that may be set
*
* This is done to ensure the NDNLPv2 fragmentation feature functions properly.
* This is done to ensure the NDNLPv2 fragmentation feature functions properly.
*/
inline constexpr ssize_t MIN_MTU = 64;
const ssize_t MIN_MTU = 64;
/**
* \brief Identifies a remote endpoint on the link.
/** \brief Identifies a remote endpoint on the link.
*
* This ID is only meaningful in the context of the same Transport.
* Incoming packets from the same remote endpoint have the same EndpointId,
* and incoming packets from different remote endpoints have different EndpointIds.
* This ID is only meaningful in the context of the same Transport.
* Incoming packets from the same remote endpoint have the same EndpointId,
* and incoming packets from different remote endpoints have different EndpointIds.
*
* Typically, a point-to-point Transport has only one meaningful EndpointId,
* represented by `std::monostate`.
* Typically, a point-to-point Transport has only one meaningful EndpointId (usually 0).
*/
using EndpointId = std::variant<std::monostate, ethernet::Address, udp::Endpoint>;
using EndpointId = uint64_t;
/** \brief Parameters used to set Transport properties or LinkService options on a newly created face.
*
@@ -84,9 +78,10 @@ using EndpointId = std::variant<std::monostate, ethernet::Address, udp::Endpoint
struct FaceParams
{
ndn::nfd::FacePersistency persistency = ndn::nfd::FACE_PERSISTENCY_PERSISTENT;
std::optional<time::nanoseconds> baseCongestionMarkingInterval;
std::optional<uint64_t> defaultCongestionThreshold;
std::optional<ssize_t> mtu;
optional<time::nanoseconds> baseCongestionMarkingInterval;
optional<uint64_t> defaultCongestionThreshold;
optional<ssize_t> mtu;
optional<uint64_t> bandwidth;
bool wantLocalFields = false;
bool wantLpReliability = false;
boost::logic::tribool wantCongestionMarking = boost::logic::indeterminate;
@@ -134,7 +129,9 @@ using face::FaceId;
// implementation detail
#define NFD_LOG_FACE(level, msg) NFD_LOG_##level( \
::nfd::face::FaceLogHelper< \
std::remove_cv_t<std::remove_reference_t<decltype(*this)>> \
typename std::remove_cv< \
typename std::remove_reference<decltype(*this)>::type \
>::type \
>(*this) \
<< msg)
/** \endcond */
+5 -3
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, 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,
@@ -25,7 +25,8 @@
#include "face-counters.hpp"
namespace nfd::face {
namespace nfd {
namespace face {
FaceCounters::FaceCounters(const LinkService::Counters& linkServiceCounters,
const Transport::Counters& transportCounters)
@@ -45,4 +46,5 @@ FaceCounters::FaceCounters(const LinkService::Counters& linkServiceCounters,
{
}
} // namespace nfd::face
} // namespace face
} // namespace nfd
+10 -8
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, 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,9 +29,10 @@
#include "link-service.hpp"
#include "transport.hpp"
namespace nfd::face {
namespace nfd {
namespace face {
/** \brief Gives access to counters provided by Face.
/** \brief gives access to counters provided by Face
*
* This type is a facade that exposes common counters of a Face.
*
@@ -49,7 +50,7 @@ public:
* \throw std::bad_cast counters type mismatch
*/
template<typename T>
std::enable_if_t<std::is_base_of_v<LinkService::Counters, T>, const T&>
typename std::enable_if<std::is_base_of<LinkService::Counters, T>::value, const T&>::type
get() const
{
return dynamic_cast<const T&>(m_linkServiceCounters);
@@ -60,7 +61,7 @@ public:
* \throw std::bad_cast counters type mismatch
*/
template<typename T>
std::enable_if_t<std::is_base_of_v<Transport::Counters, T>, const T&>
typename std::enable_if<std::is_base_of<Transport::Counters, T>::value, const T&>::type
get() const
{
return dynamic_cast<const T&>(m_transportCounters);
@@ -80,11 +81,11 @@ public:
const ByteCounter& nInBytes;
const ByteCounter& nOutBytes;
/** \brief Count of incoming Interests dropped due to HopLimit == 0.
/** \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.
/** \brief count of outgoing Interests dropped due to HopLimit == 0 on non-local faces
*/
PacketCounter nOutHopLimitZero;
@@ -93,6 +94,7 @@ private:
const Transport::Counters& m_transportCounters;
};
} // namespace nfd::face
} // namespace face
} // namespace nfd
#endif // NFD_DAEMON_FACE_FACE_COUNTERS_HPP
+12 -15
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, Regents of the University of California,
* Copyright (c) 2014-2019, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -30,25 +30,16 @@
namespace nfd {
/**
* \brief Represents a face-endpoint pair in the forwarder.
* \sa face::Face, face::EndpointId
/** \brief Represents a face-endpoint pair in the forwarder.
* \sa face::Face, face::EndpointId
*/
class FaceEndpoint
{
public:
explicit
FaceEndpoint(Face& face, const EndpointId& endpoint = {});
private:
void
print(std::ostream& os) const;
friend std::ostream&
operator<<(std::ostream& os, const FaceEndpoint& fe)
FaceEndpoint(const Face& face, EndpointId endpoint)
: face(const_cast<Face&>(face))
, endpoint(endpoint)
{
fe.print(os);
return os;
}
public:
@@ -56,6 +47,12 @@ public:
const EndpointId endpoint;
};
inline std::ostream&
operator<<(std::ostream& os, const FaceEndpoint& fe)
{
return os << '(' << fe.face.getId() << ',' << fe.endpoint << ')';
}
} // namespace nfd
#endif // NFD_DAEMON_FACE_FACE_ENDPOINT_HPP
+13 -10
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, Regents of the University of California,
* Copyright (c) 2014-2019, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -29,7 +29,8 @@
#include "common/global.hpp"
#include "fw/face-table.hpp"
namespace nfd::face {
namespace nfd {
namespace face {
NFD_LOG_INIT(FaceSystem);
@@ -93,9 +94,7 @@ FaceSystem::hasFactoryForScheme(const std::string& scheme) const
void
FaceSystem::setConfigFile(ConfigFile& configFile)
{
configFile.addSectionHandler(CFGSEC_FACESYSTEM, [this] (auto&&... args) {
processConfig(std::forward<decltype(args)>(args)...);
});
configFile.addSectionHandler(CFGSEC_FACESYSTEM, bind(&FaceSystem::processConfig, this, _1, _2, _3));
}
void
@@ -119,19 +118,22 @@ FaceSystem::processConfig(const ConfigSection& configSection, bool isDryRun, con
}
// process in protocol factories
for (const auto& [sectionName, factory] : m_factories) {
for (const auto& pair : m_factories) {
const std::string& sectionName = pair.first;
ProtocolFactory* factory = pair.second.get();
std::set<std::string> oldProvidedSchemes = factory->getProvidedSchemes();
factory->processConfig(configSection.get_child_optional(sectionName), context);
if (!isDryRun) {
for (const auto& scheme : factory->getProvidedSchemes()) {
m_factoryByScheme[scheme] = factory.get();
for (const std::string& scheme : factory->getProvidedSchemes()) {
m_factoryByScheme[scheme] = factory;
if (oldProvidedSchemes.erase(scheme) == 0) {
NFD_LOG_TRACE("factory " << sectionName <<
" provides " << scheme << " FaceUri scheme");
}
}
for (const auto& scheme : oldProvidedSchemes) {
for (const std::string& scheme : oldProvidedSchemes) {
m_factoryByScheme.erase(scheme);
NFD_LOG_TRACE("factory " << sectionName <<
" no longer provides " << scheme << " FaceUri scheme");
@@ -162,4 +164,5 @@ FaceSystem::processConfig(const ConfigSection& configSection, bool isDryRun, con
}
}
} // namespace nfd::face
} // namespace face
} // namespace nfd
+15 -17
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, Regents of the University of California,
* Copyright (c) 2014-2019, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -43,11 +43,10 @@ class NetdevBound;
class ProtocolFactory;
struct ProtocolFactoryCtorParams;
/**
* \brief Entry point of NFD's face system.
/** \brief entry point of the face system
*
* NFD's face system is organized as a FaceSystem-ProtocolFactory-Channel-Face hierarchy.
* The FaceSystem class is the entry point of the face system and owns all ProtocolFactory objects.
* NFD's face system is organized as a FaceSystem-ProtocolFactory-Channel-Face hierarchy.
* FaceSystem class is the entry point of NFD's face system and owns ProtocolFactory objects.
*/
class FaceSystem : noncopyable
{
@@ -56,18 +55,17 @@ public:
~FaceSystem();
/**
* \brief Returns all ProtocolFactory objects owned by the face system.
/** \return ProtocolFactory objects owned by the FaceSystem
*/
[[nodiscard]] std::set<const ProtocolFactory*>
std::set<const ProtocolFactory*>
listProtocolFactories() const;
/** \return ProtocolFactory for the specified registered factory id or nullptr if not found.
/** \return ProtocolFactory for the specified registered factory id or nullptr if not found
*/
ProtocolFactory*
getFactoryById(const std::string& id);
/** \return ProtocolFactory for the specified FaceUri scheme or nullptr if not found.
/** \return ProtocolFactory for the specified FaceUri scheme or nullptr if not found
*/
ProtocolFactory*
getFactoryByScheme(const std::string& scheme);
@@ -81,19 +79,19 @@ public:
return m_faceTable;
}
/** \brief Register handler for the `face_system` section of NFD's configuration file.
/** \brief register handler for face_system section of NFD configuration file
*/
void
setConfigFile(ConfigFile& configFile);
/** \brief Configuration options from `general` section.
/** \brief configuration options from "general" section
*/
struct GeneralConfig
{
bool wantCongestionMarking = true;
};
/** \brief Context for processing a config section in ProtocolFactory.
/** \brief context for processing a config section in ProtocolFactory
*/
class ConfigContext : noncopyable
{
@@ -102,7 +100,7 @@ public:
bool isDryRun;
};
NFD_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
PUBLIC_WITH_TESTS_ELSE_PRIVATE:
ProtocolFactoryCtorParams
makePFCtorParams();
@@ -111,14 +109,14 @@ private:
processConfig(const ConfigSection& configSection, bool isDryRun,
const std::string& filename);
NFD_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
/** \brief Config section name => protocol factory.
PUBLIC_WITH_TESTS_ELSE_PRIVATE:
/** \brief config section name => protocol factory
*/
std::map<std::string, unique_ptr<ProtocolFactory>> m_factories;
unique_ptr<NetdevBound> m_netdevBound;
private:
/** \brief Scheme => protocol factory.
/** \brief scheme => protocol factory
*
* The same protocol factory may be available under multiple schemes.
*/
+6 -3
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, Regents of the University of California,
* Copyright (c) 2014-2017, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -25,7 +25,8 @@
#include "face.hpp"
namespace nfd::face {
namespace nfd {
namespace face {
Face::Face(unique_ptr<LinkService> service, unique_ptr<Transport> transport)
: afterReceiveInterest(service->afterReceiveInterest)
@@ -33,6 +34,7 @@ Face::Face(unique_ptr<LinkService> service, unique_ptr<Transport> transport)
, afterReceiveNack(service->afterReceiveNack)
, onDroppedInterest(service->onDroppedInterest)
, afterStateChange(transport->afterStateChange)
, m_id(INVALID_FACEID)
, m_service(std::move(service))
, m_transport(std::move(transport))
, m_counters(m_service->getCounters(), m_transport->getCounters())
@@ -50,4 +52,5 @@ operator<<(std::ostream& os, const FaceLogHelper<Face>& flh)
return os;
}
} // namespace nfd::face
} // namespace face
} // namespace nfd
+68 -72
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, 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,12 +36,11 @@ namespace face {
class Channel;
/**
* \brief Indicates the state of a face.
/** \brief indicates the state of a face
*/
using FaceState = TransportState;
typedef TransportState FaceState;
/** \brief Generalization of a network interface.
/** \brief generalization of a network interface
*
* A face generalizes a network interface.
* It provides best-effort network-layer packet delivery services
@@ -52,24 +51,18 @@ using FaceState = TransportState;
* LinkService is the upper part, which translates between network-layer packets
* and TLV blocks, and may provide additional services such as fragmentation and reassembly.
*/
class Face NFD_FINAL_UNLESS_WITH_TESTS : public std::enable_shared_from_this<Face>, noncopyable
class Face FINAL_UNLESS_WITH_TESTS : public std::enable_shared_from_this<Face>, noncopyable
{
public:
Face(unique_ptr<LinkService> service, unique_ptr<Transport> transport);
LinkService*
getLinkService() const noexcept
{
return m_service.get();
}
getLinkService() const;
Transport*
getTransport() const noexcept
{
return m_transport.get();
}
getTransport() const;
/** \brief Request that the face be closed.
/** \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.
@@ -82,133 +75,106 @@ public:
close();
public: // upper interface connected to forwarding
/** \brief Send Interest.
/** \brief send Interest
*/
void
sendInterest(const Interest& interest);
/** \brief Send Data.
/** \brief send Data
*/
void
sendData(const Data& data);
/** \brief Send Nack.
/** \brief send Nack
*/
void
sendNack(const lp::Nack& nack);
/** \brief Signals on Interest received.
/** \brief signals on Interest received
*/
signal::Signal<LinkService, Interest, EndpointId>& afterReceiveInterest;
/** \brief Signals on Data received.
/** \brief signals on Data received
*/
signal::Signal<LinkService, Data, EndpointId>& afterReceiveData;
/** \brief Signals on Nack received.
/** \brief signals on Nack received
*/
signal::Signal<LinkService, lp::Nack, EndpointId>& afterReceiveNack;
/** \brief Signals on Interest dropped by reliability system for exceeding allowed number of retx.
/** \brief signals on Interest dropped by reliability system for exceeding allowed number of retx
*/
signal::Signal<LinkService, Interest>& onDroppedInterest;
public: // properties
/**
* \brief Returns the face ID.
/** \return face ID
*/
FaceId
getId() const noexcept
{
return m_id;
}
getId() const;
/**
* \brief Sets the face ID.
* \note Normally, this should only be invoked by FaceTable.
/** \brief sets face ID
* \note Normally, this should only be invoked by FaceTable.
*/
void
setId(FaceId id) noexcept
{
m_id = id;
}
setId(FaceId id);
/**
* \brief Returns a FaceUri representing the local endpoint.
/** \return a FaceUri representing local endpoint
*/
FaceUri
getLocalUri() const;
/**
* \brief Returns a FaceUri representing the remote endpoint.
/** \return a FaceUri representing remote endpoint
*/
FaceUri
getRemoteUri() const;
/**
* \brief Returns whether the face is local or non-local for scope control purposes.
/** \return whether face is local or non-local for scope control purpose
*/
ndn::nfd::FaceScope
getScope() const;
/**
* \brief Returns the current persistency setting of the face.
/** \return face persistency setting
*/
ndn::nfd::FacePersistency
getPersistency() const;
/**
* \brief Changes the face persistency setting.
/** \brief changes face persistency setting
*/
void
setPersistency(ndn::nfd::FacePersistency persistency);
/**
* \brief Returns the link type of the face (point-to-point, multi-access, ...).
/** \return whether face is point-to-point or multi-access
*/
ndn::nfd::LinkType
getLinkType() const;
/**
* \brief Returns the effective MTU of the face.
/** \brief Returns face effective MTU
*
* This function is a wrapper. The effective MTU of a face is determined by the link service.
* This function is a wrapper. The effective MTU of a face is determined by the link service.
*/
ssize_t
getMtu() const;
/**
* \brief Returns the face state.
/** \return face state
*/
FaceState
getState() const;
/**
* \brief Signals after face state changed.
/** \brief signals after face state changed
*/
signal::Signal<Transport, FaceState/*old*/, FaceState/*new*/>& afterStateChange;
/**
* \brief Returns the expiration time of the face.
* \retval time::steady_clock::time_point::max() The face has an indefinite lifetime.
/** \return expiration time of the face
* \retval time::steady_clock::TimePoint::max() the face has an indefinite lifetime
*/
time::steady_clock::time_point
time::steady_clock::TimePoint
getExpirationTime() const;
const FaceCounters&
getCounters() const noexcept
{
return m_counters;
}
FaceCounters&
getCounters() noexcept
{
return m_counters;
}
getCounters() const;
/**
* \brief Get channel on which face was created (unicast) or the associated channel (multicast).
* \brief Get channel on which face was created (unicast) or the associated channel (multicast)
*/
weak_ptr<Channel>
getChannel() const
@@ -217,7 +183,7 @@ public: // properties
}
/**
* \brief Set channel on which face was created (unicast) or the associated channel (multicast).
* \brief Set channel on which face was created (unicast) or the associated channel (multicast)
*/
void
setChannel(weak_ptr<Channel> channel)
@@ -226,13 +192,25 @@ public: // properties
}
private:
FaceId m_id = INVALID_FACEID;
FaceId m_id;
unique_ptr<LinkService> m_service;
unique_ptr<Transport> m_transport;
FaceCounters m_counters;
weak_ptr<Channel> m_channel;
};
inline LinkService*
Face::getLinkService() const
{
return m_service.get();
}
inline Transport*
Face::getTransport() const
{
return m_transport.get();
}
inline void
Face::close()
{
@@ -257,6 +235,18 @@ Face::sendNack(const lp::Nack& nack)
m_service->sendNack(nack);
}
inline FaceId
Face::getId() const
{
return m_id;
}
inline void
Face::setId(FaceId id)
{
m_id = id;
}
inline FaceUri
Face::getLocalUri() const
{
@@ -305,12 +295,18 @@ Face::getState() const
return m_transport->getState();
}
inline time::steady_clock::time_point
inline time::steady_clock::TimePoint
Face::getExpirationTime() const
{
return m_transport->getExpirationTime();
}
inline const FaceCounters&
Face::getCounters() const
{
return m_counters;
}
std::ostream&
operator<<(std::ostream& os, const FaceLogHelper<Face>& flh);
+101 -30
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, 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,
@@ -24,13 +24,14 @@
*/
#include "generic-link-service.hpp"
#include <iostream>
#include <ndn-cxx/lp/pit-token.hpp>
#include <ndn-cxx/lp/tags.hpp>
#include <cmath>
namespace nfd::face {
namespace nfd {
namespace face {
NFD_LOG_INIT(GenericLinkService);
@@ -44,12 +45,46 @@ GenericLinkService::GenericLinkService(const GenericLinkService::Options& option
, m_reassembler(m_options.reassemblerOptions, this)
, m_reliability(m_options.reliabilityOptions, this)
, m_lastSeqNo(-2)
, m_nextMarkTime(time::steady_clock::time_point::max())
, m_nextMarkTime(time::steady_clock::TimePoint::max())
, m_nMarkedSinceInMarkingState(0)
, globalSp(options.C * 0.99, options.vqSize)
{
m_reassembler.beforeTimeout.connect([this] (auto&&...) { ++nReassemblyTimeouts; });
m_reliability.onDroppedInterest.connect([this] (const auto& i) { notifyDroppedInterest(i); });
std::cout << "C: " << options.C << std::endl;
m_reassembler.beforeTimeout.connect([this] (auto...) { ++this->nReassemblyTimeouts; });
m_reliability.onDroppedInterest.connect([this] (const auto& i) { this->notifyDroppedInterest(i); });
nReassembling.observe(&m_reassembler);
this->sendPacketCallback = [this](std::shared_ptr<VirtualQueueItem> taskPtr) {
this->globalSp.triggerCalObjectRate();
if (taskPtr != nullptr) {
const Block &block = taskPtr->item->wireEncode();
// std::cout << "interest wireEncode size: " << block.size() << std::endl;
lp::Packet lpPacket(block);
// std::cout << "Interest lppacket size before encode lp fields: " << lpPacket.wireEncode().size() << std::endl;
encodeLpFields(*(taskPtr->item), lpPacket);
// std::cout << "Interest lppacket size after encode lp fields: " << lpPacket.wireEncode().size() << std::endl;
this->sendNetPacket(std::move(lpPacket), true);
// lp::Packet lpPacket(taskPtr->item->wireEncode());
// encodeLpFields(*(taskPtr->item), lpPacket);
// this->sendNetPacket(std::move(lpPacket), taskPtr->endpointId, true);
}
// 得到下一个需要调度的包
auto newTaskPtr = this->globalSp.scheduleNext();
if (newTaskPtr == nullptr) {
//NFD_LOG_ERROR("FUCK");
// std::cout << "FUCK" << std::endl;
// 如果没有可调度的包,则 1 ms 之后再调度
this->canScheduler = true;
// getScheduler().schedule(time::milliseconds(1), std::bind(this->sendPacketCallback, nullptr));
} else {
// 等待足够的 token 再发送
this->canScheduler = false;
// std::cout << "Route waitTime: " << newTaskPtr->waitNsTime << std::endl;
// NFD_LOG_DEBUG("Route waitTime: " << newTaskPtr->waitNsTime);
getScheduler().schedule(time::nanoseconds((uint32_t)(0)),
std::bind(this->sendPacketCallback, newTaskPtr));
}
};
// getScheduler().schedule(time::nanoseconds(0), std::bind(this->sendPacketCallback, nullptr));
}
void
@@ -104,7 +139,7 @@ GenericLinkService::sendLpPacket(lp::Packet&& pkt)
auto block = pkt.wireEncode();
if (mtu != MTU_UNLIMITED && block.size() > static_cast<size_t>(mtu)) {
++nOutOverMtu;
++this->nOutOverMtu;
NFD_LOG_FACE_WARN("attempted to send packet over MTU limit");
return;
}
@@ -114,11 +149,34 @@ GenericLinkService::sendLpPacket(lp::Packet&& pkt)
void
GenericLinkService::doSendInterest(const Interest& interest)
{
lp::Packet lpPacket(interest.wireEncode());
if (interest.getName().getPrefix(1).toUri() == "/localhost") {
const Block &block = interest.wireEncode();
// // std::cout << "interest wireEncode size: " << block.size() << std::endl;
lp::Packet lpPacket(block);
// // std::cout << "lppacket size before encode lp fields: " << lpPacket.wireEncode().size() << std::endl;
encodeLpFields(interest, lpPacket);
// // std::cout << "lppacket size after encode lp fields: " << lpPacket.wireEncode().size() << std::endl;
this->sendNetPacket(std::move(lpPacket), true);
} else {
this->globalSp.appendInterest(interest);
if (this->canScheduler) {
this->sendPacketCallback(nullptr);
}
//if (!success) {
// // send Nack
// lp::Nack nack(interest);
// nack.setReason(lp::NackReason::CONGESTION);
// if (this->nwfq.canMark(nack)) {
// // 拥塞标记
// nack.getInterest().setTag(make_shared<lp::CongestionMarkTag>(1));
// }
// this->receiveNack(nack, endpointId);
//}
}
encodeLpFields(interest, lpPacket);
// encodeLpFields(interest, lpPacket);
this->sendNetPacket(std::move(lpPacket), true);
// this->sendNetPacket(std::move(lpPacket), true);
}
void
@@ -206,7 +264,7 @@ GenericLinkService::sendNetPacket(lp::Packet&& pkt, bool isInterest)
std::tie(isOk, frags) = m_fragmenter.fragmentPacket(pkt, mtu);
if (!isOk) {
// fragmentation failed (warning is logged by LpFragmenter)
++nFragmentationErrors;
++this->nFragmentationErrors;
return;
}
}
@@ -260,7 +318,7 @@ GenericLinkService::checkCongestionLevel(lp::Packet& pkt)
if (static_cast<size_t>(sendQueueLength) > m_options.defaultCongestionThreshold) {
const auto now = time::steady_clock::now();
if (m_nextMarkTime == time::steady_clock::time_point::max()) {
if (m_nextMarkTime == time::steady_clock::TimePoint::max()) {
m_nextMarkTime = now + m_options.baseCongestionMarkingInterval;
}
// Mark packet if sendQueue stays above target for one interval
@@ -278,10 +336,10 @@ GenericLinkService::checkCongestionLevel(lp::Packet& pkt)
m_nextMarkTime += interval;
}
}
else if (m_nextMarkTime != time::steady_clock::time_point::max()) {
else if (m_nextMarkTime != time::steady_clock::TimePoint::max()) {
// Congestion incident has ended, so reset
NFD_LOG_FACE_DEBUG("Send queue length dropped below congestion threshold");
m_nextMarkTime = time::steady_clock::time_point::max();
m_nextMarkTime = time::steady_clock::TimePoint::max();
m_nMarkedSinceInMarkingState = 0;
}
}
@@ -295,7 +353,7 @@ GenericLinkService::doReceivePacket(const Block& packet, const EndpointId& endpo
if (m_options.reliabilityOptions.isEnabled) {
if (!m_reliability.processIncomingPacket(pkt)) {
NFD_LOG_FACE_TRACE("received duplicate fragment: DROP");
++nDuplicateSequence;
++this->nDuplicateSequence;
return;
}
}
@@ -311,13 +369,16 @@ GenericLinkService::doReceivePacket(const Block& packet, const EndpointId& endpo
return;
}
auto [isReassembled, netPkt, firstPkt] = m_reassembler.receiveFragment(endpoint, pkt);
bool isReassembled = false;
Block netPkt;
lp::Packet firstPkt;
std::tie(isReassembled, netPkt, firstPkt) = m_reassembler.receiveFragment(endpoint, pkt);
if (isReassembled) {
this->decodeNetPacket(netPkt, firstPkt, endpoint);
}
}
catch (const tlv::Error& e) {
++nInLpInvalid;
++this->nInLpInvalid;
NFD_LOG_FACE_WARN("packet parse error (" << e.what() << "): DROP");
}
}
@@ -340,14 +401,14 @@ GenericLinkService::decodeNetPacket(const Block& netPkt, const lp::Packet& first
this->decodeData(netPkt, firstPkt, endpointId);
break;
default:
++nInNetInvalid;
++this->nInNetInvalid;
NFD_LOG_FACE_WARN("unrecognized network-layer packet TLV-TYPE " << netPkt.type() << ": DROP");
return;
}
}
catch (const tlv::Error& e) {
++nInNetInvalid;
NFD_LOG_FACE_WARN("packet parse error (" << e.what() << "): DROP");
++this->nInNetInvalid;
NFD_LOG_FACE_WARN("packet parse error (" << e.what() << "): DROP" << netPkt.type());
}
}
@@ -372,7 +433,7 @@ GenericLinkService::decodeInterest(const Block& netPkt, const lp::Packet& firstP
}
if (firstPkt.has<lp::CachePolicyField>()) {
++nInNetInvalid;
++this->nInNetInvalid;
NFD_LOG_FACE_WARN("received CachePolicy with Interest: DROP");
return;
}
@@ -395,7 +456,7 @@ GenericLinkService::decodeInterest(const Block& netPkt, const lp::Packet& firstP
}
if (firstPkt.has<lp::PrefixAnnouncementField>()) {
++nInNetInvalid;
++this->nInNetInvalid;
NFD_LOG_FACE_WARN("received PrefixAnnouncement with Interest: DROP");
return;
}
@@ -404,6 +465,8 @@ GenericLinkService::decodeInterest(const Block& netPkt, const lp::Packet& firstP
interest->setTag(make_shared<lp::PitToken>(firstPkt.get<lp::PitTokenField>()));
}
this->globalSp.receiveInterest(*interest);
this->globalSp.triggerCalObjectRate();
this->receiveInterest(*interest, endpointId);
}
@@ -417,13 +480,13 @@ GenericLinkService::decodeData(const Block& netPkt, const lp::Packet& firstPkt,
auto data = make_shared<Data>(netPkt);
if (firstPkt.has<lp::NackField>()) {
++nInNetInvalid;
++this->nInNetInvalid;
NFD_LOG_FACE_WARN("received Nack with Data: DROP");
return;
}
if (firstPkt.has<lp::NextHopFaceIdField>()) {
++nInNetInvalid;
++this->nInNetInvalid;
NFD_LOG_FACE_WARN("received NextHopFaceId with Data: DROP");
return;
}
@@ -444,7 +507,7 @@ GenericLinkService::decodeData(const Block& netPkt, const lp::Packet& firstPkt,
}
if (firstPkt.has<lp::NonDiscoveryField>()) {
++nInNetInvalid;
++this->nInNetInvalid;
NFD_LOG_FACE_WARN("received NonDiscovery with Data: DROP");
return;
}
@@ -458,6 +521,13 @@ GenericLinkService::decodeData(const Block& netPkt, const lp::Packet& firstPkt,
}
}
// 不处理本地命令通信
if (data->getName().getPrefix(1).toUri() != "/localhost") {
// TR = min(TR, OR)
this->globalSp.assignObjectRate(*data);
}
this->globalSp.triggerCalObjectRate();
this->receiveData(*data, endpointId);
}
@@ -472,13 +542,13 @@ GenericLinkService::decodeNack(const Block& netPkt, const lp::Packet& firstPkt,
nack.setHeader(firstPkt.get<lp::NackField>());
if (firstPkt.has<lp::NextHopFaceIdField>()) {
++nInNetInvalid;
++this->nInNetInvalid;
NFD_LOG_FACE_WARN("received NextHopFaceId with Nack: DROP");
return;
}
if (firstPkt.has<lp::CachePolicyField>()) {
++nInNetInvalid;
++this->nInNetInvalid;
NFD_LOG_FACE_WARN("received CachePolicy with Nack: DROP");
return;
}
@@ -492,13 +562,13 @@ GenericLinkService::decodeNack(const Block& netPkt, const lp::Packet& firstPkt,
}
if (firstPkt.has<lp::NonDiscoveryField>()) {
++nInNetInvalid;
++this->nInNetInvalid;
NFD_LOG_FACE_WARN("received NonDiscovery with Nack: DROP");
return;
}
if (firstPkt.has<lp::PrefixAnnouncementField>()) {
++nInNetInvalid;
++this->nInNetInvalid;
NFD_LOG_FACE_WARN("received PrefixAnnouncement with Nack: DROP");
return;
}
@@ -506,4 +576,5 @@ GenericLinkService::decodeNack(const Block& netPkt, const lp::Packet& firstPkt,
this->receiveNack(nack, endpointId);
}
} // namespace nfd::face
} // namespace face
} // namespace nfd
+84 -70
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, 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,74 +30,75 @@
#include "lp-fragmenter.hpp"
#include "lp-reassembler.hpp"
#include "lp-reliability.hpp"
#include "queues.hpp"
namespace nfd::face {
namespace nfd {
namespace face {
/** \brief Counters provided by GenericLinkService.
* \note The type name GenericLinkServiceCounters is an implementation detail.
* Use GenericLinkService::Counters in public API.
/** \brief counters provided by GenericLinkService
* \note The type name 'GenericLinkServiceCounters' is implementation detail.
* Use 'GenericLinkService::Counters' in public API.
*/
class GenericLinkServiceCounters : public virtual LinkService::Counters
{
public:
/** \brief Count of failed fragmentations.
/** \brief count of failed fragmentations
*/
PacketCounter nFragmentationErrors;
/** \brief Count of outgoing LpPackets dropped due to exceeding MTU limit.
/** \brief count of outgoing LpPackets dropped due to exceeding MTU limit
*
* If this counter is non-zero, the operator should enable fragmentation.
*/
PacketCounter nOutOverMtu;
/** \brief Count of invalid LpPackets dropped before reassembly.
/** \brief count of invalid LpPackets dropped before reassembly
*/
PacketCounter nInLpInvalid;
/** \brief Count of network-layer packets currently being reassembled.
/** \brief count of network-layer packets currently being reassembled
*/
SizeCounter<LpReassembler> nReassembling;
/** \brief Count of dropped partial network-layer packets due to reassembly timeout.
/** \brief count of dropped partial network-layer packets due to reassembly timeout
*/
PacketCounter nReassemblyTimeouts;
/** \brief Count of invalid reassembled network-layer packets dropped.
/** \brief count of invalid reassembled network-layer packets dropped
*/
PacketCounter nInNetInvalid;
/** \brief Count of network-layer packets that did not require retransmission of a fragment.
/** \brief count of network-layer packets that did not require retransmission of a fragment
*/
PacketCounter nAcknowledged;
/** \brief Count of network-layer packets that had at least one fragment retransmitted, but were
* eventually received in full.
/** \brief count of network-layer packets that had at least one fragment retransmitted, but were
* eventually received in full
*/
PacketCounter nRetransmitted;
/** \brief Count of network-layer packets dropped because a fragment reached the maximum number
* of retransmissions.
/** \brief count of network-layer packets dropped because a fragment reached the maximum number
* of retransmissions
*/
PacketCounter nRetxExhausted;
/** \brief Count of LpPackets dropped due to duplicate Sequence numbers.
/** \brief count of LpPackets dropped due to duplicate Sequence numbers
*/
PacketCounter nDuplicateSequence;
/** \brief Count of outgoing LpPackets that were marked with congestion marks.
/** \brief count of outgoing LpPackets that were marked with congestion marks
*/
PacketCounter nCongestionMarked;
};
/**
* \brief GenericLinkService is a LinkService that implements the NDNLPv2 protocol.
* \sa https://redmine.named-data.net/projects/nfd/wiki/NDNLPv2
/** \brief GenericLinkService is a LinkService that implements the NDNLPv2 protocol
* \sa https://redmine.named-data.net/projects/nfd/wiki/NDNLPv2
*/
class GenericLinkService NFD_FINAL_UNLESS_WITH_TESTS : public LinkService
, protected virtual GenericLinkServiceCounters
class GenericLinkService FINAL_UNLESS_WITH_TESTS : public LinkService
, protected virtual GenericLinkServiceCounters
{
public:
/** \brief %Options that control the behavior of GenericLinkService.
/** \brief Options that control the behavior of GenericLinkService
*/
class Options
{
@@ -107,35 +108,35 @@ public:
}
public:
/** \brief Enables encoding of IncomingFaceId, and decoding of NextHopFaceId and CachePolicy.
/** \brief enables encoding of IncomingFaceId, and decoding of NextHopFaceId and CachePolicy
*/
bool allowLocalFields = false;
/** \brief Enables fragmentation.
/** \brief enables fragmentation
*/
bool allowFragmentation = false;
/** \brief Options for fragmentation.
/** \brief options for fragmentation
*/
LpFragmenter::Options fragmenterOptions;
/** \brief Enables reassembly.
/** \brief enables reassembly
*/
bool allowReassembly = false;
/** \brief Options for reassembly.
/** \brief options for reassembly
*/
LpReassembler::Options reassemblerOptions;
/** \brief Options for reliability.
/** \brief options for reliability
*/
LpReliability::Options reliabilityOptions;
/** \brief Enables send queue congestion detection and marking.
/** \brief enables send queue congestion detection and marking
*/
bool allowCongestionMarking = false;
/** \brief Starting value for congestion marking interval.
/** \brief starting value for congestion marking interval
*
* Packets are marked if the queue size stays above THRESHOLD for at least one INTERVAL.
*
@@ -143,7 +144,7 @@ public:
*/
time::nanoseconds baseCongestionMarkingInterval = 100_ms;
/** \brief Default congestion threshold in bytes.
/** \brief default congestion threshold in bytes
*
* Packets are marked if the queue size stays above THRESHOLD for at least one INTERVAL.
*
@@ -151,99 +152,96 @@ public:
*/
size_t defaultCongestionThreshold = 65536;
/** \brief Enables self-learning forwarding support.
/** \brief enables self-learning forwarding support
*/
bool allowSelfLearning = true;
/** \brief Overrides the MTU provided by Transport.
/** \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 this option are values >= #MIN_MTU, which can be validated before
* 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();
uint64_t C = 100000000; // 100Mbps
size_t vqSize = 20;
};
/** \brief %Counters provided by GenericLinkService.
/** \brief counters provided by GenericLinkService
*/
using Counters = GenericLinkServiceCounters;
explicit
GenericLinkService(const Options& options = {});
/** \brief Get the options used by GenericLinkService.
/** \brief get Options used by GenericLinkService
*/
const Options&
getOptions() const
{
return m_options;
}
getOptions() const;
/** \brief Sets the options used by GenericLinkService.
/** \brief sets Options used by GenericLinkService
*/
void
setOptions(const Options& options);
const Counters&
getCounters() const NFD_OVERRIDE_WITH_TESTS_ELSE_FINAL
{
return *this;
}
getCounters() const OVERRIDE_WITH_TESTS_ELSE_FINAL;
ssize_t
getEffectiveMtu() const NFD_OVERRIDE_WITH_TESTS_ELSE_FINAL;
getEffectiveMtu() const OVERRIDE_WITH_TESTS_ELSE_FINAL;
/** \brief Whether MTU can be overridden to the specified value.
/** \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;
NFD_PROTECTED_WITH_TESTS_ELSE_PRIVATE: // send path
/** \brief Request an IDLE packet to transmit pending service fields.
PROTECTED_WITH_TESTS_ELSE_PRIVATE: // send path
/** \brief request an IDLE packet to transmit pending service fields
*/
void
requestIdlePacket();
/** \brief Send an LpPacket.
/** \brief send an LpPacket
*/
void
sendLpPacket(lp::Packet&& pkt);
void
doSendInterest(const Interest& interest) NFD_OVERRIDE_WITH_TESTS_ELSE_FINAL;
doSendInterest(const Interest& interest) OVERRIDE_WITH_TESTS_ELSE_FINAL;
void
doSendData(const Data& data) NFD_OVERRIDE_WITH_TESTS_ELSE_FINAL;
doSendData(const Data& data) OVERRIDE_WITH_TESTS_ELSE_FINAL;
void
doSendNack(const ndn::lp::Nack& nack) NFD_OVERRIDE_WITH_TESTS_ELSE_FINAL;
doSendNack(const ndn::lp::Nack& nack) OVERRIDE_WITH_TESTS_ELSE_FINAL;
/** \brief Assign consecutive sequence numbers to LpPackets.
/** \brief assign consecutive sequence numbers to LpPackets
*/
void
assignSequences(std::vector<lp::Packet>& pkts);
private: // send path
/** \brief Encode link protocol fields from tags onto an outgoing LpPacket.
/** \brief encode link protocol fields from tags onto an outgoing LpPacket
* \param netPkt network-layer packet to extract tags from
* \param lpPacket LpPacket to add link protocol fields to
*/
void
encodeLpFields(const ndn::PacketBase& netPkt, lp::Packet& lpPacket);
/** \brief Send a complete network layer packet.
/** \brief send a complete network layer packet
* \param pkt LpPacket containing a complete network layer packet
* \param isInterest whether the network layer packet is an Interest
*/
void
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.
/** \brief if the send queue is found to be congested, add a congestion mark to the packet
* according to CoDel
* \sa https://tools.ietf.org/html/rfc8289
*/
void
@@ -251,9 +249,9 @@ private: // send path
private: // receive path
void
doReceivePacket(const Block& packet, const EndpointId& endpoint) NFD_OVERRIDE_WITH_TESTS_ELSE_FINAL;
doReceivePacket(const Block& packet, const EndpointId& endpoint) OVERRIDE_WITH_TESTS_ELSE_FINAL;
/** \brief Decode incoming network-layer packet.
/** \brief decode incoming network-layer packet
* \param netPkt reassembled network-layer packet
* \param firstPkt LpPacket of first fragment
* \param endpointId endpoint of peer who sent the packet
@@ -264,7 +262,7 @@ private: // receive path
void
decodeNetPacket(const Block& netPkt, const lp::Packet& firstPkt, const EndpointId& endpointId);
/** \brief Decode incoming Interest.
/** \brief decode incoming Interest
* \param netPkt reassembled network-layer packet; TLV-TYPE must be Interest
* \param firstPkt LpPacket of first fragment; must not have Nack field
* \param endpointId endpoint of peer who sent the Interest
@@ -277,7 +275,7 @@ private: // receive path
void
decodeInterest(const Block& netPkt, const lp::Packet& firstPkt, const EndpointId& endpointId);
/** \brief Decode incoming Interest.
/** \brief decode incoming Interest
* \param netPkt reassembled network-layer packet; TLV-TYPE must be Data
* \param firstPkt LpPacket of first fragment
* \param endpointId endpoint of peer who sent the Data
@@ -290,7 +288,7 @@ private: // receive path
void
decodeData(const Block& netPkt, const lp::Packet& firstPkt, const EndpointId& endpointId);
/** \brief Decode incoming Interest.
/** \brief decode incoming Interest
* \param netPkt reassembled network-layer packet; TLV-TYPE must be Interest
* \param firstPkt LpPacket of first fragment; must have Nack field
* \param endpointId endpoint of peer who sent the Nack
@@ -303,22 +301,38 @@ private: // receive path
void
decodeNack(const Block& netPkt, const lp::Packet& firstPkt, const EndpointId& endpointId);
NFD_PROTECTED_WITH_TESTS_ELSE_PRIVATE:
PROTECTED_WITH_TESTS_ELSE_PRIVATE:
Options m_options;
LpFragmenter m_fragmenter;
LpReassembler m_reassembler;
LpReliability m_reliability;
lp::Sequence m_lastSeqNo;
NFD_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
PUBLIC_WITH_TESTS_ELSE_PRIVATE:
/// Time to mark next packet due to send queue congestion
time::steady_clock::time_point m_nextMarkTime;
time::steady_clock::TimePoint m_nextMarkTime;
/// number of marked packets in the current incident of congestion
size_t m_nMarkedSinceInMarkingState;
friend LpReliability;
GlobalSP globalSp;
bool canScheduler = true;
std::function<void(std::shared_ptr<VirtualQueueItem>)> sendPacketCallback;
friend class LpReliability;
};
} // namespace nfd::face
inline const GenericLinkService::Options&
GenericLinkService::getOptions() const
{
return m_options;
}
inline const GenericLinkService::Counters&
GenericLinkService::getCounters() const
{
return *this;
}
} // namespace face
} // namespace nfd
#endif // NFD_DAEMON_FACE_GENERIC_LINK_SERVICE_HPP
+6 -4
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, Regents of the University of California,
* Copyright (c) 2014-2019, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -28,7 +28,8 @@
#include "internal-transport.hpp"
#include "common/global.hpp"
namespace nfd::face {
namespace nfd {
namespace face {
std::tuple<shared_ptr<Face>, shared_ptr<ndn::Face>>
makeInternalFace(ndn::KeyChain& clientKeyChain)
@@ -45,7 +46,8 @@ makeInternalFace(ndn::KeyChain& clientKeyChain)
auto clientFace = make_shared<ndn::Face>(clientTransport, getGlobalIoService(), clientKeyChain);
return {face, clientFace};
return std::make_tuple(face, clientFace);
}
} // namespace nfd::face
} // namespace face
} // namespace nfd
+9 -8
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, Regents of the University of California,
/**
* Copyright (c) 2014-2015, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -27,16 +27,16 @@
#define NFD_DAEMON_FACE_INTERNAL_FACE_HPP
#include "face.hpp"
#include <ndn-cxx/face.hpp>
namespace nfd::face {
namespace nfd {
namespace face {
/** \brief Make a pair of forwarder-side face and client-side face
* that are connected to each other.
/** \brief make a pair of forwarder-side face and client-side face
* that are connected with each other
*
* Network-layer packets sent by one face will be received by the other face
* after `io.poll()`.
* after io.poll().
*
* \param clientKeyChain A KeyChain used by client-side face to sign
* prefix registration commands.
@@ -45,6 +45,7 @@ namespace nfd::face {
std::tuple<shared_ptr<Face>, shared_ptr<ndn::Face>>
makeInternalFace(ndn::KeyChain& clientKeyChain);
} // namespace nfd::face
} // namespace face
} // namespace nfd
#endif // NFD_DAEMON_FACE_INTERNAL_FACE_HPP
+15 -3
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, 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,8 @@
#include "internal-transport.hpp"
#include "common/global.hpp"
namespace nfd::face {
namespace nfd {
namespace face {
NFD_LOG_MEMBER_INIT(InternalForwarderTransport, InternalForwarderTransport);
NFD_LOG_MEMBER_INIT(InternalClientTransport, InternalClientTransport);
@@ -122,4 +123,15 @@ InternalClientTransport::send(const Block& wire)
m_forwarder->receivePacket(wire);
}
} // namespace nfd::face
void
InternalClientTransport::send(const Block& header, const Block& payload)
{
ndn::EncodingBuffer encoder(header.size() + payload.size(), header.size() + payload.size());
encoder.appendByteArray(header.wire(), header.size());
encoder.appendByteArray(payload.wire(), payload.size());
send(encoder.block());
}
} // namespace face
} // namespace nfd
+9 -4
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, 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,8 @@
#include <ndn-cxx/transport/transport.hpp>
namespace nfd::face {
namespace nfd {
namespace face {
/** \brief Abstracts a transport that can be paired with another.
*/
@@ -100,7 +101,10 @@ public:
receivePacket(const Block& packet) final;
void
send(const Block& block) final;
send(const Block& wire) final;
void
send(const Block& header, const Block& payload) final;
void
close() final
@@ -124,6 +128,7 @@ private:
signal::ScopedConnection m_fwTransportStateConn;
};
} // namespace nfd::face
} // namespace face
} // namespace nfd
#endif // NFD_DAEMON_FACE_INTERNAL_TRANSPORT_HPP
+15 -5
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, 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,14 +26,23 @@
#include "link-service.hpp"
#include "face.hpp"
namespace nfd::face {
namespace nfd {
namespace face {
NFD_LOG_INIT(LinkService);
LinkService::~LinkService() = default;
LinkService::LinkService()
: m_face(nullptr)
, m_transport(nullptr)
{
}
LinkService::~LinkService()
{
}
void
LinkService::setFaceAndTransport(Face& face, Transport& transport) noexcept
LinkService::setFaceAndTransport(Face& face, Transport& transport)
{
BOOST_ASSERT(m_face == nullptr);
BOOST_ASSERT(m_transport == nullptr);
@@ -126,4 +135,5 @@ operator<<(std::ostream& os, const FaceLogHelper<LinkService>& flh)
return os;
}
} // namespace nfd::face
} // namespace face
} // namespace nfd
+77 -67
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, 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,162 +30,147 @@
#include "transport.hpp"
#include "common/counter.hpp"
namespace nfd::face {
namespace nfd {
namespace face {
/** \brief Counters provided by LinkService.
* \note The type name LinkServiceCounters is an implementation detail.
* Use LinkService::Counters in public API.
/** \brief counters provided by LinkService
* \note The type name 'LinkServiceCounters' is implementation detail.
* Use 'LinkService::Counters' in public API.
*/
class LinkServiceCounters
{
public:
/** \brief Count of incoming Interests.
/** \brief count of incoming Interests
*/
PacketCounter nInInterests;
/** \brief Count of outgoing Interests.
/** \brief count of outgoing Interests
*/
PacketCounter nOutInterests;
/** \brief Count of Interests dropped by reliability system for exceeding allowed number of retx.
/** \brief count of Interests dropped by reliability system for exceeding allowed number of retx
*/
PacketCounter nInterestsExceededRetx;
/** \brief Count of incoming Data packets.
/** \brief count of incoming Data packets
*/
PacketCounter nInData;
/** \brief Count of outgoing Data packets.
/** \brief count of outgoing Data packets
*/
PacketCounter nOutData;
/** \brief Count of incoming Nacks.
/** \brief count of incoming Nacks
*/
PacketCounter nInNacks;
/** \brief Count of outgoing Nacks.
/** \brief count of outgoing Nacks
*/
PacketCounter nOutNacks;
};
/**
* \brief The upper half of a Face.
* \sa Face, Transport
/** \brief the upper part of a Face
* \sa Face
*/
class LinkService : protected virtual LinkServiceCounters, noncopyable
{
public:
/**
* \brief %Counters provided by LinkService.
/** \brief counters provided by LinkService
*/
using Counters = LinkServiceCounters;
typedef LinkServiceCounters Counters;
public:
LinkService();
virtual
~LinkService();
/**
* \brief Set Face and Transport for this LinkService.
* \pre setFaceAndTransport() has not been called.
/** \brief set Face and Transport for LinkService
* \pre setFaceAndTransport has not been called
*/
void
setFaceAndTransport(Face& face, Transport& transport) noexcept;
setFaceAndTransport(Face& face, Transport& transport);
/**
* \brief Returns the Face to which this LinkService is attached.
/** \return Face to which this LinkService is attached
*/
const Face*
getFace() const noexcept
{
return m_face;
}
getFace() const;
/**
* \brief Returns the Transport to which this LinkService is attached.
/** \return Transport to which this LinkService is attached
*/
const Transport*
getTransport() const noexcept
{
return m_transport;
}
getTransport() const;
/**
* \brief Returns the Transport to which this LinkService is attached.
/** \return Transport to which this LinkService is attached
*/
Transport*
getTransport() noexcept
{
return m_transport;
}
getTransport();
virtual const Counters&
getCounters() const
{
return *this;
}
getCounters() const;
virtual ssize_t
getEffectiveMtu() const;
public: // upper interface to be used by forwarding
/** \brief Send Interest.
* \pre setFaceAndTransport() has been called.
/** \brief Send Interest
* \pre setTransport has been called
*/
void
sendInterest(const Interest& interest);
/** \brief Send Data.
* \pre setFaceAndTransport() has been called.
/** \brief Send Data
* \pre setTransport has been called
*/
void
sendData(const Data& data);
/** \brief Send Nack.
* \pre setFaceAndTransport() has been called.
/** \brief Send Nack
* \pre setTransport has been called
*/
void
sendNack(const ndn::lp::Nack& nack);
/** \brief Signals on Interest received.
/** \brief signals on Interest received
*/
signal::Signal<LinkService, Interest, EndpointId> afterReceiveInterest;
/** \brief Signals on Data received.
/** \brief signals on Data received
*/
signal::Signal<LinkService, Data, EndpointId> afterReceiveData;
/** \brief Signals on Nack received.
/** \brief signals on Nack received
*/
signal::Signal<LinkService, lp::Nack, EndpointId> afterReceiveNack;
/** \brief Signals on Interest dropped by reliability system for exceeding allowed number of retx.
/** \brief signals on Interest dropped by reliability system for exceeding allowed number of retx
*/
signal::Signal<LinkService, Interest> onDroppedInterest;
public: // lower interface to be invoked by Transport
/** \brief Performs LinkService specific operations to receive a lower-layer packet.
/** \brief performs LinkService specific operations to receive a lower-layer packet
*/
void
receivePacket(const Block& packet, const EndpointId& endpoint);
protected: // upper interface to be invoked in subclass (receive path termination)
/** \brief Delivers received Interest to forwarding.
/** \brief delivers received Interest to forwarding
*/
void
receiveInterest(const Interest& interest, const EndpointId& endpoint);
/** \brief Delivers received Data to forwarding.
/** \brief delivers received Data to forwarding
*/
void
receiveData(const Data& data, const EndpointId& endpoint);
/** \brief Delivers received Nack to forwarding.
/** \brief delivers received Nack to forwarding
*/
void
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.
/** \brief send a lower-layer packet via Transport
*/
void
sendPacket(const Block& packet);
@@ -195,17 +180,17 @@ protected:
notifyDroppedInterest(const Interest& packet);
private: // upper interface to be overridden in subclass (send path entrypoint)
/** \brief Performs LinkService specific operations to send an Interest.
/** \brief performs LinkService specific operations to send an Interest
*/
virtual void
doSendInterest(const Interest& interest) = 0;
/** \brief Performs LinkService specific operations to send a Data.
/** \brief performs LinkService specific operations to send a Data
*/
virtual void
doSendData(const Data& data) = 0;
/** \brief Performs LinkService specific operations to send a Nack.
/** \brief performs LinkService specific operations to send a Nack
*/
virtual void
doSendNack(const lp::Nack& nack) = 0;
@@ -215,10 +200,34 @@ private: // lower interface to be overridden in subclass
doReceivePacket(const Block& packet, const EndpointId& endpoint) = 0;
private:
Face* m_face = nullptr;
Transport* m_transport = nullptr;
Face* m_face;
Transport* m_transport;
};
inline const Face*
LinkService::getFace() const
{
return m_face;
}
inline const Transport*
LinkService::getTransport() const
{
return m_transport;
}
inline Transport*
LinkService::getTransport()
{
return m_transport;
}
inline const LinkService::Counters&
LinkService::getCounters() const
{
return *this;
}
inline ssize_t
LinkService::getEffectiveMtu() const
{
@@ -241,13 +250,14 @@ std::ostream&
operator<<(std::ostream& os, const FaceLogHelper<LinkService>& flh);
template<typename T>
std::enable_if_t<std::is_base_of_v<LinkService, T> && !std::is_same_v<LinkService, T>,
std::ostream&>
typename std::enable_if<std::is_base_of<LinkService, T>::value &&
!std::is_same<LinkService, T>::value, std::ostream&>::type
operator<<(std::ostream& os, const FaceLogHelper<T>& flh)
{
return os << FaceLogHelper<LinkService>(flh.obj);
}
} // namespace nfd::face
} // namespace face
} // namespace nfd
#endif // NFD_DAEMON_FACE_LINK_SERVICE_HPP
+19 -16
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, Regents of the University of California,
* Copyright (c) 2014-2018, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -28,7 +28,8 @@
#include <ndn-cxx/encoding/tlv.hpp>
namespace nfd::face {
namespace nfd {
namespace face {
NFD_LOG_INIT(LpFragmenter);
@@ -38,18 +39,18 @@ static_assert(lp::tlv::FragIndex < 253, "FragIndex TLV-TYPE must fit in 1 octet"
static_assert(lp::tlv::FragCount < 253, "FragCount TLV-TYPE must fit in 1 octet");
static_assert(lp::tlv::Fragment < 253, "Fragment TLV-TYPE must fit in 1 octet");
/**
* \brief Maximum overhead on a single fragment, not counting other NDNLPv2 headers.
/** \brief maximum overhead on a single fragment,
* not counting other NDNLPv2 headers
*/
constexpr size_t MAX_SINGLE_FRAG_OVERHEAD =
static const size_t MAX_SINGLE_FRAG_OVERHEAD =
1 + 9 + // LpPacket TLV-TYPE and TLV-LENGTH
1 + 1 + 8 + // Sequence TLV
1 + 9; // Fragment TLV-TYPE and TLV-LENGTH
/**
* \brief Maximum overhead of adding fragmentation to payload, not counting other NDNLPv2 headers.
/** \brief maximum overhead of adding fragmentation to payload,
* not counting other NDNLPv2 headers
*/
constexpr size_t MAX_FRAG_OVERHEAD =
static const size_t MAX_FRAG_OVERHEAD =
1 + 9 + // LpPacket TLV-TYPE and TLV-LENGTH
1 + 1 + 8 + // Sequence TLV
1 + 1 + 8 + // FragIndex TLV
@@ -85,17 +86,18 @@ LpFragmenter::fragmentPacket(const lp::Packet& packet, size_t mtu)
// fast path: fragmentation not needed
// To qualify for fast path, the packet must have space for adding a sequence number,
// because another NDNLPv2 feature may require the sequence number.
return {true, {packet}};
return std::make_tuple(true, std::vector<lp::Packet>{packet});
}
auto [netPktBegin, netPktEnd] = packet.get<lp::FragmentField>();
ndn::Buffer::const_iterator netPktBegin, netPktEnd;
std::tie(netPktBegin, netPktEnd) = packet.get<lp::FragmentField>();
size_t netPktSize = std::distance(netPktBegin, netPktEnd);
// compute size of other NDNLPv2 headers to be placed on the first fragment
size_t firstHeaderSize = 0;
const auto& packetWire = packet.wireEncode();
const Block& packetWire = packet.wireEncode();
if (packetWire.type() == lp::tlv::LpPacket) {
for (const auto& element : packetWire.elements()) {
for (const Block& element : packetWire.elements()) {
if (element.type() != lp::tlv::Fragment) {
firstHeaderSize += element.size();
}
@@ -105,7 +107,7 @@ LpFragmenter::fragmentPacket(const lp::Packet& packet, size_t mtu)
// compute payload size
if (MAX_FRAG_OVERHEAD + firstHeaderSize + 1 > mtu) { // 1-octet fragment
NFD_LOG_FACE_WARN("fragmentation error, MTU too small for first fragment: DROP");
return {false, {}};
return std::make_tuple(false, std::vector<lp::Packet>{});
}
size_t firstPayloadSize = std::min(netPktSize, mtu - firstHeaderSize - MAX_FRAG_OVERHEAD);
size_t payloadSize = mtu - MAX_FRAG_OVERHEAD;
@@ -115,7 +117,7 @@ LpFragmenter::fragmentPacket(const lp::Packet& packet, size_t mtu)
// compute FragCount
if (fragCount > m_options.nMaxFragments) {
NFD_LOG_FACE_WARN("fragmentation error, FragCount over limit: DROP");
return {false, {}};
return std::make_tuple(false, std::vector<lp::Packet>{});
}
// populate fragments
@@ -137,7 +139,7 @@ LpFragmenter::fragmentPacket(const lp::Packet& packet, size_t mtu)
}
BOOST_ASSERT(fragIndex == fragCount);
return {true, frags};
return std::make_tuple(true, frags);
}
std::ostream&
@@ -152,4 +154,5 @@ operator<<(std::ostream& os, const FaceLogHelper<LpFragmenter>& flh)
return os;
}
} // namespace nfd::face
} // namespace face
} // namespace nfd
+10 -8
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, Regents of the University of California,
* Copyright (c) 2014-2019, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -30,19 +30,20 @@
#include <ndn-cxx/lp/packet.hpp>
namespace nfd::face {
namespace nfd {
namespace face {
/** \brief Fragments network-layer packets into NDNLPv2 link-layer packets.
/** \brief fragments network-layer packets into NDNLPv2 link-layer packets
* \sa https://redmine.named-data.net/projects/nfd/wiki/NDNLPv2
*/
class LpFragmenter
{
public:
/** \brief %Options that control the behavior of LpFragmenter.
/** \brief Options that control the behavior of LpFragmenter
*/
struct Options
{
/** \brief Maximum number of fragments in a packet.
/** \brief maximum number of fragments in a packet
*/
size_t nMaxFragments = 400;
};
@@ -50,7 +51,7 @@ public:
explicit
LpFragmenter(const Options& options, const LinkService* linkService = nullptr);
/** \brief Set options for fragmenter.
/** \brief set options for fragmenter
*/
void
setOptions(const Options& options);
@@ -62,7 +63,7 @@ public:
const LinkService*
getLinkService() const;
/** \brief Fragments a network-layer packet into link-layer packets.
/** \brief fragments a network-layer packet into link-layer packets
* \param packet an LpPacket that contains a network-layer packet;
* must have Fragment field, must not have FragIndex and FragCount fields
* \param mtu maximum allowable LpPacket size after fragmentation and sequence number assignment
@@ -79,6 +80,7 @@ private:
std::ostream&
operator<<(std::ostream& os, const FaceLogHelper<LpFragmenter>& flh);
} // namespace nfd::face
} // namespace face
} // namespace nfd
#endif // NFD_DAEMON_FACE_LP_FRAGMENTER_HPP
+27 -19
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, Regents of the University of California,
* Copyright (c) 2014-2019, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -29,7 +29,8 @@
#include <numeric>
namespace nfd::face {
namespace nfd {
namespace face {
NFD_LOG_INIT(LpReassembler);
@@ -40,10 +41,12 @@ LpReassembler::LpReassembler(const LpReassembler::Options& options, const LinkSe
}
std::tuple<bool, Block, lp::Packet>
LpReassembler::receiveFragment(const EndpointId& remoteEndpoint, const lp::Packet& packet)
LpReassembler::receiveFragment(EndpointId remoteEndpoint, const lp::Packet& packet)
{
BOOST_ASSERT(packet.has<lp::FragmentField>());
static auto FALSE_RETURN = std::make_tuple(false, Block(), lp::Packet());
// read and check FragIndex and FragCount
uint64_t fragIndex = 0;
uint64_t fragCount = 1;
@@ -56,29 +59,29 @@ LpReassembler::receiveFragment(const EndpointId& remoteEndpoint, const lp::Packe
if (fragIndex >= fragCount) {
NFD_LOG_FACE_WARN("reassembly error, FragIndex>=FragCount: DROP");
return {false, {}, {}};
return FALSE_RETURN;
}
if (fragCount > m_options.nMaxFragments) {
NFD_LOG_FACE_WARN("reassembly error, FragCount over limit: DROP");
return {false, {}, {}};
return FALSE_RETURN;
}
// check for fast path
if (fragIndex == 0 && fragCount == 1) {
auto frag = packet.get<lp::FragmentField>();
Block netPkt({frag.first, frag.second});
return {true, netPkt, packet};
ndn::Buffer::const_iterator fragBegin, fragEnd;
std::tie(fragBegin, fragEnd) = packet.get<lp::FragmentField>();
Block netPkt(&*fragBegin, std::distance(fragBegin, fragEnd));
return std::make_tuple(true, netPkt, packet);
}
// check Sequence and compute message identifier
if (!packet.has<lp::SequenceField>()) {
NFD_LOG_FACE_WARN("reassembly error, Sequence missing: DROP");
return {false, {}, {}};
return FALSE_RETURN;
}
lp::Sequence messageIdentifier = packet.get<lp::SequenceField>() - fragIndex;
Key key(remoteEndpoint, messageIdentifier);
Key key = std::make_tuple(remoteEndpoint, messageIdentifier);
// add to PartialPacket
PartialPacket& pp = m_partialPackets[key];
@@ -90,13 +93,13 @@ LpReassembler::receiveFragment(const EndpointId& remoteEndpoint, const lp::Packe
else {
if (fragCount != pp.fragCount) {
NFD_LOG_FACE_WARN("reassembly error, FragCount changed: DROP");
return {false, {}, {}};
return FALSE_RETURN;
}
}
if (pp.fragments[fragIndex].has<lp::SequenceField>()) {
NFD_LOG_FACE_TRACE("fragment already received: DROP");
return {false, {}, {}};
return FALSE_RETURN;
}
pp.fragments[fragIndex] = packet;
@@ -107,13 +110,13 @@ LpReassembler::receiveFragment(const EndpointId& remoteEndpoint, const lp::Packe
Block reassembled = doReassembly(key);
lp::Packet firstFrag(std::move(pp.fragments[0]));
m_partialPackets.erase(key);
return {true, reassembled, firstFrag};
return std::make_tuple(true, reassembled, firstFrag);
}
// set drop timer
pp.dropTimer = getScheduler().schedule(m_options.reassemblyTimeout, [=] { timeoutPartialPacket(key); });
return {false, {}, {}};
return FALSE_RETURN;
}
Block
@@ -123,17 +126,21 @@ LpReassembler::doReassembly(const Key& key)
size_t payloadSize = std::accumulate(pp.fragments.begin(), pp.fragments.end(), 0U,
[&] (size_t sum, const lp::Packet& pkt) -> size_t {
auto [fragBegin, fragEnd] = pkt.get<lp::FragmentField>();
ndn::Buffer::const_iterator fragBegin, fragEnd;
std::tie(fragBegin, fragEnd) = pkt.get<lp::FragmentField>();
return sum + std::distance(fragBegin, fragEnd);
});
ndn::Buffer fragBuffer(payloadSize);
auto it = fragBuffer.begin();
for (const lp::Packet& frag : pp.fragments) {
auto [fragBegin, fragEnd] = frag.get<lp::FragmentField>();
ndn::Buffer::const_iterator fragBegin, fragEnd;
std::tie(fragBegin, fragEnd) = frag.get<lp::FragmentField>();
it = std::copy(fragBegin, fragEnd, it);
}
return Block(fragBuffer);
return Block(&*(fragBuffer.cbegin()), std::distance(fragBuffer.cbegin(), fragBuffer.cend()));
}
void
@@ -160,4 +167,5 @@ operator<<(std::ostream& os, const FaceLogHelper<LpReassembler>& flh)
return os;
}
} // namespace nfd::face
} // namespace face
} // namespace nfd
+25 -27
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, Regents of the University of California,
* Copyright (c) 2014-2019, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -30,26 +30,26 @@
#include <ndn-cxx/lp/packet.hpp>
namespace nfd::face {
namespace nfd {
namespace face {
/**
* \brief Reassembles fragmented network-layer packets.
* \sa https://redmine.named-data.net/projects/nfd/wiki/NDNLPv2
/** \brief reassembles fragmented network-layer packets
* \sa https://redmine.named-data.net/projects/nfd/wiki/NDNLPv2
*/
class LpReassembler : noncopyable
{
public:
/** \brief %Options that control the behavior of LpReassembler.
/** \brief Options that control the behavior of LpReassembler
*/
struct Options
{
/** \brief Maximum number of fragments in a packet.
/** \brief maximum number of fragments in a packet
*
* LpPackets with FragCount over this limit are dropped.
*/
size_t nMaxFragments = 400;
/** \brief Timeout before a partially reassembled packet is dropped.
/** \brief timeout before a partially reassembled packet is dropped
*/
time::nanoseconds reassemblyTimeout = 500_ms;
};
@@ -57,7 +57,7 @@ public:
explicit
LpReassembler(const Options& options, const LinkService* linkService = nullptr);
/** \brief Set options for reassembler.
/** \brief set options for reassembler
*/
void
setOptions(const Options& options);
@@ -69,7 +69,7 @@ public:
const LinkService*
getLinkService() const;
/** \brief Adds received fragment to the buffer.
/** \brief adds received fragment to the buffer
* \param remoteEndpoint endpoint that sent the packet
* \param packet received fragment; must have Fragment field
* \return a tuple containing:
@@ -79,26 +79,24 @@ public:
* \throw tlv::Error packet is malformed
*/
std::tuple<bool, Block, lp::Packet>
receiveFragment(const EndpointId& remoteEndpoint, const lp::Packet& packet);
receiveFragment(EndpointId remoteEndpoint, const lp::Packet& packet);
/** \brief Count of partial packets.
/** \brief count of partial packets
*/
size_t
size() const;
/**
* \brief Notifies before a partial packet is dropped due to timeout.
/** \brief signals before a partial packet is dropped due to timeout
*
* If a partial packet is incomplete and no new fragments are received within
* Options::reassemblyTimeout, the partial packet is dropped due to timeout.
* Before dropping the packet, this signal is emitted with the remote endpoint
* and the number of fragments being dropped.
* If a partial packet is incomplete and no new fragment is received
* within Options::reassemblyTimeout, it would be dropped due to timeout.
* Before it's erased, this signal is emitted with the remote endpoint,
* and the number of fragments being dropped.
*/
signal::Signal<LpReassembler, EndpointId, size_t> beforeTimeout;
private:
/**
* \brief Holds all fragments of a packet until reassembled.
/** \brief holds all fragments of packet until reassembled
*/
struct PartialPacket
{
@@ -108,13 +106,12 @@ private:
scheduler::ScopedEventId dropTimer;
};
/**
* \brief Index key for PartialPackets.
/** \brief index key for PartialPackets
*/
using Key = std::tuple<
EndpointId, // remote endpoint
lp::Sequence // message identifier (sequence number of the first fragment)
>;
typedef std::tuple<
EndpointId, // remoteEndpoint
lp::Sequence // message identifier (sequence of the first fragment)
> Key;
Block
doReassembly(const Key& key);
@@ -149,6 +146,7 @@ LpReassembler::size() const
return m_partialPackets.size();
}
} // namespace nfd::face
} // namespace face
} // namespace nfd
#endif // NFD_DAEMON_FACE_LP_REASSEMBLER_HPP
+23 -13
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, 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,7 +28,8 @@
#include "transport.hpp"
#include "common/global.hpp"
namespace nfd::face {
namespace nfd {
namespace face {
NFD_LOG_INIT(LpReliability);
@@ -79,7 +80,10 @@ LpReliability::handleOutgoing(std::vector<lp::Packet>& frags, lp::Packet&& pkt,
lp::Sequence txSeq = assignTxSequence(frag);
// Store LpPacket for future retransmissions
unackedFragsIt = m_unackedFrags.try_emplace(unackedFragsIt, txSeq, frag);
unackedFragsIt = m_unackedFrags.emplace_hint(unackedFragsIt,
std::piecewise_construct,
std::forward_as_tuple(txSeq),
std::forward_as_tuple(frag));
unackedFragsIt->second.sendTime = sendTime;
auto rto = m_rttEst.getEstimatedRto();
lp::Sequence seq = frag.get<lp::SequenceField>();
@@ -170,12 +174,12 @@ LpReliability::processIncomingPacket(const lp::Packet& pkt)
// Check for recent received Sequences to remove
auto now = time::steady_clock::now();
auto rto = m_rttEst.getEstimatedRto();
while (!m_recentRecvSeqsQueue.empty() &&
while (m_recentRecvSeqsQueue.size() > 0 &&
now > m_recentRecvSeqs[m_recentRecvSeqsQueue.front()] + rto) {
m_recentRecvSeqs.erase(m_recentRecvSeqsQueue.front());
m_recentRecvSeqsQueue.pop();
}
m_recentRecvSeqs.try_emplace(pktSequence, now);
m_recentRecvSeqs.emplace(pktSequence, now);
m_recentRecvSeqsQueue.push(pktSequence);
}
@@ -222,7 +226,7 @@ LpReliability::assignTxSequence(lp::Packet& frag)
{
lp::Sequence txSeq = ++m_lastTxSeqNo;
frag.set<lp::TxSequenceField>(txSeq);
if (!m_unackedFrags.empty() && m_lastTxSeqNo == m_firstUnackedFrag->first) {
if (m_unackedFrags.size() > 0 && m_lastTxSeqNo == m_firstUnackedFrag->first) {
NDN_THROW(std::length_error("TxSequence range exceeded"));
}
return m_lastTxSeqNo;
@@ -306,8 +310,10 @@ LpReliability::onLpPacketLost(lp::Sequence txSeq, bool isTimeout)
// Notify strategy of dropped Interest (if any)
if (netPkt->isInterest) {
BOOST_ASSERT(netPkt->pkt.has<lp::FragmentField>());
auto frag = netPkt->pkt.get<lp::FragmentField>();
onDroppedInterest(Interest(Block({frag.first, frag.second})));
ndn::Buffer::const_iterator fragBegin, fragEnd;
std::tie(fragBegin, fragEnd) = netPkt->pkt.get<lp::FragmentField>();
Block frag(&*fragBegin, std::distance(fragBegin, fragEnd));
onDroppedInterest(Interest(frag));
}
// Delete this LpPacket from m_unackedFrags
@@ -320,10 +326,13 @@ LpReliability::onLpPacketLost(lp::Sequence txSeq, bool isTimeout)
netPkt->didRetx = true;
// Move fragment to new TxSequence mapping
auto hint = m_firstUnackedFrag != m_unackedFrags.end() && m_firstUnackedFrag->first > newTxSeq
? m_firstUnackedFrag
: m_unackedFrags.end();
auto newTxFragIt = m_unackedFrags.try_emplace(hint, newTxSeq, txFrag.pkt);
auto newTxFragIt = m_unackedFrags.emplace_hint(
m_firstUnackedFrag != m_unackedFrags.end() && m_firstUnackedFrag->first > newTxSeq
? m_firstUnackedFrag
: m_unackedFrags.end(),
std::piecewise_construct,
std::forward_as_tuple(newTxSeq),
std::forward_as_tuple(txFrag.pkt));
auto& newTxFrag = newTxFragIt->second;
newTxFrag.retxCount = txFrag.retxCount + 1;
newTxFrag.netPkt = netPkt;
@@ -425,4 +434,5 @@ operator<<(std::ostream& os, const FaceLogHelper<LpReliability>& flh)
return os;
}
} // namespace nfd::face
} // namespace face
} // namespace nfd
+45 -42
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, 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,49 +34,44 @@
#include <queue>
namespace nfd::face {
namespace nfd {
namespace face {
class GenericLinkService;
/**
* \brief Provides for reliable sending and receiving of link-layer packets.
* \sa https://redmine.named-data.net/projects/nfd/wiki/NDNLPv2
/** \brief provides for reliable sending and receiving of link-layer packets
* \sa https://redmine.named-data.net/projects/nfd/wiki/NDNLPv2
*/
class LpReliability : noncopyable
{
public:
/// TxSequence TLV-TYPE (3 octets) + TLV-LENGTH (1 octet) + lp::Sequence (8 octets)
static constexpr size_t RESERVED_HEADER_SPACE = tlv::sizeOfVarNumber(lp::tlv::TxSequence) +
tlv::sizeOfVarNumber(sizeof(lp::Sequence)) +
sizeof(lp::Sequence);
struct Options
{
/** \brief Enables link-layer reliability.
/** \brief enables link-layer reliability
*/
bool isEnabled = false;
/** \brief Maximum number of retransmissions for an LpPacket.
/** \brief maximum number of retransmissions for an LpPacket
*/
size_t maxRetx = 3;
/** \brief Period between sending pending Acks in an IDLE packet.
/** \brief period between sending pending Acks in an IDLE packet
*/
time::nanoseconds idleAckTimerPeriod = 5_ms;
/** \brief A fragment is considered lost if this number of fragments with greater sequence
* numbers are acknowledged.
/** \brief a fragment is considered lost if this number of fragments with greater sequence
* numbers are acknowledged
*/
size_t seqNumLossThreshold = 3;
};
LpReliability(const Options& options, GenericLinkService* linkService);
/** \brief Signals on Interest dropped by reliability system for exceeding allowed number of retx.
/** \brief signals on Interest dropped by reliability system for exceeding allowed number of retx
*/
signal::Signal<LpReliability, Interest> onDroppedInterest;
/** \brief Set options for reliability.
/** \brief set options for reliability
*/
void
setOptions(const Options& options);
@@ -88,7 +83,7 @@ public:
const GenericLinkService*
getLinkService() const;
/** \brief Observe outgoing fragment(s) of a network packet and store for potential retransmission.
/** \brief observe outgoing fragment(s) of a network packet and store for potential retransmission
* \param frags fragments of network packet
* \param pkt encapsulated network packet
* \param isInterest whether the network packet is an Interest
@@ -96,26 +91,27 @@ public:
void
handleOutgoing(std::vector<lp::Packet>& frags, lp::Packet&& pkt, bool isInterest);
/** \brief Extract and parse all Acks and add Ack for contained Fragment (if any) to AckQueue.
/** \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
*/
bool
processIncomingPacket(const lp::Packet& pkt);
/** \brief Called by GenericLinkService to attach Acks onto an outgoing LpPacket.
/** \brief called by GenericLinkService to attach Acks onto an outgoing LpPacket
* \param pkt outgoing LpPacket to attach Acks to
* \param mtu MTU of the transport
* \param mtu MTU of the Transport
*/
void
piggyback(lp::Packet& pkt, ssize_t mtu);
NFD_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
PUBLIC_WITH_TESTS_ELSE_PRIVATE:
class UnackedFrag;
class NetPkt;
using UnackedFrags = std::map<lp::Sequence, UnackedFrag>;
/** \brief Assign TxSequence number to a fragment.
PUBLIC_WITH_TESTS_ELSE_PRIVATE:
/** \brief assign TxSequence number to a fragment
* \param frag fragment to assign TxSequence to
* \return assigned TxSequence number
* \throw std::length_error assigned TxSequence is equal to the start of the existing window
@@ -123,7 +119,7 @@ NFD_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
lp::Sequence
assignTxSequence(lp::Packet& frag);
/** \brief Start the idle Ack timer.
/** \brief start the idle Ack timer
*
* This timer requests an IDLE packet to acknowledge pending fragments not already piggybacked.
* It is called regularly on a period configured in Options::idleAckTimerPeriod. This allows Acks
@@ -132,22 +128,22 @@ NFD_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
void
startIdleAckTimer();
/** \brief Find and mark as lost fragments where a configurable number of Acks
* (Options::seqNumLossThreshold) have been received for greater TxSequence numbers.
/** \brief find and mark as lost fragments where a configurable number of Acks
* (\p m_options.seqNumLossThreshold) have been received for greater TxSequence numbers
* \param ackIt iterator pointing to acknowledged fragment
* \return vector containing TxSequences of fragments marked lost by this mechanism
*/
std::vector<lp::Sequence>
findLostLpPackets(UnackedFrags::iterator ackIt);
/** \brief Resend (or give up on) a lost fragment.
/** \brief resend (or give up on) a lost fragment
* \return vector of the TxSequences of fragments removed due to a network packet being removed
*/
std::vector<lp::Sequence>
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).
/** \brief remove the fragment with the given sequence number from the map of unacknowledged
* fragments, as well as its associated network packet (if any)
* \param fragIt iterator to acknowledged fragment
*
* If the given TxSequence marks the beginning of the send window, the window will be incremented.
@@ -156,7 +152,7 @@ NFD_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
void
onLpPacketAcknowledged(UnackedFrags::iterator fragIt);
/** \brief Delete a fragment from UnackedFrags and advance acknowledge window if necessary.
/** \brief delete a fragment from UnackedFrags and advance acknowledge window if necessary
* \param fragIt iterator to an UnackedFrag, must be dereferencable
* \post fragIt is not in m_unackedFrags
* \post if was equal to m_firstUnackedFrag,
@@ -166,9 +162,8 @@ NFD_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
void
deleteUnackedFrag(UnackedFrags::iterator fragIt);
NFD_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
/**
* \brief Contains a sent fragment that has not been acknowledged and associated data.
PUBLIC_WITH_TESTS_ELSE_PRIVATE:
/** \brief contains a sent fragment that has not been acknowledged and associated data
*/
class UnackedFrag
{
@@ -179,14 +174,13 @@ NFD_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
public:
lp::Packet pkt;
scheduler::ScopedEventId rtoTimer;
time::steady_clock::time_point sendTime;
time::steady_clock::TimePoint sendTime;
size_t retxCount;
size_t nGreaterSeqAcks; //!< number of Acks received for sequences greater than this fragment
shared_ptr<NetPkt> netPkt;
};
/**
* \brief Contains a network-layer packet with unacknowledged fragments.
/** \brief contains a network-layer packet with unacknowledged fragments
*/
class NetPkt
{
@@ -200,16 +194,24 @@ NFD_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
bool didRetx;
};
public:
/// TxSequence TLV-TYPE (3 octets) + TLV-LENGTH (1 octet) + lp::Sequence (8 octets)
static constexpr size_t RESERVED_HEADER_SPACE = tlv::sizeOfVarNumber(lp::tlv::TxSequence) +
tlv::sizeOfVarNumber(sizeof(lp::Sequence)) +
sizeof(lp::Sequence);
PUBLIC_WITH_TESTS_ELSE_PRIVATE:
Options m_options;
GenericLinkService* m_linkService;
UnackedFrags m_unackedFrags;
// An iterator that points to the first unacknowledged fragment in the current window. The window
// can wrap around so that the beginning of the window is at a TxSequence greater than other
// fragments in the window. When the window is moved past the last item in the iterator, the
// first fragment in the map will become the start of the window.
/** An iterator that points to the first unacknowledged fragment in the current window. The window
* can wrap around so that the beginning of the window is at a TxSequence greater than other
* fragments in the window. When the window is moved past the last item in the iterator, the
* first fragment in the map will become the start of the window.
*/
UnackedFrags::iterator m_firstUnackedFrag;
std::queue<lp::Sequence> m_ackQueue;
std::map<lp::Sequence, time::steady_clock::time_point> m_recentRecvSeqs;
std::map<lp::Sequence, time::steady_clock::TimePoint> m_recentRecvSeqs;
std::queue<lp::Sequence> m_recentRecvSeqsQueue;
lp::Sequence m_lastTxSeqNo;
scheduler::ScopedEventId m_idleAckTimer;
@@ -219,6 +221,7 @@ NFD_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
std::ostream&
operator<<(std::ostream& os, const FaceLogHelper<LpReliability>& flh);
} // namespace nfd::face
} // namespace face
} // namespace nfd
#endif // NFD_DAEMON_FACE_LP_RELIABILITY_HPP
+16 -13
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, Regents of the University of California,
* Copyright (c) 2014-2019, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -27,9 +27,9 @@
#include "common/global.hpp"
#include <cerrno> // for errno
#include <cstdio> // for snprintf()
#include <cstring> // for memcpy(), strerror(), strncpy()
#include <net/if.h> // for struct ifreq
#include <stdio.h> // for snprintf()
#include <sys/ioctl.h> // for ioctl()
#if defined(__linux__)
@@ -43,7 +43,8 @@
#endif
#endif
namespace nfd::face {
namespace nfd {
namespace face {
NFD_LOG_INIT(MulticastEthernetTransport);
@@ -65,19 +66,20 @@ MulticastEthernetTransport::MulticastEthernetTransport(const ndn::net::NetworkIn
NFD_LOG_FACE_DEBUG("Creating transport");
char filter[110];
// Note: "not vlan" must appear last in the filter expression, or the
// rest of the filter won't work as intended (see pcap-filter(7))
std::snprintf(filter, sizeof(filter),
"(ether proto 0x%x) && (ether dst %s) && (not ether src %s) && (not vlan)",
ethernet::ETHERTYPE_NDN,
m_destAddress.toString().data(),
m_srcAddress.toString().data());
// note #1: we cannot use std::snprintf because it's not available
// on some platforms (see #2299)
// note #2: "not vlan" must appear last in the filter expression, or the
// rest of the filter won't work as intended (see pcap-filter(7))
snprintf(filter, sizeof(filter),
"(ether proto 0x%x) && (ether dst %s) && (not ether src %s) && (not vlan)",
ethernet::ETHERTYPE_NDN,
m_destAddress.toString().data(),
m_srcAddress.toString().data());
m_pcap.setPacketFilter(filter);
BOOST_ASSERT(m_destAddress.isMulticast());
if (!m_destAddress.isBroadcast()) {
if (!m_destAddress.isBroadcast())
joinMulticastGroup();
}
}
void
@@ -145,4 +147,5 @@ MulticastEthernetTransport::joinMulticastGroup()
NDN_THROW(Error("Failed to join multicast group"));
}
} // namespace nfd::face
} // namespace face
} // namespace nfd
+5 -3
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, Regents of the University of California,
* Copyright (c) 2014-2017, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -28,7 +28,8 @@
#include "ethernet-transport.hpp"
namespace nfd::face {
namespace nfd {
namespace face {
/**
* @brief A multicast Transport that uses raw Ethernet II frames
@@ -56,6 +57,7 @@ private:
#endif
};
} // namespace nfd::face
} // namespace face
} // namespace nfd
#endif // NFD_DAEMON_FACE_MULTICAST_ETHERNET_TRANSPORT_HPP
+34 -9
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, 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,8 +29,7 @@
#include "common/privilege-helper.hpp"
#include <boost/asio/ip/multicast.hpp>
#include <boost/asio/ip/v6_only.hpp>
#include <boost/functional/hash.hpp>
#ifdef __linux__
#include <cerrno> // for errno
@@ -38,7 +37,8 @@
#include <sys/socket.h> // for setsockopt()
#endif // __linux__
namespace nfd::face {
namespace nfd {
namespace face {
NFD_LOG_MEMBER_INIT_SPECIALIZED((DatagramTransport<boost::asio::ip::udp, Multicast>), MulticastUdpTransport);
@@ -134,7 +134,7 @@ void
MulticastUdpTransport::openRxSocket(protocol::socket& sock,
const protocol::endpoint& multicastGroup,
const boost::asio::ip::address& localAddress,
const ndn::net::NetworkInterface* netif)
const shared_ptr<const ndn::net::NetworkInterface>& netif)
{
BOOST_ASSERT(!sock.is_open());
@@ -148,9 +148,16 @@ MulticastUdpTransport::openRxSocket(protocol::socket& sock,
localAddress.to_v4()));
}
else {
BOOST_ASSERT(multicastGroup.address().to_v6().scope_id() != 0);
BOOST_ASSERT(localAddress.is_v6());
sock.set_option(boost::asio::ip::v6_only(true));
sock.bind(multicastGroup);
#ifdef WITH_TESTS
// To simplify unit tests, we bind to the "any" IPv6 address if the supplied multicast
// address lacks a scope id. Calling bind() without a scope id would otherwise fail.
if (multicastGroup.address().to_v6().scope_id() == 0)
sock.bind(protocol::endpoint(boost::asio::ip::address_v6::any(), multicastGroup.port()));
else
#endif
sock.bind(multicastGroup);
sock.set_option(boost::asio::ip::multicast::join_group(multicastGroup.address().to_v6()));
}
@@ -161,7 +168,7 @@ MulticastUdpTransport::openRxSocket(protocol::socket& sock,
void
MulticastUdpTransport::openTxSocket(protocol::socket& sock,
const protocol::endpoint& localEndpoint,
const ndn::net::NetworkInterface* netif,
const shared_ptr<const ndn::net::NetworkInterface>& netif,
bool enableLoopback)
{
BOOST_ASSERT(!sock.is_open());
@@ -183,4 +190,22 @@ MulticastUdpTransport::openTxSocket(protocol::socket& sock,
}
}
} // namespace nfd::face
template<>
EndpointId
DatagramTransport<boost::asio::ip::udp, Multicast>::makeEndpointId(const protocol::endpoint& ep)
{
if (ep.address().is_v4()) {
return (static_cast<uint64_t>(ep.port()) << 32) |
static_cast<uint64_t>(ep.address().to_v4().to_ulong());
}
else {
size_t seed = 0;
const auto& addrBytes = ep.address().to_v6().to_bytes();
boost::hash_range(seed, addrBytes.begin(), addrBytes.end());
boost::hash_combine(seed, ep.port());
return seed;
}
}
} // namespace face
} // namespace nfd
+16 -13
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, 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,13 +28,21 @@
#include "datagram-transport.hpp"
#include <boost/asio/ip/udp.hpp>
#include <ndn-cxx/net/network-interface.hpp>
namespace nfd::face {
namespace nfd {
namespace face {
NFD_LOG_MEMBER_DECL_SPECIALIZED((DatagramTransport<boost::asio::ip::udp, Multicast>));
// Explicit specialization of makeEndpointId for the UDP multicast case.
// Note that this "shall be declared before the first use of the specialization
// that would cause an implicit instantiation to take place, in every translation
// unit in which such a use occurs".
template<>
EndpointId
DatagramTransport<boost::asio::ip::udp, Multicast>::makeEndpointId(const protocol::endpoint& ep);
/**
* \brief A Transport that communicates on a UDP multicast group
*/
@@ -62,22 +70,16 @@ public:
ssize_t
getSendQueueLength() final;
/**
* \brief Opens and configures the receive-side socket
*/
static void
openRxSocket(protocol::socket& sock,
const protocol::endpoint& multicastGroup,
const boost::asio::ip::address& localAddress = {},
const ndn::net::NetworkInterface* netif = nullptr);
const boost::asio::ip::address& localAddress,
const shared_ptr<const ndn::net::NetworkInterface>& netif = nullptr);
/**
* \brief Opens and configures the transmit-side socket
*/
static void
openTxSocket(protocol::socket& sock,
const protocol::endpoint& localEndpoint,
const ndn::net::NetworkInterface* netif = nullptr,
const shared_ptr<const ndn::net::NetworkInterface>& netif = nullptr,
bool enableLoopback = false);
private:
@@ -92,6 +94,7 @@ private:
protocol::socket m_sendSocket;
};
} // namespace nfd::face
} // namespace face
} // namespace nfd
#endif // NFD_DAEMON_FACE_MULTICAST_UDP_TRANSPORT_HPP
+11 -5
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, Regents of the University of California,
* Copyright (c) 2014-2019, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -27,7 +27,8 @@
#include "face-system.hpp"
#include "common/logger.hpp"
namespace nfd::face {
namespace nfd {
namespace face {
NFD_LOG_INIT(NetdevBound);
@@ -45,7 +46,9 @@ NetdevBound::processConfig(OptionalConfigSection configSection,
std::vector<Rule> rules;
if (configSection) {
int ruleIndex = 0;
for (const auto& [key, value] : *configSection) {
for (const auto& pair : *configSection) {
const std::string& key = pair.first;
const ConfigSection& value = pair.second;
if (key == "rule") {
rules.push_back(parseRule(ruleIndex++, value));
}
@@ -91,7 +94,9 @@ NetdevBound::parseRule(int index, const ConfigSection& confRule) const
bool hasWhitelist = false;
bool hasBlacklist = false;
for (const auto& [key, value] : confRule) {
for (const auto& pair : confRule) {
const std::string& key = pair.first;
const ConfigSection& value = pair.second;
if (key == "remote") {
try {
rule.remotes.emplace_back(value.get_value<std::string>());
@@ -140,4 +145,5 @@ NetdevBound::parseRule(int index, const ConfigSection& confRule) const
return rule;
}
} // namespace nfd::face
} // namespace face
} // namespace nfd
+9 -7
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, Regents of the University of California,
* Copyright (c) 2014-2019, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -28,11 +28,12 @@
#include "protocol-factory.hpp"
namespace nfd::face {
namespace nfd {
namespace face {
class FaceSystem;
/** \brief Manages netdev-bound faces.
/** \brief manages netdev-bound faces
*/
class NetdevBound : noncopyable
{
@@ -54,13 +55,13 @@ public:
NetdevBound(const ProtocolFactoryCtorParams& params, const FaceSystem& faceSystem);
/** \brief Process `face_system.netdev_bound` config section.
/** \brief process face_system.netdev_bound config section
*/
void
processConfig(OptionalConfigSection configSection,
FaceSystem::ConfigContext& context);
NFD_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
PUBLIC_WITH_TESTS_ELSE_PRIVATE:
struct Rule
{
std::vector<FaceUri> remotes;
@@ -70,7 +71,7 @@ NFD_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
Rule
parseRule(int index, const ConfigSection& confRule) const;
NFD_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
PUBLIC_WITH_TESTS_ELSE_PRIVATE:
const FaceSystem& m_faceSystem;
FaceCreatedCallback m_addFace;
shared_ptr<ndn::net::NetworkMonitor> m_netmon;
@@ -81,6 +82,7 @@ NFD_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
std::map<Key, shared_ptr<Face>> m_faces;
};
} // namespace nfd::face
} // namespace face
} // namespace nfd
#endif // NFD_DAEMON_FACE_NETDEV_BOUND_HPP
+9 -13
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, Regents of the University of California,
* Copyright (c) 2014-2019, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -29,9 +29,8 @@
#include <fnmatch.h>
#include <boost/lexical_cast.hpp>
namespace nfd::face {
namespace nfd {
namespace face {
NetworkPredicateBase::NetworkPredicateBase()
{
@@ -199,10 +198,8 @@ doesNetifMatchRule(const ndn::net::NetworkInterface& netif, const std::string& r
bool
NetworkInterfacePredicate::operator()(const ndn::net::NetworkInterface& netif) const
{
return std::any_of(m_whitelist.begin(), m_whitelist.end(),
[&netif] (const auto& rule) { return doesNetifMatchRule(netif, rule); }) &&
std::none_of(m_blacklist.begin(), m_blacklist.end(),
[&netif] (const auto& rule) { return doesNetifMatchRule(netif, rule); });
return std::any_of(m_whitelist.begin(), m_whitelist.end(), bind(&doesNetifMatchRule, std::cref(netif), _1)) &&
std::none_of(m_blacklist.begin(), m_blacklist.end(), bind(&doesNetifMatchRule, std::cref(netif), _1));
}
static bool
@@ -222,10 +219,9 @@ doesAddressMatchRule(const boost::asio::ip::address& address, const std::string&
bool
IpAddressPredicate::operator()(const boost::asio::ip::address& address) const
{
return std::any_of(m_whitelist.begin(), m_whitelist.end(),
[&address] (const auto& rule) { return doesAddressMatchRule(address, rule); }) &&
std::none_of(m_blacklist.begin(), m_blacklist.end(),
[&address] (const auto& rule) { return doesAddressMatchRule(address, rule); });
return std::any_of(m_whitelist.begin(), m_whitelist.end(), bind(&doesAddressMatchRule, std::cref(address), _1)) &&
std::none_of(m_blacklist.begin(), m_blacklist.end(), bind(&doesAddressMatchRule, std::cref(address), _1));
}
} // namespace nfd::face
} // namespace face
} // namespace nfd
+6 -5
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, Regents of the University of California,
* Copyright (c) 2014-2019, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -28,10 +28,10 @@
#include "core/common.hpp"
#include <boost/property_tree/ptree_fwd.hpp>
#include <ndn-cxx/net/network-interface.hpp>
namespace nfd::face {
namespace nfd {
namespace face {
class NetworkPredicateBase
{
@@ -79,7 +79,7 @@ private:
void
parseList(std::set<std::string>& set, std::initializer_list<std::pair<std::string, std::string>> list);
NFD_PUBLIC_WITH_TESTS_ELSE_PROTECTED:
PUBLIC_WITH_TESTS_ELSE_PROTECTED:
std::set<std::string> m_whitelist;
std::set<std::string> m_blacklist;
};
@@ -130,6 +130,7 @@ private:
isRuleValid(const std::string& key, const std::string& value) final;
};
} // namespace nfd::face
} // namespace face
} // namespace nfd
#endif // NFD_DAEMON_FACE_NETWORK_PREDICATE_HPP
+5 -3
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, Regents of the University of California,
* Copyright (c) 2014-2019, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -27,7 +27,8 @@
#include "null-link-service.hpp"
#include "null-transport.hpp"
namespace nfd::face {
namespace nfd {
namespace face {
shared_ptr<Face>
makeNullFace(const FaceUri& uri)
@@ -38,4 +39,5 @@ makeNullFace(const FaceUri& uri)
make_unique<NullTransport>(uri, uri, ndn::nfd::FACE_SCOPE_LOCAL));
}
} // namespace nfd::face
} // namespace face
} // namespace nfd
+7 -6
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, Regents of the University of California,
/**
* Copyright (c) 2014-2015, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -28,14 +28,15 @@
#include "face.hpp"
namespace nfd::face {
namespace nfd {
namespace face {
/**
* \brief Returns a Face that has no underlying transport and drops every packet.
/** \return a Face that has no underlying transport and drops every packet
*/
shared_ptr<Face>
makeNullFace(const FaceUri& uri = FaceUri("null://"));
} // namespace nfd::face
} // namespace face
} // namespace nfd
#endif // NFD_DAEMON_FACE_NULL_FACE_HPP
+5 -3
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, 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,7 +28,8 @@
#include "link-service.hpp"
namespace nfd::face {
namespace nfd {
namespace face {
/** \brief A LinkService that drops every packet.
*/
@@ -56,6 +57,7 @@ private:
}
};
} // namespace nfd::face
} // namespace face
} // namespace nfd
#endif // NFD_DAEMON_FACE_NULL_LINK_SERVICE_HPP
+5 -3
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, Regents of the University of California,
* Copyright (c) 2014-2019, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -25,7 +25,8 @@
#include "null-transport.hpp"
namespace nfd::face {
namespace nfd {
namespace face {
NFD_LOG_INIT(NullTransport);
@@ -42,4 +43,5 @@ NullTransport::NullTransport(const FaceUri& localUri, const FaceUri& remoteUri,
NFD_LOG_FACE_DEBUG("Creating transport");
}
} // namespace nfd::face
} // namespace face
} // namespace nfd
+8 -6
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, 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,11 +28,12 @@
#include "transport.hpp"
namespace nfd::face {
namespace nfd {
namespace face {
/** \brief A Transport that drops every packet.
*/
class NullTransport NFD_FINAL_UNLESS_WITH_TESTS : public Transport
class NullTransport FINAL_UNLESS_WITH_TESTS : public Transport
{
public:
explicit
@@ -43,18 +44,19 @@ public:
protected:
void
doClose() NFD_OVERRIDE_WITH_TESTS_ELSE_FINAL
doClose() OVERRIDE_WITH_TESTS_ELSE_FINAL
{
setState(TransportState::CLOSED);
}
private:
void
doSend(const Block&) NFD_OVERRIDE_WITH_TESTS_ELSE_FINAL
doSend(const Block&) OVERRIDE_WITH_TESTS_ELSE_FINAL
{
}
};
} // namespace nfd::face
} // namespace face
} // namespace nfd
#endif // NFD_DAEMON_FACE_NULL_TRANSPORT_HPP
+17 -22
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, Regents of the University of California,
* Copyright (c) 2014-2019, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -26,8 +26,6 @@
#include "pcap-helper.hpp"
#include "ethernet-protocol.hpp"
#include "common/privilege-helper.hpp"
#include <pcap/pcap.h>
#include <unistd.h>
@@ -35,9 +33,11 @@
#define PCAP_NETMASK_UNKNOWN 0xffffffff
#endif
namespace nfd::face {
namespace nfd {
namespace face {
PcapHelper::PcapHelper(const std::string& interfaceName)
: m_pcap(nullptr)
{
char errbuf[PCAP_ERRBUF_SIZE] = {};
m_pcap = pcap_create(interfaceName.data(), errbuf);
@@ -55,7 +55,7 @@ PcapHelper::PcapHelper(const std::string& interfaceName)
pcap_set_buffer_size(m_pcap, 4 * 1024 * 1024);
}
PcapHelper::~PcapHelper() noexcept
PcapHelper::~PcapHelper()
{
close();
}
@@ -63,15 +63,9 @@ PcapHelper::~PcapHelper() noexcept
void
PcapHelper::activate(int dlt)
{
PrivilegeHelper::runElevated([this] {
int ret = pcap_activate(m_pcap);
if (ret < 0)
NDN_THROW(Error("pcap_activate: " + std::string(pcap_statustostr(ret))));
});
char errbuf[PCAP_ERRBUF_SIZE] = {};
if (pcap_setnonblock(m_pcap, 1, errbuf) < 0)
NDN_THROW(Error("pcap_setnonblock: " + std::string(errbuf)));
int ret = pcap_activate(m_pcap);
if (ret < 0)
NDN_THROW(Error("pcap_activate: " + std::string(pcap_statustostr(ret))));
if (pcap_set_datalink(m_pcap, dlt) < 0)
NDN_THROW(Error("pcap_set_datalink: " + getLastError()));
@@ -81,7 +75,7 @@ PcapHelper::activate(int dlt)
}
void
PcapHelper::close() noexcept
PcapHelper::close()
{
if (m_pcap) {
pcap_close(m_pcap);
@@ -102,7 +96,7 @@ PcapHelper::getFd() const
}
std::string
PcapHelper::getLastError() const noexcept
PcapHelper::getLastError() const
{
return pcap_geterr(m_pcap);
}
@@ -130,19 +124,20 @@ PcapHelper::setPacketFilter(const char* filter) const
NDN_THROW(Error("pcap_setfilter: " + getLastError()));
}
std::tuple<span<const uint8_t>, std::string>
PcapHelper::readNextPacket() const noexcept
std::tuple<const uint8_t*, size_t, std::string>
PcapHelper::readNextPacket() const
{
pcap_pkthdr* header;
const uint8_t* packet;
int ret = pcap_next_ex(m_pcap, &header, &packet);
if (ret < 0)
return {span<uint8_t>{}, getLastError()};
return std::make_tuple(nullptr, 0, getLastError());
else if (ret == 0)
return {span<uint8_t>{}, "Nothing to read"};
return std::make_tuple(nullptr, 0, "timed out");
else
return {{packet, header->caplen}, ""};
return std::make_tuple(packet, header->caplen, "");
}
} // namespace nfd::face
} // namespace face
} // namespace nfd
+25 -18
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, Regents of the University of California,
/**
* Copyright (c) 2014-2017, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -28,7 +28,7 @@
#include "core/common.hpp"
#ifndef NFD_HAVE_LIBPCAP
#ifndef HAVE_LIBPCAP
#error "Cannot include this file when libpcap is not available"
#endif
@@ -36,7 +36,8 @@
struct pcap;
typedef pcap pcap_t;
namespace nfd::face {
namespace nfd {
namespace face {
/**
* @brief Helper class for dealing with libpcap handles.
@@ -47,7 +48,11 @@ public:
class Error : public std::runtime_error
{
public:
using std::runtime_error::runtime_error;
explicit
Error(const std::string& what)
: std::runtime_error(what)
{
}
};
/**
@@ -58,7 +63,7 @@ public:
explicit
PcapHelper(const std::string& interfaceName);
~PcapHelper() noexcept;
~PcapHelper();
/**
* @brief Start capturing packets.
@@ -74,7 +79,7 @@ public:
* @sa pcap_close(3pcap)
*/
void
close() noexcept;
close();
/**
* @brief Obtain a file descriptor that can be used in calls such as select(2) and poll(2).
@@ -93,7 +98,7 @@ public:
* @sa pcap_geterr(3pcap)
*/
std::string
getLastError() const noexcept;
getLastError() const;
/**
* @brief Get the number of packets dropped by the kernel, as reported by libpcap.
@@ -115,25 +120,27 @@ public:
/**
* @brief Read the next packet captured on the interface.
* @return If successful, returns a tuple containing a read-only view of the received
* packet bytes (including the link-layer header) and a second element that
* must be ignored. On failure, returns a tuple containing an empty span and
* the reason for the failure.
* @warning The returned span is valid only until the next call to this function.
* @return If successful, returns a tuple containing a pointer to the received packet
* (including the link-layer header) and the size of the packet; the third
* element must be ignored. On failure, returns a tuple containing nullptr,
* 0, and the reason for the failure.
* @warning The returned pointer must not be freed by the caller, and is valid only
* until the next call to this function.
* @sa pcap_next_ex(3pcap)
*/
std::tuple<span<const uint8_t>, std::string>
readNextPacket() const noexcept;
std::tuple<const uint8_t*, size_t, std::string>
readNextPacket() const;
operator pcap_t*() const noexcept
operator pcap_t*() const
{
return m_pcap;
}
private:
pcap_t* m_pcap = nullptr;
pcap_t* m_pcap;
};
} // namespace nfd::face
} // namespace face
} // namespace nfd
#endif // NFD_DAEMON_FACE_PCAP_HELPER_HPP
+5 -3
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, Regents of the University of California,
* Copyright (c) 2014-2019, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -28,7 +28,8 @@
#include <boost/range/adaptor/map.hpp>
#include <boost/range/algorithm/copy.hpp>
namespace nfd::face {
namespace nfd {
namespace face {
ProtocolFactory::Registry&
ProtocolFactory::getRegistry()
@@ -128,4 +129,5 @@ ProtocolFactory::doGetChannels() const
return {};
}
} // namespace nfd::face
} // namespace face
} // namespace nfd
+31 -41
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, Regents of the University of California,
* Copyright (c) 2014-2019, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -33,16 +33,15 @@
#include <boost/range/adaptor/map.hpp>
#include <boost/range/algorithm/copy.hpp>
namespace nfd::face {
namespace nfd {
namespace face {
/**
* \brief Parameters to ProtocolFactory constructor.
/** \brief Parameters to ProtocolFactory constructor
*
* Every ProtocolFactory subclass is expected to have a constructor that accepts
* ProtocolFactory::CtorParams, which in turn passes it to ProtocolFactory base class
* constructor. Parameters are passed as a struct rather than individually, so that
* any future changes in the list of parameters will not require updates to all subclass
* constructors.
* Every ProtocolFactory subclass is expected to have a constructor that accepts CtorParams,
* which in turn passes it to ProtocolFactory base class constructor. Parameters are passed as a
* struct rather than individually, so that a future change in list of parameters does not
* require updates to subclass constructors.
*/
struct ProtocolFactoryCtorParams
{
@@ -50,52 +49,44 @@ struct ProtocolFactoryCtorParams
shared_ptr<ndn::net::NetworkMonitor> netmon;
};
/**
* \brief Provides support for an underlying protocol.
/** \brief Provides support for an underlying protocol
* \sa FaceSystem
*
* A protocol factory provides support for an underlying protocol and owns Channel objects.
* It can process a subsection of the `face_system` configuration section and create channels
* and multicast faces accordingly.
*
* \sa FaceSystem
* A protocol factory provides support for an underlying protocol and owns Channel objects.
* It can process a subsection of face_system config section and create channels and multicast
* faces accordingly.
*/
class ProtocolFactory : noncopyable
{
public: // registry
using CtorParams = ProtocolFactoryCtorParams;
/**
* \brief Register a protocol factory type.
* \tparam PF subclass of ProtocolFactory
* \param id factory identifier
/** \brief Register a protocol factory type
* \tparam PF subclass of ProtocolFactory
* \param id factory identifier
*/
template<typename PF>
static void
registerType(const std::string& id = PF::getId())
{
BOOST_ASSERT(!id.empty());
auto r = getRegistry().insert_or_assign(id, [] (auto&&... p) {
return make_unique<PF>(std::forward<decltype(p)>(p)...);
});
BOOST_VERIFY(r.second);
Registry& registry = getRegistry();
BOOST_ASSERT(registry.count(id) == 0);
registry[id] = [] (const CtorParams& p) { return make_unique<PF>(p); };
}
/**
* \brief Create a protocol factory instance.
* \retval nullptr if a factory with the given \p id is not registered
/** \brief Create a protocol factory instance
* \retval nullptr if a factory with the given \p id is not registered
*/
static unique_ptr<ProtocolFactory>
create(const std::string& id, const CtorParams& params);
/**
* \brief Get all registered protocol factory IDs.
/** \brief Get all registered protocol factory ids
*/
[[nodiscard]] static std::set<std::string>
static std::set<std::string>
listRegistered();
public:
/**
* \brief Base class for all exceptions thrown by ProtocolFactory subclasses.
/** \brief Base class for all exceptions thrown by ProtocolFactory subclasses
*/
class Error : public std::runtime_error
{
@@ -110,20 +101,18 @@ public:
~ProtocolFactory() = 0;
#ifdef DOXYGEN
/**
* \brief Get the ID of this protocol factory.
/** \brief Get id for this protocol factory
*
* `face_system.<factory-id>` config section is processed by the protocol factory.
* face_system.factory-id config section is processed by the protocol factory.
*/
static const std::string&
getId() noexcept;
#endif
/**
* \brief Get FaceUri schemes accepted by this protocol factory.
/** \brief Get FaceUri schemes accepted by this protocol factory
*/
const std::set<std::string>&
getProvidedSchemes() const noexcept
getProvidedSchemes() const
{
return providedSchemes;
}
@@ -144,7 +133,7 @@ public:
struct CreateFaceRequest
{
FaceUri remoteUri;
std::optional<FaceUri> localUri;
optional<FaceUri> localUri;
FaceParams params;
};
@@ -257,7 +246,8 @@ protected:
shared_ptr<ndn::net::NetworkMonitor> netmon;
};
} // namespace nfd::face
} // namespace face
} // namespace nfd
/** \brief Registers a protocol factory
*
+534
View File
@@ -0,0 +1,534 @@
#include "queues.hpp"
#include "common/global.hpp"
#include <ndn-cxx/encoding/estimator.hpp>
namespace nfd
{
namespace face
{
NFD_LOG_INIT(QSCCPQueue);
bool VirtualQueue::push(int seq, const std::shared_ptr<const Interest> &interest,
uint64_t dataSize, bool needInsert)
{
this->recvBits += dataSize;
if (!needInsert)
{
return false;
}
if (this->currentSize >= this->size)
{
return false;
}
this->lastSeq = seq;
VirtualQueueItem vqi;
vqi.seq = seq;
vqi.item = interest;
vqi.queue = shared_from_this();
vqi.dataSize = dataSize;
this->innerQueue.push_back(vqi);
this->currentSize++;
auto serviceClass = interest->getServiceClass();
if (serviceClass && *serviceClass > 7)
{
this->penaltyFactor = 0.5;
}
return true;
}
WDRRQueue::WDRRQueue(uint32_t rateLimit, uint32_t availableBandwidth, double weight, const std::string &name,
uint32_t tos, size_t vqSize) : availableBandwidth(availableBandwidth),
weight(weight), name(name), tos(tos), vqSize(vqSize)
{
if (rateLimit > 0)
{
this->needRateLimit = true;
this->tokenBucket = std::make_shared<TokenBucket>(rateLimit, 20 * 1000 * 8, name);
// this->tokenBucket->start();
}
else
{
this->needRateLimit = false;
}
}
void WDRRQueue::updateAvailableBandwidth(uint32_t C)
{
this->availableBandwidth = C;
}
bool WDRRQueue::appendInterest(const Interest &interest)
{
std::string key = interest.getName().getPrefix(1).toUri();
if (this->virtualQueues.count(key) == 0)
{
this->virtualQueues[key] = std::make_shared<VirtualQueue>(1, this->vqSize);
this->virtualQueues[key]->tos = this->tos;
this->flows.push_back(key);
this->totalWeight += 1;
for (auto &item : this->virtualQueues)
{
item.second->objectRate = this->availableBandwidth * item.second->weight / this->totalWeight;
item.second->objectRate = item.second->objectRate * item.second->penaltyFactor;
}
}
bool needInsert = true;
if (this->cdt > 0 && this->currentPacketNum >= this->cdt)
{
needInsert = false;
}
uint64_t dataSize = 9000;
auto dsz = interest.getDsz();
if (dsz)
{
dataSize = *dsz;
}
this->recvBits += dataSize;
auto success = this->virtualQueues[key]->push(0, interest.shared_from_this(), dataSize, needInsert);
if (success)
{
this->currentPacketNum++;
}
return success;
}
std::shared_ptr<VirtualQueueItem> WDRRQueue::scheduleNext()
{
if (this->nextScheduleQueue >= this->flows.size())
{
for (auto &key : this->flows)
{
if (this->virtualQueues.count(key) == 0)
{
continue;
}
auto &item = this->virtualQueues[key];
item->balance += item->weight * item->penaltyFactor * this->MTU_QUANTA;
}
this->nextScheduleQueue = 0;
}
std::shared_ptr<VirtualQueue> selectedVQ = nullptr;
for (; this->nextScheduleQueue < this->flows.size(); this->nextScheduleQueue++)
{
auto &item = this->virtualQueues[this->flows[this->nextScheduleQueue]];
if (item->empty())
{
item->balance = 0;
continue;
}
if (item->front().dataSize < item->balance)
{
selectedVQ = item;
break;
}
if (item->len() > 10)
{
}
}
if (selectedVQ == nullptr && this->currentPacketNum > 0)
{
return scheduleNext();
}
if (selectedVQ != nullptr)
{
if (needRateLimit && !this->tokenBucket->use(selectedVQ->front().dataSize))
{
return nullptr;
}
auto item = std::make_shared<VirtualQueueItem>(selectedVQ->front());
selectedVQ->balance -= item->dataSize;
selectedVQ->pop();
if (selectedVQ->penaltyFactor < 0.9)
{
item->item->setServiceClass(selectedVQ->tos + 8);
}
this->sendBits += item->dataSize;
this->currentPacketNum--;
return item;
}
return nullptr;
}
uint32_t WDRRQueue::calObjectRate(bool getCurrentRateOnly)
{
uint32_t currentRate = this->recvBits * 1000 / this->calObjectRateInterval;
uint32_t currentSendRate = this->sendBits * 1000 / this->calObjectRateInterval;
if (getCurrentRateOnly)
{
return currentRate;
}
// if (currentRate > 0) {
// std::cout << "currentRate: " << currentRate << ", " << this->recvBits << "," << this->calObjectRateInterval << ", AvaliableBandwidth: " << this->availableBandwidth << std::endl;
// }
bool hasCleanFlow = false;
for (auto it = this->virtualQueues.begin(); it != this->virtualQueues.end();)
{
// std::cout << "key: " << it->first << ", recvBits" << it->second->recvBits << std::endl;
if (it->second->recvBits == 0 && it->second->empty())
{
this->totalWeight -= it->second->weight;
this->virtualQueues.erase(it++); // here is the key
// std::cout << "do clean: " << std::endl;
hasCleanFlow = true;
}
else
{
it++;
}
}
if (hasCleanFlow)
{
this->flows.resize(this->virtualQueues.size());
int idx = 0;
for (auto it = this->virtualQueues.begin(); it != this->virtualQueues.end(); it++, idx++)
{
this->flows[idx] = it->first;
}
}
double totalHightSpeedFlowWeight = 0;
int hightSppedFlowNum = 0;
uint32_t consumeRate = 0;
double totalWeightThisTerm = 0;
for (auto &item : this->virtualQueues)
{
totalWeightThisTerm += (item.second->weight * item.second->penaltyFactor);
}
for (auto &item : this->virtualQueues)
{
item.second->objectRate = this->availableBandwidth * item.second->weight * item.second->penaltyFactor / totalWeightThisTerm;
item.second->currentFlowRate = item.second->recvBits * 1000 / this->calObjectRateInterval;
item.second->currentRatio = item.second->currentFlowRate * 1.0 / item.second->objectRate;
auto targetHighFlowRate = (item.second->objectRate - 500000) * 1.0 / item.second->objectRate;
if (item.second->currentRatio > targetHighFlowRate)
{
if (item.second->penaltyFactor > 0.99)
{
hightSppedFlowNum++;
totalHightSpeedFlowWeight += item.second->weight;
}
consumeRate += item.second->objectRate;
}
else
{
consumeRate += item.second->currentFlowRate;
}
NFD_LOG_DEBUG(this->name << " => currentRate: " << item.second->currentFlowRate << ", consumerRate: " << consumeRate << ", objectRate: " << item.second->objectRate << ", availableBandwidth" << this->availableBandwidth << ", weight: " << item.second->weight << ", totalWeight: " << this->totalWeight << ", currentSendRate: " << currentSendRate);
// std::cout << this->name << " => currentRate: " << item.second->currentFlowRate << ", consumerRate: " << consumeRate << ", objectRate: " << item.second->objectRate <<
// ", availableBandwidth" << this->availableBandwidth << ", weight: " << item.second->weight << ", totalWeight: " <<
// this->totalWeight << ", currentSendRate: " << currentSendRate << std::endl;
item.second->recvBits = 0;
}
if (consumeRate < this->availableBandwidth && hightSppedFlowNum > 0)
{
auto remainRate = this->availableBandwidth - consumeRate;
for (auto &item : this->virtualQueues)
{
if (item.second->penaltyFactor > 0.99 && item.second->currentRatio > 0.8)
{
item.second->objectRate += (remainRate * item.second->weight / totalHightSpeedFlowWeight);
}
NFD_LOG_DEBUG(this->name << " => objectRate: " << item.second->objectRate << ", remainRate: " << remainRate << ", item.weight: " << item.second->weight << ", totalWeight: " << totalHightSpeedFlowWeight);
// std::cout << this->name << " => objectRate: " << item.second->objectRate << ", remainRate: " <<
// remainRate << ", item.weight: " << item.second->weight << ", totalWeight: " << totalHightSpeedFlowWeight << std::endl;
}
}
for (auto &item : this->virtualQueues)
{
if (item.second->currentFlowRate * 1.0 / item.second->objectRate > item.second->gredyRatio)
{
if (item.second->gredyTimes < item.second->gredyThreshold)
{
item.second->gredyTimes++;
}
if (item.second->gredyTimes == item.second->gredyThreshold)
{
// std::cout << item.first << ": PenaltyFactor => " << item.second->gredyTimes << ", currentFlowRate: " << item.second->currentFlowRate << ", objectRate: " << item.second->objectRate << std::endl;
item.second->penaltyFactor = 0.5;
item.second->size = 20;
}
}
else
{
if (item.second->gredyTimes > 0)
{
item.second->gredyTimes--;
}
}
}
// if (this->virtualQueues.size() > 0)
// {
// std::cout << "\n\n=====================: " << this->availableBandwidth << std::endl;
// }
for (auto &item : this->virtualQueues)
{
if (item.second->penaltyFactor > 0.99)
{
auto rate = this->calDiscountFactor(item.second->currentSize * 1.0 / item.second->size);
item.second->objectRate *= rate;
}
// std::cout << item.first << ", currentFlowRate: " << item.second->currentFlowRate
// << ", objectRate: " << item.second->objectRate << ", size: " << item.second->currentSize
// << ", weight: " << item.second->weight << ", penaltyFactor: " << item.second->penaltyFactor
// << std::endl;
}
// if (this->virtualQueues.size() > 0)
// {
// std::cout << "\n----------------------" << std::endl;
// }
this->sendBits = 0;
this->recvBits = 0;
return currentRate;
}
uint32_t WDRRQueue::scheduleOnePacketForWFQ(uint32_t totalLastSeq)
{
if (this->cachePacketForWFQ != nullptr)
{
return this->cachePacketForWFQ->seq;
}
if (this->currentPacketNum == 0)
{
return UINT32_MAX;
}
this->cachePacketForWFQ = this->scheduleNext();
if (this->cachePacketForWFQ == nullptr)
{
return UINT32_MAX;
}
if (this->lastSeq == -1)
{
this->lastSeq = totalLastSeq;
}
this->cachePacketForWFQ->seq = this->lastSeq + 1.0 * this->cachePacketForWFQ->dataSize / this->weight;
if (this->currentPacketNum == 0)
{
this->lastSeq = -1;
}
else
{
this->lastSeq = this->cachePacketForWFQ->seq;
}
return this->cachePacketForWFQ->seq;
}
std::shared_ptr<VirtualQueueItem> DelaySensitiveServiceSP::scheduleNext()
{
auto res = this->CS7Queue->scheduleNext();
if (res == nullptr)
{
res = this->CS6Queue->scheduleNext();
}
if (res == nullptr)
{
res = this->EFQueue->scheduleNext();
}
return res;
}
uint32_t DelaySensitiveServiceSP::calObjectRate(bool getCurrentRateOnly)
{
uint32_t res = this->CS7Queue->calObjectRate(getCurrentRateOnly);
res += this->CS6Queue->calObjectRate(getCurrentRateOnly);
res += this->EFQueue->calObjectRate(getCurrentRateOnly);
return res;
}
std::shared_ptr<VirtualQueueItem> WFQQueue::scheduleNext()
{
std::shared_ptr<WDRRQueue> selectedQueue = nullptr;
uint32_t currentMinSeq = UINT32_MAX;
for (auto &queue : this->queues)
{
uint32_t seq = queue->scheduleOnePacketForWFQ(this->lastSeq);
if (seq < currentMinSeq)
{
currentMinSeq = seq;
selectedQueue = queue;
}
}
if (selectedQueue != nullptr)
{
this->lastSeq = currentMinSeq;
auto selectPacket = selectedQueue->frontForWFQ(this->lastSeq);
selectedQueue->popForWFQ();
return selectPacket;
}
return nullptr;
}
uint32_t WFQQueue::calObjectRate(uint32_t availableBandwidth)
{
int totalRate = 0;
double totalHightSpeedFlowWeight = 0;
int hightSppedFlowNum = 0;
double totalHasFlowQueueWeight = 0;
int hasFlowQueueNum = 0;
for (auto &queue : this->queues)
{
auto recvRate = queue->calObjectRate(true);
queue->originAvaliableBandwidth = (queue->getWeight() / totalWeight) * availableBandwidth;
auto remainRate = queue->getRemainBandwidthRate(queue->originAvaliableBandwidth);
if (remainRate < 0.2)
{
hightSppedFlowNum++;
totalHightSpeedFlowWeight += queue->getWeight();
totalRate += queue->originAvaliableBandwidth;
}
else if (remainRate < 0.95)
{
hasFlowQueueNum++;
totalHasFlowQueueWeight += queue->getWeight();
totalRate += recvRate;
}
else
{
totalRate += recvRate;
}
}
this->availableBandwidth = availableBandwidth;
int remain = this->availableBandwidth - totalRate;
if (hightSppedFlowNum > 0)
{
// std::cout << "high speed flow num: " << hightSppedFlowNum << ", totalHightSpeedFlowWeight: " << totalHightSpeedFlowWeight << std::endl;
for (auto &queue : this->queues)
{
if (queue->getRemainBandwidthRate(queue->originAvaliableBandwidth) < 0.2)
{
// std::cout << "!!!" << queue->getWeight() * remain * 1.0 / totalHightSpeedFlowWeight +
// queue->originAvaliableBandwidth << std::endl;
queue->updateAvailableBandwidth(
queue->getWeight() * remain * 1.0 / totalHightSpeedFlowWeight +
queue->originAvaliableBandwidth);
}
else
{
queue->updateAvailableBandwidth(queue->originAvaliableBandwidth);
}
}
}
else
{
// std::cout << "has flow queue num: " << hasFlowQueueNum << ", totalHasFlowQueueWeight: " << totalHasFlowQueueWeight << std::endl;
for (auto &queue : this->queues)
{
if (queue->getRemainBandwidthRate(queue->originAvaliableBandwidth) < 0.95)
{
queue->updateAvailableBandwidth(
queue->getWeight() * remain * 1.0 / totalHasFlowQueueWeight +
queue->originAvaliableBandwidth);
}
else
{
queue->updateAvailableBandwidth(queue->originAvaliableBandwidth);
}
}
}
uint32_t currentTotalRate = 0;
for (auto &queue : this->queues)
{
currentTotalRate += queue->calObjectRate(false);
}
return currentTotalRate;
}
std::shared_ptr<VirtualQueueItem> GlobalSP::scheduleNext()
{
std::shared_ptr<VirtualQueueItem> selectedPacket = this->delaySensitiveServiceSp.scheduleNext();
if (selectedPacket == nullptr)
{
selectedPacket = wfqQueue.scheduleNext();
}
if (selectedPacket != nullptr)
{
selectedPacket->waitNsTime = selectedPacket->dataSize * 1000000000.0 / this->availableBandwidth + 1;
// 计算 DR => DR'(/p, j) = min(OR(/p, j), RR(/p, j) / sum(RR(/p)) * sum(AR(/p)))
auto currentObjectRate = selectedPacket->queue->objectRate;
auto downstreamRate = selectedPacket->item->getDownstreamRate();
if (downstreamRate)
{
if (*downstreamRate > currentObjectRate)
{
selectedPacket->item->setDownstreamRate(currentObjectRate);
}
}
else
{
selectedPacket->item->setDownstreamRate(currentObjectRate);
}
}
return selectedPacket;
}
std::shared_ptr<WDRRQueue> GlobalSP::getQueueByTos(int tosValue)
{
switch (tosValue)
{
case 0:
return this->delaySensitiveServiceSp.getCS7Queue();
case 1:
return this->delaySensitiveServiceSp.getCS6Queue();
case 2:
return this->delaySensitiveServiceSp.getEFQueue();
case 3:
return this->wfqQueue.getAF4Queue();
case 4:
return this->wfqQueue.getAF3Queue();
case 5:
return this->wfqQueue.getAF2Queue();
case 6:
return this->wfqQueue.getAF1Queue();
case 7:
default:
return this->wfqQueue.getBEQueue();
}
}
bool GlobalSP::appendInterest(const Interest &interest)
{
int serviceClass = 7;
if (interest.getServiceClass())
{
serviceClass = (*interest.getServiceClass()) % 8;
}
// std::cout << "appendInterest => serviceClass: " << serviceClass << std::endl;
return this->getQueueByTos(serviceClass)->appendInterest(interest);
}
void GlobalSP::receiveInterest(const Interest &interest)
{
ndn::encoding::EncodingEstimator estimator;
auto size = interest.wireEncode(estimator) + 9;
this->interestBytes += size;
// std::cout << this << "receiveInterest => size: " << size << ", interestBytes: " << this->interestBytes << std::endl;
}
void GlobalSP::calObjectRate(bool getCurrentRateOnly)
{
// getScheduler().schedule(time::nanoseconds(1000000 * this->calObjectRateInterval),
// [this] { this->calObjectRate(false); });
uint32_t remain = this->availableBandwidth;
remain -= this->interestBytes * 8000 / this->calObjectRateInterval;
this->interestBytes = 0;
remain -= this->delaySensitiveServiceSp.calObjectRate(false);
// std::cout << "AvaliableBandwidth: " << this->availableBandwidth << ", remain: " << remain << ", interestBytes" << this->interestBytes << std::endl;
this->wfqQueue.calObjectRate(remain);
}
void GlobalSP::assignObjectRate(const Data &data)
{
std::string key = data.getName().getPrefix(1).toUri();
int serviceClass = 7;
if (data.getServiceClass())
{
serviceClass = (*data.getServiceClass()) % 8;
}
// std::cout << "assignObjectRate => serviceClass: " << serviceClass << std::endl;
auto objectRate = this->getQueueByTos(serviceClass)->getObjectRateByFlowKey(key);
auto targetRate = data.getTargetRate();
if (!targetRate || *targetRate > objectRate)
{
data.setTargetRate(objectRate);
}
}
}
}
+309
View File
@@ -0,0 +1,309 @@
#ifndef NS_QUEUES_HPP
#define NS_QUEUES_HPP
#include <deque>
#include <unordered_map>
#include <memory>
#include <iostream>
#include "common/global.hpp"
#include "link-service.hpp"
#include <ndn-cxx/lp/tags.hpp>
#include "TokenBucket.hpp"
namespace nfd {
namespace face {
class VirtualQueue;
struct VirtualQueueItem {
int seq;
std::shared_ptr<const Interest> item;
uint32_t dataSize;
uint32_t waitNsTime;
std::shared_ptr<VirtualQueue> queue;
};
class VirtualQueue : public std::enable_shared_from_this<VirtualQueue>{
public:
explicit VirtualQueue(double weight, int size) :
std::enable_shared_from_this<VirtualQueue>(),
penaltyFactor(1.0),
weight(weight), size(size), currentSize(0), lastSeq(0),
C(0) {
}
void enableTokenBucket(uint32_t limitRate) {
this->C = limitRate;
}
bool push(int seq, const std::shared_ptr<const Interest>& interest,
uint64_t dataSize, bool needInsert);
bool empty() {
return this->innerQueue.empty();
}
uint32_t frontSeq() {
if (this->innerQueue.empty()) {
return this->lastSeq;
}
return this->innerQueue.front().seq;
}
VirtualQueueItem front() {
return this->innerQueue.front();
}
uint32_t backSeq() {
return this->lastSeq;
}
VirtualQueueItem back() {
return this->innerQueue.back();
}
void pop() {
if (this->currentSize <= 0) {
return;
}
this->currentSize--;
this->innerQueue.pop_front();
}
void popBack() {
if (this->currentSize <= 0) {
return;
}
this->currentSize--;
this->innerQueue.pop_back();
}
int len() {
return this->innerQueue.size();
}
void setLastSeq(uint32_t seq) {
this->lastSeq = seq;
}
uint32_t getLastSeq() {
return lastSeq;
}
void setWeight(double weight) {
this->weight = weight;
}
double getWeight() {
return this->weight;
}
public:
uint32_t objectRate;
double penaltyFactor = 1.0;
uint32_t gredyTimes = 0;
double gredyRatio = 1.2;
double gredyThreshold = 10;
double weight = 1.0;
uint32_t tos = 5;
double balance = 0;
int size = 0;
int currentSize = 0;
uint32_t recvBits = 0;
uint32_t currentFlowRate = 0;
double currentRatio = 0.0;
private:
uint32_t lastSeq;
int C;
std::deque<VirtualQueueItem> innerQueue;
};
class WDRRQueue {
public:
explicit WDRRQueue(uint32_t rateLimit, uint32_t availableBandwidth, double weight, const std::string& name,
uint32_t tos = 5, size_t vqSize = 20);
void updateAvailableBandwidth(uint32_t C);
bool appendInterest(const Interest &interest);
std::shared_ptr<VirtualQueueItem> scheduleNext();
uint32_t calObjectRate(bool getCurrentRateOnly);
void setCDTLimit(int cdt) {
this->cdt = cdt;
}
uint32_t scheduleOnePacketForWFQ(uint32_t totalLastSeq);
std::shared_ptr<VirtualQueueItem> frontForWFQ(uint32_t totalLastSeq) {
if (this->cachePacketForWFQ == nullptr) {
this->scheduleOnePacketForWFQ(totalLastSeq);
}
return this->cachePacketForWFQ;
}
void popForWFQ() {
this->cachePacketForWFQ = nullptr;
}
double getRemainBandwidthRate(double curAvailableBandWidth) {
auto currentRate = this->calObjectRate(true);
if (currentRate > curAvailableBandWidth) {
return 0;
}
return (curAvailableBandWidth - currentRate) * 1.0 / curAvailableBandWidth;
}
uint32_t getRemainBandwidth() {
return this->availableBandwidth - this->calObjectRate(true);
}
double getWeight() {
return this->weight;
}
uint32_t getAvailableBandwidth() {
return this->availableBandwidth;
}
/**
* @brief
*
* \sigma=\frac{1}{3}\arccot\funcapply(8\delta-4)
* @param x
* @return double
*/
double calDiscountFactor(double x) {
return 1.0 / 3 * (M_PI / 2 - atan(8 * x - 4)) + 0.034;
}
/**
* @brief Get the Object Rate By Flow Key object
*
* @param key
* @return uint32_t
*/
uint32_t getObjectRateByFlowKey(const std::string& key) {
if (this->virtualQueues.count(key) == 0) {
std::cout << "FUCK: " << key << ", count: " << this->virtualQueues.size() <<
", flow: " << this->flows.size() << "availbleRate: " << this->availableBandwidth << std::endl;
return 0;
}
return this->virtualQueues[key]->objectRate;
}
void triggerByCurrentTime(long currentTime) {
if (this->needRateLimit) {
this->tokenBucket->generateTokenByCurrentTime(currentTime);
}
}
public:
double originAvaliableBandwidth = 0;
private:
std::unordered_map<std::string, std::shared_ptr<VirtualQueue>> virtualQueues;
std::vector<std::string> flows;
size_t nextScheduleQueue = 0;
std::shared_ptr<TokenBucket> tokenBucket;
uint32_t availableBandwidth;
// uint32_t extraBandwidth;
double weight;
std::string name;
uint32_t tos = 5;
bool needRateLimit;
double totalWeight;
uint32_t sendBits = 0;
uint32_t recvBits = 0;
int vqSize = 20;
int cdt = -1;
int currentPacketNum = 0;
int MTU_QUANTA = 2 * 1000 * 8;
int calObjectRateInterval = 100;
int64_t lastSeq = -1;
std::shared_ptr<VirtualQueueItem> cachePacketForWFQ = nullptr;
};
class DelaySensitiveServiceSP {
public:
explicit DelaySensitiveServiceSP(uint32_t availableBandwidth, size_t vqSize = 20) {
this->CS7Queue = std::make_shared<WDRRQueue>((uint32_t) (0.2 * availableBandwidth), (uint32_t) (0.2 * availableBandwidth), 2, "CS7", 2, vqSize);
this->CS6Queue = std::make_shared<WDRRQueue>((uint32_t) (0.2 * availableBandwidth), (uint32_t) (0.2 * availableBandwidth), 2, "CS6", 1, vqSize);
this->EFQueue = std::make_shared<WDRRQueue>((uint32_t) (0.3 * availableBandwidth), (uint32_t) (0.3 * availableBandwidth), 3, "EF", 0, vqSize);
}
std::shared_ptr<VirtualQueueItem> scheduleNext();
uint32_t calObjectRate(bool getCurrentRateOnly);
std::shared_ptr<WDRRQueue> getCS7Queue() {
return this->CS7Queue;
}
std::shared_ptr<WDRRQueue> getCS6Queue() {
return this->CS6Queue;
}
std::shared_ptr<WDRRQueue> getEFQueue() {
return this->EFQueue;
}
void triggerByCurrentTime(long currentTime) {
this->CS7Queue->triggerByCurrentTime(currentTime);
this->CS6Queue->triggerByCurrentTime(currentTime);
this->EFQueue->triggerByCurrentTime(currentTime);
}
private:
std::shared_ptr<WDRRQueue> CS7Queue;
std::shared_ptr<WDRRQueue> CS6Queue;
std::shared_ptr<WDRRQueue> EFQueue;
};
class WFQQueue {
public:
explicit WFQQueue(uint32_t availableBandwidth, size_t vqSize) :
AF4Weight(5),
AF3Weight(4),
AF2Weight(3),
AF1Weight(2),
BEWeight(1),
totalWeight(AF4Weight + AF3Weight + AF2Weight + AF1Weight + BEWeight),
queues(5),
lastSeq(0),
availableBandwidth(availableBandwidth) {
this->queues[0] = std::make_shared<WDRRQueue>(0, availableBandwidth * AF4Weight / totalWeight, 5, "AF4", 3, vqSize);
this->queues[1] = std::make_shared<WDRRQueue>(0, availableBandwidth * AF3Weight / totalWeight, 4, "AF3", 4, vqSize);
this->queues[2] = std::make_shared<WDRRQueue>(0, availableBandwidth * AF2Weight / totalWeight, 3, "AF2", 5, vqSize);
this->queues[3] = std::make_shared<WDRRQueue>(0, availableBandwidth * AF1Weight / totalWeight, 2, "AF1", 6, vqSize);
this->queues[4] = std::make_shared<WDRRQueue>(0, availableBandwidth * BEWeight / totalWeight, 1, "BE", 7, vqSize);
for (auto &queue: this->queues) {
queue->setCDTLimit(this->cdt);
}
}
std::shared_ptr<VirtualQueueItem> scheduleNext();
uint32_t calObjectRate(uint32_t availableBandwidth);
std::shared_ptr<WDRRQueue> getAF4Queue() {
return this->queues[0];
}
std::shared_ptr<WDRRQueue> getAF3Queue() {
return this->queues[1];
}
std::shared_ptr<WDRRQueue> getAF2Queue() {
return this->queues[2];
}
std::shared_ptr<WDRRQueue> getAF1Queue() {
return this->queues[3];
}
std::shared_ptr<WDRRQueue> getBEQueue() {
return this->queues[4];
}
private:
double AF4Weight = 5;
double AF3Weight = 4;
double AF2Weight = 3;
double AF1Weight = 2;
double BEWeight = 1;
double totalWeight = 15;
std::vector<std::shared_ptr<WDRRQueue>> queues;
uint32_t lastSeq;
u_int32_t availableBandwidth;
int cdt = 200;
int hql;
};
class GlobalSP {
public:
explicit GlobalSP(uint32_t availableBandwidth, size_t vqSize = 20) :
delaySensitiveServiceSp(availableBandwidth, vqSize),
wfqQueue(availableBandwidth, vqSize),
availableBandwidth(availableBandwidth) {
lastTriggerTime = getCurrentTime();
// getScheduler().schedule(time::nanoseconds(1000000 * this->calObjectRateInterval),
// [this] { this->calObjectRate(false); });
}
std::shared_ptr<VirtualQueueItem> scheduleNext();
bool appendInterest(const Interest &interest);
void receiveInterest(const Interest &interest);
void calObjectRate(bool getCurrentRateOnly);
std::shared_ptr<WDRRQueue> getQueueByTos(int tosValue);
long getCurrentTime() {
return std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch()).count();
}
void triggerCalObjectRate() {
auto currentTime = getCurrentTime();
this->delaySensitiveServiceSp.triggerByCurrentTime(currentTime);
if (currentTime - lastTriggerTime > calObjectRateInterval) {
this->calObjectRate(false);
lastTriggerTime = currentTime;
}
}
void assignObjectRate(const Data &data);
private:
DelaySensitiveServiceSP delaySensitiveServiceSp;
WFQQueue wfqQueue;
int calObjectRateInterval = 100;
uint32_t availableBandwidth;
size_t interestBytes = 0;
long lastTriggerTime = 0;
};
}
}
#endif //NS_QUEUES_HPP
+5 -3
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, Regents of the University of California,
* Copyright (c) 2014-2018, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -33,7 +33,8 @@
#include <sys/socket.h>
#endif
namespace nfd::face {
namespace nfd {
namespace face {
ssize_t
getTxQueueLength(int fd)
@@ -52,4 +53,5 @@ getTxQueueLength(int fd)
return queueLength;
}
} // namespace nfd::face
} // namespace face
} // namespace nfd
+6 -4
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, Regents of the University of California,
* Copyright (c) 2014-2018, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -28,9 +28,10 @@
#include "core/common.hpp"
namespace nfd::face {
namespace nfd {
namespace face {
/** \brief Obtain send queue length from a specified system socket.
/** \brief obtain send queue length from a specified system socket
* \param fd file descriptor of the socket
* \retval QUEUE_UNSUPPORTED this operation is unsupported on the current platform
* \retval QUEUE_ERROR there was an error retrieving the send queue length
@@ -41,6 +42,7 @@ namespace nfd::face {
ssize_t
getTxQueueLength(int fd);
} // namespace nfd::face
} // namespace face
} // namespace nfd
#endif // NFD_DAEMON_FACE_SOCKET_UTILS_HPP
+9 -10
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, 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,9 +32,8 @@
#include <queue>
#include <boost/asio/write.hpp>
namespace nfd::face {
namespace nfd {
namespace face {
/** \brief Implements Transport for stream-based protocols.
*
@@ -44,7 +43,7 @@ template<class Protocol>
class StreamTransport : public Transport
{
public:
using protocol = Protocol;
typedef Protocol protocol;
/** \brief Construct stream transport.
*
@@ -245,17 +244,16 @@ StreamTransport<T>::handleReceive(const boost::system::error_code& error,
NFD_LOG_FACE_TRACE("Received: " << nBytesReceived << " bytes");
m_receiveBufferSize += nBytesReceived;
auto bufferView = ndn::make_span(m_receiveBuffer, m_receiveBufferSize);
size_t offset = 0;
bool isOk = true;
while (offset < bufferView.size()) {
while (m_receiveBufferSize - offset > 0) {
Block element;
std::tie(isOk, element) = Block::fromBuffer(bufferView.subspan(offset));
std::tie(isOk, element) = Block::fromBuffer(m_receiveBuffer + offset, m_receiveBufferSize - offset);
if (!isOk)
break;
offset += element.size();
BOOST_ASSERT(offset <= bufferView.size());
BOOST_ASSERT(offset <= m_receiveBufferSize);
this->receive(element);
}
@@ -334,6 +332,7 @@ StreamTransport<T>::getSendQueueBytes() const
return m_sendQueueBytes;
}
} // namespace nfd::face
} // namespace face
} // namespace nfd
#endif // NFD_DAEMON_FACE_STREAM_TRANSPORT_HPP
+13 -19
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, 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,9 +29,8 @@
#include "tcp-transport.hpp"
#include "common/global.hpp"
#include <boost/asio/ip/v6_only.hpp>
namespace nfd::face {
namespace nfd {
namespace face {
NFD_LOG_INIT(TcpChannel);
@@ -99,19 +98,10 @@ TcpChannel::connect(const tcp::Endpoint& remoteEndpoint,
void
TcpChannel::createFace(ip::tcp::socket&& socket,
const FaceParams& params,
const FaceCreatedCallback& onFaceCreated,
const FaceCreationFailedCallback& onFaceCreationFailed)
const FaceCreatedCallback& onFaceCreated)
{
shared_ptr<Face> face;
boost::system::error_code ec;
tcp::Endpoint remoteEndpoint = socket.remote_endpoint(ec);
if (ec) {
NFD_LOG_CHAN_DEBUG("Retrieve socket remote endpoint failed: " << ec.message());
if (onFaceCreationFailed) {
onFaceCreationFailed(500, "Retrieve socket remote endpoint failed: " + ec.message());
}
return;
}
tcp::Endpoint remoteEndpoint = socket.remote_endpoint();
auto it = m_channelFaces.find(remoteEndpoint);
if (it == m_channelFaces.end()) {
@@ -133,13 +123,16 @@ TcpChannel::createFace(ip::tcp::socket&& socket,
if (params.defaultCongestionThreshold) {
options.defaultCongestionThreshold = *params.defaultCongestionThreshold;
}
if (params.bandwidth) {
options.C = *params.bandwidth;
}
auto linkService = make_unique<GenericLinkService>(options);
auto faceScope = m_determineFaceScope(socket.local_endpoint().address(),
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(weak_from_this());
face->setChannel(shared_from_this()); // use weak_from_this() in C++17
m_channelFaces[remoteEndpoint] = face;
connectFaceClosedSignal(*face, [this, remoteEndpoint] { m_channelFaces.erase(remoteEndpoint); });
@@ -184,7 +177,7 @@ TcpChannel::handleAccept(const boost::system::error_code& error,
FaceParams params;
params.persistency = ndn::nfd::FACE_PERSISTENCY_ON_DEMAND;
createFace(std::move(m_socket), params, onFaceCreated, onAcceptFailed);
createFace(std::move(m_socket), params, onFaceCreated);
// prepare accepting the next connection
accept(onFaceCreated, onAcceptFailed);
@@ -211,7 +204,7 @@ TcpChannel::handleConnect(const boost::system::error_code& error,
}
NFD_LOG_CHAN_TRACE("Connected to " << socket->remote_endpoint());
createFace(std::move(*socket), params, onFaceCreated, onConnectFailed);
createFace(std::move(*socket), params, onFaceCreated);
}
void
@@ -229,4 +222,5 @@ TcpChannel::handleConnectTimeout(const tcp::Endpoint& remoteEndpoint,
onConnectFailed(504, "Connection timed out");
}
} // namespace nfd::face
} // namespace face
} // namespace nfd
+12 -12
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, Regents of the University of California,
* Copyright (c) 2014-2019, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -28,13 +28,13 @@
#include "channel.hpp"
#include <boost/asio/ip/tcp.hpp>
namespace nfd {
namespace nfd::tcp {
using Endpoint = boost::asio::ip::tcp::endpoint;
} // namespace nfd::tcp
namespace tcp {
typedef boost::asio::ip::tcp::endpoint Endpoint;
} // namespace tcp
namespace nfd::face {
namespace face {
using DetermineFaceScopeFromAddress = std::function<ndn::nfd::FaceScope(const boost::asio::ip::address& local,
const boost::asio::ip::address& remote)>;
@@ -46,7 +46,7 @@ using DetermineFaceScopeFromAddress = std::function<ndn::nfd::FaceScope(const bo
* connections (TcpChannel::listen needs to be called for that
* to work) or explicitly after using TcpChannel::connect method.
*/
class TcpChannel final : public Channel
class TcpChannel : public Channel
{
public:
/**
@@ -59,13 +59,13 @@ public:
DetermineFaceScopeFromAddress determineFaceScope);
bool
isListening() const final
isListening() const override
{
return m_acceptor.is_open();
}
size_t
size() const final
size() const override
{
return m_channelFaces.size();
}
@@ -98,8 +98,7 @@ private:
void
createFace(boost::asio::ip::tcp::socket&& socket,
const FaceParams& params,
const FaceCreatedCallback& onFaceCreated,
const FaceCreationFailedCallback& onFaceCreationFailed);
const FaceCreatedCallback& onFaceCreated);
void
accept(const FaceCreatedCallback& onFaceCreated,
@@ -133,6 +132,7 @@ private:
DetermineFaceScopeFromAddress m_determineFaceScope;
};
} // namespace nfd::face
} // namespace face
} // namespace nfd
#endif // NFD_DAEMON_FACE_TCP_CHANNEL_HPP
+7 -8
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, Regents of the University of California,
* Copyright (c) 2014-2019, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -25,9 +25,8 @@
#include "tcp-factory.hpp"
#include <boost/lexical_cast.hpp>
namespace nfd::face {
namespace nfd {
namespace face {
namespace ip = boost::asio::ip;
@@ -201,9 +200,8 @@ TcpFactory::createChannel(const tcp::Endpoint& endpoint)
if (it != m_channels.end())
return it->second;
auto channel = make_shared<TcpChannel>(endpoint, m_wantCongestionMarking, [this] (auto&&... args) {
return determineFaceScopeFromAddresses(std::forward<decltype(args)>(args)...);
});
auto channel = make_shared<TcpChannel>(endpoint, m_wantCongestionMarking,
bind(&TcpFactory::determineFaceScopeFromAddresses, this, _1, _2));
m_channels[endpoint] = channel;
return channel;
}
@@ -224,4 +222,5 @@ TcpFactory::determineFaceScopeFromAddresses(const boost::asio::ip::address& loca
return ndn::nfd::FACE_SCOPE_NON_LOCAL;
}
} // namespace nfd::face
} // namespace face
} // namespace nfd
+14 -10
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, Regents of the University of California,
* Copyright (c) 2014-2018, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -29,11 +29,12 @@
#include "protocol-factory.hpp"
#include "tcp-channel.hpp"
namespace nfd::face {
namespace nfd {
namespace face {
/** \brief Protocol factory for TCP over IPv4 and IPv6.
/** \brief Protocol factory for TCP over IPv4 and IPv6
*/
class TcpFactory final : public ProtocolFactory
class TcpFactory : public ProtocolFactory
{
public:
static const std::string&
@@ -42,7 +43,7 @@ public:
using ProtocolFactory::ProtocolFactory;
/**
* \brief Create TCP-based channel using tcp::Endpoint.
* \brief Create TCP-based channel using tcp::Endpoint
*
* tcp::Endpoint is really an alias for boost::asio::ip::tcp::endpoint.
*
@@ -56,17 +57,19 @@ public:
createChannel(const tcp::Endpoint& localEndpoint);
private:
/** \brief process face_system.tcp config section
*/
void
doProcessConfig(OptionalConfigSection configSection,
FaceSystem::ConfigContext& context) final;
FaceSystem::ConfigContext& context) override;
void
doCreateFace(const CreateFaceRequest& req,
const FaceCreatedCallback& onCreated,
const FaceCreationFailedCallback& onFailure) final;
const FaceCreationFailedCallback& onFailure) override;
std::vector<shared_ptr<const Channel>>
doGetChannels() const final;
doGetChannels() const override;
ndn::nfd::FaceScope
determineFaceScopeFromAddresses(const boost::asio::ip::address& local,
@@ -76,10 +79,11 @@ private:
bool m_wantCongestionMarking = false;
std::map<tcp::Endpoint, shared_ptr<TcpChannel>> m_channels;
NFD_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
PUBLIC_WITH_TESTS_ELSE_PRIVATE:
IpAddressPredicate m_local;
};
} // namespace nfd::face
} // namespace face
} // namespace nfd
#endif // NFD_DAEMON_FACE_TCP_FACTORY_HPP
+13 -7
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, Regents of the University of California,
* Copyright (c) 2014-2019, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -31,16 +31,21 @@
#include <sys/ioctl.h>
#endif
namespace nfd::face {
namespace nfd {
namespace face {
NFD_LOG_MEMBER_INIT_SPECIALIZED(StreamTransport<boost::asio::ip::tcp>, TcpTransport);
time::milliseconds TcpTransport::s_initialReconnectWait = 1_s;
time::milliseconds TcpTransport::s_maxReconnectWait = 5_min;
float TcpTransport::s_reconnectWaitMultiplier = 2.0f;
TcpTransport::TcpTransport(protocol::socket&& socket,
ndn::nfd::FacePersistency persistency,
ndn::nfd::FaceScope faceScope)
: StreamTransport(std::move(socket))
, m_remoteEndpoint(m_socket.remote_endpoint())
, m_nextReconnectWait(INITIAL_RECONNECT_DELAY)
, m_nextReconnectWait(s_initialReconnectWait)
{
this->setLocalUri(FaceUri(m_socket.local_endpoint()));
this->setRemoteUri(FaceUri(m_socket.remote_endpoint()));
@@ -160,7 +165,7 @@ TcpTransport::handleReconnect(const boost::system::error_code& error)
}
m_reconnectEvent.cancel();
m_nextReconnectWait = INITIAL_RECONNECT_DELAY;
m_nextReconnectWait = s_initialReconnectWait;
this->setLocalUri(FaceUri(m_socket.local_endpoint()));
NFD_LOG_FACE_TRACE("TCP connection reestablished");
@@ -177,8 +182,8 @@ TcpTransport::handleReconnectTimeout()
// exponentially back off the reconnection timer
m_nextReconnectWait =
std::min(time::duration_cast<time::milliseconds>(m_nextReconnectWait * RECONNECT_DELAY_MULTIPLIER),
MAX_RECONNECT_DELAY);
std::min(time::duration_cast<time::milliseconds>(m_nextReconnectWait * s_reconnectWaitMultiplier),
s_maxReconnectWait);
// do this asynchronously because there could be some callbacks still pending
getGlobalIoService().post([this] { reconnect(); });
@@ -191,4 +196,5 @@ TcpTransport::doClose()
StreamTransport::doClose();
}
} // namespace nfd::face
} // namespace face
} // namespace nfd
+17 -20
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, Regents of the University of California,
* Copyright (c) 2014-2019, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -28,9 +28,8 @@
#include "stream-transport.hpp"
#include <boost/asio/ip/tcp.hpp>
namespace nfd::face {
namespace nfd {
namespace face {
NFD_LOG_MEMBER_DECL_SPECIALIZED(StreamTransport<boost::asio::ip::tcp>);
@@ -41,7 +40,7 @@ NFD_LOG_MEMBER_DECL_SPECIALIZED(StreamTransport<boost::asio::ip::tcp>);
* state is set to DOWN, and the connection is retried periodically with exponential backoff
* until it is reestablished
*/
class TcpTransport NFD_FINAL_UNLESS_WITH_TESTS : public StreamTransport<boost::asio::ip::tcp>
class TcpTransport FINAL_UNLESS_WITH_TESTS : public StreamTransport<boost::asio::ip::tcp>
{
public:
TcpTransport(protocol::socket&& socket, ndn::nfd::FacePersistency persistency, ndn::nfd::FaceScope faceScope);
@@ -62,31 +61,28 @@ protected:
void
handleError(const boost::system::error_code& error) final;
NFD_PROTECTED_WITH_TESTS_ELSE_PRIVATE:
NFD_VIRTUAL_WITH_TESTS void
PROTECTED_WITH_TESTS_ELSE_PRIVATE:
VIRTUAL_WITH_TESTS void
reconnect();
NFD_VIRTUAL_WITH_TESTS void
VIRTUAL_WITH_TESTS void
handleReconnect(const boost::system::error_code& error);
NFD_VIRTUAL_WITH_TESTS void
VIRTUAL_WITH_TESTS void
handleReconnectTimeout();
NFD_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
/**
* \brief Delay before the first reconnection attempt after the TCP connection has been severed
PUBLIC_WITH_TESTS_ELSE_PRIVATE:
/** \brief how long to wait before the first reconnection attempt after the TCP connection has been severed
*/
static constexpr time::milliseconds INITIAL_RECONNECT_DELAY = 1_s;
static time::milliseconds s_initialReconnectWait;
/**
* \brief Maximum amount of time to wait before a reconnection attempt
/** \brief maximum amount of time to wait before a reconnection attempt
*/
static constexpr time::milliseconds MAX_RECONNECT_DELAY = 5_min;
static time::milliseconds s_maxReconnectWait;
/**
* \brief Multiplier for the exponential backoff of the reconnection timer
/** \brief multiplier for the exponential backoff of the reconnection timer
*/
static constexpr float RECONNECT_DELAY_MULTIPLIER = 2.0f;
static float s_reconnectWaitMultiplier;
private:
typename protocol::endpoint m_remoteEndpoint;
@@ -100,6 +96,7 @@ private:
time::milliseconds m_nextReconnectWait;
};
} // namespace nfd::face
} // namespace face
} // namespace nfd
#endif // NFD_DAEMON_FACE_TCP_TRANSPORT_HPP
+19 -6
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, 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,8 @@
#include "transport.hpp"
#include "face.hpp"
namespace nfd::face {
namespace nfd {
namespace face {
NFD_LOG_INIT(Transport);
@@ -49,12 +50,23 @@ operator<<(std::ostream& os, TransportState state)
}
}
Transport::Transport() = default;
Transport::Transport()
: m_face(nullptr)
, m_service(nullptr)
, m_scope(ndn::nfd::FACE_SCOPE_NONE)
, m_persistency(ndn::nfd::FACE_PERSISTENCY_NONE)
, m_linkType(ndn::nfd::LINK_TYPE_NONE)
, m_mtu(MTU_INVALID)
, m_sendQueueCapacity(QUEUE_UNSUPPORTED)
, m_state(TransportState::UP)
, m_expirationTime(time::steady_clock::TimePoint::max())
{
}
Transport::~Transport() = default;
void
Transport::setFaceAndLinkService(Face& face, LinkService& service) noexcept
Transport::setFaceAndLinkService(Face& face, LinkService& service)
{
BOOST_ASSERT(m_face == nullptr);
BOOST_ASSERT(m_service == nullptr);
@@ -111,7 +123,7 @@ Transport::receive(const Block& packet, const EndpointId& endpoint)
}
void
Transport::setMtu(ssize_t mtu) noexcept
Transport::setMtu(ssize_t mtu)
{
BOOST_ASSERT(mtu == MTU_UNLIMITED || mtu >= 0);
@@ -223,4 +235,5 @@ operator<<(std::ostream& os, const FaceLogHelper<Transport>& flh)
return os;
}
} // namespace nfd::face
} // namespace face
} // namespace nfd
+212 -177
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, 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,10 +29,10 @@
#include "face-common.hpp"
#include "common/counter.hpp"
namespace nfd::face {
namespace nfd {
namespace face {
/**
* \brief Indicates the state of a transport.
/** \brief Indicates the state of a transport.
*/
enum class TransportState {
NONE,
@@ -53,7 +53,7 @@ operator<<(std::ostream& os, TransportState state);
class TransportCounters
{
public:
/** \brief Count of incoming packets.
/** \brief count of incoming packets
*
* A 'packet' typically means a top-level TLV block.
* For a datagram-based transport, an incoming packet that cannot be parsed as TLV
@@ -61,14 +61,14 @@ public:
*/
PacketCounter nInPackets;
/** \brief Count of outgoing packets.
/** \brief count of outgoing packets
*
* A 'packet' typically means a top-level TLV block.
* This counter is incremented only if transport is UP.
*/
PacketCounter nOutPackets;
/** \brief Total incoming bytes.
/** \brief total incoming bytes
*
* This counter includes headers imposed by NFD (such as NDNLP),
* but excludes overhead of underlying protocol (such as IP header).
@@ -77,7 +77,7 @@ public:
*/
ByteCounter nInBytes;
/** \brief Total outgoing bytes.
/** \brief total outgoing bytes
*
* This counter includes headers imposed by NFD (such as NDNLP),
* but excludes overhead of underlying protocol (such as IP header).
@@ -86,29 +86,24 @@ public:
ByteCounter nOutBytes;
};
/**
* \brief Indicates that the transport has no limit on payload size.
/** \brief indicates the transport has no limit on payload size
*/
inline constexpr ssize_t MTU_UNLIMITED = -1;
const ssize_t MTU_UNLIMITED = -1;
/**
* \brief (for internal use) Indicates that the MTU field is unset.
/** \brief (for internal use) indicates MTU field is unset
*/
inline constexpr ssize_t MTU_INVALID = -2;
const ssize_t MTU_INVALID = -2;
/**
* \brief Indicates that the transport does not support reading the queue capacity/length.
/** \brief indicates that the transport does not support reading the queue capacity/length
*/
inline constexpr ssize_t QUEUE_UNSUPPORTED = -1;
const ssize_t QUEUE_UNSUPPORTED = -1;
/**
* \brief Indicates that the transport was unable to retrieve the queue capacity/length.
/** \brief indicates that the transport was unable to retrieve the queue capacity/length
*/
inline constexpr ssize_t QUEUE_ERROR = -2;
const ssize_t QUEUE_ERROR = -2;
/**
* \brief The lower half of a Face.
* \sa Face, LinkService
/** \brief The lower half of a Face.
* \sa Face
*/
class Transport : protected virtual TransportCounters, noncopyable
{
@@ -132,48 +127,32 @@ public:
~Transport();
public:
/**
* \brief Set Face and LinkService for this transport.
* \pre setFaceAndLinkService() has not been called.
/** \brief set Face and LinkService for Transport
* \pre setFaceAndLinkService has not been called
*/
void
setFaceAndLinkService(Face& face, LinkService& service) noexcept;
setFaceAndLinkService(Face& face, LinkService& service);
/**
* \brief Returns the Face to which this transport is attached.
/** \return Face to which this Transport is attached
*/
const Face*
getFace() const noexcept
{
return m_face;
}
getFace() const;
/**
* \brief Returns the LinkService to which this transport is attached.
/** \return LinkService to which this Transport is attached
*/
const LinkService*
getLinkService() const noexcept
{
return m_service;
}
getLinkService() const;
/**
* \brief Returns the LinkService to which this transport is attached.
/** \return LinkService to which this Transport is attached
*/
LinkService*
getLinkService() noexcept
{
return m_service;
}
getLinkService();
virtual const Counters&
getCounters() const
{
return *this;
}
getCounters() const;
public: // upper interface
/** \brief Request the transport to be closed.
/** \brief Request the transport to be closed
*
* This operation is effective only if transport is in UP or DOWN state,
* otherwise it has no effect.
@@ -184,7 +163,7 @@ public: // upper interface
void
close();
/** \brief Send a link-layer packet.
/** \brief Send a link-layer packet
* \param packet the packet to be sent, must be a valid and well-formed TLV block
* \note This operation has no effect if getState() is neither UP nor DOWN
* \warning Behavior is undefined if packet size exceeds the MTU limit
@@ -193,125 +172,85 @@ public: // upper interface
send(const Block& packet);
public: // static properties
/**
* \brief Returns a FaceUri representing the local endpoint.
/** \return a FaceUri representing local endpoint
*/
FaceUri
getLocalUri() const noexcept
{
return m_localUri;
}
getLocalUri() const;
/**
* \brief Returns a FaceUri representing the remote endpoint.
/** \return a FaceUri representing remote endpoint
*/
FaceUri
getRemoteUri() const noexcept
{
return m_remoteUri;
}
getRemoteUri() const;
/**
* \brief Returns whether the transport is local or non-local for scope control purposes.
/** \return whether face is local or non-local for scope control purpose
*/
ndn::nfd::FaceScope
getScope() const noexcept
{
return m_scope;
}
getScope() const;
/**
* \brief Returns the current persistency setting of the transport.
/** \return face persistency setting
*/
ndn::nfd::FacePersistency
getPersistency() const noexcept
{
return m_persistency;
}
getPersistency() const;
/**
* \brief Check whether the persistency can be changed to \p newPersistency.
/** \brief check whether the face persistency can be changed to \p newPersistency
*
* This function serves as the external API, and invokes the protected function
* canChangePersistencyToImpl() to perform further checks if \p newPersistency differs
* from the current persistency.
* This function serves as the external API, and invokes the protected function
* canChangePersistencyToImpl to perform further checks if \p newPersistency differs
* from the current persistency.
*
* \return true if the change can be performed, false otherwise
* \return true if the change can be performed, false otherwise
*/
bool
canChangePersistencyTo(ndn::nfd::FacePersistency newPersistency) const;
/**
* \brief Changes the persistency setting of the transport.
/** \brief changes face persistency setting
*/
void
setPersistency(ndn::nfd::FacePersistency newPersistency);
/**
* \brief Returns the link type of the transport.
/** \return the link type of the transport
*/
ndn::nfd::LinkType
getLinkType() const noexcept
{
return m_linkType;
}
getLinkType() const;
/**
* \brief Returns the maximum payload size.
* \retval MTU_UNLIMITED The transport has no limit on payload size.
/** \return maximum payload size
* \retval MTU_UNLIMITED transport has no limit on payload size
*
* This size is the maximum packet size that can be sent or received through this transport.
* This size is the maximum packet size that can be sent or received through this transport.
*
* For a datagram-based transport, this is typically the Maximum Transmission Unit (MTU),
* after the overhead of headers introduced by the transport has been accounted for.
* For a stream-based transport, this is typically unlimited (MTU_UNLIMITED).
* For a datagram-based transport, this is typically the Maximum Transmission Unit (MTU),
* after the overhead of headers introduced by the transport has been accounted for.
* For a stream-based transport, this is typically unlimited (MTU_UNLIMITED).
*/
ssize_t
getMtu() const noexcept
{
return m_mtu;
}
getMtu() const;
/**
* \brief Returns the capacity of the send queue (in bytes).
* \retval QUEUE_UNSUPPORTED The transport does not support queue capacity retrieval.
* \retval QUEUE_ERROR The transport was unable to retrieve the queue capacity.
/** \return capacity of the send queue (in bytes)
* \retval QUEUE_UNSUPPORTED transport does not support queue capacity retrieval
* \retval QUEUE_ERROR transport was unable to retrieve the queue capacity
*/
ssize_t
getSendQueueCapacity() const noexcept
{
return m_sendQueueCapacity;
}
getSendQueueCapacity() const;
public: // dynamic properties
/**
* \brief Returns the current transport state.
/** \return transport state
*/
TransportState
getState() const noexcept
{
return m_state;
}
getState() const;
/**
* \brief Signals when the transport state changes.
/** \brief signals when transport state changes
*/
signal::Signal<Transport, TransportState/*old*/, TransportState/*new*/> afterStateChange;
/**
* \brief Returns the expiration time of the transport.
* \retval time::steady_clock::time_point::max() The transport has an indefinite lifetime.
/** \return expiration time of the transport
* \retval time::steady_clock::TimePoint::max() the transport has indefinite lifetime
*/
time::steady_clock::time_point
getExpirationTime() const noexcept
{
return m_expirationTime;
}
time::steady_clock::TimePoint
getExpirationTime() const;
/**
* \brief Returns the current send queue length of the transport (in octets).
* \retval QUEUE_UNSUPPORTED The transport does not support queue length retrieval.
* \retval QUEUE_ERROR The transport was unable to retrieve the queue length.
/** \return current send queue length of the transport (in octets)
* \retval QUEUE_UNSUPPORTED transport does not support queue length retrieval
* \retval QUEUE_ERROR transport was unable to retrieve the queue length
*/
virtual ssize_t
getSendQueueLength()
@@ -320,50 +259,34 @@ public: // dynamic properties
}
protected: // upper interface to be invoked by subclass
/**
* \brief Pass a received link-layer packet to the upper layer for further processing.
* \param packet The received packet, must be a valid and well-formed TLV block
* \param endpoint The source endpoint, optional for unicast transports
* \warning Behavior is undefined if packet size exceeds the MTU limit.
/** \brief Pass a received link-layer packet to the upper layer for further processing
* \param packet the received packet, must be a valid and well-formed TLV block
* \param endpoint the source endpoint
* \warning Behavior is undefined if packet size exceeds the MTU limit
*/
void
receive(const Block& packet, const EndpointId& endpoint = {});
receive(const Block& packet, const EndpointId& endpoint = 0);
protected: // properties to be set by subclass
void
setLocalUri(const FaceUri& uri) noexcept
{
m_localUri = uri;
}
setLocalUri(const FaceUri& uri);
void
setRemoteUri(const FaceUri& uri) noexcept
{
m_remoteUri = uri;
}
setRemoteUri(const FaceUri& uri);
void
setScope(ndn::nfd::FaceScope scope) noexcept
{
m_scope = scope;
}
setScope(ndn::nfd::FaceScope scope);
void
setLinkType(ndn::nfd::LinkType linkType) noexcept
{
m_linkType = linkType;
}
setLinkType(ndn::nfd::LinkType linkType);
void
setMtu(ssize_t mtu) noexcept;
setMtu(ssize_t mtu);
void
setSendQueueCapacity(ssize_t sendQueueCapacity) noexcept
{
m_sendQueueCapacity = sendQueueCapacity;
}
setSendQueueCapacity(ssize_t sendQueueCapacity);
/** \brief Set transport state.
/** \brief set transport state
*
* Only the following transitions are valid:
* UP->DOWN, DOWN->UP, UP/DOWN->CLOSING/FAILED, CLOSING/FAILED->CLOSED
@@ -374,13 +297,10 @@ protected: // properties to be set by subclass
setState(TransportState newState);
void
setExpirationTime(const time::steady_clock::time_point& expirationTime) noexcept
{
m_expirationTime = expirationTime;
}
setExpirationTime(const time::steady_clock::TimePoint& expirationTime);
protected: // to be overridden by subclass
/** \brief Invoked by canChangePersistencyTo to perform the check.
/** \brief invoked by canChangePersistencyTo to perform the check
*
* Base class implementation returns false.
*
@@ -389,7 +309,7 @@ protected: // to be overridden by subclass
virtual bool
canChangePersistencyToImpl(ndn::nfd::FacePersistency newPersistency) const;
/** \brief Invoked after the persistency has been changed.
/** \brief invoked after the persistency has been changed
*
* The base class implementation does nothing.
* When overridden in a subclass, the function should update internal states
@@ -398,9 +318,9 @@ protected: // to be overridden by subclass
virtual void
afterChangePersistency(ndn::nfd::FacePersistency oldPersistency);
/** \brief Performs Transport specific operations to close the transport.
/** \brief performs Transport specific operations to close the transport
*
* This is invoked once by close() after changing state to CLOSING.
* This is invoked once by \p close() after changing state to CLOSING.
* It will not be invoked by Transport class if the transport is already CLOSING or CLOSED.
*
* When the cleanup procedure is complete, this method should change state to CLOSED.
@@ -410,7 +330,7 @@ protected: // to be overridden by subclass
doClose() = 0;
private: // to be overridden by subclass
/** \brief Performs Transport specific operations to send a packet.
/** \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
* \pre transport state is either UP or DOWN
*/
@@ -418,30 +338,145 @@ private: // to be overridden by subclass
doSend(const Block& packet) = 0;
private:
Face* m_face = nullptr;
LinkService* m_service = nullptr;
Face* m_face;
LinkService* m_service;
FaceUri m_localUri;
FaceUri m_remoteUri;
ndn::nfd::FaceScope m_scope = ndn::nfd::FACE_SCOPE_NONE;
ndn::nfd::FacePersistency m_persistency = ndn::nfd::FACE_PERSISTENCY_NONE;
ndn::nfd::LinkType m_linkType = ndn::nfd::LINK_TYPE_NONE;
ssize_t m_mtu = MTU_INVALID;
ssize_t m_sendQueueCapacity = QUEUE_UNSUPPORTED;
TransportState m_state = TransportState::UP;
time::steady_clock::time_point m_expirationTime = time::steady_clock::time_point::max();
ndn::nfd::FaceScope m_scope;
ndn::nfd::FacePersistency m_persistency;
ndn::nfd::LinkType m_linkType;
ssize_t m_mtu;
ssize_t m_sendQueueCapacity;
TransportState m_state;
time::steady_clock::TimePoint m_expirationTime;
};
inline const Face*
Transport::getFace() const
{
return m_face;
}
inline const LinkService*
Transport::getLinkService() const
{
return m_service;
}
inline LinkService*
Transport::getLinkService()
{
return m_service;
}
inline const Transport::Counters&
Transport::getCounters() const
{
return *this;
}
inline FaceUri
Transport::getLocalUri() const
{
return m_localUri;
}
inline void
Transport::setLocalUri(const FaceUri& uri)
{
m_localUri = uri;
}
inline FaceUri
Transport::getRemoteUri() const
{
return m_remoteUri;
}
inline void
Transport::setRemoteUri(const FaceUri& uri)
{
m_remoteUri = uri;
}
inline ndn::nfd::FaceScope
Transport::getScope() const
{
return m_scope;
}
inline void
Transport::setScope(ndn::nfd::FaceScope scope)
{
m_scope = scope;
}
inline ndn::nfd::FacePersistency
Transport::getPersistency() const
{
return m_persistency;
}
inline ndn::nfd::LinkType
Transport::getLinkType() const
{
return m_linkType;
}
inline void
Transport::setLinkType(ndn::nfd::LinkType linkType)
{
m_linkType = linkType;
}
inline ssize_t
Transport::getMtu() const
{
return m_mtu;
}
inline ssize_t
Transport::getSendQueueCapacity() const
{
return m_sendQueueCapacity;
}
inline void
Transport::setSendQueueCapacity(ssize_t sendQueueCapacity)
{
m_sendQueueCapacity = sendQueueCapacity;
}
inline TransportState
Transport::getState() const
{
return m_state;
}
inline time::steady_clock::TimePoint
Transport::getExpirationTime() const
{
return m_expirationTime;
}
inline void
Transport::setExpirationTime(const time::steady_clock::TimePoint& expirationTime)
{
m_expirationTime = expirationTime;
}
std::ostream&
operator<<(std::ostream& os, const FaceLogHelper<Transport>& flh);
template<typename T>
std::enable_if_t<std::is_base_of_v<Transport, T> && !std::is_same_v<Transport, T>,
std::ostream&>
typename std::enable_if<std::is_base_of<Transport, T>::value &&
!std::is_same<Transport, T>::value, std::ostream&>::type
operator<<(std::ostream& os, const FaceLogHelper<T>& flh)
{
return os << FaceLogHelper<Transport>(flh.obj);
}
} // namespace nfd::face
} // namespace face
} // namespace nfd
#endif // NFD_DAEMON_FACE_TRANSPORT_HPP
+15 -12
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, 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,9 +29,8 @@
#include "unicast-udp-transport.hpp"
#include "common/global.hpp"
#include <boost/asio/ip/v6_only.hpp>
namespace nfd::face {
namespace nfd {
namespace face {
NFD_LOG_INIT(UdpChannel);
@@ -39,15 +38,13 @@ namespace ip = boost::asio::ip;
UdpChannel::UdpChannel(const udp::Endpoint& localEndpoint,
time::nanoseconds idleTimeout,
bool wantCongestionMarking,
size_t defaultMtu)
bool wantCongestionMarking)
: m_localEndpoint(localEndpoint)
, m_socket(getGlobalIoService())
, m_idleFaceTimeout(idleTimeout)
, m_wantCongestionMarking(wantCongestionMarking)
{
setUri(FaceUri(m_localEndpoint));
setDefaultMtu(defaultMtu);
NFD_LOG_CHAN_INFO("Creating channel");
}
@@ -125,7 +122,6 @@ UdpChannel::handleNewPeer(const boost::system::error_code& error,
try {
FaceParams params;
params.persistency = ndn::nfd::FACE_PERSISTENCY_ON_DEMAND;
params.mtu = getDefaultMtu();
std::tie(isCreated, face) = createFace(m_remoteEndpoint, params);
}
catch (const boost::system::system_error& e) {
@@ -142,7 +138,7 @@ UdpChannel::handleNewPeer(const boost::system::error_code& error,
// dispatch the datagram to the face for processing
auto* transport = static_cast<UnicastUdpTransport*>(face->getTransport());
transport->receiveDatagram(ndn::make_span(m_receiveBuffer).first(nBytesReceived), error);
transport->receiveDatagram(m_receiveBuffer.data(), nBytesReceived, error);
waitForNewPeer(onFaceCreated, onReceiveFailed);
}
@@ -184,13 +180,19 @@ UdpChannel::createFace(const udp::Endpoint& remoteEndpoint,
options.defaultCongestionThreshold = *params.defaultCongestionThreshold;
}
options.overrideMtu = params.mtu.value_or(getDefaultMtu());
if (params.mtu) {
options.overrideMtu = *params.mtu;
}
if (params.bandwidth) {
options.C = *params.bandwidth;
}
auto linkService = make_unique<GenericLinkService>(options);
auto transport = make_unique<UnicastUdpTransport>(std::move(socket), params.persistency,
m_idleFaceTimeout);
auto face = make_shared<Face>(std::move(linkService), std::move(transport));
face->setChannel(weak_from_this());
face->setChannel(shared_from_this()); // use weak_from_this() in C++17
m_channelFaces[remoteEndpoint] = face;
connectFaceClosedSignal(*face, [this, remoteEndpoint] { m_channelFaces.erase(remoteEndpoint); });
@@ -198,4 +200,5 @@ UdpChannel::createFace(const udp::Endpoint& remoteEndpoint,
return {true, face};
}
} // namespace nfd::face
} // namespace face
} // namespace nfd
+9 -8
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, Regents of the University of California,
* Copyright (c) 2014-2018, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -31,12 +31,13 @@
#include <array>
namespace nfd::face {
namespace nfd {
namespace face {
/**
* \brief Class implementing UDP-based channel to create faces
*/
class UdpChannel final : public Channel
class UdpChannel : public Channel
{
public:
/**
@@ -48,17 +49,16 @@ public:
*/
UdpChannel(const udp::Endpoint& localEndpoint,
time::nanoseconds idleTimeout,
bool wantCongestionMarking,
size_t defaultMtu);
bool wantCongestionMarking);
bool
isListening() const final
isListening() const override
{
return m_socket.is_open();
}
size_t
size() const final
size() const override
{
return m_channelFaces.size();
}
@@ -116,6 +116,7 @@ private:
bool m_wantCongestionMarking;
};
} // namespace nfd::face
} // namespace face
} // namespace nfd
#endif // NFD_DAEMON_FACE_UDP_CHANNEL_HPP
Loaded 100 of 526 files, more files were not shown because too many files have changed in this diff. Show more