Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9bc57b880b | ||
|
|
9b877c3a23 | ||
|
|
23135a4cdd | ||
|
|
6ba08cd5cb | ||
|
|
e277f8b9e8 | ||
|
|
9a63bf22d0 | ||
|
|
ef6a528ae0 | ||
|
|
05bd6c2d69 | ||
|
|
a9ec67c52b | ||
|
|
d7083a507f | ||
|
|
c5a9f81fce | ||
|
|
0a05f7aea6 | ||
|
|
c0df94ed10 | ||
|
|
9c36a65b11 | ||
|
|
1e0c88e184 | ||
|
|
9bf64cc60d | ||
|
|
d91fe6d921 | ||
|
|
5d64263dcb | ||
|
|
a9e1ab2664 | ||
|
|
910232fce0 | ||
|
|
decaf509b4 | ||
|
|
8f0b8b6063 | ||
|
|
11f1fd8340 | ||
|
|
bf2e67fb14 | ||
|
|
5b15e2fe97 | ||
|
|
95afc6d8a4 | ||
|
|
653eb07e29 | ||
|
|
6bf94c02f5 | ||
|
|
191a7a24e6 | ||
|
|
ae43030f6f | ||
|
|
63b3ae818f | ||
|
|
4064127b97 | ||
|
|
d6ea0b1e0e | ||
|
|
c5e3e7a55d | ||
|
|
bf4c131f82 | ||
|
|
39c67f6291 | ||
|
|
269b702f3d | ||
|
|
3bc8e19a89 | ||
|
|
0b0156887b | ||
|
|
6b78a53cf7 | ||
|
|
a68af8129e | ||
|
|
a42efcb408 | ||
|
|
aa9e3b2148 | ||
|
|
b83d3df256 | ||
|
|
6d6f207661 | ||
|
|
9bfdaef62d | ||
|
|
20d94f67f8 | ||
|
|
36184f6893 | ||
|
|
6cc9541220 | ||
|
|
279af1ceac | ||
|
|
d94b7b3b24 | ||
|
|
e541d1b250 | ||
|
|
4791fcb8ba | ||
|
|
72517b5510 | ||
|
|
20cafa8715 | ||
|
|
2150da8ee5 | ||
|
|
990620ac3b | ||
|
|
a9b09b6994 | ||
|
|
9a28c3f752 | ||
|
|
e422f9e1e9 | ||
|
|
a3a7a4e330 | ||
|
|
b7bfcb904a | ||
|
|
4b84a2c9be | ||
|
|
6153eafa62 | ||
|
|
1ef93d0316 | ||
|
|
deb5427bb4 | ||
|
|
1b22a8c156 | ||
|
|
c52cd5eec1 | ||
|
|
5006c1d6af | ||
|
|
a599d2aac9 | ||
|
|
b98aa3aca6 | ||
|
|
727b61087a | ||
|
|
80111b72f9 | ||
|
|
07da3fec95 | ||
|
|
5e02c04ca7 | ||
|
|
c414ca5895 | ||
|
|
f28a061c22 | ||
|
|
af3ff5a8c6 | ||
|
|
2c61bad944 | ||
|
|
4d030c3896 | ||
|
|
13dae355cb | ||
|
|
8f0028de4e | ||
|
|
412c982a63 | ||
|
|
a103334b1c | ||
|
|
0498ce85b0 | ||
|
|
7647cc7635 | ||
|
|
e08cc4cd7e | ||
|
|
67ad70fbd5 | ||
|
|
d69070ef50 | ||
|
|
d412393379 | ||
|
|
6a699be8cd | ||
|
|
a47cca2634 | ||
|
|
7249fb4d52 | ||
|
|
86644d36ff | ||
|
|
358414d82f | ||
|
|
22085365d2 | ||
|
|
432be57380 | ||
|
|
3db9807200 | ||
|
|
03a75f6c88 | ||
|
|
7922d12449 | ||
|
|
580915891e | ||
|
|
29abf4cda2 | ||
|
|
a6286a9e5a | ||
|
|
40604e3a1f | ||
|
|
4400e428d4 | ||
|
|
05590471e0 | ||
|
|
b21bed88ed | ||
|
|
264af77369 | ||
|
|
6aecc500e5 | ||
|
|
7fb9071230 | ||
|
|
9ab43e67db | ||
|
|
cabd980030 | ||
|
|
2135375d36 | ||
|
|
3dc9fd0b82 | ||
|
|
c0c089314b | ||
|
|
9f6a7d97bc | ||
|
|
0bba81df36 | ||
|
|
2377ada11a | ||
|
|
b7e72c3a0a | ||
|
|
c1d4837b6f | ||
|
|
bc0e617e48 | ||
|
|
5bafd2c7c4 | ||
|
|
13d582abec | ||
|
|
d82134b850 | ||
|
|
ebc20f6000 | ||
|
|
fdc0645d77 | ||
|
|
e1cf4ba46a | ||
|
|
6bead9b6de | ||
|
|
f3bc3ae906 | ||
|
|
a158370ecb | ||
|
|
34b2b57831 | ||
|
|
1f237abbf1 | ||
|
|
3a2339a1b4 | ||
|
|
1752159ae0 | ||
|
|
4995bf960d | ||
|
|
c68b2e8a46 | ||
|
|
c29eb7f50e | ||
|
|
9d283adac4 | ||
|
|
b93fb6c831 | ||
|
|
8f290fc884 | ||
|
|
cb27d91658 | ||
|
|
9cec699867 | ||
|
|
d656aff913 | ||
|
|
22974904d3 | ||
|
|
69857c37c2 | ||
|
|
feeb918ea8 | ||
|
|
13ff259ec8 | ||
|
|
cb6551e96f | ||
|
|
56c68a364a | ||
|
|
51cf75c8f0 | ||
|
|
854866f424 | ||
|
|
32f7eac7cd | ||
|
|
5ab4cf83d9 | ||
|
|
f3ee808927 | ||
|
|
97f26a2618 | ||
|
|
e89118e8be |
No files matched your search
@@ -0,0 +1,8 @@
|
||||
Dockerfile
|
||||
|
||||
/build/
|
||||
.waf-*-*/
|
||||
.waf3-*-*/
|
||||
.lock-waf*
|
||||
|
||||
/VERSION.info
|
||||
@@ -0,0 +1,21 @@
|
||||
name: CI
|
||||
on:
|
||||
push:
|
||||
paths-ignore:
|
||||
- 'docs/**'
|
||||
- '*.conf.sample*'
|
||||
- '*.md'
|
||||
- '.mailmap'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
Ubuntu:
|
||||
uses: named-data/actions/.github/workflows/jenkins-script-ubuntu.yml@v1
|
||||
with:
|
||||
submodules: true
|
||||
macOS:
|
||||
uses: named-data/actions/.github/workflows/jenkins-script-macos.yml@v1
|
||||
with:
|
||||
submodules: true
|
||||
@@ -0,0 +1,81 @@
|
||||
name: Publish Docker image
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths-ignore:
|
||||
- '*.md'
|
||||
- '.mailmap'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
env:
|
||||
REGISTRY: ghcr.io
|
||||
|
||||
jobs:
|
||||
nfd:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Login to ${{ env.REGISTRY }}
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Extract metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ github.repository_owner }}/nfd
|
||||
flavor: latest=true
|
||||
|
||||
- name: Build and push Docker image
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
pull: true
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
|
||||
nfd-status-http-server:
|
||||
needs: nfd
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Login to ${{ env.REGISTRY }}
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Extract metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ github.repository_owner }}/nfd-status-http-server
|
||||
flavor: latest=true
|
||||
|
||||
- name: Build and push Docker image
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: ./tools
|
||||
file: ./tools/Dockerfile.nfd-status-http-server
|
||||
pull: true
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
@@ -0,0 +1,24 @@
|
||||
name: Docs
|
||||
on:
|
||||
push:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
skip-deploy:
|
||||
description: 'Skip deployment?'
|
||||
required: true
|
||||
type: boolean
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
html:
|
||||
uses: named-data/actions/.github/workflows/docs-html.yml@v1
|
||||
with:
|
||||
submodules: true
|
||||
# Deploy only the master branch and release tags
|
||||
deploy: ${{ !inputs.skip-deploy && (github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/NFD-')) }}
|
||||
secrets: inherit
|
||||
man:
|
||||
uses: named-data/actions/.github/workflows/docs-man.yml@v1
|
||||
with:
|
||||
submodules: true
|
||||
+1
-1
@@ -26,4 +26,4 @@ __pycache__/
|
||||
*.py[cod]
|
||||
|
||||
# Other
|
||||
/VERSION
|
||||
/VERSION.info
|
||||
@@ -1,27 +1,52 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
set -eo pipefail
|
||||
|
||||
nanos() {
|
||||
# Cannot use date(1) because macOS does not support %N format specifier
|
||||
python -c 'import time; print(int(time.time() * 1e9))'
|
||||
}
|
||||
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
|
||||
|
||||
export CACHE_DIR=${CACHE_DIR:-/tmp}
|
||||
|
||||
if [[ $JOB_NAME == *"code-coverage" ]]; then
|
||||
export DISABLE_ASAN=yes
|
||||
export DISABLE_HEADERS_CHECK=yes
|
||||
fi
|
||||
|
||||
# https://reproducible-builds.org/docs/source-date-epoch/
|
||||
export SOURCE_DATE_EPOCH=$(git log -1 --format=%ct)
|
||||
|
||||
for file in .jenkins.d/*; do
|
||||
[[ -f $file && -x $file ]] || continue
|
||||
|
||||
if [[ -n $TRAVIS ]]; then
|
||||
if [[ -n $GITHUB_ACTIONS ]]; then
|
||||
label=$(basename "$file" | sed -E 's/[[:digit:]]+-(.*)\..*/\1/')
|
||||
echo -ne "travis_fold:start:${label}\r"
|
||||
echo -ne "travis_time:start:${label}\r"
|
||||
start=$(nanos)
|
||||
echo "::group::${label}"
|
||||
fi
|
||||
|
||||
echo "\$ $file"
|
||||
"$file"
|
||||
|
||||
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"
|
||||
if [[ -n $GITHUB_ACTIONS ]]; then
|
||||
echo "::endgroup::"
|
||||
fi
|
||||
done
|
||||
+30
-38
@@ -1,48 +1,40 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
set -eo pipefail
|
||||
|
||||
JDIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||
source "$JDIR"/util.sh
|
||||
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 has OSX $NODE_LABELS; then
|
||||
FORMULAE=(boost openssl pkg-config)
|
||||
if [[ $ID == macos ]]; then
|
||||
if [[ -n $GITHUB_ACTIONS ]]; then
|
||||
export HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1
|
||||
fi
|
||||
brew update
|
||||
if [[ -n $TRAVIS ]]; then
|
||||
# Travis images come with a large number of brew packages
|
||||
# pre-installed, don't waste time upgrading all of them
|
||||
for FORMULA in "${FORMULAE[@]}"; do
|
||||
brew outdated $FORMULA || brew upgrade $FORMULA
|
||||
done
|
||||
else
|
||||
brew upgrade
|
||||
fi
|
||||
brew install "${FORMULAE[@]}"
|
||||
brew cleanup
|
||||
fi
|
||||
|
||||
if has Ubuntu $NODE_LABELS; then
|
||||
brew install --formula "${FORMULAE[@]}"
|
||||
elif [[ $ID_LIKE == *debian* ]]; then
|
||||
sudo apt-get -qq update
|
||||
sudo apt-get -qy install build-essential pkg-config libboost-all-dev \
|
||||
libsqlite3-dev libssl-dev libpcap-dev libsystemd-dev
|
||||
|
||||
if [[ $JOB_NAME == *"code-coverage" ]]; then
|
||||
sudo apt-get -qy install gcovr lcov libgd-perl
|
||||
fi
|
||||
sudo apt-get -qy install "${APT_PKGS[@]}"
|
||||
elif [[ $ID_LIKE == *fedora* ]]; then
|
||||
sudo dnf -y install gcc-c++ libasan lld pkgconf-pkg-config python3 \
|
||||
boost-devel openssl-devel sqlite-devel \
|
||||
libpcap-devel systemd-devel
|
||||
fi
|
||||
|
||||
if has CentOS-7 $NODE_LABELS; then
|
||||
sudo yum -y install yum-utils pkgconfig \
|
||||
openssl-devel libtranslit-icu \
|
||||
python-devel sqlite-devel \
|
||||
libpcap-devel systemd-devel \
|
||||
devtoolset-7-libasan-devel \
|
||||
devtoolset-7-liblsan-devel
|
||||
sudo yum -y groupinstall 'Development Tools'
|
||||
|
||||
svn checkout https://github.com/cmscaltech/sandie-ndn/trunk/packaging/RPMS/x86_64/boost1_58_0
|
||||
pushd boost1_58_0 >/dev/null
|
||||
sudo rpm -Uv --replacepkgs --replacefiles boost-devel* boost-license* libboost_*
|
||||
popd >/dev/null
|
||||
if (( ${#PIP_PKGS[@]} )); then
|
||||
pip3 install --user --upgrade --upgrade-strategy=eager "${PIP_PKGS[@]}"
|
||||
fi
|
||||
+15
-21
@@ -1,16 +1,11 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
set -exo pipefail
|
||||
|
||||
JDIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||
source "$JDIR"/util.sh
|
||||
|
||||
set -x
|
||||
|
||||
pushd "${CACHE_DIR:-/tmp}" >/dev/null
|
||||
pushd "$CACHE_DIR" >/dev/null
|
||||
|
||||
INSTALLED_VERSION=
|
||||
if has OSX $NODE_LABELS; then
|
||||
BOOST=$(brew ls --versions boost)
|
||||
if [[ $ID == macos ]]; then
|
||||
BOOST=$(brew list --formula --versions boost)
|
||||
OLD_BOOST=$(cat boost.txt || :)
|
||||
if [[ $OLD_BOOST != $BOOST ]]; then
|
||||
echo "$BOOST" > boost.txt
|
||||
@@ -22,17 +17,15 @@ if [[ -z $INSTALLED_VERSION ]]; then
|
||||
INSTALLED_VERSION=$(git -C ndn-cxx rev-parse HEAD 2>/dev/null || echo NONE)
|
||||
fi
|
||||
|
||||
sudo rm -Rf ndn-cxx-latest
|
||||
|
||||
git clone --depth 1 git://github.com/named-data/ndn-cxx ndn-cxx-latest
|
||||
|
||||
sudo rm -rf ndn-cxx-latest
|
||||
git clone --depth 1 https://github.com/named-data/ndn-cxx.git ndn-cxx-latest
|
||||
LATEST_VERSION=$(git -C ndn-cxx-latest rev-parse HEAD 2>/dev/null || echo UNKNOWN)
|
||||
|
||||
if [[ $INSTALLED_VERSION != $LATEST_VERSION ]]; then
|
||||
sudo rm -Rf ndn-cxx
|
||||
sudo rm -rf ndn-cxx
|
||||
mv ndn-cxx-latest ndn-cxx
|
||||
else
|
||||
sudo rm -Rf ndn-cxx-latest
|
||||
sudo rm -rf ndn-cxx-latest
|
||||
fi
|
||||
|
||||
sudo rm -f /usr/local/bin/ndnsec*
|
||||
@@ -42,15 +35,16 @@ sudo rm -f /usr/local/lib{,64}/pkgconfig/libndn-cxx.pc
|
||||
|
||||
pushd ndn-cxx >/dev/null
|
||||
|
||||
./waf configure --color=yes --enable-shared --disable-static --without-osx-keychain
|
||||
./waf build --color=yes -j${WAF_JOBS:-1}
|
||||
sudo_preserve_env PATH -- ./waf install --color=yes
|
||||
./waf --color=yes configure --without-osx-keychain
|
||||
./waf --color=yes build
|
||||
sudo ./waf --color=yes install
|
||||
|
||||
popd >/dev/null
|
||||
popd >/dev/null
|
||||
|
||||
if has Linux $NODE_LABELS; then
|
||||
if [[ $ID_LIKE == *fedora* ]]; then
|
||||
sudo tee /etc/ld.so.conf.d/ndn.conf >/dev/null <<< /usr/local/lib64
|
||||
fi
|
||||
if [[ $ID_LIKE == *linux* ]]; then
|
||||
sudo ldconfig
|
||||
elif has FreeBSD10 $NODE_LABELS; then
|
||||
sudo ldconfig -m
|
||||
fi
|
||||
+25
-31
@@ -1,45 +1,39 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
set -eo pipefail
|
||||
|
||||
JDIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||
source "$JDIR"/util.sh
|
||||
if [[ -z $DISABLE_ASAN ]]; then
|
||||
ASAN="--with-sanitizer=address"
|
||||
fi
|
||||
if [[ $JOB_NAME == *"code-coverage" ]]; then
|
||||
COVERAGE="--with-coverage"
|
||||
fi
|
||||
if [[ -n $DISABLE_PCH ]]; then
|
||||
PCH="--without-pch"
|
||||
fi
|
||||
|
||||
set -x
|
||||
|
||||
git submodule init
|
||||
git submodule sync
|
||||
git submodule update
|
||||
|
||||
if [[ $JOB_NAME == *"code-coverage" ]]; then
|
||||
COVERAGE="--with-coverage"
|
||||
elif [[ -z $DISABLE_ASAN ]]; then
|
||||
ASAN="--with-sanitizer=address"
|
||||
fi
|
||||
|
||||
# Cleanup
|
||||
sudo_preserve_env PATH -- ./waf --color=yes distclean
|
||||
|
||||
if [[ $JOB_NAME != *"code-coverage" && $JOB_NAME != *"limited-build" ]]; then
|
||||
# Configure/build in optimized mode with tests
|
||||
./waf --color=yes configure --with-tests
|
||||
./waf --color=yes build -j${WAF_JOBS:-1}
|
||||
# Build in release mode with tests and without precompiled headers
|
||||
./waf --color=yes configure --with-tests --without-pch
|
||||
./waf --color=yes build
|
||||
|
||||
# Cleanup
|
||||
sudo_preserve_env PATH -- ./waf --color=yes distclean
|
||||
# Cleanup
|
||||
./waf --color=yes distclean
|
||||
|
||||
# Configure/build in optimized mode without tests, but with "other tests"
|
||||
./waf --color=yes configure --with-other-tests
|
||||
./waf --color=yes build -j${WAF_JOBS:-1}
|
||||
# Build in release mode without tests, but with "other tests"
|
||||
./waf --color=yes configure --with-other-tests $PCH
|
||||
./waf --color=yes build
|
||||
|
||||
# Cleanup
|
||||
sudo_preserve_env PATH -- ./waf --color=yes distclean
|
||||
# Cleanup
|
||||
./waf --color=yes distclean
|
||||
fi
|
||||
|
||||
# Configure/build in debug mode with tests and without precompiled headers
|
||||
./waf --color=yes configure --debug --with-tests --without-pch $ASAN $COVERAGE
|
||||
./waf --color=yes build -j${WAF_JOBS:-1}
|
||||
# Build in debug mode with tests
|
||||
./waf --color=yes configure --debug --with-tests $ASAN $COVERAGE $PCH
|
||||
./waf --color=yes build
|
||||
|
||||
# (tests will be run against debug version)
|
||||
# (tests will be run against the debug version)
|
||||
|
||||
# Install
|
||||
sudo_preserve_env PATH -- ./waf --color=yes install
|
||||
sudo ./waf --color=yes install
|
||||
+25
-42
@@ -1,48 +1,31 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
set -eo pipefail
|
||||
|
||||
JDIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||
source "$JDIR"/util.sh
|
||||
# https://github.com/google/sanitizers/wiki/AddressSanitizerFlags
|
||||
ASAN_OPTIONS="color=always"
|
||||
ASAN_OPTIONS+=":check_initialization_order=1"
|
||||
ASAN_OPTIONS+=":detect_stack_use_after_return=1"
|
||||
ASAN_OPTIONS+=":strict_init_order=1"
|
||||
ASAN_OPTIONS+=":strict_string_checks=1"
|
||||
ASAN_OPTIONS+=":detect_invalid_pointer_pairs=2"
|
||||
ASAN_OPTIONS+=":detect_container_overflow=0"
|
||||
ASAN_OPTIONS+=":detect_leaks=0"
|
||||
ASAN_OPTIONS+=":strip_path_prefix=${PWD}/"
|
||||
export ASAN_OPTIONS
|
||||
|
||||
# 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
|
||||
|
||||
ut_log_args() {
|
||||
echo --logger=HRF,test_suite,stdout:XML,all,build/xunit-log${1:+-$1}.xml
|
||||
}
|
||||
|
||||
set -x
|
||||
|
||||
# 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 -
|
||||
|
||||
BOOST_VERSION=$(python -c "import sys; sys.path.append('build/c4che'); import _cache; print(_cache.BOOST_VERSION_NUMBER);")
|
||||
|
||||
ut_log_args() {
|
||||
if (( BOOST_VERSION >= 106200 )); then
|
||||
echo --logger=HRF,test_suite,stdout:XML,all,build/xunit-${1:-report}.xml
|
||||
else
|
||||
if [[ -n $XUNIT ]]; then
|
||||
echo --log_level=all $( (( BOOST_VERSION >= 106000 )) && echo -- ) \
|
||||
--log_format2=XML --log_sink2=build/xunit-${1:-report}.xml
|
||||
else
|
||||
echo --log_level=test_suite
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
ASAN_OPTIONS="color=always"
|
||||
ASAN_OPTIONS+=":detect_leaks=false"
|
||||
ASAN_OPTIONS+=":detect_stack_use_after_return=true"
|
||||
ASAN_OPTIONS+=":check_initialization_order=true"
|
||||
ASAN_OPTIONS+=":strict_init_order=true"
|
||||
ASAN_OPTIONS+=":detect_invalid_pointer_pairs=1"
|
||||
ASAN_OPTIONS+=":detect_container_overflow=false"
|
||||
ASAN_OPTIONS+=":strict_string_checks=true"
|
||||
ASAN_OPTIONS+=":strip_path_prefix=${PWD}/"
|
||||
export ASAN_OPTIONS
|
||||
|
||||
export BOOST_TEST_BUILD_INFO=1
|
||||
export BOOST_TEST_COLOR_OUTPUT=1
|
||||
rm -rf ~/.ndn
|
||||
|
||||
# First run all tests as unprivileged user
|
||||
./build/unit-tests-core $(ut_log_args core)
|
||||
@@ -51,9 +34,9 @@ export BOOST_TEST_COLOR_OUTPUT=1
|
||||
./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)
|
||||
+15
-24
@@ -1,41 +1,32 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
JDIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||
source "$JDIR"/util.sh
|
||||
|
||||
set -x
|
||||
set -exo pipefail
|
||||
|
||||
if [[ $JOB_NAME == *"code-coverage" ]]; then
|
||||
gcovr --object-directory=build \
|
||||
--output=build/coverage.xml \
|
||||
--exclude="$PWD/(tests|websocketpp)" \
|
||||
--root=. \
|
||||
--xml
|
||||
# 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
|
||||
|
||||
# Generate also a detailed HTML output, but using lcov (better results)
|
||||
# Generate a detailed HTML report using lcov
|
||||
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 \
|
||||
--frames \
|
||||
--legend \
|
||||
--output-directory build/coverage \
|
||||
--output-directory build/lcov \
|
||||
--title "NFD unit tests" \
|
||||
build/coverage.info
|
||||
fi
|
||||
+24
-24
@@ -1,36 +1,36 @@
|
||||
CONTINUOUS INTEGRATION SCRIPTS
|
||||
==============================
|
||||
# Continuous Integration Scripts
|
||||
|
||||
Environment Variables Used in Build Scripts
|
||||
-------------------------------------------
|
||||
## Environment Variables
|
||||
|
||||
- `NODE_LABELS`: the variable defines a list of OS properties. The set values are used by the
|
||||
build scripts to select proper behavior for different OS.
|
||||
- `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`.
|
||||
|
||||
The list should include at least `[OS_TYPE]`, `[DISTRO_TYPE]`, and `[DISTRO_VERSION]`.
|
||||
- `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.
|
||||
|
||||
Possible values for Linux:
|
||||
Examples:
|
||||
|
||||
* `[OS_TYPE]`: `Linux`
|
||||
* `[DISTRO_TYPE]`: `Ubuntu`
|
||||
* `[DISTRO_VERSION]`: `Ubuntu-16.04`, `Ubuntu-18.04`
|
||||
- On CentOS, `ID_LIKE="centos rhel fedora linux"`
|
||||
- On Ubuntu, `ID_LIKE="ubuntu debian linux"`
|
||||
|
||||
Possible values for OS X / macOS:
|
||||
- `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`.
|
||||
|
||||
* `[OS_TYPE]`: `OSX`
|
||||
* `[DISTRO_TYPE]`: `OSX` (can be absent)
|
||||
* `[DISTRO_VERSION]`: `OSX-10.11`, `OSX-10.12`, `OSX-10.13`
|
||||
- `JOB_NAME`: defines the type of the current CI job. Depending on the job type, the CI
|
||||
scripts can perform different tasks.
|
||||
|
||||
- `JOB_NAME`: optional variable to define type of the job. Depending on the defined job type,
|
||||
the build scripts can perform different tasks.
|
||||
Supported values:
|
||||
|
||||
Possible values:
|
||||
- empty: default build task
|
||||
- `code-coverage`: debug build with tests and code coverage analysis
|
||||
- `limited-build`: only a single debug build with tests
|
||||
|
||||
* empty: default build process
|
||||
* `code-coverage` (Ubuntu Linux is assumed): debug build with tests and code coverage analysis
|
||||
* `limited-build`: only a single debug build with tests
|
||||
- `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`: the variable defines a path to folder containing cached files from previous builds,
|
||||
e.g., a compiled version of ndn-cxx library. If not set, `/tmp` is used.
|
||||
- `DISABLE_ASAN`: disable building with AddressSanitizer. This is automatically set for
|
||||
the `code-coverage` job type.
|
||||
|
||||
- `WAF_JOBS`: number of parallel build jobs used by waf, defaults to 1.
|
||||
[os-release(5)]: https://www.freedesktop.org/software/systemd/man/os-release.html
|
||||
@@ -1,37 +0,0 @@
|
||||
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}
|
||||
}
|
||||
|
||||
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[@]}" "$@"
|
||||
}
|
||||
@@ -1,14 +1,16 @@
|
||||
<aa@cs.fiu.edu> <alexander.afanasyev@ucla.edu>
|
||||
Alexander Lane <awlane@memphis.edu>
|
||||
<chghasemi@cs.arizona.edu> <chavoosh.ghasemi@gmail.com>
|
||||
<davidepesa@gmail.com> <davide.pesavento@lip6.fr>
|
||||
<enewberry@email.arizona.edu> <enewberry@cs.arizona.edu>
|
||||
Vince Lehman <vslehman@memphis.edu> <vlehman1@gmail.com>
|
||||
<lybmath2009@gmail.com> <lybmath@ucla.edu>
|
||||
Hila Ben Abraham <hilata@gmail.com>
|
||||
<tuyukai1994@gmail.com> <tyk@bupt.edu.cn>
|
||||
Haowei Yuan <hyuan@wustl.edu>
|
||||
Hila Ben Abraham <hilata@gmail.com>
|
||||
<lybmath2009@gmail.com> <lybmath@ucla.edu>
|
||||
Md Ashiqur Rahman <marahman@email.arizona.edu>
|
||||
Minsheng Zhang <jimmyzms5@gmail.com>
|
||||
Spyridon Mastorakis <spiros.mastorakis@gmail.com>
|
||||
Md Ashiqur Rahman <marahman@email.arizona.edu>
|
||||
Yumin Xia <me@yumin-xia.com>
|
||||
<chghasemi@cs.arizona.edu> <chavoosh.ghasemi@gmail.com>
|
||||
Susmit Shannigrahi <susmit@cs.colostate.edu>
|
||||
Tai-Lin Chu <tailinchu@gmail.com>
|
||||
<tuyukai1994@gmail.com> <tyk@bupt.edu.cn>
|
||||
Vince Lehman <vslehman@memphis.edu> <vlehman1@gmail.com>
|
||||
Yumin Xia <me@yumin-xia.com>
|
||||
-102
@@ -1,102 +0,0 @@
|
||||
language: cpp
|
||||
dist: bionic
|
||||
env:
|
||||
global:
|
||||
- JOB_NAME=limited-build
|
||||
- WAF_JOBS=2
|
||||
|
||||
matrix:
|
||||
include:
|
||||
# Linux/gcc
|
||||
# https://launchpad.net/~ubuntu-toolchain-r/+archive/ubuntu/test/+packages
|
||||
- os: linux
|
||||
env: COMPILER=g++-5
|
||||
- os: linux
|
||||
env: COMPILER=g++-6
|
||||
- os: linux
|
||||
env: COMPILER=g++-7
|
||||
- os: linux
|
||||
env: COMPILER=g++-8
|
||||
- os: linux
|
||||
env: COMPILER=g++-9
|
||||
|
||||
# Linux/clang
|
||||
# https://apt.llvm.org/
|
||||
- os: linux
|
||||
env: COMPILER=clang++-3.9
|
||||
- os: linux
|
||||
env: COMPILER=clang++-4.0
|
||||
- os: linux
|
||||
env: COMPILER=clang++-5.0
|
||||
- os: linux
|
||||
env: COMPILER=clang++-6.0
|
||||
# disable AddressSanitizer with clang 7 and 8
|
||||
# due to https://bugs.llvm.org/show_bug.cgi?id=40808
|
||||
- os: linux
|
||||
env: COMPILER=clang++-7 DISABLE_ASAN=yes
|
||||
- os: linux
|
||||
env: COMPILER=clang++-8 DISABLE_ASAN=yes
|
||||
- os: linux
|
||||
env: COMPILER=clang++-9
|
||||
- os: linux
|
||||
env: COMPILER=clang++-10
|
||||
|
||||
# macOS/clang
|
||||
# https://docs.travis-ci.com/user/reference/osx/#macos-version
|
||||
- os: osx
|
||||
osx_image: xcode9.2
|
||||
env: OSX_VERSION=10.12
|
||||
- os: osx
|
||||
osx_image: xcode9.4
|
||||
env: OSX_VERSION=10.13
|
||||
- os: osx
|
||||
osx_image: xcode10.1
|
||||
env: OSX_VERSION=10.13
|
||||
- os: osx
|
||||
osx_image: xcode10.3
|
||||
env: OSX_VERSION=10.14
|
||||
- os: osx
|
||||
osx_image: xcode11
|
||||
env: OSX_VERSION=10.14
|
||||
|
||||
allow_failures:
|
||||
- env: COMPILER=clang++-10
|
||||
|
||||
fast_finish: true
|
||||
|
||||
before_install: |
|
||||
case ${COMPILER} in
|
||||
g++-[567]|clang++-[3456].*)
|
||||
;;
|
||||
g++-*)
|
||||
travis_retry sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
|
||||
travis_retry sudo apt-get -qq update
|
||||
;;
|
||||
clang++-*)
|
||||
LLVM_REPO=${COMPILER/clang++/llvm-toolchain-${TRAVIS_DIST}}
|
||||
travis_retry wget -nv -O - "https://apt.llvm.org/llvm-snapshot.gpg.key" | sudo apt-key add -
|
||||
travis_retry sudo add-apt-repository -y "deb http://apt.llvm.org/${TRAVIS_DIST}/ ${LLVM_REPO%-10} main"
|
||||
travis_retry sudo apt-get -qq update
|
||||
;;
|
||||
esac
|
||||
|
||||
install:
|
||||
- if [[ -n ${COMPILER} ]]; then travis_retry sudo apt-get -qy install "${COMPILER/clang++/clang}"; fi
|
||||
|
||||
before_script:
|
||||
- if [[ ${TRAVIS_OS_NAME} == linux ]]; then export NODE_LABELS="Linux Ubuntu Ubuntu-18.04"; fi
|
||||
- if [[ ${TRAVIS_OS_NAME} == linux ]]; then sudo sysctl -e -w net.ipv6.conf.all.disable_ipv6=0; fi
|
||||
- if [[ ${TRAVIS_OS_NAME} == osx ]]; then export NODE_LABELS="OSX OSX-${OSX_VERSION}"; fi
|
||||
# do not waste time upgrading useless packages
|
||||
- if [[ ${TRAVIS_OS_NAME} == osx ]]; then brew pin cgal gdal numpy postgis sfcgal || true; fi
|
||||
- if [[ ${OSX_VERSION} == 10.12 ]]; then brew update; fi
|
||||
# workaround for https://github.com/Homebrew/homebrew-core/issues/26358
|
||||
- if [[ ${OSX_VERSION} == 10.12 ]]; then brew outdated python || brew upgrade python; fi
|
||||
# workaround for https://github.com/travis-ci/travis-ci/issues/6688
|
||||
- if [[ ${OSX_VERSION} == 10.12 ]]; then /usr/bin/yes | pip2 uninstall numpy || true; fi
|
||||
- if [[ -n ${COMPILER} ]]; then export CXX=${COMPILER}; fi
|
||||
- ${CXX:-c++} --version
|
||||
- python --version
|
||||
|
||||
script:
|
||||
- ./.jenkins
|
||||
+2
-2
@@ -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/local/lib', '/sw/lib', '/lib']
|
||||
BOOST_INCLUDES = ['/usr/include', '/usr/local/include', '/opt/local/include', '/sw/include']
|
||||
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_VERSION_FILE = 'boost/version.hpp'
|
||||
BOOST_VERSION_CODE = '''
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
# -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
|
||||
|
||||
"""
|
||||
Copyright (c) 2014-2016, Regents of the University of California,
|
||||
Arizona Board of Regents,
|
||||
Colorado State University,
|
||||
University Pierre & Marie Curie, Sorbonne University,
|
||||
Washington University in St. Louis,
|
||||
Beijing Institute of Technology,
|
||||
The University of Memphis.
|
||||
|
||||
This file is part of NFD (Named Data Networking Forwarding Daemon).
|
||||
See AUTHORS.md for complete list of NFD authors and contributors.
|
||||
|
||||
NFD is free software: you can redistribute it and/or modify it under the terms
|
||||
of the GNU General Public License as published by the Free Software Foundation,
|
||||
either version 3 of the License, or (at your option) any later version.
|
||||
|
||||
NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
from waflib.Configure import conf
|
||||
|
||||
def configure(conf):
|
||||
pass
|
||||
@@ -1,10 +1,13 @@
|
||||
# -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
|
||||
|
||||
import platform
|
||||
from waflib import Configure, Logs, Utils
|
||||
|
||||
|
||||
def options(opt):
|
||||
opt.add_option('--debug', '--with-debug', action='store_true', default=False,
|
||||
help='Compile in debugging mode with minimal optimizations (-O0 or -Og)')
|
||||
help='Compile in debugging mode with minimal optimizations (-Og)')
|
||||
|
||||
|
||||
def configure(conf):
|
||||
conf.start_msg('Checking C++ compiler version')
|
||||
@@ -15,17 +18,27 @@ def configure(conf):
|
||||
errmsg = ''
|
||||
warnmsg = ''
|
||||
if cxx == 'gcc':
|
||||
if ccver < (5, 3, 0):
|
||||
if ccver < (7, 4, 0):
|
||||
errmsg = ('The version of gcc you are using is too old.\n'
|
||||
'The minimum supported gcc version is 5.3.0.')
|
||||
'The minimum supported gcc version is 9.3.')
|
||||
elif ccver < (9, 3, 0):
|
||||
warnmsg = ('Using a version of gcc older than 9.3 is not '
|
||||
'officially supported and may result in build failures.')
|
||||
conf.flags = GccFlags()
|
||||
elif cxx == 'clang':
|
||||
if ccver < (3, 6, 0):
|
||||
if Utils.unversioned_sys_platform() == 'darwin':
|
||||
if ccver < (10, 0, 0):
|
||||
errmsg = ('The version of Xcode you are using is too old.\n'
|
||||
'The minimum supported Xcode version is 12.4.')
|
||||
elif ccver < (12, 0, 0):
|
||||
warnmsg = ('Using a version of Xcode older than 12.4 is not '
|
||||
'officially supported and may result in build failures.')
|
||||
elif ccver < (7, 0, 0):
|
||||
errmsg = ('The version of clang you are using is too old.\n'
|
||||
'The minimum supported clang version is 3.6.0.')
|
||||
'The minimum supported clang version is 7.0.')
|
||||
conf.flags = ClangFlags()
|
||||
else:
|
||||
warnmsg = 'Note: %s compiler is unsupported' % cxx
|
||||
warnmsg = f'{cxx} compiler is unsupported'
|
||||
conf.flags = CompilerFlags()
|
||||
|
||||
if errmsg:
|
||||
@@ -33,11 +46,11 @@ def configure(conf):
|
||||
conf.fatal(errmsg)
|
||||
elif warnmsg:
|
||||
conf.end_msg(ccverstr, color='YELLOW')
|
||||
Logs.warn(warnmsg)
|
||||
Logs.warn('WARNING: ' + warnmsg)
|
||||
else:
|
||||
conf.end_msg(ccverstr)
|
||||
|
||||
conf.areCustomCxxflagsPresent = (len(conf.env.CXXFLAGS) > 0)
|
||||
conf.areCustomCxxflagsPresent = len(conf.env.CXXFLAGS) > 0
|
||||
|
||||
# General flags are always applied (e.g., selecting C++ language standard)
|
||||
generalFlags = conf.flags.getGeneralFlags(conf)
|
||||
@@ -45,6 +58,7 @@ def configure(conf):
|
||||
conf.add_supported_linkflags(generalFlags['LINKFLAGS'])
|
||||
conf.env.DEFINES += generalFlags['DEFINES']
|
||||
|
||||
|
||||
@Configure.conf
|
||||
def check_compiler_flags(conf):
|
||||
# Debug or optimized CXXFLAGS and LINKFLAGS are applied only if the
|
||||
@@ -67,10 +81,11 @@ def check_compiler_flags(conf):
|
||||
|
||||
conf.env.DEFINES += extraFlags['DEFINES']
|
||||
|
||||
|
||||
@Configure.conf
|
||||
def add_supported_cxxflags(self, cxxflags):
|
||||
"""
|
||||
Check which cxxflags are supported by compiler and add them to env.CXXFLAGS variable
|
||||
Check which cxxflags are supported by the active compiler and add them to env.CXXFLAGS variable.
|
||||
"""
|
||||
if len(cxxflags) == 0:
|
||||
return
|
||||
@@ -86,10 +101,11 @@ def add_supported_cxxflags(self, cxxflags):
|
||||
self.end_msg(' '.join(supportedFlags))
|
||||
self.env.prepend_value('CXXFLAGS', supportedFlags)
|
||||
|
||||
|
||||
@Configure.conf
|
||||
def add_supported_linkflags(self, linkflags):
|
||||
"""
|
||||
Check which linkflags are supported by compiler and add them to env.LINKFLAGS variable
|
||||
Check which linkflags are supported by the active compiler and add them to env.LINKFLAGS variable.
|
||||
"""
|
||||
if len(linkflags) == 0:
|
||||
return
|
||||
@@ -106,13 +122,17 @@ def add_supported_linkflags(self, linkflags):
|
||||
self.env.prepend_value('LINKFLAGS', supportedFlags)
|
||||
|
||||
|
||||
class CompilerFlags(object):
|
||||
class CompilerFlags:
|
||||
def getCompilerVersion(self, conf):
|
||||
return tuple(int(i) for i in conf.env.CC_VERSION)
|
||||
|
||||
def getGeneralFlags(self, conf):
|
||||
"""Get dict of CXXFLAGS, LINKFLAGS, and DEFINES that are always needed"""
|
||||
return {'CXXFLAGS': [], 'LINKFLAGS': [], 'DEFINES': []}
|
||||
return {
|
||||
'CXXFLAGS': [],
|
||||
'LINKFLAGS': [],
|
||||
'DEFINES': ['BOOST_FILESYSTEM_NO_DEPRECATED'],
|
||||
}
|
||||
|
||||
def getDebugFlags(self, conf):
|
||||
"""Get dict of CXXFLAGS, LINKFLAGS, and DEFINES that are needed only in debug mode"""
|
||||
@@ -122,95 +142,99 @@ class CompilerFlags(object):
|
||||
"""Get dict of CXXFLAGS, LINKFLAGS, and DEFINES that are needed only in optimized mode"""
|
||||
return {'CXXFLAGS': [], 'LINKFLAGS': [], 'DEFINES': ['NDEBUG']}
|
||||
|
||||
class GccBasicFlags(CompilerFlags):
|
||||
|
||||
class GccClangCommonFlags(CompilerFlags):
|
||||
"""
|
||||
This class defines basic flags that work for both gcc and clang compilers
|
||||
This class defines common flags that work for both gcc and clang compilers.
|
||||
"""
|
||||
|
||||
def getGeneralFlags(self, conf):
|
||||
flags = super(GccBasicFlags, self).getGeneralFlags(conf)
|
||||
flags['CXXFLAGS'] += ['-std=c++14']
|
||||
if Utils.unversioned_sys_platform() == 'linux':
|
||||
flags['LINKFLAGS'] += ['-fuse-ld=gold']
|
||||
elif Utils.unversioned_sys_platform() == 'freebsd':
|
||||
flags = super().getGeneralFlags(conf)
|
||||
flags['CXXFLAGS'] += ['-std=c++17']
|
||||
if Utils.unversioned_sys_platform() != 'darwin':
|
||||
flags['LINKFLAGS'] += ['-fuse-ld=lld']
|
||||
return flags
|
||||
|
||||
__cxxFlags = [
|
||||
'-fdiagnostics-color',
|
||||
'-Wall',
|
||||
'-Wextra',
|
||||
'-Wpedantic',
|
||||
'-Wenum-conversion',
|
||||
'-Wextra-semi',
|
||||
'-Wno-unused-parameter',
|
||||
]
|
||||
__linkFlags = ['-Wl,-O1']
|
||||
|
||||
def getDebugFlags(self, conf):
|
||||
flags = super(GccBasicFlags, self).getDebugFlags(conf)
|
||||
flags['CXXFLAGS'] += ['-O0',
|
||||
'-Og', # gcc >= 4.8, clang >= 4.0
|
||||
'-g3',
|
||||
'-pedantic',
|
||||
'-Wall',
|
||||
'-Wextra',
|
||||
'-Werror',
|
||||
'-Wnon-virtual-dtor',
|
||||
'-Wno-error=deprecated-declarations', # Bug #3795
|
||||
'-Wno-error=maybe-uninitialized', # Bug #1615
|
||||
'-Wno-unused-parameter',
|
||||
]
|
||||
flags['LINKFLAGS'] += ['-Wl,-O1']
|
||||
flags = super().getDebugFlags(conf)
|
||||
flags['CXXFLAGS'] += ['-Og', '-g'] + self.__cxxFlags + [
|
||||
'-Werror',
|
||||
'-Wno-error=deprecated-declarations', # Bug #3795
|
||||
'-Wno-error=maybe-uninitialized', # Bug #1615
|
||||
]
|
||||
flags['LINKFLAGS'] += self.__linkFlags
|
||||
return flags
|
||||
|
||||
def getOptimizedFlags(self, conf):
|
||||
flags = super(GccBasicFlags, self).getOptimizedFlags(conf)
|
||||
flags['CXXFLAGS'] += ['-O2',
|
||||
'-g',
|
||||
'-pedantic',
|
||||
'-Wall',
|
||||
'-Wextra',
|
||||
'-Wnon-virtual-dtor',
|
||||
'-Wno-unused-parameter',
|
||||
]
|
||||
flags['LINKFLAGS'] += ['-Wl,-O1']
|
||||
flags = super().getOptimizedFlags(conf)
|
||||
flags['CXXFLAGS'] += ['-O2', '-g1'] + self.__cxxFlags
|
||||
flags['LINKFLAGS'] += self.__linkFlags
|
||||
return flags
|
||||
|
||||
class GccFlags(GccBasicFlags):
|
||||
|
||||
class GccFlags(GccClangCommonFlags):
|
||||
__cxxFlags = [
|
||||
'-Wcatch-value=2',
|
||||
'-Wcomma-subscript', # enabled by default in C++20
|
||||
'-Wduplicated-branches',
|
||||
'-Wduplicated-cond',
|
||||
'-Wlogical-op',
|
||||
'-Wredundant-tags',
|
||||
'-Wvolatile', # enabled by default in C++20
|
||||
]
|
||||
|
||||
def getDebugFlags(self, conf):
|
||||
flags = super(GccFlags, self).getDebugFlags(conf)
|
||||
flags['CXXFLAGS'] += ['-fdiagnostics-color']
|
||||
flags = super().getDebugFlags(conf)
|
||||
flags['CXXFLAGS'] += self.__cxxFlags
|
||||
if platform.machine() == 'armv7l':
|
||||
flags['CXXFLAGS'] += ['-Wno-psabi'] # Bug #5106
|
||||
return flags
|
||||
|
||||
def getOptimizedFlags(self, conf):
|
||||
flags = super(GccFlags, self).getOptimizedFlags(conf)
|
||||
flags['CXXFLAGS'] += ['-fdiagnostics-color']
|
||||
flags = super().getOptimizedFlags(conf)
|
||||
flags['CXXFLAGS'] += self.__cxxFlags
|
||||
if platform.machine() == 'armv7l':
|
||||
flags['CXXFLAGS'] += ['-Wno-psabi'] # Bug #5106
|
||||
return flags
|
||||
|
||||
class ClangFlags(GccBasicFlags):
|
||||
|
||||
class ClangFlags(GccClangCommonFlags):
|
||||
def getGeneralFlags(self, conf):
|
||||
flags = super(ClangFlags, self).getGeneralFlags(conf)
|
||||
if Utils.unversioned_sys_platform() == 'darwin' and self.getCompilerVersion(conf) >= (9, 0, 0):
|
||||
flags = super().getGeneralFlags(conf)
|
||||
if Utils.unversioned_sys_platform() == 'darwin':
|
||||
# Bug #4296
|
||||
flags['CXXFLAGS'] += [['-isystem', '/usr/local/include'], # for Homebrew
|
||||
['-isystem', '/opt/local/include']] # for MacPorts
|
||||
if Utils.unversioned_sys_platform() == 'freebsd':
|
||||
flags['CXXFLAGS'] += [['-isystem', '/usr/local/include']] # Bug #4790
|
||||
brewdir = '/opt/homebrew' if platform.machine() == 'arm64' else '/usr/local'
|
||||
flags['CXXFLAGS'] += [
|
||||
['-isystem', f'{brewdir}/include'], # for Homebrew
|
||||
['-isystem', '/opt/local/include'], # for MacPorts
|
||||
]
|
||||
elif Utils.unversioned_sys_platform() == 'freebsd':
|
||||
# Bug #4790
|
||||
flags['CXXFLAGS'] += [['-isystem', '/usr/local/include']]
|
||||
return flags
|
||||
|
||||
__cxxFlags = [
|
||||
'-Wundefined-func-template',
|
||||
'-Wno-unused-local-typedef', # Bugs #2657 and #3209
|
||||
]
|
||||
|
||||
def getDebugFlags(self, conf):
|
||||
flags = super(ClangFlags, self).getDebugFlags(conf)
|
||||
flags['CXXFLAGS'] += ['-fcolor-diagnostics',
|
||||
'-Wextra-semi',
|
||||
'-Wundefined-func-template',
|
||||
'-Wno-unused-local-typedef', # Bugs #2657 and #3209
|
||||
]
|
||||
version = self.getCompilerVersion(conf)
|
||||
if version < (3, 9, 0) or (Utils.unversioned_sys_platform() == 'darwin' and version < (8, 1, 0)):
|
||||
flags['CXXFLAGS'] += ['-Wno-unknown-pragmas']
|
||||
if version < (6, 0, 0):
|
||||
flags['CXXFLAGS'] += ['-Wno-missing-braces'] # Bug #4721
|
||||
flags = super().getDebugFlags(conf)
|
||||
flags['CXXFLAGS'] += self.__cxxFlags
|
||||
return flags
|
||||
|
||||
def getOptimizedFlags(self, conf):
|
||||
flags = super(ClangFlags, self).getOptimizedFlags(conf)
|
||||
flags['CXXFLAGS'] += ['-fcolor-diagnostics',
|
||||
'-Wextra-semi',
|
||||
'-Wundefined-func-template',
|
||||
'-Wno-unused-local-typedef', # Bugs #2657 and #3209
|
||||
]
|
||||
version = self.getCompilerVersion(conf)
|
||||
if version < (3, 9, 0) or (Utils.unversioned_sys_platform() == 'darwin' and version < (8, 1, 0)):
|
||||
flags['CXXFLAGS'] += ['-Wno-unknown-pragmas']
|
||||
if version < (6, 0, 0):
|
||||
flags['CXXFLAGS'] += ['-Wno-missing-braces'] # Bug #4721
|
||||
flags = super().getOptimizedFlags(conf)
|
||||
flags['CXXFLAGS'] += self.__cxxFlags
|
||||
return flags
|
||||
@@ -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:
|
||||
|
||||
+59
-78
@@ -1,82 +1,63 @@
|
||||
NFD Authors
|
||||
===========
|
||||
# NFD Authors
|
||||
|
||||
NFD is an open source project started in late 2013, includes contributions
|
||||
from many people around the world, and open for new contributions from new
|
||||
volunteers.
|
||||
The following lists maintainers, primary developers, and all much-appreciated contributors to NFD in alphabetical 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/main/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>
|
||||
* Hila Ben Abraham <https://sites.wustl.edu/hbabraham>
|
||||
* Muktadir R Chowdhury <https://github.com/alvyC>
|
||||
* Tai-Lin Chu <https://www.linkedin.com/pub/tai-lin-chu/55/5b2/669>
|
||||
* Stephanie DiBenedetto
|
||||
* Saurab Dulal <https://dulalsaurab.github.io>
|
||||
* Chengyu Fan <https://github.com/chengyu>
|
||||
* Ashlesh Gawande <https://www.linkedin.com/in/agawande>
|
||||
* Chavoosh Ghasemi <https://chavoosh.github.io>
|
||||
* Mathias Gibbens <https://calenhad.com>
|
||||
* Nick Gordon <https://github.com/gorgonical>
|
||||
* Giulio Grassi <https://www.lip6.fr/actualite/personnes-fiche.php?ident=D1461>
|
||||
* Yi Huang <https://www.linkedin.com/in/yihuang1991>
|
||||
* Alexander Lane <https://github.com/awlane>
|
||||
* Jongseok Lee <https://github.com/imwhiz>
|
||||
* Spencer Lee <https://www.linkedin.com/in/spenlee>
|
||||
* Vince Lehman <http://vslehman.com>
|
||||
* Yanbiao Li <https://www.linkedin.com/pub/yanbiao-li/24/7a1/4ba>
|
||||
* Teng Liang <https://cs.arizona.edu/~philoliang>
|
||||
* Weiwei Liu <https://www.linkedin.com/in/weiweiliu10>
|
||||
* Spyridon Mastorakis <https://sites.google.com/site/spyridonmastorakis>
|
||||
* Ernest McCracken <https://github.com/emccrckn>
|
||||
* Ilya Moiseenko <https://www.linkedin.com/in/ilya-moiseenko-52884317>
|
||||
* Eric Newberry <https://ericnewberry.com>
|
||||
* Ju Pan <https://cs-jupan.com>
|
||||
* João Pereira <http://website.jpereira.co.uk>
|
||||
* ***(Maintainer)*** Davide Pesavento <https://github.com/Pesa>
|
||||
* Felix Rabe <https://twitter.com/felixrabe>
|
||||
* Md Ashiqur Rahman <https://ashiqrahman.com>
|
||||
* Matteo Sammarco <https://www.linkedin.com/in/matteo-sammarco-9b544530>
|
||||
* Niv Sardi <http://core.evilgiggle.com>
|
||||
* Klaus Schneider <https://cs.arizona.edu/~klaus>
|
||||
* Wentao Shang <https://irl.cs.ucla.edu/~wentao>
|
||||
* Susmit Shannigrahi <https://susm.it>
|
||||
* ***(Former Maintainer)*** Junxiao Shi <https://cs.arizona.edu/~shijunxiao>
|
||||
* Yukai Tu <https://irl.cs.ucla.edu/~yukai>
|
||||
* Sebastian Wölke <https://inet.haw-hamburg.de/members/alumni-1/sebastian-woelke>
|
||||
* Yumin Xia <https://github.com/Stumble>
|
||||
* Yingdi Yu <https://irl.cs.ucla.edu/~yingdi>
|
||||
* Haowei Yuan <http://www.cse.wustl.edu/~yuanh>
|
||||
* Hang Zhang <http://netlab.bit.edu.cn/z_hang>
|
||||
* Minsheng Zhang <https://github.com/mzhang4>
|
||||
* Zhiyi Zhang <https://zhiyi-zhang.com>
|
||||
* Qi Zhao <https://web.cs.ucla.edu/~qi.zhao>
|
||||
* Wenkai Zheng <https://github.com/wenkaizheng>
|
||||
|
||||
## Project technical leads:
|
||||
## Technical Advisors
|
||||
|
||||
* Alexander Afanasyev <http://lasr.cs.ucla.edu/afanasyev/index.html>
|
||||
* Junxiao Shi <http://www.cs.arizona.edu/people/shijunxiao/>
|
||||
|
||||
|
||||
## Technical advisors:
|
||||
|
||||
* Beichuan Zhang <http://www.cs.arizona.edu/~bzhang/>
|
||||
* Lixia Zhang <http://www.cs.ucla.edu/~lixia/>
|
||||
|
||||
|
||||
## Main project authors and their affiliations:
|
||||
|
||||
* University of California, Los Angeles
|
||||
|
||||
* Alexander Afanasyev <http://lasr.cs.ucla.edu/afanasyev/index.html>
|
||||
* Ilya Moiseenko <http://ilyamoiseenko.com/>
|
||||
* Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/web/index.html>
|
||||
* Wentao Shang <http://irl.cs.ucla.edu/~wentao/>
|
||||
* Lixia Zhang <http://www.cs.ucla.edu/~lixia/>
|
||||
|
||||
* The University of Arizona
|
||||
|
||||
* Junxiao Shi <http://www.cs.arizona.edu/people/shijunxiao/>
|
||||
* Yi Huang <ethanhuang1991@gmail.com>
|
||||
* Jerald Paul Abraham <http://www.cs.arizona.edu/people/jeraldabraham/>
|
||||
* Beichuan Zhang <http://www.cs.arizona.edu/~bzhang/>
|
||||
|
||||
* Colorado State University
|
||||
|
||||
* Steve DiBenedetto <http://www.cs.colostate.edu/~dibenede/>
|
||||
* Chengyu Fan <chengyu@cs.colostate.edu>
|
||||
* Christos Papadopoulos <http://www.cs.colostate.edu/~christos/>
|
||||
|
||||
* University Pierre & Marie Curie, Sorbonne University
|
||||
|
||||
* Davide Pesavento <https://www.linkedin.com/in/davidepesavento>
|
||||
* Giulio Grassi <http://www.lip6.fr/actualite/personnes-fiche.php?ident=D1461>
|
||||
* Giovanni Pau <http://www.cs.ucla.edu/~gpau/Giovanni_Paus_Home_Page/Home.html>
|
||||
|
||||
* Beijing Institute of Technology
|
||||
|
||||
* Hang Zhang <http://netlab.bit.edu.cn/z_hang>
|
||||
* Tian Song <http://cs.bit.edu.cn/songtian>
|
||||
|
||||
* Washington University in St. Louis
|
||||
|
||||
* Haowei Yuan <http://www.cse.wustl.edu/~yuanh/>
|
||||
* Hila Ben Abraham <http://research.engineering.wustl.edu/~abrahamh/>
|
||||
* Patrick Crowley <http://www.arl.wustl.edu/~pcrowley/>
|
||||
|
||||
* The University of Memphis
|
||||
|
||||
* Syed Obaid Amin <http://obaidamin.weebly.com/>
|
||||
* Vince Lehman <vslehman@memphis.edu>
|
||||
* Minsheng Zhang <mzhang4@memphis.edu>
|
||||
* Lan Wang <http://www.cs.memphis.edu/~lanwang/>
|
||||
|
||||
## Project contributors
|
||||
|
||||
The following is an inevitably incomplete list of MUCH-APPRECIATED CONTRIBUTORS,
|
||||
people who have reported bugs, submitted patches, and implemented new features
|
||||
in the library:
|
||||
|
||||
* Tai-Lin Chu <https://www.linkedin.com/pub/tai-lin-chu/55/5b2/669>
|
||||
* Spyridon Mastorakis <http://cs.ucla.edu/~mastorakis/>
|
||||
* Eric Newberry <http://cs.arizona.edu/~enewberry/>
|
||||
* Yukai Tu <tuyukai1994@gmail.com>
|
||||
* João Pereira <http://website.jpereira.co.uk>
|
||||
* Mathias Gibbens <gibmat@cs.arizona.edu>
|
||||
* Yanbiao Li <https://www.linkedin.com/pub/yanbiao-li/24/7a1/4ba>
|
||||
* Weiwei Liu <https://www.linkedin.com/in/weiweiliu10>
|
||||
* Spencer Lee <https://www.linkedin.com/in/spenlee>
|
||||
* Patrick Crowley <https://www.arl.wustl.edu/~pcrowley>
|
||||
* Christos Papadopoulos <https://www.cs.colostate.edu/~christos>
|
||||
* Giovanni Pau <https://www.unibo.it/sitoweb/giovanni.pau/en>
|
||||
* Tian Song <http://www.bit-netlab.org/songtian>
|
||||
* Lan Wang <http://www.cs.memphis.edu/~lanwang>
|
||||
* Beichuan Zhang <https://cs.arizona.edu/~bzhang>
|
||||
* Lixia Zhang <https://cs.ucla.edu/~lixia>
|
||||
@@ -0,0 +1,17 @@
|
||||
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://docs.named-data.net/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
|
||||
@@ -1,81 +0,0 @@
|
||||
# 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
@@ -1,489 +0,0 @@
|
||||
# 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.
|
||||

|
||||
|
||||
In that case, add it under contact information panel.
|
||||
.
|
||||
|
||||
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
|
||||
+4
-5
@@ -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 a
|
||||
- CityHash is licensed under the
|
||||
[MIT license](https://github.com/google/cityhash/blob/master/COPYING)
|
||||
|
||||
- Libpcap is licensed under a
|
||||
- Libpcap is licensed under the
|
||||
[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,11 +21,10 @@ 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/
|
||||
these licenses, see <https://www.gnu.org/licenses/>
|
||||
|
||||
----------------------------------------------------------------------------------
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
### GNU GENERAL PUBLIC LICENSE
|
||||
|
||||
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
FROM ghcr.io/named-data/ndn-cxx:latest as builder
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends libpcap-dev \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
COPY . /NFD
|
||||
|
||||
RUN cd /NFD \
|
||||
&& ./waf configure --without-pch --prefix=/usr --sysconfdir=/etc --localstatedir=/var \
|
||||
&& ./waf \
|
||||
&& ./waf install \
|
||||
# get list of dependencies
|
||||
&& mkdir -p /shlibdeps/debian && cd /shlibdeps && touch debian/control \
|
||||
&& dpkg-shlibdeps --ignore-missing-info /usr/lib/libndn-cxx.so* /usr/bin/nfdc /usr/bin/nfd \
|
||||
&& sed -n '/^shlibs:Depends=/ s|shlibs:Depends=||p' debian/substvars | sed -e 's|,||g' -e 's| ([^)]*)||g' > /deps.txt
|
||||
|
||||
# use same base distro version as named-data/ndn-cxx
|
||||
FROM debian:bookworm
|
||||
|
||||
COPY --from=builder /deps.txt /
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends $(cat /deps.txt) \
|
||||
&& rm -rf /var/lib/apt/lists/* /deps.txt
|
||||
|
||||
COPY --from=builder /usr/lib/libndn-cxx.so* /usr/lib/
|
||||
COPY --from=builder /usr/bin/nfd /usr/bin/
|
||||
COPY --from=builder /usr/bin/nfdc /usr/bin/
|
||||
|
||||
COPY --from=builder /usr/bin/nfd-status-http-server /usr/bin/
|
||||
COPY --from=builder /usr/share/ndn/ /usr/share/ndn/
|
||||
|
||||
COPY --from=builder /etc/ndn/nfd.conf.sample /config/nfd.conf
|
||||
|
||||
ENV HOME=/config
|
||||
|
||||
VOLUME /config
|
||||
VOLUME /run/nfd
|
||||
|
||||
EXPOSE 6363/tcp
|
||||
EXPOSE 6363/udp
|
||||
EXPOSE 9696/tcp
|
||||
|
||||
ENTRYPOINT ["/usr/bin/nfd"]
|
||||
CMD ["--config", "/config/nfd.conf"]
|
||||
+9
-12
@@ -1,7 +1,7 @@
|
||||
# Notes for NFD developers
|
||||
|
||||
If you are new to the NDN software community, please read the
|
||||
[Contributor's Guide](https://github.com/named-data/NFD/blob/master/CONTRIBUTING.md).
|
||||
If you are new to the NDN software community, please read our
|
||||
[Contributor's Guide](https://github.com/named-data/.github/blob/main/CONTRIBUTING.md).
|
||||
|
||||
## Code style
|
||||
|
||||
@@ -9,11 +9,9 @@ NFD code is subject to [NFD code style](https://redmine.named-data.net/projects/
|
||||
|
||||
## Licensing
|
||||
|
||||
Contributions to NFD must be licensed under the GPL 3.0 or compatible license. If you
|
||||
are choosing GPL 3.0, please use the following license boilerplate in all `.hpp` and
|
||||
`.cpp` files:
|
||||
|
||||
Include the following license boilerplate into all `.hpp` and `.cpp` files:
|
||||
Contributions to NFD must be licensed under the GPL v3 or a compatible license.
|
||||
If you choose the GPL v3, please use the following license boilerplate in all `.hpp`
|
||||
and `.cpp` files:
|
||||
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
@@ -61,12 +59,12 @@ The simplest way to run the tests is to launch the compiled binary without any p
|
||||
# Run NFD RIB management tests
|
||||
./build/unit-tests-rib
|
||||
|
||||
[Boost.Test framework](https://www.boost.org/doc/libs/1_58_0/libs/test/doc/html/index.html)
|
||||
The [Boost.Test framework](https://www.boost.org/doc/libs/1_71_0/libs/test/doc/html/index.html)
|
||||
is very flexible and allows a number of run-time customization of what tests should be run.
|
||||
For example, it is possible to choose to run only a specific test suite, only a specific
|
||||
test case within a suite, or specific test cases within specific test suites:
|
||||
|
||||
# Run only TCP Face test suite of NFD daemon tests (see tests/daemon/face/tcp.cpp)
|
||||
# Run only the TCP Face test suite of NFD daemon tests
|
||||
./build/unit-tests-daemon -t FaceTcp
|
||||
|
||||
# Run only test case EndToEnd4 from the same test suite
|
||||
@@ -93,6 +91,5 @@ or `-p` to show a progress bar:
|
||||
./build/unit-tests-core -p
|
||||
|
||||
There are many more command line options available, information about which can be obtained
|
||||
either from the command line using `--help` switch, or online on
|
||||
[Boost.Test library](https://www.boost.org/doc/libs/1_58_0/libs/test/doc/html/index.html)
|
||||
website.
|
||||
either from the command line using the `--help` switch, or online on the
|
||||
[Boost.Test website](https://www.boost.org/doc/libs/1_71_0/libs/test/doc/html/boost_test/runtime_config.html).
|
||||
@@ -1,13 +1,20 @@
|
||||
# NFD - Named Data Networking Forwarding Daemon
|
||||
<div align="center">
|
||||
|
||||

|
||||
[](https://travis-ci.org/named-data/NFD)
|
||||

|
||||
[<img alt height="65" src="docs/named_data_theme/static/ndn-logo.svg"/>](https://named-data.net/)
|
||||
|
||||
# NFD: Named Data Networking Forwarding Daemon
|
||||
|
||||
</div>
|
||||
|
||||
[](https://github.com/named-data/NFD/actions/workflows/ci.yml)
|
||||
[](https://github.com/named-data/NFD/actions/workflows/docs.yml)
|
||||

|
||||

|
||||
|
||||
## Overview
|
||||
|
||||
NFD is a network forwarder that implements and evolves together with the Named Data
|
||||
Networking (NDN) [protocol](https://named-data.net/doc/NDN-packet-spec/current/).
|
||||
NFD is a network forwarder that implements and evolves together with the Named
|
||||
Data Networking (NDN) [protocol](https://docs.named-data.net/NDN-packet-spec/).
|
||||
Since the initial public release in 2014, NFD has been a core component of the
|
||||
[NDN Platform](https://named-data.net/codebase/platform/).
|
||||
|
||||
@@ -27,13 +34,12 @@ various features, some of which may eventually work into the protocol spec.
|
||||
|
||||
See [`docs/INSTALL.rst`](docs/INSTALL.rst) for compilation and installation instructions.
|
||||
|
||||
Extensive documentation is available on NFD's [homepage](https://named-data.net/doc/NFD/).
|
||||
Extensive documentation is available on NFD's [homepage](https://docs.named-data.net/NFD/).
|
||||
|
||||
## Reporting bugs
|
||||
|
||||
Bug reports and feedback are highly appreciated and can be submitted through the
|
||||
[NFD issue tracker](https://redmine.named-data.net/projects/nfd/issues) or the
|
||||
[ndn-interest mailing list](http://www.lists.cs.ucla.edu/mailman/listinfo/ndn-interest).
|
||||
Please submit any bug reports or feature requests to the
|
||||
[NFD issue tracker](https://redmine.named-data.net/projects/nfd/issues).
|
||||
|
||||
## Contributing
|
||||
|
||||
@@ -43,12 +49,13 @@ it already contains significant contributions from people outside the project te
|
||||
[`AUTHORS.md`](AUTHORS.md)). We strongly encourage participation from all interested parties,
|
||||
since broader community support is key for NDN to succeed as a new Internet architecture.
|
||||
|
||||
If you are new to the NDN software community, please read [`README-dev.md`](README-dev.md)
|
||||
and the [Contributor's Guide](CONTRIBUTING.md) to get started.
|
||||
Contributions to NFD are greatly appreciated and can be made through our
|
||||
[Gerrit code review site](https://gerrit.named-data.net/).
|
||||
If you are new to the NDN software community, please read our
|
||||
[Contributor's Guide](https://github.com/named-data/.github/blob/main/CONTRIBUTING.md)
|
||||
and [`README-dev.md`](README-dev.md) to get started.
|
||||
|
||||
## License
|
||||
|
||||
NFD is an open and free software package licensed under the GPL version 3 and is the
|
||||
centerpiece of our committement to making NDN's core technology open and free to all
|
||||
Internet users and developers. For more information about the licensing details and
|
||||
limitations, refer to [`COPYING.md`](COPYING.md).
|
||||
NFD is free software distributed under the GNU General Public License version 3.
|
||||
See [`COPYING.md`](COPYING.md) for details.
|
||||
@@ -1 +0,0 @@
|
||||
docs/release-notes-latest.rst
|
||||
+25
-33
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2023, 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 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
|
||||
#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
|
||||
#else
|
||||
#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
|
||||
#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
|
||||
#endif
|
||||
|
||||
#include <cstddef>
|
||||
@@ -50,17 +50,15 @@
|
||||
#include <limits>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <set>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <string_view>
|
||||
#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>
|
||||
@@ -70,20 +68,16 @@
|
||||
#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/lexical_cast.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
#include <boost/core/noncopyable.hpp>
|
||||
|
||||
namespace nfd {
|
||||
|
||||
using std::size_t;
|
||||
|
||||
using boost::noncopyable;
|
||||
|
||||
using std::shared_ptr;
|
||||
using std::unique_ptr;
|
||||
using std::weak_ptr;
|
||||
@@ -94,18 +88,15 @@ using std::static_pointer_cast;
|
||||
using std::dynamic_pointer_cast;
|
||||
using std::const_pointer_cast;
|
||||
|
||||
using std::bind;
|
||||
|
||||
using std::to_string;
|
||||
using namespace std::string_literals;
|
||||
using namespace std::string_view_literals;
|
||||
|
||||
using ndn::optional;
|
||||
using ndn::nullopt;
|
||||
using ndn::to_string;
|
||||
using boost::noncopyable;
|
||||
|
||||
using ndn::span;
|
||||
using ndn::Block;
|
||||
using ndn::Data;
|
||||
using ndn::Delegation;
|
||||
using ndn::DelegationList;
|
||||
using ndn::FaceUri;
|
||||
using ndn::Interest;
|
||||
using ndn::Name;
|
||||
@@ -121,10 +112,11 @@ using namespace ndn::tlv;
|
||||
namespace lp = ndn::lp;
|
||||
namespace name = ndn::name;
|
||||
namespace scheduler = ndn::scheduler;
|
||||
namespace signal = ndn::util::signal;
|
||||
namespace signal = ndn::signal;
|
||||
namespace time = ndn::time;
|
||||
|
||||
using namespace ndn::block_literals;
|
||||
using namespace ndn::time_literals;
|
||||
using ndn::operator""_block;
|
||||
|
||||
} // namespace nfd
|
||||
|
||||
|
||||
+13
-9
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2018, Regents of the University of California,
|
||||
* Copyright (c) 2014-2023, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -25,9 +25,13 @@
|
||||
|
||||
#include "network.hpp"
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/utility/value_init.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <istream>
|
||||
#include <ostream>
|
||||
|
||||
namespace nfd {
|
||||
|
||||
@@ -44,7 +48,7 @@ const Network&
|
||||
Network::getMaxRangeV4()
|
||||
{
|
||||
using boost::asio::ip::address_v4;
|
||||
static Network range{address_v4{}, address_v4{0xffffffff}};
|
||||
static const Network range{address_v4{}, address_v4{0xffffffff}};
|
||||
return range;
|
||||
}
|
||||
|
||||
@@ -52,14 +56,14 @@ const Network&
|
||||
Network::getMaxRangeV6()
|
||||
{
|
||||
using boost::asio::ip::address_v6;
|
||||
static address_v6::bytes_type maxV6 = {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};
|
||||
static Network range{address_v6{}, address_v6{maxV6}};
|
||||
static const address_v6::bytes_type maxV6 = {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};
|
||||
static const Network range{address_v6{}, address_v6{maxV6}};
|
||||
return range;
|
||||
}
|
||||
|
||||
bool
|
||||
Network::isValidCidr(const std::string& cidr)
|
||||
Network::isValidCidr(std::string_view cidr) noexcept
|
||||
{
|
||||
auto pos = cidr.find('/');
|
||||
if (pos == std::string::npos) {
|
||||
@@ -92,8 +96,8 @@ operator>>(std::istream& is, Network& network)
|
||||
size_t position = networkStr.find('/');
|
||||
if (position == std::string::npos) {
|
||||
try {
|
||||
network.m_minAddress = ip::address::from_string(networkStr);
|
||||
network.m_maxAddress = ip::address::from_string(networkStr);
|
||||
network.m_minAddress = ip::make_address(networkStr);
|
||||
network.m_maxAddress = ip::make_address(networkStr);
|
||||
}
|
||||
catch (const boost::system::system_error&) {
|
||||
is.setstate(std::ios::failbit);
|
||||
@@ -102,7 +106,7 @@ operator>>(std::istream& is, Network& network)
|
||||
}
|
||||
else {
|
||||
boost::system::error_code ec;
|
||||
auto address = ip::address::from_string(networkStr.substr(0, position), ec);
|
||||
auto address = ip::make_address(networkStr.substr(0, position), ec);
|
||||
if (ec) {
|
||||
is.setstate(std::ios::failbit);
|
||||
return is;
|
||||
|
||||
+18
-19
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/**
|
||||
* Copyright (c) 2014-2016, Regents of the University of California,
|
||||
/*
|
||||
* Copyright (c) 2014-2023, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -26,11 +26,14 @@
|
||||
#ifndef NFD_CORE_NETWORK_HPP
|
||||
#define NFD_CORE_NETWORK_HPP
|
||||
|
||||
#include "common.hpp"
|
||||
#include <boost/asio/ip/address.hpp>
|
||||
#include <boost/operators.hpp>
|
||||
|
||||
#include <string_view>
|
||||
|
||||
namespace nfd {
|
||||
|
||||
class Network
|
||||
class Network : private boost::equality_comparable<Network>
|
||||
{
|
||||
public:
|
||||
Network();
|
||||
@@ -39,7 +42,7 @@ public:
|
||||
const boost::asio::ip::address& maxAddress);
|
||||
|
||||
bool
|
||||
doesContain(const boost::asio::ip::address& address) const
|
||||
doesContain(const boost::asio::ip::address& address) const noexcept
|
||||
{
|
||||
return m_minAddress <= address && address <= m_maxAddress;
|
||||
}
|
||||
@@ -51,29 +54,25 @@ public:
|
||||
getMaxRangeV6();
|
||||
|
||||
static bool
|
||||
isValidCidr(const std::string& cidr);
|
||||
isValidCidr(std::string_view cidr) noexcept;
|
||||
|
||||
bool
|
||||
operator==(const Network& rhs) const
|
||||
private: // non-member operators
|
||||
friend bool
|
||||
operator==(const Network& lhs, const Network& rhs) noexcept
|
||||
{
|
||||
return m_minAddress == rhs.m_minAddress && m_maxAddress == rhs.m_maxAddress;
|
||||
return lhs.m_minAddress == rhs.m_minAddress &&
|
||||
lhs.m_maxAddress == rhs.m_maxAddress;
|
||||
}
|
||||
|
||||
bool
|
||||
operator!=(const Network& rhs) const
|
||||
{
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
private:
|
||||
boost::asio::ip::address m_minAddress;
|
||||
boost::asio::ip::address m_maxAddress;
|
||||
|
||||
friend std::ostream&
|
||||
operator<<(std::ostream& os, const Network& network);
|
||||
|
||||
friend std::istream&
|
||||
operator>>(std::istream& is, Network& network);
|
||||
|
||||
private:
|
||||
boost::asio::ip::address m_minAddress;
|
||||
boost::asio::ip::address m_maxAddress;
|
||||
};
|
||||
|
||||
std::ostream&
|
||||
|
||||
+16
-12
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2022, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -26,14 +26,16 @@
|
||||
#ifndef NFD_CORE_VERSION_HPP
|
||||
#define NFD_CORE_VERSION_HPP
|
||||
|
||||
// NFD version follows Semantic Versioning 2.0.0
|
||||
// https://semver.org/spec/v2.0.0.html
|
||||
// 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.
|
||||
//
|
||||
// To change version number, modify VERSION variable in top-level wscript.
|
||||
// To change version number, modify the VERSION variable in the 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@
|
||||
|
||||
@@ -44,7 +46,8 @@
|
||||
/// 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
|
||||
@@ -53,20 +56,21 @@
|
||||
*/
|
||||
extern const char NFD_VERSION_STRING[];
|
||||
|
||||
/** \brief NFD version string, including git commit information, if NFD is build from
|
||||
* specific git commit.
|
||||
/**
|
||||
* \brief NFD version string, including git commit information if NFD is build from a
|
||||
* 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: 0.1.0-rc1-1-g5c86570
|
||||
* Example: 2022.02-1-g5c86570
|
||||
*/
|
||||
extern const char NFD_VERSION_BUILD_STRING[];
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2022, 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 unknownSectionCallback)
|
||||
: m_unknownSectionCallback(unknownSectionCallback)
|
||||
ConfigFile::ConfigFile(UnknownConfigSectionHandler callback)
|
||||
: m_unknownSectionCallback(std::move(callback))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ void
|
||||
ConfigFile::addSectionHandler(const std::string& sectionName,
|
||||
ConfigSectionHandler subscriber)
|
||||
{
|
||||
m_subscriptions[sectionName] = subscriber;
|
||||
m_subscriptions[sectionName] = std::move(subscriber);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2023, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -32,27 +32,32 @@
|
||||
|
||||
namespace nfd {
|
||||
|
||||
/** \brief a config file section
|
||||
/**
|
||||
* \brief A configuration file section.
|
||||
*/
|
||||
using ConfigSection = boost::property_tree::ptree;
|
||||
|
||||
/** \brief an optional config file section
|
||||
/**
|
||||
* \brief An optional configuration file section.
|
||||
*/
|
||||
using OptionalConfigSection = boost::optional<const ConfigSection&>;
|
||||
|
||||
/** \brief callback to process a config file section
|
||||
/**
|
||||
* \brief Callback to process a configuration file section.
|
||||
*/
|
||||
using ConfigSectionHandler = std::function<void(const ConfigSection& section, bool isDryRun,
|
||||
const std::string& filename)>;
|
||||
|
||||
/** \brief callback to process a config file section without a \p ConfigSectionHandler
|
||||
/**
|
||||
* \brief Callback to process a configuration file section without a #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
|
||||
{
|
||||
@@ -80,7 +85,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"
|
||||
@@ -95,7 +100,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
|
||||
@@ -105,25 +110,44 @@ public: // parse helpers
|
||||
static T
|
||||
parseNumber(const ConfigSection& node, const std::string& key, const std::string& sectionName)
|
||||
{
|
||||
static_assert(std::is_arithmetic<T>::value, "T must be an arithmetic type");
|
||||
static_assert(std::is_arithmetic_v<T>);
|
||||
|
||||
boost::optional<T> value = node.get_value_optional<T>();
|
||||
if (value) {
|
||||
auto value = node.get_value_optional<T>();
|
||||
// Unsigned logic is workaround for https://redmine.named-data.net/issues/4489
|
||||
if (value &&
|
||||
(std::is_signed_v<T> || node.get_value<std::string>().find("-") == std::string::npos)) {
|
||||
return *value;
|
||||
}
|
||||
NDN_THROW(Error("Invalid value '" + node.get_value<std::string>() +
|
||||
"' 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);
|
||||
|
||||
+29
-21
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2023, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -30,24 +30,27 @@
|
||||
|
||||
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;
|
||||
using rep = uint64_t;
|
||||
|
||||
/** \brief observe the counter
|
||||
/**
|
||||
* \brief Return the counter's value.
|
||||
*/
|
||||
operator rep() const noexcept
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
|
||||
/** \brief replace the counter value
|
||||
/**
|
||||
* \brief Replace the counter's value.
|
||||
*/
|
||||
void
|
||||
set(rep value) noexcept
|
||||
@@ -59,14 +62,16 @@ 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.
|
||||
* \warning The counter value may wrap after exceeding the range of the underlying integer type.
|
||||
*/
|
||||
class PacketCounter : public SimpleCounter
|
||||
{
|
||||
public:
|
||||
/** \brief increment the counter by one
|
||||
/**
|
||||
* \brief Increment the counter by one.
|
||||
*/
|
||||
PacketCounter&
|
||||
operator++() noexcept
|
||||
@@ -74,17 +79,18 @@ public:
|
||||
++m_value;
|
||||
return *this;
|
||||
}
|
||||
// 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.
|
||||
* \warning The counter value may wrap after exceeding the range of the underlying integer type.
|
||||
*/
|
||||
class ByteCounter : public SimpleCounter
|
||||
{
|
||||
public:
|
||||
/** \brief increase the counter
|
||||
/**
|
||||
* \brief Increase the counter.
|
||||
*/
|
||||
ByteCounter&
|
||||
operator+=(rep n) noexcept
|
||||
@@ -94,16 +100,17 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/** \brief provides a counter that observes the size of a table
|
||||
* \tparam T a type that provides a size() const member function
|
||||
/**
|
||||
* \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()
|
||||
* If the table is not specified in the constructor, it can be added later by calling observe().
|
||||
*/
|
||||
template<typename T>
|
||||
class SizeCounter : noncopyable
|
||||
{
|
||||
public:
|
||||
typedef size_t Rep;
|
||||
using rep = size_t;
|
||||
|
||||
explicit constexpr
|
||||
SizeCounter(const T* table = nullptr) noexcept
|
||||
@@ -117,16 +124,17 @@ public:
|
||||
m_table = table;
|
||||
}
|
||||
|
||||
/** \brief observe the counter
|
||||
/**
|
||||
* \brief Return the counter's value, i.e., the current size of the table being observed.
|
||||
*/
|
||||
operator Rep() const
|
||||
operator rep() const
|
||||
{
|
||||
BOOST_ASSERT(m_table != nullptr);
|
||||
return m_table->size();
|
||||
}
|
||||
|
||||
private:
|
||||
const T* m_table;
|
||||
const T* m_table = nullptr;
|
||||
};
|
||||
|
||||
} // namespace nfd
|
||||
|
||||
+20
-32
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2023, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -27,18 +27,18 @@
|
||||
|
||||
namespace nfd {
|
||||
|
||||
static thread_local unique_ptr<boost::asio::io_service> g_ioService;
|
||||
static thread_local unique_ptr<boost::asio::io_context> g_ioCtx;
|
||||
static thread_local unique_ptr<Scheduler> g_scheduler;
|
||||
static boost::asio::io_service* g_mainIoService = nullptr;
|
||||
static boost::asio::io_service* g_ribIoService = nullptr;
|
||||
static boost::asio::io_context* g_mainIoCtx = nullptr;
|
||||
static boost::asio::io_context* g_ribIoCtx = nullptr;
|
||||
|
||||
boost::asio::io_service&
|
||||
boost::asio::io_context&
|
||||
getGlobalIoService()
|
||||
{
|
||||
if (g_ioService == nullptr) {
|
||||
g_ioService = make_unique<boost::asio::io_service>();
|
||||
if (g_ioCtx == nullptr) {
|
||||
g_ioCtx = make_unique<boost::asio::io_context>();
|
||||
}
|
||||
return *g_ioService;
|
||||
return *g_ioCtx;
|
||||
}
|
||||
|
||||
Scheduler&
|
||||
@@ -50,51 +50,39 @@ getScheduler()
|
||||
return *g_scheduler;
|
||||
}
|
||||
|
||||
#ifdef WITH_TESTS
|
||||
#ifdef NFD_WITH_TESTS
|
||||
void
|
||||
resetGlobalIoService()
|
||||
{
|
||||
g_scheduler.reset();
|
||||
g_ioService.reset();
|
||||
g_ioCtx.reset();
|
||||
}
|
||||
#endif
|
||||
|
||||
boost::asio::io_service&
|
||||
boost::asio::io_context&
|
||||
getMainIoService()
|
||||
{
|
||||
BOOST_ASSERT(g_mainIoService != nullptr);
|
||||
return *g_mainIoService;
|
||||
BOOST_ASSERT(g_mainIoCtx != nullptr);
|
||||
return *g_mainIoCtx;
|
||||
}
|
||||
|
||||
boost::asio::io_service&
|
||||
boost::asio::io_context&
|
||||
getRibIoService()
|
||||
{
|
||||
BOOST_ASSERT(g_ribIoService != nullptr);
|
||||
return *g_ribIoService;
|
||||
BOOST_ASSERT(g_ribIoCtx != nullptr);
|
||||
return *g_ribIoCtx;
|
||||
}
|
||||
|
||||
void
|
||||
setMainIoService(boost::asio::io_service* mainIo)
|
||||
setMainIoService(boost::asio::io_context* mainIo)
|
||||
{
|
||||
g_mainIoService = mainIo;
|
||||
g_mainIoCtx = mainIo;
|
||||
}
|
||||
|
||||
void
|
||||
setRibIoService(boost::asio::io_service* ribIo)
|
||||
setRibIoService(boost::asio::io_context* ribIo)
|
||||
{
|
||||
g_ribIoService = ribIo;
|
||||
}
|
||||
|
||||
void
|
||||
runOnMainIoService(const std::function<void()>& f)
|
||||
{
|
||||
getMainIoService().post(f);
|
||||
}
|
||||
|
||||
void
|
||||
runOnRibIoService(const std::function<void()>& f)
|
||||
{
|
||||
getRibIoService().post(f);
|
||||
g_ribIoCtx = ribIo;
|
||||
}
|
||||
|
||||
} // namespace nfd
|
||||
+16
-21
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019 Regents of the University of California,
|
||||
* Copyright (c) 2014-2023 Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -27,44 +27,39 @@
|
||||
|
||||
#include "core/common.hpp"
|
||||
|
||||
#include <boost/asio/io_context.hpp>
|
||||
|
||||
namespace nfd {
|
||||
|
||||
/** \brief Returns the global io_service instance for the calling thread.
|
||||
/**
|
||||
* \brief Returns the global io_context instance for the calling thread.
|
||||
*/
|
||||
boost::asio::io_service&
|
||||
boost::asio::io_context&
|
||||
getGlobalIoService();
|
||||
|
||||
/** \brief Returns the global Scheduler instance for the calling thread.
|
||||
/**
|
||||
* \brief Returns the global Scheduler instance for the calling thread.
|
||||
*/
|
||||
Scheduler&
|
||||
getScheduler();
|
||||
|
||||
boost::asio::io_service&
|
||||
boost::asio::io_context&
|
||||
getMainIoService();
|
||||
|
||||
boost::asio::io_service&
|
||||
boost::asio::io_context&
|
||||
getRibIoService();
|
||||
|
||||
void
|
||||
setMainIoService(boost::asio::io_service* mainIo);
|
||||
setMainIoService(boost::asio::io_context* mainIo);
|
||||
|
||||
void
|
||||
setRibIoService(boost::asio::io_service* ribIo);
|
||||
setRibIoService(boost::asio::io_context* ribIo);
|
||||
|
||||
/** \brief Run a function on the main io_service instance.
|
||||
*/
|
||||
void
|
||||
runOnMainIoService(const std::function<void()>& f);
|
||||
|
||||
/** \brief Run a function on the RIB io_service instance.
|
||||
*/
|
||||
void
|
||||
runOnRibIoService(const std::function<void()>& f);
|
||||
|
||||
#ifdef WITH_TESTS
|
||||
/** \brief Destroy the global io_service instance.
|
||||
#ifdef NFD_WITH_TESTS
|
||||
/**
|
||||
* \brief Destroy the global io_context instance.
|
||||
*
|
||||
* It will be recreated at the next invocation of getGlobalIoService().
|
||||
* It will be recreated at the next invocation of getGlobalIoService().
|
||||
*/
|
||||
void
|
||||
resetGlobalIoService();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2021, 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 HAVE_PRIVILEGE_DROP_AND_ELEVATE
|
||||
#ifdef NFD_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 // HAVE_PRIVILEGE_DROP_AND_ELEVATE
|
||||
#endif // NFD_HAVE_PRIVILEGE_DROP_AND_ELEVATE
|
||||
|
||||
void
|
||||
PrivilegeHelper::initialize(const std::string& userName, const std::string& groupName)
|
||||
{
|
||||
#ifdef HAVE_PRIVILEGE_DROP_AND_ELEVATE
|
||||
#ifdef NFD_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;
|
||||
|
||||
@@ -63,25 +63,23 @@ PrivilegeHelper::initialize(const std::string& userName, const std::string& grou
|
||||
groupSize = FALLBACK_GROUP_BUFFER_SIZE;
|
||||
|
||||
std::vector<char> groupBuffer(static_cast<size_t>(groupSize));
|
||||
struct group group;
|
||||
struct group* groupResult = nullptr;
|
||||
group gr;
|
||||
group* grResult = nullptr;
|
||||
|
||||
int errorCode = getgrnam_r(groupName.data(), &group,
|
||||
groupBuffer.data(), groupBuffer.size(), &groupResult);
|
||||
int errorCode = getgrnam_r(groupName.data(), &gr, groupBuffer.data(), groupBuffer.size(), &grResult);
|
||||
|
||||
while (errorCode == ERANGE) {
|
||||
if (groupBuffer.size() * 2 > MAX_GROUP_BUFFER_SIZE)
|
||||
throw Error("Cannot allocate large enough buffer for struct group");
|
||||
|
||||
groupBuffer.resize(groupBuffer.size() * 2);
|
||||
errorCode = getgrnam_r(groupName.data(), &group,
|
||||
groupBuffer.data(), groupBuffer.size(), &groupResult);
|
||||
errorCode = getgrnam_r(groupName.data(), &gr, groupBuffer.data(), groupBuffer.size(), &grResult);
|
||||
}
|
||||
|
||||
if (errorCode != 0 || !groupResult)
|
||||
if (errorCode != 0 || !grResult)
|
||||
throw Error("Failed to get gid for \"" + groupName + "\"");
|
||||
|
||||
s_normalGid = group.gr_gid;
|
||||
s_normalGid = gr.gr_gid;
|
||||
}
|
||||
|
||||
if (!userName.empty()) {
|
||||
@@ -91,37 +89,35 @@ PrivilegeHelper::initialize(const std::string& userName, const std::string& grou
|
||||
passwdSize = FALLBACK_PASSWD_BUFFER_SIZE;
|
||||
|
||||
std::vector<char> passwdBuffer(static_cast<size_t>(passwdSize));
|
||||
struct passwd passwd;
|
||||
struct passwd* passwdResult = nullptr;
|
||||
passwd pw;
|
||||
passwd* pwResult = nullptr;
|
||||
|
||||
int errorCode = getpwnam_r(userName.data(), &passwd,
|
||||
passwdBuffer.data(), passwdBuffer.size(), &passwdResult);
|
||||
int errorCode = getpwnam_r(userName.data(), &pw, passwdBuffer.data(), passwdBuffer.size(), &pwResult);
|
||||
|
||||
while (errorCode == ERANGE) {
|
||||
if (passwdBuffer.size() * 2 > MAX_PASSWD_BUFFER_SIZE)
|
||||
throw Error("Cannot allocate large enough buffer for struct passwd");
|
||||
|
||||
passwdBuffer.resize(passwdBuffer.size() * 2);
|
||||
errorCode = getpwnam_r(userName.data(), &passwd,
|
||||
passwdBuffer.data(), passwdBuffer.size(), &passwdResult);
|
||||
errorCode = getpwnam_r(userName.data(), &pw, passwdBuffer.data(), passwdBuffer.size(), &pwResult);
|
||||
}
|
||||
|
||||
if (errorCode != 0 || !passwdResult)
|
||||
if (errorCode != 0 || !pwResult)
|
||||
throw Error("Failed to get uid for \"" + userName + "\"");
|
||||
|
||||
s_normalUid = passwd.pw_uid;
|
||||
s_normalUid = pw.pw_uid;
|
||||
}
|
||||
#else
|
||||
if (!userName.empty() || !groupName.empty()) {
|
||||
throw Error("Dropping and raising privileges is not supported on this platform");
|
||||
}
|
||||
#endif // HAVE_PRIVILEGE_DROP_AND_ELEVATE
|
||||
#endif // NFD_HAVE_PRIVILEGE_DROP_AND_ELEVATE
|
||||
}
|
||||
|
||||
void
|
||||
PrivilegeHelper::drop()
|
||||
{
|
||||
#ifdef HAVE_PRIVILEGE_DROP_AND_ELEVATE
|
||||
#ifdef NFD_HAVE_PRIVILEGE_DROP_AND_ELEVATE
|
||||
if (::geteuid() == s_normalUid && ::getegid() == s_normalGid)
|
||||
return;
|
||||
|
||||
@@ -136,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 // HAVE_PRIVILEGE_DROP_AND_ELEVATE
|
||||
#endif // NFD_HAVE_PRIVILEGE_DROP_AND_ELEVATE
|
||||
}
|
||||
|
||||
void
|
||||
PrivilegeHelper::raise()
|
||||
{
|
||||
#ifdef HAVE_PRIVILEGE_DROP_AND_ELEVATE
|
||||
#ifdef NFD_HAVE_PRIVILEGE_DROP_AND_ELEVATE
|
||||
if (::geteuid() == s_privilegedUid && ::getegid() == s_privilegedGid)
|
||||
return;
|
||||
|
||||
@@ -157,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 // HAVE_PRIVILEGE_DROP_AND_ELEVATE
|
||||
#endif // NFD_HAVE_PRIVILEGE_DROP_AND_ELEVATE
|
||||
}
|
||||
|
||||
} // namespace nfd
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2022, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -35,10 +35,12 @@ namespace nfd {
|
||||
class PrivilegeHelper
|
||||
{
|
||||
public:
|
||||
/** \brief represents a serious seteuid/gid failure
|
||||
/**
|
||||
* \brief Indicates a serious seteuid/setegid 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
|
||||
{
|
||||
@@ -71,7 +73,7 @@ public:
|
||||
{
|
||||
raise();
|
||||
try {
|
||||
f();
|
||||
std::invoke(std::forward<F>(f));
|
||||
}
|
||||
catch (...) {
|
||||
drop();
|
||||
@@ -80,18 +82,18 @@ public:
|
||||
drop();
|
||||
}
|
||||
|
||||
PUBLIC_WITH_TESTS_ELSE_PRIVATE:
|
||||
NFD_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
|
||||
static void
|
||||
raise();
|
||||
|
||||
PUBLIC_WITH_TESTS_ELSE_PRIVATE:
|
||||
#ifdef HAVE_PRIVILEGE_DROP_AND_ELEVATE
|
||||
NFD_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
|
||||
#ifdef NFD_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 // HAVE_PRIVILEGE_DROP_AND_ELEVATE
|
||||
#endif // NFD_HAVE_PRIVILEGE_DROP_AND_ELEVATE
|
||||
};
|
||||
|
||||
} // namespace nfd
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
|
||||
#include "TokenBucket.hpp"
|
||||
#include "common/global.hpp"
|
||||
#include "common/logger.hpp"
|
||||
#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));
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
//
|
||||
// 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();
|
||||
/**
|
||||
* 尝试消费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; // 标识是否启动
|
||||
};
|
||||
}
|
||||
}
|
||||
#endif //NS_TOKENBUCKET_H
|
||||
+10
-6
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2022, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -26,17 +26,22 @@
|
||||
#include "channel.hpp"
|
||||
#include "face.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
namespace nfd::face {
|
||||
|
||||
Channel::~Channel() = default;
|
||||
|
||||
void
|
||||
Channel::setUri(const FaceUri& uri)
|
||||
Channel::setUri(const FaceUri& uri) noexcept
|
||||
{
|
||||
m_uri = uri;
|
||||
}
|
||||
|
||||
void
|
||||
Channel::setDefaultMtu(size_t mtu) noexcept
|
||||
{
|
||||
m_defaultMtu = mtu;
|
||||
}
|
||||
|
||||
void
|
||||
connectFaceClosedSignal(Face& face, std::function<void()> f)
|
||||
{
|
||||
@@ -47,5 +52,4 @@ connectFaceClosedSignal(Face& face, std::function<void()> f)
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
} // namespace nfd::face
|
||||
+23
-10
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2022, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -29,8 +29,7 @@
|
||||
#include "channel-log.hpp"
|
||||
#include "face-common.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
namespace nfd::face {
|
||||
|
||||
/** \brief Represents a channel that listens on a local endpoint.
|
||||
* \sa FaceSystem
|
||||
@@ -38,34 +37,49 @@ namespace face {
|
||||
* A channel can listen on a local endpoint and initiate outgoing connection from a local endpoint.
|
||||
* A channel creates Face objects and retains shared ownership of them.
|
||||
*/
|
||||
class Channel : noncopyable
|
||||
class Channel : public std::enable_shared_from_this<Channel>, noncopyable
|
||||
{
|
||||
public:
|
||||
virtual
|
||||
~Channel();
|
||||
|
||||
const FaceUri&
|
||||
getUri() const
|
||||
getUri() const noexcept
|
||||
{
|
||||
return m_uri;
|
||||
}
|
||||
|
||||
/** \brief Returns whether the channel is listening
|
||||
/**
|
||||
* \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.
|
||||
*/
|
||||
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);
|
||||
setUri(const FaceUri& uri) noexcept;
|
||||
|
||||
void
|
||||
setDefaultMtu(size_t mtu) noexcept;
|
||||
|
||||
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
|
||||
@@ -87,7 +101,6 @@ using FaceCreationFailedCallback = std::function<void(uint32_t status, const std
|
||||
void
|
||||
connectFaceClosedSignal(Face& face, std::function<void()> f);
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
} // namespace nfd::face
|
||||
|
||||
#endif // NFD_DAEMON_FACE_CHANNEL_HPP
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2023, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -32,25 +32,30 @@
|
||||
|
||||
#include <array>
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
#include <boost/asio/defer.hpp>
|
||||
|
||||
namespace nfd::face {
|
||||
|
||||
struct Unicast {};
|
||||
struct Multicast {};
|
||||
|
||||
/** \brief Implements Transport for datagram-based protocols.
|
||||
/**
|
||||
* \brief Implements a Transport for datagram-based protocols.
|
||||
*
|
||||
* \tparam Protocol a datagram-based protocol in Boost.Asio
|
||||
* \tparam Protocol A datagram-based protocol in Boost.Asio
|
||||
* \tparam Addressing The addressing mode, either Unicast or Multicast
|
||||
*/
|
||||
template<class Protocol, class Addressing = Unicast>
|
||||
template<class Protocol, class Addressing>
|
||||
class DatagramTransport : public Transport
|
||||
{
|
||||
public:
|
||||
typedef Protocol protocol;
|
||||
using protocol = Protocol;
|
||||
using addressing = Addressing;
|
||||
|
||||
/** \brief Construct datagram transport.
|
||||
/**
|
||||
* \brief Construct datagram transport.
|
||||
*
|
||||
* \param socket Protocol-specific socket for the created transport
|
||||
* \param socket Protocol-specific socket for the created transport
|
||||
*/
|
||||
explicit
|
||||
DatagramTransport(typename protocol::socket&& socket);
|
||||
@@ -58,18 +63,18 @@ 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(const uint8_t* buffer, size_t nBytesReceived,
|
||||
const boost::system::error_code& error);
|
||||
receiveDatagram(span<const uint8_t> buffer, const boost::system::error_code& error);
|
||||
|
||||
protected:
|
||||
void
|
||||
doClose() override;
|
||||
|
||||
void
|
||||
doSend(const Block& packet, const EndpointId& endpoint) override;
|
||||
doSend(const Block& packet) override;
|
||||
|
||||
void
|
||||
handleSend(const boost::system::error_code& error, size_t nBytesSent);
|
||||
@@ -86,9 +91,6 @@ protected:
|
||||
void
|
||||
resetRecentlyReceived();
|
||||
|
||||
static EndpointId
|
||||
makeEndpointId(const typename protocol::endpoint& ep);
|
||||
|
||||
protected:
|
||||
typename protocol::socket m_socket;
|
||||
typename protocol::endpoint m_sender;
|
||||
@@ -150,14 +152,14 @@ DatagramTransport<T, U>::doClose()
|
||||
|
||||
// Ensure that the Transport stays alive at least until
|
||||
// all pending handlers are dispatched
|
||||
getGlobalIoService().post([this] {
|
||||
boost::asio::defer(getGlobalIoService(), [this] {
|
||||
this->setState(TransportState::CLOSED);
|
||||
});
|
||||
}
|
||||
|
||||
template<class T, class U>
|
||||
void
|
||||
DatagramTransport<T, U>::doSend(const Block& packet, const EndpointId&)
|
||||
DatagramTransport<T, U>::doSend(const Block& packet)
|
||||
{
|
||||
NFD_LOG_FACE_TRACE(__func__);
|
||||
|
||||
@@ -170,37 +172,38 @@ DatagramTransport<T, U>::doSend(const Block& packet, const EndpointId&)
|
||||
|
||||
template<class T, class U>
|
||||
void
|
||||
DatagramTransport<T, U>::receiveDatagram(const uint8_t* buffer, size_t nBytesReceived,
|
||||
DatagramTransport<T, U>::receiveDatagram(span<const uint8_t> buffer,
|
||||
const boost::system::error_code& error)
|
||||
{
|
||||
if (error)
|
||||
return processErrorCode(error);
|
||||
|
||||
NFD_LOG_FACE_TRACE("Received: " << nBytesReceived << " bytes from " << m_sender);
|
||||
NFD_LOG_FACE_TRACE("Received: " << buffer.size() << " bytes from " << m_sender);
|
||||
|
||||
bool isOk = false;
|
||||
Block element;
|
||||
std::tie(isOk, element) = Block::fromBuffer(buffer, nBytesReceived);
|
||||
auto [isOk, element] = Block::fromBuffer(buffer);
|
||||
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() != nBytesReceived) {
|
||||
if (element.size() != buffer.size()) {
|
||||
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;
|
||||
|
||||
this->receive(element, makeEndpointId(m_sender));
|
||||
if constexpr (std::is_same_v<addressing, Multicast>)
|
||||
this->receive(element, m_sender);
|
||||
else
|
||||
this->receive(element);
|
||||
}
|
||||
|
||||
template<class T, class U>
|
||||
void
|
||||
DatagramTransport<T, U>::handleReceive(const boost::system::error_code& error, size_t nBytesReceived)
|
||||
{
|
||||
receiveDatagram(m_receiveBuffer.data(), nBytesReceived, error);
|
||||
receiveDatagram(ndn::make_span(m_receiveBuffer).first(nBytesReceived), error);
|
||||
|
||||
if (m_socket.is_open())
|
||||
m_socket.async_receive_from(boost::asio::buffer(m_receiveBuffer), m_sender,
|
||||
@@ -257,14 +260,6 @@ DatagramTransport<T, U>::resetRecentlyReceived()
|
||||
m_hasRecentlyReceived = false;
|
||||
}
|
||||
|
||||
template<class T, class U>
|
||||
EndpointId
|
||||
DatagramTransport<T, U>::makeEndpointId(const typename protocol::endpoint&)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
} // namespace nfd::face
|
||||
|
||||
#endif // NFD_DAEMON_FACE_DATAGRAM_TRANSPORT_HPP
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2023, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -33,8 +33,7 @@
|
||||
#include <boost/range/adaptor/map.hpp>
|
||||
#include <pcap/pcap.h>
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
namespace nfd::face {
|
||||
|
||||
NFD_LOG_INIT(EthernetChannel);
|
||||
|
||||
@@ -102,8 +101,9 @@ void
|
||||
EthernetChannel::asyncRead(const FaceCreatedCallback& onFaceCreated,
|
||||
const FaceCreationFailedCallback& onReceiveFailed)
|
||||
{
|
||||
m_socket.async_read_some(boost::asio::null_buffers(),
|
||||
[=] (const auto& e, auto) { this->handleRead(e, onFaceCreated, onReceiveFailed); });
|
||||
m_socket.async_wait(boost::asio::posix::stream_descriptor::wait_read, [=] (const auto& e) {
|
||||
handleRead(e, onFaceCreated, onReceiveFailed);
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
@@ -120,26 +120,20 @@ EthernetChannel::handleRead(const boost::system::error_code& error,
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
auto [pkt, readErr] = m_pcap.readNextPacket();
|
||||
if (pkt.empty()) {
|
||||
NFD_LOG_CHAN_WARN("Read error: " << readErr);
|
||||
}
|
||||
else {
|
||||
const ether_header* eh;
|
||||
std::tie(eh, err) = ethernet::checkFrameHeader(pkt, len, m_localEndpoint->getEthernetAddress(),
|
||||
m_localEndpoint->getEthernetAddress());
|
||||
auto [eh, frameErr] = ethernet::checkFrameHeader(pkt, m_localEndpoint->getEthernetAddress(),
|
||||
m_localEndpoint->getEthernetAddress());
|
||||
if (eh == nullptr) {
|
||||
NFD_LOG_CHAN_DEBUG(err);
|
||||
NFD_LOG_CHAN_DEBUG(frameErr);
|
||||
}
|
||||
else {
|
||||
ethernet::Address sender(eh->ether_shost);
|
||||
pkt += ethernet::HDR_LEN;
|
||||
len -= ethernet::HDR_LEN;
|
||||
processIncomingPacket(pkt, len, sender, onFaceCreated, onReceiveFailed);
|
||||
pkt = pkt.subspan(ethernet::HDR_LEN);
|
||||
processIncomingPacket(pkt, sender, onFaceCreated, onReceiveFailed);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,7 +148,7 @@ EthernetChannel::handleRead(const boost::system::error_code& error,
|
||||
}
|
||||
|
||||
void
|
||||
EthernetChannel::processIncomingPacket(const uint8_t* packet, size_t length,
|
||||
EthernetChannel::processIncomingPacket(span<const uint8_t> packet,
|
||||
const ethernet::Address& sender,
|
||||
const FaceCreatedCallback& onFaceCreated,
|
||||
const FaceCreationFailedCallback& onReceiveFailed)
|
||||
@@ -182,7 +176,7 @@ EthernetChannel::processIncomingPacket(const uint8_t* packet, size_t length,
|
||||
|
||||
// dispatch the packet to the face for processing
|
||||
auto* transport = static_cast<UnicastEthernetTransport*>(face->getTransport());
|
||||
transport->receivePayload(packet, length, sender);
|
||||
transport->receivePayload(packet, sender);
|
||||
}
|
||||
|
||||
std::pair<bool, shared_ptr<Face>>
|
||||
@@ -201,12 +195,15 @@ EthernetChannel::createFace(const ethernet::Address& remoteEndpoint,
|
||||
options.allowFragmentation = true;
|
||||
options.allowReassembly = true;
|
||||
options.reliabilityOptions.isEnabled = params.wantLpReliability;
|
||||
if (params.mtu) {
|
||||
options.overrideMtu = *params.mtu;
|
||||
}
|
||||
|
||||
auto linkService = make_unique<GenericLinkService>(options);
|
||||
auto transport = make_unique<UnicastEthernetTransport>(*m_localEndpoint, remoteEndpoint,
|
||||
params.persistency, m_idleFaceTimeout,
|
||||
params.mtu);
|
||||
params.persistency, m_idleFaceTimeout);
|
||||
auto face = make_shared<Face>(std::move(linkService), std::move(transport));
|
||||
face->setChannel(weak_from_this());
|
||||
|
||||
m_channelFaces[remoteEndpoint] = face;
|
||||
connectFaceClosedSignal(*face, [this, remoteEndpoint] {
|
||||
@@ -237,5 +234,4 @@ EthernetChannel::updateFilter()
|
||||
m_pcap.setPacketFilter(filter.data());
|
||||
}
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
} // namespace nfd::face
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2018, Regents of the University of California,
|
||||
* Copyright (c) 2014-2023, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -29,53 +29,50 @@
|
||||
#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 {
|
||||
namespace face {
|
||||
namespace nfd::face {
|
||||
|
||||
/**
|
||||
* \brief Class implementing Ethernet-based channel to create faces
|
||||
* \brief Class implementing an Ethernet-based channel to create faces.
|
||||
*/
|
||||
class EthernetChannel : public Channel
|
||||
class EthernetChannel final : public Channel
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* \brief EthernetChannel-related error
|
||||
* \brief EthernetChannel-related error.
|
||||
*/
|
||||
class Error : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
explicit
|
||||
Error(const std::string& what)
|
||||
: std::runtime_error(what)
|
||||
{
|
||||
}
|
||||
using std::runtime_error::runtime_error;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Create an Ethernet channel on the given \p localEndpoint (network interface)
|
||||
* \brief Create an Ethernet channel on the given \p localEndpoint (network interface).
|
||||
*
|
||||
* To enable creation of faces upon incoming connections,
|
||||
* one needs to explicitly call EthernetChannel::listen method.
|
||||
* To enable the creation of faces upon incoming connections, one needs to
|
||||
* explicitly call listen().
|
||||
*/
|
||||
EthernetChannel(shared_ptr<const ndn::net::NetworkInterface> localEndpoint,
|
||||
time::nanoseconds idleTimeout);
|
||||
|
||||
bool
|
||||
isListening() const override
|
||||
isListening() const final
|
||||
{
|
||||
return m_isListening;
|
||||
}
|
||||
|
||||
size_t
|
||||
size() const override
|
||||
size() const final
|
||||
{
|
||||
return m_channelFaces.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Create a unicast Ethernet face toward \p remoteEndpoint
|
||||
* \brief Create a unicast Ethernet face toward \p remoteEndpoint.
|
||||
*/
|
||||
void
|
||||
connect(const ethernet::Address& remoteEndpoint,
|
||||
@@ -84,7 +81,7 @@ public:
|
||||
const FaceCreationFailedCallback& onConnectFailed);
|
||||
|
||||
/**
|
||||
* \brief Start listening
|
||||
* \brief Start listening.
|
||||
*
|
||||
* Enable listening on the local endpoint, waiting for incoming frames,
|
||||
* and creating a face when a frame is received from a new remote host.
|
||||
@@ -110,7 +107,7 @@ private:
|
||||
const FaceCreationFailedCallback& onReceiveFailed);
|
||||
|
||||
void
|
||||
processIncomingPacket(const uint8_t* packet, size_t length,
|
||||
processIncomingPacket(span<const uint8_t> packet,
|
||||
const ethernet::Address& sender,
|
||||
const FaceCreatedCallback& onFaceCreated,
|
||||
const FaceCreationFailedCallback& onReceiveFailed);
|
||||
@@ -136,7 +133,6 @@ private:
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
} // namespace nfd::face
|
||||
|
||||
#endif // NFD_DAEMON_FACE_ETHERNET_CHANNEL_HPP
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2023, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -30,8 +30,7 @@
|
||||
#include <boost/range/adaptors.hpp>
|
||||
#include <boost/range/algorithm/copy.hpp>
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
namespace nfd::face {
|
||||
|
||||
NFD_LOG_INIT(EthernetFactory);
|
||||
NFD_REGISTER_PROTOCOL_FACTORY(EthernetFactory);
|
||||
@@ -47,8 +46,8 @@ EthernetFactory::EthernetFactory(const CtorParams& params)
|
||||
: ProtocolFactory(params)
|
||||
{
|
||||
m_netifAddConn = netmon->onInterfaceAdded.connect([this] (const auto& netif) {
|
||||
this->applyUnicastConfigToNetif(netif);
|
||||
this->applyMcastConfigToNetif(*netif);
|
||||
applyUnicastConfigToNetif(netif);
|
||||
applyMcastConfigToNetif(*netif);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -157,11 +156,11 @@ EthernetFactory::doProcessConfig(OptionalConfigSection configSection,
|
||||
}
|
||||
}
|
||||
|
||||
// Even if there's no configuration change, we still need to re-apply configuration because
|
||||
// netifs may have changed.
|
||||
m_unicastConfig = unicastConfig;
|
||||
m_mcastConfig = mcastConfig;
|
||||
this->applyConfig(context);
|
||||
// Even if there are no configuration changes, we still need to re-apply
|
||||
// the configuration because netifs may have changed.
|
||||
m_unicastConfig = std::move(unicastConfig);
|
||||
m_mcastConfig = std::move(mcastConfig);
|
||||
applyConfig(context);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -170,13 +169,13 @@ EthernetFactory::doCreateFace(const CreateFaceRequest& req,
|
||||
const FaceCreationFailedCallback& onFailure)
|
||||
{
|
||||
if (!req.localUri || req.localUri->getScheme() != "dev") {
|
||||
NFD_LOG_TRACE("Cannot create unicast Ethernet face without dev:// LocalUri");
|
||||
NFD_LOG_TRACE("createFace: dev:// LocalUri required");
|
||||
onFailure(406, "Creation of unicast Ethernet faces requires a LocalUri with dev:// scheme");
|
||||
return;
|
||||
}
|
||||
|
||||
if (req.params.persistency == ndn::nfd::FACE_PERSISTENCY_ON_DEMAND) {
|
||||
NFD_LOG_TRACE("createFace does not support FACE_PERSISTENCY_ON_DEMAND");
|
||||
NFD_LOG_TRACE("createFace: unsupported FacePersistency");
|
||||
onFailure(406, "Outgoing Ethernet faces do not support on-demand persistency");
|
||||
return;
|
||||
}
|
||||
@@ -185,22 +184,22 @@ EthernetFactory::doCreateFace(const CreateFaceRequest& req,
|
||||
std::string localEndpoint(req.localUri->getHost());
|
||||
|
||||
if (remoteEndpoint.isMulticast()) {
|
||||
NFD_LOG_TRACE("createFace does not support multicast faces");
|
||||
NFD_LOG_TRACE("createFace: unsupported multicast endpoint");
|
||||
onFailure(406, "Cannot create multicast Ethernet faces");
|
||||
return;
|
||||
}
|
||||
|
||||
if (req.params.wantLocalFields) {
|
||||
// Ethernet faces are never local
|
||||
NFD_LOG_TRACE("createFace cannot create non-local face with local fields enabled");
|
||||
NFD_LOG_TRACE("createFace: cannot create non-local face with local fields enabled");
|
||||
onFailure(406, "Local fields can only be enabled on faces with local scope");
|
||||
return;
|
||||
}
|
||||
|
||||
if (req.params.mtu && *req.params.mtu < Transport::MIN_MTU) {
|
||||
if (req.params.mtu && *req.params.mtu < MIN_MTU) {
|
||||
// The specified MTU must be greater than the minimum possible
|
||||
NFD_LOG_TRACE("createFace cannot create a face with an MTU less than " << Transport::MIN_MTU);
|
||||
onFailure(406, "MTU cannot be less than " + to_string(Transport::MIN_MTU));
|
||||
NFD_LOG_TRACE("createFace: override MTU cannot be less than " << MIN_MTU);
|
||||
onFailure(406, "Override MTU cannot be less than " + to_string(MIN_MTU));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -240,7 +239,7 @@ EthernetFactory::createMulticastFace(const ndn::net::NetworkInterface& netif,
|
||||
{
|
||||
BOOST_ASSERT(address.isMulticast());
|
||||
|
||||
auto key = std::make_pair(netif.getName(), address);
|
||||
std::pair key(netif.getName(), address);
|
||||
auto found = m_mcastFaces.find(key);
|
||||
if (found != m_mcastFaces.end()) {
|
||||
return found->second;
|
||||
@@ -257,6 +256,11 @@ EthernetFactory::createMulticastFace(const ndn::net::NetworkInterface& netif,
|
||||
m_mcastFaces[key] = face;
|
||||
connectFaceClosedSignal(*face, [this, key] { m_mcastFaces.erase(key); });
|
||||
|
||||
auto channelIt = m_channels.find(netif.getName());
|
||||
if (channelIt != m_channels.end()) {
|
||||
face->setChannel(channelIt->second);
|
||||
}
|
||||
|
||||
return face;
|
||||
}
|
||||
|
||||
@@ -267,13 +271,13 @@ EthernetFactory::applyUnicastConfigToNetif(const shared_ptr<const ndn::net::Netw
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (netif->getType() != ndn::net::InterfaceType::ETHERNET) {
|
||||
NFD_LOG_DEBUG("Not creating channel on " << netif->getName() << ": incompatible netif type");
|
||||
if (!netif->isUp()) {
|
||||
NFD_LOG_DEBUG("Not creating channel on " << netif->getName() << ": netif is down");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!netif->isUp()) {
|
||||
NFD_LOG_DEBUG("Not creating channel on " << netif->getName() << ": netif is down");
|
||||
if (netif->getType() != ndn::net::InterfaceType::ETHERNET) {
|
||||
NFD_LOG_DEBUG("Not creating channel on " << netif->getName() << ": incompatible netif type");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -301,18 +305,13 @@ EthernetFactory::applyMcastConfigToNetif(const ndn::net::NetworkInterface& netif
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (netif.getType() != ndn::net::InterfaceType::ETHERNET) {
|
||||
NFD_LOG_DEBUG("Not creating multicast face on " << netif.getName() << ": incompatible netif type");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!netif.isUp()) {
|
||||
NFD_LOG_DEBUG("Not creating multicast face on " << netif.getName() << ": netif is down");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!netif.canMulticast()) {
|
||||
NFD_LOG_DEBUG("Not creating multicast face on " << netif.getName() << ": netif cannot multicast");
|
||||
if (netif.getType() != ndn::net::InterfaceType::ETHERNET) {
|
||||
NFD_LOG_DEBUG("Not creating multicast face on " << netif.getName() << ": incompatible netif type");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -321,6 +320,11 @@ EthernetFactory::applyMcastConfigToNetif(const ndn::net::NetworkInterface& netif
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!netif.canMulticast()) {
|
||||
NFD_LOG_DEBUG("Not creating multicast face on " << netif.getName() << ": netif cannot multicast");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!m_mcastConfig.netifPredicate(netif)) {
|
||||
NFD_LOG_DEBUG("Not creating multicast face on " << netif.getName() << ": rejected by whitelist/blacklist");
|
||||
return nullptr;
|
||||
@@ -329,17 +333,18 @@ EthernetFactory::applyMcastConfigToNetif(const ndn::net::NetworkInterface& netif
|
||||
NFD_LOG_DEBUG("Creating multicast face on " << netif.getName());
|
||||
shared_ptr<Face> face;
|
||||
try {
|
||||
face = this->createMulticastFace(netif, m_mcastConfig.group);
|
||||
face = createMulticastFace(netif, m_mcastConfig.group);
|
||||
}
|
||||
catch (const EthernetTransport::Error& e) {
|
||||
catch (const std::runtime_error& e) {
|
||||
NFD_LOG_WARN("Cannot create multicast face on " << netif.getName() << ": " << e.what());
|
||||
return nullptr;
|
||||
return nullptr; // not a fatal error
|
||||
}
|
||||
|
||||
if (face->getId() == face::INVALID_FACEID) {
|
||||
if (face->getId() == INVALID_FACEID) {
|
||||
// new face: register with forwarding
|
||||
this->addFace(face);
|
||||
}
|
||||
|
||||
return face;
|
||||
}
|
||||
|
||||
@@ -359,9 +364,9 @@ EthernetFactory::applyConfig(const FaceSystem::ConfigContext&)
|
||||
|
||||
// create channels and multicast faces if requested by config
|
||||
for (const auto& netif : netmon->listNetworkInterfaces()) {
|
||||
this->applyUnicastConfigToNetif(netif);
|
||||
applyUnicastConfigToNetif(netif);
|
||||
|
||||
auto face = this->applyMcastConfigToNetif(*netif);
|
||||
auto face = applyMcastConfigToNetif(*netif);
|
||||
if (face != nullptr) {
|
||||
// don't destroy face
|
||||
oldFaces.erase(face);
|
||||
@@ -374,5 +379,4 @@ EthernetFactory::applyConfig(const FaceSystem::ConfigContext&)
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
} // namespace nfd::face
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2018, Regents of the University of California,
|
||||
* Copyright (c) 2014-2023, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -28,13 +28,14 @@
|
||||
|
||||
#include "protocol-factory.hpp"
|
||||
#include "ethernet-channel.hpp"
|
||||
#include "network-predicate.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
namespace nfd::face {
|
||||
|
||||
/** \brief Protocol factory for Ethernet
|
||||
/**
|
||||
* \brief Protocol factory for Ethernet.
|
||||
*/
|
||||
class EthernetFactory : public ProtocolFactory
|
||||
class EthernetFactory final : public ProtocolFactory
|
||||
{
|
||||
public:
|
||||
static const std::string&
|
||||
@@ -44,12 +45,12 @@ 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.
|
||||
*
|
||||
* \return always a valid pointer to a EthernetChannel object, an exception
|
||||
* \return Always a valid pointer to a EthernetChannel object, an exception
|
||||
* is thrown if it cannot be created.
|
||||
* \throw PcapHelper::Error channel creation failed
|
||||
*/
|
||||
@@ -58,7 +59,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.
|
||||
@@ -66,35 +67,35 @@ public:
|
||||
* \param localEndpoint local network interface
|
||||
* \param group multicast group address
|
||||
*
|
||||
* \throw EthernetTransport::Error transport creation fails
|
||||
* \throw std::runtime_error %Face creation failed
|
||||
*/
|
||||
shared_ptr<Face>
|
||||
createMulticastFace(const ndn::net::NetworkInterface& localEndpoint,
|
||||
const ethernet::Address& group);
|
||||
|
||||
private:
|
||||
/** \brief process face_system.ether config section
|
||||
*/
|
||||
void
|
||||
doProcessConfig(OptionalConfigSection configSection,
|
||||
FaceSystem::ConfigContext& context) override;
|
||||
FaceSystem::ConfigContext& context) final;
|
||||
|
||||
void
|
||||
doCreateFace(const CreateFaceRequest& req,
|
||||
const FaceCreatedCallback& onCreated,
|
||||
const FaceCreationFailedCallback& onFailure) override;
|
||||
const FaceCreationFailedCallback& onFailure) final;
|
||||
|
||||
std::vector<shared_ptr<const Channel>>
|
||||
doGetChannels() const override;
|
||||
doGetChannels() const final;
|
||||
|
||||
/** \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
|
||||
/**
|
||||
* \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.
|
||||
*/
|
||||
shared_ptr<EthernetChannel>
|
||||
applyUnicastConfigToNetif(const shared_ptr<const ndn::net::NetworkInterface>& netif);
|
||||
|
||||
/** \brief Create Ethernet multicast face on \p netif if requested by \p m_mcastConfig.
|
||||
* \return new or existing face, or nullptr if no face should be created
|
||||
/**
|
||||
* \brief Create Ethernet multicast face on \p netif if requested by \p m_mcastConfig.
|
||||
* \return New or existing face, or nullptr if no face should be created.
|
||||
*/
|
||||
shared_ptr<Face>
|
||||
applyMcastConfigToNetif(const ndn::net::NetworkInterface& netif);
|
||||
@@ -103,7 +104,8 @@ private:
|
||||
applyConfig(const FaceSystem::ConfigContext& context);
|
||||
|
||||
private:
|
||||
std::map<std::string, shared_ptr<EthernetChannel>> m_channels; ///< ifname => channel
|
||||
// ifname => channel
|
||||
std::map<std::string, shared_ptr<EthernetChannel>> m_channels;
|
||||
|
||||
struct UnicastConfig
|
||||
{
|
||||
@@ -122,13 +124,12 @@ 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 face
|
||||
} // namespace nfd
|
||||
} // namespace nfd::face
|
||||
|
||||
#endif // NFD_DAEMON_FACE_ETHERNET_FACTORY_HPP
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2018, Regents of the University of California,
|
||||
* Copyright (c) 2014-2022, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -27,17 +27,15 @@
|
||||
|
||||
#include <boost/endian/conversion.hpp>
|
||||
|
||||
namespace nfd {
|
||||
namespace ethernet {
|
||||
namespace nfd::ethernet {
|
||||
|
||||
std::pair<const ether_header*, std::string>
|
||||
checkFrameHeader(const uint8_t* packet, size_t length,
|
||||
const Address& localAddr, const Address& destAddr)
|
||||
std::tuple<const ether_header*, std::string>
|
||||
checkFrameHeader(span<const uint8_t> packet, const Address& localAddr, const Address& destAddr)
|
||||
{
|
||||
if (length < HDR_LEN + MIN_DATA_LEN)
|
||||
return {nullptr, "Received frame too short: " + to_string(length) + " bytes"};
|
||||
if (packet.size() < HDR_LEN + MIN_DATA_LEN)
|
||||
return {nullptr, "Received frame too short: " + to_string(packet.size()) + " bytes"};
|
||||
|
||||
const ether_header* eh = reinterpret_cast<const ether_header*>(packet);
|
||||
const ether_header* eh = reinterpret_cast<const ether_header*>(packet.data());
|
||||
|
||||
// in some cases VLAN-tagged frames may survive the BPF filter,
|
||||
// make sure we do not process those frames (see #3348)
|
||||
@@ -58,5 +56,4 @@ checkFrameHeader(const uint8_t* packet, size_t length,
|
||||
return {eh, ""};
|
||||
}
|
||||
|
||||
} // namespace ethernet
|
||||
} // namespace nfd
|
||||
} // namespace nfd::ethernet
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2017, Regents of the University of California,
|
||||
* Copyright (c) 2014-2022, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -27,19 +27,17 @@
|
||||
#define NFD_DAEMON_FACE_ETHERNET_PROTOCOL_HPP
|
||||
|
||||
#include "core/common.hpp"
|
||||
|
||||
#include <ndn-cxx/net/ethernet.hpp>
|
||||
#include <net/ethernet.h>
|
||||
|
||||
namespace nfd {
|
||||
namespace ethernet {
|
||||
namespace nfd::ethernet {
|
||||
|
||||
using namespace ndn::ethernet;
|
||||
|
||||
std::pair<const ether_header*, std::string>
|
||||
checkFrameHeader(const uint8_t* packet, size_t length,
|
||||
const Address& localAddr, const Address& destAddr);
|
||||
std::tuple<const ether_header*, std::string>
|
||||
checkFrameHeader(span<const uint8_t> packet, const Address& localAddr, const Address& destAddr);
|
||||
|
||||
} // namespace ethernet
|
||||
} // namespace nfd
|
||||
} // namespace nfd::ethernet
|
||||
|
||||
#endif // NFD_DAEMON_FACE_ETHERNET_PROTOCOL_HPP
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2023, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -29,12 +29,10 @@
|
||||
|
||||
#include <pcap/pcap.h>
|
||||
|
||||
#include <cstring> // for memcpy()
|
||||
|
||||
#include <boost/asio/defer.hpp>
|
||||
#include <boost/endian/conversion.hpp>
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
namespace nfd::face {
|
||||
|
||||
NFD_LOG_INIT(EthernetTransport);
|
||||
|
||||
@@ -58,11 +56,19 @@ EthernetTransport::EthernetTransport(const ndn::net::NetworkInterface& localEndp
|
||||
NDN_THROW_NESTED(Error(e.what()));
|
||||
}
|
||||
|
||||
m_netifStateConn = localEndpoint.onStateChanged.connect(
|
||||
[=] (ndn::net::InterfaceState, ndn::net::InterfaceState newState) {
|
||||
// Set initial transport state based upon the state of the underlying NetworkInterface
|
||||
handleNetifStateChange(localEndpoint.getState());
|
||||
|
||||
m_netifStateChangedConn = localEndpoint.onStateChanged.connect(
|
||||
[this] (ndn::net::InterfaceState, ndn::net::InterfaceState newState) {
|
||||
handleNetifStateChange(newState);
|
||||
});
|
||||
|
||||
m_netifMtuChangedConn = localEndpoint.onMtuChanged.connect(
|
||||
[this] (uint32_t, uint32_t mtu) {
|
||||
setMtu(mtu);
|
||||
});
|
||||
|
||||
asyncRead();
|
||||
}
|
||||
|
||||
@@ -82,7 +88,7 @@ EthernetTransport::doClose()
|
||||
|
||||
// Ensure that the Transport stays alive at least
|
||||
// until all pending handlers are dispatched
|
||||
getGlobalIoService().post([this] {
|
||||
boost::asio::defer(getGlobalIoService(), [this] {
|
||||
this->setState(TransportState::CLOSED);
|
||||
});
|
||||
}
|
||||
@@ -102,7 +108,7 @@ EthernetTransport::handleNetifStateChange(ndn::net::InterfaceState netifState)
|
||||
}
|
||||
|
||||
void
|
||||
EthernetTransport::doSend(const Block& packet, const EndpointId&)
|
||||
EthernetTransport::doSend(const Block& packet)
|
||||
{
|
||||
NFD_LOG_FACE_TRACE(__func__);
|
||||
|
||||
@@ -117,17 +123,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.appendByteArray(padding, ethernet::MIN_DATA_LEN - block.size());
|
||||
buffer.appendBytes(ndn::make_span(padding).subspan(block.size()));
|
||||
}
|
||||
|
||||
// construct and prepend the ethernet header
|
||||
uint16_t ethertype = boost::endian::native_to_big(ethernet::ETHERTYPE_NDN);
|
||||
buffer.prependByteArray(reinterpret_cast<const uint8_t*>(ðertype), ethernet::TYPE_LEN);
|
||||
buffer.prependByteArray(m_srcAddress.data(), m_srcAddress.size());
|
||||
buffer.prependByteArray(m_destAddress.data(), m_destAddress.size());
|
||||
buffer.prependBytes({reinterpret_cast<const uint8_t*>(ðertype), ethernet::TYPE_LEN});
|
||||
buffer.prependBytes(m_srcAddress);
|
||||
buffer.prependBytes(m_destAddress);
|
||||
|
||||
// send the frame
|
||||
int sent = pcap_inject(m_pcap, buffer.buf(), buffer.size());
|
||||
int sent = pcap_inject(m_pcap, buffer.data(), buffer.size());
|
||||
if (sent < 0)
|
||||
handleError("Send operation failed: " + m_pcap.getLastError());
|
||||
else if (static_cast<size_t>(sent) < buffer.size())
|
||||
@@ -141,8 +147,8 @@ EthernetTransport::sendPacket(const ndn::Block& block)
|
||||
void
|
||||
EthernetTransport::asyncRead()
|
||||
{
|
||||
m_socket.async_read_some(boost::asio::null_buffers(),
|
||||
[this] (const auto& e, auto) { this->handleRead(e); });
|
||||
m_socket.async_wait(boost::asio::posix::stream_descriptor::wait_read,
|
||||
[this] (const auto& e) { this->handleRead(e); });
|
||||
}
|
||||
|
||||
void
|
||||
@@ -160,26 +166,20 @@ EthernetTransport::handleRead(const boost::system::error_code& error)
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
auto [pkt, readErr] = m_pcap.readNextPacket();
|
||||
if (pkt.empty()) {
|
||||
NFD_LOG_FACE_DEBUG("Read error: " << readErr);
|
||||
}
|
||||
else {
|
||||
const ether_header* eh;
|
||||
std::tie(eh, err) = ethernet::checkFrameHeader(pkt, len, m_srcAddress,
|
||||
m_destAddress.isMulticast() ? m_destAddress : m_srcAddress);
|
||||
auto [eh, frameErr] = ethernet::checkFrameHeader(pkt, m_srcAddress,
|
||||
m_destAddress.isMulticast() ? m_destAddress : m_srcAddress);
|
||||
if (eh == nullptr) {
|
||||
NFD_LOG_FACE_WARN(err);
|
||||
NFD_LOG_FACE_WARN(frameErr);
|
||||
}
|
||||
else {
|
||||
ethernet::Address sender(eh->ether_shost);
|
||||
pkt += ethernet::HDR_LEN;
|
||||
len -= ethernet::HDR_LEN;
|
||||
receivePayload(pkt, len, sender);
|
||||
pkt = pkt.subspan(ethernet::HDR_LEN);
|
||||
receivePayload(pkt, sender);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -194,14 +194,11 @@ EthernetTransport::handleRead(const boost::system::error_code& error)
|
||||
}
|
||||
|
||||
void
|
||||
EthernetTransport::receivePayload(const uint8_t* payload, size_t length,
|
||||
const ethernet::Address& sender)
|
||||
EthernetTransport::receivePayload(span<const uint8_t> payload, const ethernet::Address& sender)
|
||||
{
|
||||
NFD_LOG_FACE_TRACE("Received: " << length << " bytes from " << sender);
|
||||
NFD_LOG_FACE_TRACE("Received: " << payload.size() << " bytes from " << sender);
|
||||
|
||||
bool isOk = false;
|
||||
Block element;
|
||||
std::tie(isOk, element) = Block::fromBuffer(payload, length);
|
||||
auto [isOk, element] = Block::fromBuffer(payload);
|
||||
if (!isOk) {
|
||||
NFD_LOG_FACE_WARN("Failed to parse incoming packet from " << sender);
|
||||
// This packet won't extend the face lifetime
|
||||
@@ -209,13 +206,7 @@ EthernetTransport::receivePayload(const uint8_t* payload, size_t length,
|
||||
}
|
||||
m_hasRecentlyReceived = true;
|
||||
|
||||
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);
|
||||
this->receive(element, m_destAddress.isMulticast() ? sender : EndpointId{});
|
||||
}
|
||||
|
||||
void
|
||||
@@ -231,5 +222,4 @@ EthernetTransport::handleError(const std::string& errorMessage)
|
||||
doClose();
|
||||
}
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
} // namespace nfd::face
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2023, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -30,13 +30,13 @@
|
||||
#include "pcap-helper.hpp"
|
||||
#include "transport.hpp"
|
||||
|
||||
#include <boost/asio/posix/stream_descriptor.hpp>
|
||||
#include <ndn-cxx/net/network-interface.hpp>
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
namespace nfd::face {
|
||||
|
||||
/**
|
||||
* @brief Base class for Ethernet-based Transports
|
||||
* @brief Base class for Ethernet-based Transports.
|
||||
*/
|
||||
class EthernetTransport : public Transport
|
||||
{
|
||||
@@ -48,14 +48,12 @@ public:
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Processes the payload of an incoming frame
|
||||
* @param payload Pointer to the first byte of data after the Ethernet header
|
||||
* @param length Payload length
|
||||
* @brief Processes the payload of an incoming frame.
|
||||
* @param payload Payload bytes, starting from the first byte after the Ethernet header
|
||||
* @param sender Sender address
|
||||
*/
|
||||
void
|
||||
receivePayload(const uint8_t* payload, size_t length,
|
||||
const ethernet::Address& sender);
|
||||
receivePayload(span<const uint8_t> payload, const ethernet::Address& sender);
|
||||
|
||||
protected:
|
||||
EthernetTransport(const ndn::net::NetworkInterface& localEndpoint,
|
||||
@@ -81,10 +79,10 @@ private:
|
||||
handleNetifStateChange(ndn::net::InterfaceState netifState);
|
||||
|
||||
void
|
||||
doSend(const Block& packet, const EndpointId& endpoint) final;
|
||||
doSend(const Block& packet) final;
|
||||
|
||||
/**
|
||||
* @brief Sends the specified TLV block on the network wrapped in an Ethernet frame
|
||||
* @brief Sends the specified TLV block on the network wrapped in an Ethernet frame.
|
||||
*/
|
||||
void
|
||||
sendPacket(const ndn::Block& block);
|
||||
@@ -106,7 +104,8 @@ protected:
|
||||
std::string m_interfaceName;
|
||||
|
||||
private:
|
||||
signal::ScopedConnection m_netifStateConn;
|
||||
signal::ScopedConnection m_netifStateChangedConn;
|
||||
signal::ScopedConnection m_netifMtuChangedConn;
|
||||
bool m_hasRecentlyReceived;
|
||||
#ifdef _DEBUG
|
||||
/// number of frames dropped by the kernel, as reported by libpcap
|
||||
@@ -114,7 +113,6 @@ private:
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
} // namespace nfd::face
|
||||
|
||||
#endif // NFD_DAEMON_FACE_ETHERNET_TRANSPORT_HPP
|
||||
+36
-26
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2022, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -26,12 +26,14 @@
|
||||
#ifndef NFD_DAEMON_FACE_FACE_COMMON_HPP
|
||||
#define NFD_DAEMON_FACE_FACE_COMMON_HPP
|
||||
|
||||
#include "core/common.hpp"
|
||||
#include "ethernet-protocol.hpp"
|
||||
#include "udp-protocol.hpp"
|
||||
#include "common/logger.hpp"
|
||||
|
||||
#include <ndn-cxx/encoding/nfd-constants.hpp>
|
||||
|
||||
#include <boost/logic/tribool.hpp>
|
||||
#include <variant>
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
@@ -39,30 +41,40 @@ namespace face {
|
||||
class Face;
|
||||
class LinkService;
|
||||
|
||||
/** \brief Identifies a face.
|
||||
/**
|
||||
* \brief Identifies a face.
|
||||
*/
|
||||
using FaceId = uint64_t;
|
||||
|
||||
/// 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;
|
||||
/// 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;
|
||||
|
||||
/** \brief Identifies a remote endpoint on the link.
|
||||
/**
|
||||
* \brief Minimum MTU that may be set.
|
||||
*
|
||||
* 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 (usually 0).
|
||||
* This is done to ensure the NDNLPv2 fragmentation feature functions properly.
|
||||
*/
|
||||
using EndpointId = uint64_t;
|
||||
inline constexpr ssize_t MIN_MTU = 64;
|
||||
|
||||
/**
|
||||
* \brief Identifies a remote endpoint on the link.
|
||||
*
|
||||
* This ID is only meaningful in the context of the same Transport.
|
||||
* 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`.
|
||||
*/
|
||||
using EndpointId = std::variant<std::monostate, ethernet::Address, udp::Endpoint>;
|
||||
|
||||
/** \brief Parameters used to set Transport properties or LinkService options on a newly created face.
|
||||
*
|
||||
@@ -72,9 +84,9 @@ using EndpointId = uint64_t;
|
||||
struct FaceParams
|
||||
{
|
||||
ndn::nfd::FacePersistency persistency = ndn::nfd::FACE_PERSISTENCY_PERSISTENT;
|
||||
optional<time::nanoseconds> baseCongestionMarkingInterval;
|
||||
optional<uint64_t> defaultCongestionThreshold;
|
||||
optional<ssize_t> mtu;
|
||||
std::optional<time::nanoseconds> baseCongestionMarkingInterval;
|
||||
std::optional<uint64_t> defaultCongestionThreshold;
|
||||
std::optional<ssize_t> mtu;
|
||||
bool wantLocalFields = false;
|
||||
bool wantLpReliability = false;
|
||||
boost::logic::tribool wantCongestionMarking = boost::logic::indeterminate;
|
||||
@@ -122,9 +134,7 @@ using face::FaceId;
|
||||
// implementation detail
|
||||
#define NFD_LOG_FACE(level, msg) NFD_LOG_##level( \
|
||||
::nfd::face::FaceLogHelper< \
|
||||
typename std::remove_cv< \
|
||||
typename std::remove_reference<decltype(*this)>::type \
|
||||
>::type \
|
||||
std::remove_cv_t<std::remove_reference_t<decltype(*this)>> \
|
||||
>(*this) \
|
||||
<< msg)
|
||||
/** \endcond */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2022, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -25,14 +25,13 @@
|
||||
|
||||
#include "face-counters.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
namespace nfd::face {
|
||||
|
||||
FaceCounters::FaceCounters(const LinkService::Counters& linkServiceCounters,
|
||||
const Transport::Counters& transportCounters)
|
||||
: nInInterests(linkServiceCounters.nInInterests)
|
||||
, nOutInterests(linkServiceCounters.nOutInterests)
|
||||
, nDroppedInterests(linkServiceCounters.nDroppedInterests)
|
||||
, nInterestsExceededRetx(linkServiceCounters.nInterestsExceededRetx)
|
||||
, nInData(linkServiceCounters.nInData)
|
||||
, nOutData(linkServiceCounters.nOutData)
|
||||
, nInNacks(linkServiceCounters.nInNacks)
|
||||
@@ -46,5 +45,4 @@ FaceCounters::FaceCounters(const LinkService::Counters& linkServiceCounters,
|
||||
{
|
||||
}
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
} // namespace nfd::face
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2022, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -29,10 +29,9 @@
|
||||
#include "link-service.hpp"
|
||||
#include "transport.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
namespace nfd::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.
|
||||
*
|
||||
@@ -50,7 +49,7 @@ public:
|
||||
* \throw std::bad_cast counters type mismatch
|
||||
*/
|
||||
template<typename T>
|
||||
typename std::enable_if<std::is_base_of<LinkService::Counters, T>::value, const T&>::type
|
||||
std::enable_if_t<std::is_base_of_v<LinkService::Counters, T>, const T&>
|
||||
get() const
|
||||
{
|
||||
return dynamic_cast<const T&>(m_linkServiceCounters);
|
||||
@@ -61,7 +60,7 @@ public:
|
||||
* \throw std::bad_cast counters type mismatch
|
||||
*/
|
||||
template<typename T>
|
||||
typename std::enable_if<std::is_base_of<Transport::Counters, T>::value, const T&>::type
|
||||
std::enable_if_t<std::is_base_of_v<Transport::Counters, T>, const T&>
|
||||
get() const
|
||||
{
|
||||
return dynamic_cast<const T&>(m_transportCounters);
|
||||
@@ -70,24 +69,30 @@ public:
|
||||
public:
|
||||
const PacketCounter& nInInterests;
|
||||
const PacketCounter& nOutInterests;
|
||||
const PacketCounter& nDroppedInterests;
|
||||
const PacketCounter& nInterestsExceededRetx;
|
||||
const PacketCounter& nInData;
|
||||
const PacketCounter& nOutData;
|
||||
const PacketCounter& nInNacks;
|
||||
const PacketCounter& nOutNacks;
|
||||
PacketCounter nKeptInterests;
|
||||
|
||||
const PacketCounter& nInPackets;
|
||||
const PacketCounter& nOutPackets;
|
||||
const ByteCounter& nInBytes;
|
||||
const ByteCounter& nOutBytes;
|
||||
|
||||
/** \brief Count of incoming Interests dropped due to HopLimit == 0.
|
||||
*/
|
||||
PacketCounter nInHopLimitZero;
|
||||
|
||||
/** \brief Count of outgoing Interests dropped due to HopLimit == 0 on non-local faces.
|
||||
*/
|
||||
PacketCounter nOutHopLimitZero;
|
||||
|
||||
private:
|
||||
const LinkService::Counters& m_linkServiceCounters;
|
||||
const Transport::Counters& m_transportCounters;
|
||||
};
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
} // namespace nfd::face
|
||||
|
||||
#endif // NFD_DAEMON_FACE_FACE_COUNTERS_HPP
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2018, Regents of the University of California,
|
||||
* Copyright (c) 2014-2022, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -23,27 +23,31 @@
|
||||
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "available-commands.hpp"
|
||||
#include "cs-module.hpp"
|
||||
#include "face-module.hpp"
|
||||
#include "rib-module.hpp"
|
||||
#include "status.hpp"
|
||||
#include "strategy-choice-module.hpp"
|
||||
#include "face-endpoint.hpp"
|
||||
|
||||
#include <boost/hana/functional/overload.hpp>
|
||||
|
||||
namespace nfd {
|
||||
namespace tools {
|
||||
namespace nfdc {
|
||||
|
||||
void
|
||||
registerCommands(CommandParser& parser)
|
||||
FaceEndpoint::FaceEndpoint(Face& face, const EndpointId& endpoint)
|
||||
: face(face)
|
||||
, endpoint(endpoint)
|
||||
{
|
||||
registerStatusCommands(parser);
|
||||
FaceModule::registerCommands(parser);
|
||||
RibModule::registerCommands(parser);
|
||||
CsModule::registerCommands(parser);
|
||||
StrategyChoiceModule::registerCommands(parser);
|
||||
}
|
||||
|
||||
} // namespace nfdc
|
||||
} // namespace tools
|
||||
void
|
||||
FaceEndpoint::print(std::ostream& os) const
|
||||
{
|
||||
std::visit(boost::hana::overload(
|
||||
[&] (std::monostate) {
|
||||
os << face.getId();
|
||||
},
|
||||
[&] (const ethernet::Address& ep) {
|
||||
os << '(' << face.getId() << ", " << ep << ')';
|
||||
},
|
||||
[&] (const udp::Endpoint& ep) {
|
||||
os << '(' << face.getId() << ", " << ep << ')';
|
||||
}), endpoint);
|
||||
}
|
||||
|
||||
} // namespace nfd
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2022, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -30,16 +30,25 @@
|
||||
|
||||
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:
|
||||
FaceEndpoint(const Face& face, EndpointId endpoint)
|
||||
: face(const_cast<Face&>(face))
|
||||
, endpoint(endpoint)
|
||||
explicit
|
||||
FaceEndpoint(Face& face, const EndpointId& endpoint = {});
|
||||
|
||||
private:
|
||||
void
|
||||
print(std::ostream& os) const;
|
||||
|
||||
friend std::ostream&
|
||||
operator<<(std::ostream& os, const FaceEndpoint& fe)
|
||||
{
|
||||
fe.print(os);
|
||||
return os;
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -47,12 +56,6 @@ 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
-17
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2023, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -24,13 +24,11 @@
|
||||
*/
|
||||
|
||||
#include "face-system.hpp"
|
||||
#include "protocol-factory.hpp"
|
||||
#include "netdev-bound.hpp"
|
||||
#include "common/global.hpp"
|
||||
#include "protocol-factory.hpp"
|
||||
#include "fw/face-table.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
namespace nfd::face {
|
||||
|
||||
NFD_LOG_INIT(FaceSystem);
|
||||
|
||||
@@ -72,14 +70,14 @@ FaceSystem::listProtocolFactories() const
|
||||
}
|
||||
|
||||
ProtocolFactory*
|
||||
FaceSystem::getFactoryById(const std::string& id)
|
||||
FaceSystem::getFactoryById(const std::string& id) const
|
||||
{
|
||||
auto found = m_factories.find(id);
|
||||
return found == m_factories.end() ? nullptr : found->second.get();
|
||||
}
|
||||
|
||||
ProtocolFactory*
|
||||
FaceSystem::getFactoryByScheme(const std::string& scheme)
|
||||
FaceSystem::getFactoryByScheme(const std::string& scheme) const
|
||||
{
|
||||
auto found = m_factoryByScheme.find(scheme);
|
||||
return found == m_factoryByScheme.end() ? nullptr : found->second;
|
||||
@@ -94,7 +92,9 @@ FaceSystem::hasFactoryForScheme(const std::string& scheme) const
|
||||
void
|
||||
FaceSystem::setConfigFile(ConfigFile& configFile)
|
||||
{
|
||||
configFile.addSectionHandler(CFGSEC_FACESYSTEM, bind(&FaceSystem::processConfig, this, _1, _2, _3));
|
||||
configFile.addSectionHandler(CFGSEC_FACESYSTEM, [this] (auto&&... args) {
|
||||
processConfig(std::forward<decltype(args)>(args)...);
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
@@ -118,22 +118,19 @@ FaceSystem::processConfig(const ConfigSection& configSection, bool isDryRun, con
|
||||
}
|
||||
|
||||
// process in protocol factories
|
||||
for (const auto& pair : m_factories) {
|
||||
const std::string& sectionName = pair.first;
|
||||
ProtocolFactory* factory = pair.second.get();
|
||||
|
||||
for (const auto& [sectionName, factory] : m_factories) {
|
||||
std::set<std::string> oldProvidedSchemes = factory->getProvidedSchemes();
|
||||
factory->processConfig(configSection.get_child_optional(sectionName), context);
|
||||
|
||||
if (!isDryRun) {
|
||||
for (const std::string& scheme : factory->getProvidedSchemes()) {
|
||||
m_factoryByScheme[scheme] = factory;
|
||||
for (const auto& scheme : factory->getProvidedSchemes()) {
|
||||
m_factoryByScheme[scheme] = factory.get();
|
||||
if (oldProvidedSchemes.erase(scheme) == 0) {
|
||||
NFD_LOG_TRACE("factory " << sectionName <<
|
||||
" provides " << scheme << " FaceUri scheme");
|
||||
}
|
||||
}
|
||||
for (const std::string& scheme : oldProvidedSchemes) {
|
||||
for (const auto& scheme : oldProvidedSchemes) {
|
||||
m_factoryByScheme.erase(scheme);
|
||||
NFD_LOG_TRACE("factory " << sectionName <<
|
||||
" no longer provides " << scheme << " FaceUri scheme");
|
||||
@@ -164,5 +161,4 @@ FaceSystem::processConfig(const ConfigSection& configSection, bool isDryRun, con
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
} // namespace nfd::face
|
||||
+21
-18
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2023, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -26,7 +26,6 @@
|
||||
#ifndef NFD_DAEMON_FACE_FACE_SYSTEM_HPP
|
||||
#define NFD_DAEMON_FACE_FACE_SYSTEM_HPP
|
||||
|
||||
#include "network-predicate.hpp"
|
||||
#include "common/config-file.hpp"
|
||||
|
||||
#include <ndn-cxx/net/network-address.hpp>
|
||||
@@ -43,10 +42,11 @@ class NetdevBound;
|
||||
class ProtocolFactory;
|
||||
struct ProtocolFactoryCtorParams;
|
||||
|
||||
/** \brief entry point of the face system
|
||||
/**
|
||||
* \brief Entry point of NFD's face system.
|
||||
*
|
||||
* 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.
|
||||
* 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.
|
||||
*/
|
||||
class FaceSystem : noncopyable
|
||||
{
|
||||
@@ -55,20 +55,23 @@ public:
|
||||
|
||||
~FaceSystem();
|
||||
|
||||
/** \return ProtocolFactory objects owned by the FaceSystem
|
||||
/**
|
||||
* \brief Returns all ProtocolFactory objects owned by the face system.
|
||||
*/
|
||||
std::set<const ProtocolFactory*>
|
||||
[[nodiscard]] 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);
|
||||
getFactoryById(const std::string& id) const;
|
||||
|
||||
/** \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);
|
||||
getFactoryByScheme(const std::string& scheme) const;
|
||||
|
||||
bool
|
||||
hasFactoryForScheme(const std::string& scheme) const;
|
||||
@@ -79,19 +82,19 @@ public:
|
||||
return m_faceTable;
|
||||
}
|
||||
|
||||
/** \brief register handler for face_system section of NFD configuration file
|
||||
/** \brief Register handler for the `face_system` section of NFD's 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
|
||||
{
|
||||
@@ -100,7 +103,7 @@ public:
|
||||
bool isDryRun;
|
||||
};
|
||||
|
||||
PUBLIC_WITH_TESTS_ELSE_PRIVATE:
|
||||
NFD_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
|
||||
ProtocolFactoryCtorParams
|
||||
makePFCtorParams();
|
||||
|
||||
@@ -109,14 +112,14 @@ private:
|
||||
processConfig(const ConfigSection& configSection, bool isDryRun,
|
||||
const std::string& filename);
|
||||
|
||||
PUBLIC_WITH_TESTS_ELSE_PRIVATE:
|
||||
/** \brief config section name => protocol factory
|
||||
NFD_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.
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2017, Regents of the University of California,
|
||||
* Copyright (c) 2014-2022, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -25,8 +25,7 @@
|
||||
|
||||
#include "face.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
namespace nfd::face {
|
||||
|
||||
Face::Face(unique_ptr<LinkService> service, unique_ptr<Transport> transport)
|
||||
: afterReceiveInterest(service->afterReceiveInterest)
|
||||
@@ -34,7 +33,6 @@ 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())
|
||||
@@ -52,5 +50,4 @@ operator<<(std::ostream& os, const FaceLogHelper<Face>& flh)
|
||||
return os;
|
||||
}
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
} // namespace nfd::face
|
||||
+183
-147
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2022, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -34,11 +34,14 @@
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
|
||||
/** \brief indicates the state of a face
|
||||
*/
|
||||
typedef TransportState FaceState;
|
||||
class Channel;
|
||||
|
||||
/** \brief generalization of a network interface
|
||||
/**
|
||||
* \brief Indicates the state of a face.
|
||||
*/
|
||||
using FaceState = TransportState;
|
||||
|
||||
/** \brief Generalization of a network interface.
|
||||
*
|
||||
* A face generalizes a network interface.
|
||||
* It provides best-effort network-layer packet delivery services
|
||||
@@ -49,170 +52,209 @@ typedef TransportState FaceState;
|
||||
* 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 FINAL_UNLESS_WITH_TESTS : public std::enable_shared_from_this<Face>, noncopyable
|
||||
class Face NFD_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;
|
||||
getLinkService() const noexcept
|
||||
{
|
||||
return m_service.get();
|
||||
}
|
||||
|
||||
Transport*
|
||||
getTransport() const;
|
||||
getTransport() const noexcept
|
||||
{
|
||||
return m_transport.get();
|
||||
}
|
||||
|
||||
public: // upper interface connected to forwarding
|
||||
/** \brief send Interest to \p endpointId
|
||||
*/
|
||||
void
|
||||
sendInterest(const Interest& interest, const EndpointId& endpointId);
|
||||
|
||||
/** \brief send Data to \p endpointId
|
||||
*/
|
||||
void
|
||||
sendData(const Data& data, const EndpointId& endpointId);
|
||||
|
||||
/** \brief send Nack to \p endpointId
|
||||
*/
|
||||
void
|
||||
sendNack(const lp::Nack& nack, const EndpointId& endpointId);
|
||||
|
||||
/** \brief signals on Interest received
|
||||
*/
|
||||
signal::Signal<LinkService, Interest, EndpointId>& afterReceiveInterest;
|
||||
|
||||
/** \brief signals on Data received
|
||||
*/
|
||||
signal::Signal<LinkService, Data, EndpointId>& afterReceiveData;
|
||||
|
||||
/** \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
|
||||
*/
|
||||
signal::Signal<LinkService, Interest>& onDroppedInterest;
|
||||
|
||||
public: // static properties
|
||||
/** \return face ID
|
||||
*/
|
||||
FaceId
|
||||
getId() const;
|
||||
|
||||
/** \brief sets face ID
|
||||
* \note Normally, this should only be invoked by FaceTable.
|
||||
*/
|
||||
void
|
||||
setId(FaceId id);
|
||||
|
||||
/** \return a FaceUri representing local endpoint
|
||||
*/
|
||||
FaceUri
|
||||
getLocalUri() const;
|
||||
|
||||
/** \return a FaceUri representing remote endpoint
|
||||
*/
|
||||
FaceUri
|
||||
getRemoteUri() const;
|
||||
|
||||
/** \return whether face is local or non-local for scope control purpose
|
||||
*/
|
||||
ndn::nfd::FaceScope
|
||||
getScope() const;
|
||||
|
||||
/** \return face persistency setting
|
||||
*/
|
||||
ndn::nfd::FacePersistency
|
||||
getPersistency() const;
|
||||
|
||||
/** \brief changes face persistency setting
|
||||
*/
|
||||
void
|
||||
setPersistency(ndn::nfd::FacePersistency persistency);
|
||||
|
||||
/** \return whether face is point-to-point or multi-access
|
||||
*/
|
||||
ndn::nfd::LinkType
|
||||
getLinkType() const;
|
||||
|
||||
public: // dynamic properties
|
||||
/** \return face state
|
||||
*/
|
||||
FaceState
|
||||
getState() const;
|
||||
|
||||
/** \brief signals after face state changed
|
||||
*/
|
||||
signal::Signal<Transport, FaceState/*old*/, FaceState/*new*/>& afterStateChange;
|
||||
|
||||
/** \return expiration time of the face
|
||||
* \retval time::steady_clock::TimePoint::max() the face has an indefinite lifetime
|
||||
*/
|
||||
time::steady_clock::TimePoint
|
||||
getExpirationTime() const;
|
||||
|
||||
/** \brief request the face to be closed
|
||||
/** \brief Request that the face be closed.
|
||||
*
|
||||
* This operation is effective only if face is in UP or DOWN state,
|
||||
* otherwise it has no effect.
|
||||
* The face changes state to CLOSING, and performs cleanup procedure.
|
||||
* The state will be changed to CLOSED when cleanup is complete, which may
|
||||
* happen synchronously or asynchronously.
|
||||
* This operation is effective only if face is in the UP or DOWN state; otherwise, it has no effect.
|
||||
* The face will change state to CLOSING, and then perform a cleanup procedure.
|
||||
* When the cleanup is complete, the state will be changed to CLOSED, which may happen
|
||||
* synchronously or asynchronously.
|
||||
*
|
||||
* \warning the face must not be deallocated until its state changes to CLOSED
|
||||
* \warning The face must not be deallocated until its state changes to CLOSED.
|
||||
*/
|
||||
void
|
||||
close();
|
||||
|
||||
public: // upper interface connected to forwarding
|
||||
/** \brief Send Interest.
|
||||
*/
|
||||
void
|
||||
sendInterest(const Interest& interest);
|
||||
|
||||
/** \brief Send Data.
|
||||
*/
|
||||
void
|
||||
sendData(const Data& data);
|
||||
|
||||
/** \brief Send Nack.
|
||||
*/
|
||||
void
|
||||
sendNack(const lp::Nack& nack);
|
||||
|
||||
/** \brief Signals on Interest received.
|
||||
*/
|
||||
signal::Signal<LinkService, Interest, EndpointId>& afterReceiveInterest;
|
||||
|
||||
/** \brief Signals on Data received.
|
||||
*/
|
||||
signal::Signal<LinkService, Data, EndpointId>& afterReceiveData;
|
||||
|
||||
/** \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.
|
||||
*/
|
||||
signal::Signal<LinkService, Interest>& onDroppedInterest;
|
||||
|
||||
public: // properties
|
||||
/**
|
||||
* \brief Returns the face ID.
|
||||
*/
|
||||
FaceId
|
||||
getId() const noexcept
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Sets the face ID.
|
||||
* \note Normally, this should only be invoked by FaceTable.
|
||||
*/
|
||||
void
|
||||
setId(FaceId id) noexcept
|
||||
{
|
||||
m_id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Returns a FaceUri representing the local endpoint.
|
||||
*/
|
||||
FaceUri
|
||||
getLocalUri() const;
|
||||
|
||||
/**
|
||||
* \brief Returns a FaceUri representing the remote endpoint.
|
||||
*/
|
||||
FaceUri
|
||||
getRemoteUri() const;
|
||||
|
||||
/**
|
||||
* \brief Returns whether the face is local or non-local for scope control purposes.
|
||||
*/
|
||||
ndn::nfd::FaceScope
|
||||
getScope() const;
|
||||
|
||||
/**
|
||||
* \brief Returns the current persistency setting of the face.
|
||||
*/
|
||||
ndn::nfd::FacePersistency
|
||||
getPersistency() const;
|
||||
|
||||
/**
|
||||
* \brief Changes the face persistency setting.
|
||||
*/
|
||||
void
|
||||
setPersistency(ndn::nfd::FacePersistency persistency);
|
||||
|
||||
/**
|
||||
* \brief Returns the link type of the face (point-to-point, multi-access, ...).
|
||||
*/
|
||||
ndn::nfd::LinkType
|
||||
getLinkType() const;
|
||||
|
||||
/**
|
||||
* \brief Returns the effective MTU of the face.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
FaceState
|
||||
getState() const;
|
||||
|
||||
/**
|
||||
* \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.
|
||||
*/
|
||||
time::steady_clock::time_point
|
||||
getExpirationTime() const;
|
||||
|
||||
const FaceCounters&
|
||||
getCounters() const;
|
||||
getCounters() const noexcept
|
||||
{
|
||||
return m_counters;
|
||||
}
|
||||
|
||||
FaceCounters&
|
||||
getCounters() noexcept
|
||||
{
|
||||
return m_counters;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get channel on which face was created (unicast) or the associated channel (multicast).
|
||||
*/
|
||||
weak_ptr<Channel>
|
||||
getChannel() const
|
||||
{
|
||||
return m_channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set channel on which face was created (unicast) or the associated channel (multicast).
|
||||
*/
|
||||
void
|
||||
setChannel(weak_ptr<Channel> channel)
|
||||
{
|
||||
m_channel = std::move(channel);
|
||||
}
|
||||
|
||||
private:
|
||||
FaceId m_id;
|
||||
FaceId m_id = INVALID_FACEID;
|
||||
unique_ptr<LinkService> m_service;
|
||||
unique_ptr<Transport> m_transport;
|
||||
FaceCounters m_counters;
|
||||
weak_ptr<Channel> m_channel;
|
||||
};
|
||||
|
||||
inline LinkService*
|
||||
Face::getLinkService() const
|
||||
inline void
|
||||
Face::close()
|
||||
{
|
||||
return m_service.get();
|
||||
}
|
||||
|
||||
inline Transport*
|
||||
Face::getTransport() const
|
||||
{
|
||||
return m_transport.get();
|
||||
m_transport->close();
|
||||
}
|
||||
|
||||
inline void
|
||||
Face::sendInterest(const Interest& interest, const EndpointId& endpointId)
|
||||
Face::sendInterest(const Interest& interest)
|
||||
{
|
||||
m_service->sendInterest(interest, endpointId);
|
||||
m_service->sendInterest(interest);
|
||||
}
|
||||
|
||||
inline void
|
||||
Face::sendData(const Data& data, const EndpointId& endpointId)
|
||||
Face::sendData(const Data& data)
|
||||
{
|
||||
m_service->sendData(data, endpointId);
|
||||
m_service->sendData(data);
|
||||
}
|
||||
|
||||
inline void
|
||||
Face::sendNack(const lp::Nack& nack, const EndpointId& endpointId)
|
||||
Face::sendNack(const lp::Nack& nack)
|
||||
{
|
||||
m_service->sendNack(nack, endpointId);
|
||||
}
|
||||
|
||||
inline FaceId
|
||||
Face::getId() const
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
inline void
|
||||
Face::setId(FaceId id)
|
||||
{
|
||||
m_id = id;
|
||||
m_service->sendNack(nack);
|
||||
}
|
||||
|
||||
inline FaceUri
|
||||
@@ -251,30 +293,24 @@ Face::getLinkType() const
|
||||
return m_transport->getLinkType();
|
||||
}
|
||||
|
||||
inline ssize_t
|
||||
Face::getMtu() const
|
||||
{
|
||||
return m_service->getEffectiveMtu();
|
||||
}
|
||||
|
||||
inline FaceState
|
||||
Face::getState() const
|
||||
{
|
||||
return m_transport->getState();
|
||||
}
|
||||
|
||||
inline time::steady_clock::TimePoint
|
||||
inline time::steady_clock::time_point
|
||||
Face::getExpirationTime() const
|
||||
{
|
||||
return m_transport->getExpirationTime();
|
||||
}
|
||||
|
||||
inline void
|
||||
Face::close()
|
||||
{
|
||||
m_transport->close();
|
||||
}
|
||||
|
||||
inline const FaceCounters&
|
||||
Face::getCounters() const
|
||||
{
|
||||
return m_counters;
|
||||
}
|
||||
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, const FaceLogHelper<Face>& flh);
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2023, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -24,14 +24,14 @@
|
||||
*/
|
||||
|
||||
#include "generic-link-service.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <ndn-cxx/lp/fields.hpp>
|
||||
#include <ndn-cxx/lp/pit-token.hpp>
|
||||
#include <ndn-cxx/lp/tags.hpp>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
namespace nfd::face {
|
||||
|
||||
NFD_LOG_INIT(GenericLinkService);
|
||||
|
||||
@@ -45,12 +45,43 @@ 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::TimePoint::max())
|
||||
, m_nextMarkTime(time::steady_clock::time_point::max())
|
||||
, m_nMarkedSinceInMarkingState(0)
|
||||
, globalSp(options.C * 0.99, options.vqSize)
|
||||
{
|
||||
m_reassembler.beforeTimeout.connect([this] (auto...) { ++this->nReassemblyTimeouts; });
|
||||
m_reliability.onDroppedInterest.connect([this] (const auto& i) { this->notifyDroppedInterest(i); });
|
||||
m_reassembler.beforeTimeout.connect([this] (auto&&...) { ++nReassemblyTimeouts; });
|
||||
m_reliability.onDroppedInterest.connect([this] (const auto& i) { notifyDroppedInterest(i); });
|
||||
nReassembling.observe(&m_reassembler);
|
||||
|
||||
this->sendPacketCallback = [this](std::shared_ptr<VirtualQueueItem> taskPtr) {
|
||||
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");
|
||||
// 如果没有可调度的包,则 1 ms 之后再调度
|
||||
this->canScheduler = true;
|
||||
// getScheduler().schedule(time::milliseconds(1), std::bind(this->sendPacketCallback, nullptr));
|
||||
} else {
|
||||
// 等待足够的 token 再发送
|
||||
this->canScheduler = false;
|
||||
// NFD_LOG_DEBUG("Route waitTime: " << newTaskPtr->waitNsTime);
|
||||
getScheduler().schedule(time::nanoseconds((uint32_t)(newTaskPtr->waitNsTime)),
|
||||
std::bind(this->sendPacketCallback, newTaskPtr));
|
||||
}
|
||||
};
|
||||
// getScheduler().schedule(time::nanoseconds(0), std::bind(this->sendPacketCallback, nullptr));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -62,18 +93,38 @@ GenericLinkService::setOptions(const GenericLinkService::Options& options)
|
||||
m_reliability.setOptions(m_options.reliabilityOptions);
|
||||
}
|
||||
|
||||
void
|
||||
GenericLinkService::requestIdlePacket(const EndpointId& endpointId)
|
||||
ssize_t
|
||||
GenericLinkService::getEffectiveMtu() const
|
||||
{
|
||||
// No need to request Acks to attach to this packet from LpReliability, as they are already
|
||||
// attached in sendLpPacket
|
||||
this->sendLpPacket({}, endpointId);
|
||||
// Since MTU_UNLIMITED is negative, it will implicitly override any finite override MTU
|
||||
return std::min(m_options.overrideMtu, getTransport()->getMtu());
|
||||
}
|
||||
|
||||
bool
|
||||
GenericLinkService::canOverrideMtuTo(ssize_t mtu) const
|
||||
{
|
||||
// Not allowed to override unlimited transport MTU
|
||||
if (getTransport()->getMtu() == MTU_UNLIMITED) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Override MTU must be at least MIN_MTU (also implicitly forbids MTU_UNLIMITED and MTU_INVALID)
|
||||
return mtu >= MIN_MTU;
|
||||
}
|
||||
|
||||
void
|
||||
GenericLinkService::sendLpPacket(lp::Packet&& pkt, const EndpointId& endpointId)
|
||||
GenericLinkService::requestIdlePacket()
|
||||
{
|
||||
const ssize_t mtu = this->getTransport()->getMtu();
|
||||
// No need to request Acks to attach to this packet from LpReliability, as they are already
|
||||
// attached in sendLpPacket
|
||||
NFD_LOG_FACE_TRACE("IDLE packet requested");
|
||||
this->sendLpPacket({});
|
||||
}
|
||||
|
||||
void
|
||||
GenericLinkService::sendLpPacket(lp::Packet&& pkt)
|
||||
{
|
||||
const ssize_t mtu = getEffectiveMtu();
|
||||
|
||||
if (m_options.reliabilityOptions.isEnabled) {
|
||||
m_reliability.piggyback(pkt, mtu);
|
||||
@@ -85,42 +136,77 @@ GenericLinkService::sendLpPacket(lp::Packet&& pkt, const EndpointId& endpointId)
|
||||
|
||||
auto block = pkt.wireEncode();
|
||||
if (mtu != MTU_UNLIMITED && block.size() > static_cast<size_t>(mtu)) {
|
||||
++this->nOutOverMtu;
|
||||
++nOutOverMtu;
|
||||
NFD_LOG_FACE_WARN("attempted to send packet over MTU limit");
|
||||
return;
|
||||
}
|
||||
this->sendPacket(block, endpointId);
|
||||
this->sendPacket(block);
|
||||
}
|
||||
|
||||
void
|
||||
GenericLinkService::doSendInterest(const Interest& interest, const EndpointId& endpointId)
|
||||
GenericLinkService::doSendInterest(const Interest& interest)
|
||||
{
|
||||
lp::Packet lpPacket(interest.wireEncode());
|
||||
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);
|
||||
//}
|
||||
}
|
||||
// lp::Packet lpPacket(interest.wireEncode());
|
||||
|
||||
encodeLpFields(interest, lpPacket);
|
||||
// encodeLpFields(interest, lpPacket);
|
||||
|
||||
this->sendNetPacket(std::move(lpPacket), endpointId, true);
|
||||
// this->sendNetPacket(std::move(lpPacket), true);
|
||||
}
|
||||
|
||||
void
|
||||
GenericLinkService::doSendData(const Data& data, const EndpointId& endpointId)
|
||||
GenericLinkService::doSendData(const Data& data)
|
||||
{
|
||||
// const Block& block = data.wireEncode();
|
||||
// std::cout << "Data wireEncode size: " << block.size() << std::endl;
|
||||
lp::Packet lpPacket(data.wireEncode());
|
||||
|
||||
// std::cout << "Data before encode LpFields size: " << lpPacket.wireEncode().size() << std::endl;
|
||||
encodeLpFields(data, lpPacket);
|
||||
// std::cout << "Data After encode LpFields size: " << lpPacket.wireEncode().size() << std::endl;
|
||||
|
||||
this->sendNetPacket(std::move(lpPacket), endpointId, false);
|
||||
this->sendNetPacket(std::move(lpPacket), false);
|
||||
}
|
||||
|
||||
void
|
||||
GenericLinkService::doSendNack(const lp::Nack& nack, const EndpointId& endpointId)
|
||||
GenericLinkService::doSendNack(const lp::Nack& nack)
|
||||
{
|
||||
lp::Packet lpPacket(nack.getInterest().wireEncode());
|
||||
lpPacket.add<lp::NackField>(nack.getHeader());
|
||||
|
||||
encodeLpFields(nack, lpPacket);
|
||||
|
||||
this->sendNetPacket(std::move(lpPacket), endpointId, false);
|
||||
this->sendNetPacket(std::move(lpPacket), false);
|
||||
}
|
||||
|
||||
void
|
||||
GenericLinkService::assignSequences(std::vector<lp::Packet>& pkts)
|
||||
{
|
||||
std::for_each(pkts.begin(), pkts.end(), [this] (lp::Packet& pkt) {
|
||||
pkt.set<lp::SequenceField>(++m_lastSeqNo);
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
@@ -157,10 +243,10 @@ GenericLinkService::encodeLpFields(const ndn::PacketBase& netPkt, lp::Packet& lp
|
||||
}
|
||||
|
||||
void
|
||||
GenericLinkService::sendNetPacket(lp::Packet&& pkt, const EndpointId& endpointId, bool isInterest)
|
||||
GenericLinkService::sendNetPacket(lp::Packet&& pkt, bool isInterest)
|
||||
{
|
||||
std::vector<lp::Packet> frags;
|
||||
ssize_t mtu = this->getTransport()->getMtu();
|
||||
ssize_t mtu = getEffectiveMtu();
|
||||
|
||||
// Make space for feature fields in fragments
|
||||
if (m_options.reliabilityOptions.isEnabled && mtu != MTU_UNLIMITED) {
|
||||
@@ -171,14 +257,15 @@ GenericLinkService::sendNetPacket(lp::Packet&& pkt, const EndpointId& endpointId
|
||||
mtu -= CONGESTION_MARK_SIZE;
|
||||
}
|
||||
|
||||
BOOST_ASSERT(mtu == MTU_UNLIMITED || mtu > 0);
|
||||
// An MTU of 0 is allowed but will cause all packets to be dropped before transmission
|
||||
BOOST_ASSERT(mtu == MTU_UNLIMITED || mtu >= 0);
|
||||
|
||||
if (m_options.allowFragmentation && mtu != MTU_UNLIMITED) {
|
||||
bool isOk = false;
|
||||
std::tie(isOk, frags) = m_fragmenter.fragmentPacket(pkt, mtu);
|
||||
if (!isOk) {
|
||||
// fragmentation failed (warning is logged by LpFragmenter)
|
||||
++this->nFragmentationErrors;
|
||||
++nFragmentationErrors;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -198,8 +285,8 @@ GenericLinkService::sendNetPacket(lp::Packet&& pkt, const EndpointId& endpointId
|
||||
BOOST_ASSERT(!frags.front().has<lp::FragCountField>());
|
||||
}
|
||||
|
||||
// Only assign sequences to fragments if packet contains more than 1 fragment
|
||||
if (frags.size() > 1) {
|
||||
// Only assign sequences to fragments if reliability enabled or if packet contains >1 fragment
|
||||
if (m_options.reliabilityOptions.isEnabled || frags.size() > 1) {
|
||||
// Assign sequences to all fragments
|
||||
this->assignSequences(frags);
|
||||
}
|
||||
@@ -209,22 +296,10 @@ GenericLinkService::sendNetPacket(lp::Packet&& pkt, const EndpointId& endpointId
|
||||
}
|
||||
|
||||
for (lp::Packet& frag : frags) {
|
||||
this->sendLpPacket(std::move(frag), endpointId);
|
||||
this->sendLpPacket(std::move(frag));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GenericLinkService::assignSequence(lp::Packet& pkt)
|
||||
{
|
||||
pkt.set<lp::SequenceField>(++m_lastSeqNo);
|
||||
}
|
||||
|
||||
void
|
||||
GenericLinkService::assignSequences(std::vector<lp::Packet>& pkts)
|
||||
{
|
||||
std::for_each(pkts.begin(), pkts.end(), [this] (auto& pkt) { this->assignSequence(pkt); });
|
||||
}
|
||||
|
||||
void
|
||||
GenericLinkService::checkCongestionLevel(lp::Packet& pkt)
|
||||
{
|
||||
@@ -244,7 +319,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::TimePoint::max()) {
|
||||
if (m_nextMarkTime == time::steady_clock::time_point::max()) {
|
||||
m_nextMarkTime = now + m_options.baseCongestionMarkingInterval;
|
||||
}
|
||||
// Mark packet if sendQueue stays above target for one interval
|
||||
@@ -262,10 +337,10 @@ GenericLinkService::checkCongestionLevel(lp::Packet& pkt)
|
||||
m_nextMarkTime += interval;
|
||||
}
|
||||
}
|
||||
else if (m_nextMarkTime != time::steady_clock::TimePoint::max()) {
|
||||
else if (m_nextMarkTime != time::steady_clock::time_point::max()) {
|
||||
// Congestion incident has ended, so reset
|
||||
NFD_LOG_FACE_DEBUG("Send queue length dropped below congestion threshold");
|
||||
m_nextMarkTime = time::steady_clock::TimePoint::max();
|
||||
m_nextMarkTime = time::steady_clock::time_point::max();
|
||||
m_nMarkedSinceInMarkingState = 0;
|
||||
}
|
||||
}
|
||||
@@ -277,7 +352,11 @@ GenericLinkService::doReceivePacket(const Block& packet, const EndpointId& endpo
|
||||
lp::Packet pkt(packet);
|
||||
|
||||
if (m_options.reliabilityOptions.isEnabled) {
|
||||
m_reliability.processIncomingPacket(pkt);
|
||||
if (!m_reliability.processIncomingPacket(pkt)) {
|
||||
NFD_LOG_FACE_TRACE("received duplicate fragment: DROP");
|
||||
++nDuplicateSequence;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!pkt.has<lp::FragmentField>()) {
|
||||
@@ -291,16 +370,13 @@ GenericLinkService::doReceivePacket(const Block& packet, const EndpointId& endpo
|
||||
return;
|
||||
}
|
||||
|
||||
bool isReassembled = false;
|
||||
Block netPkt;
|
||||
lp::Packet firstPkt;
|
||||
std::tie(isReassembled, netPkt, firstPkt) = m_reassembler.receiveFragment(endpoint, pkt);
|
||||
auto [isReassembled, netPkt, firstPkt] = m_reassembler.receiveFragment(endpoint, pkt);
|
||||
if (isReassembled) {
|
||||
this->decodeNetPacket(netPkt, firstPkt, endpoint);
|
||||
}
|
||||
}
|
||||
catch (const tlv::Error& e) {
|
||||
++this->nInLpInvalid;
|
||||
++nInLpInvalid;
|
||||
NFD_LOG_FACE_WARN("packet parse error (" << e.what() << "): DROP");
|
||||
}
|
||||
}
|
||||
@@ -323,13 +399,13 @@ GenericLinkService::decodeNetPacket(const Block& netPkt, const lp::Packet& first
|
||||
this->decodeData(netPkt, firstPkt, endpointId);
|
||||
break;
|
||||
default:
|
||||
++this->nInNetInvalid;
|
||||
++nInNetInvalid;
|
||||
NFD_LOG_FACE_WARN("unrecognized network-layer packet TLV-TYPE " << netPkt.type() << ": DROP");
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (const tlv::Error& e) {
|
||||
++this->nInNetInvalid;
|
||||
++nInNetInvalid;
|
||||
NFD_LOG_FACE_WARN("packet parse error (" << e.what() << "): DROP");
|
||||
}
|
||||
}
|
||||
@@ -355,7 +431,7 @@ GenericLinkService::decodeInterest(const Block& netPkt, const lp::Packet& firstP
|
||||
}
|
||||
|
||||
if (firstPkt.has<lp::CachePolicyField>()) {
|
||||
++this->nInNetInvalid;
|
||||
++nInNetInvalid;
|
||||
NFD_LOG_FACE_WARN("received CachePolicy with Interest: DROP");
|
||||
return;
|
||||
}
|
||||
@@ -378,7 +454,7 @@ GenericLinkService::decodeInterest(const Block& netPkt, const lp::Packet& firstP
|
||||
}
|
||||
|
||||
if (firstPkt.has<lp::PrefixAnnouncementField>()) {
|
||||
++this->nInNetInvalid;
|
||||
++nInNetInvalid;
|
||||
NFD_LOG_FACE_WARN("received PrefixAnnouncement with Interest: DROP");
|
||||
return;
|
||||
}
|
||||
@@ -400,13 +476,13 @@ GenericLinkService::decodeData(const Block& netPkt, const lp::Packet& firstPkt,
|
||||
auto data = make_shared<Data>(netPkt);
|
||||
|
||||
if (firstPkt.has<lp::NackField>()) {
|
||||
++this->nInNetInvalid;
|
||||
++nInNetInvalid;
|
||||
NFD_LOG_FACE_WARN("received Nack with Data: DROP");
|
||||
return;
|
||||
}
|
||||
|
||||
if (firstPkt.has<lp::NextHopFaceIdField>()) {
|
||||
++this->nInNetInvalid;
|
||||
++nInNetInvalid;
|
||||
NFD_LOG_FACE_WARN("received NextHopFaceId with Data: DROP");
|
||||
return;
|
||||
}
|
||||
@@ -427,7 +503,7 @@ GenericLinkService::decodeData(const Block& netPkt, const lp::Packet& firstPkt,
|
||||
}
|
||||
|
||||
if (firstPkt.has<lp::NonDiscoveryField>()) {
|
||||
++this->nInNetInvalid;
|
||||
++nInNetInvalid;
|
||||
NFD_LOG_FACE_WARN("received NonDiscovery with Data: DROP");
|
||||
return;
|
||||
}
|
||||
@@ -455,13 +531,13 @@ GenericLinkService::decodeNack(const Block& netPkt, const lp::Packet& firstPkt,
|
||||
nack.setHeader(firstPkt.get<lp::NackField>());
|
||||
|
||||
if (firstPkt.has<lp::NextHopFaceIdField>()) {
|
||||
++this->nInNetInvalid;
|
||||
++nInNetInvalid;
|
||||
NFD_LOG_FACE_WARN("received NextHopFaceId with Nack: DROP");
|
||||
return;
|
||||
}
|
||||
|
||||
if (firstPkt.has<lp::CachePolicyField>()) {
|
||||
++this->nInNetInvalid;
|
||||
++nInNetInvalid;
|
||||
NFD_LOG_FACE_WARN("received CachePolicy with Nack: DROP");
|
||||
return;
|
||||
}
|
||||
@@ -475,13 +551,13 @@ GenericLinkService::decodeNack(const Block& netPkt, const lp::Packet& firstPkt,
|
||||
}
|
||||
|
||||
if (firstPkt.has<lp::NonDiscoveryField>()) {
|
||||
++this->nInNetInvalid;
|
||||
++nInNetInvalid;
|
||||
NFD_LOG_FACE_WARN("received NonDiscovery with Nack: DROP");
|
||||
return;
|
||||
}
|
||||
|
||||
if (firstPkt.has<lp::PrefixAnnouncementField>()) {
|
||||
++this->nInNetInvalid;
|
||||
++nInNetInvalid;
|
||||
NFD_LOG_FACE_WARN("received PrefixAnnouncement with Nack: DROP");
|
||||
return;
|
||||
}
|
||||
@@ -489,5 +565,4 @@ GenericLinkService::decodeNack(const Block& netPkt, const lp::Packet& firstPkt,
|
||||
this->receiveNack(nack, endpointId);
|
||||
}
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
} // namespace nfd::face
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2022, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -30,109 +30,113 @@
|
||||
#include "lp-fragmenter.hpp"
|
||||
#include "lp-reassembler.hpp"
|
||||
#include "lp-reliability.hpp"
|
||||
#include "queues.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
namespace nfd::face {
|
||||
|
||||
/** \brief counters provided by GenericLinkService
|
||||
* \note The type name 'GenericLinkServiceCounters' is implementation detail.
|
||||
* Use 'GenericLinkService::Counters' in public API.
|
||||
/** \brief Counters provided by GenericLinkService.
|
||||
* \note The type name GenericLinkServiceCounters is an 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 outgoing LpPackets that were marked with congestion marks
|
||||
/** \brief Count of LpPackets dropped due to duplicate Sequence numbers.
|
||||
*/
|
||||
PacketCounter nDuplicateSequence;
|
||||
|
||||
/** \brief Count of outgoing LpPackets that were marked with congestion marks.
|
||||
*/
|
||||
PacketCounter nCongestionMarked;
|
||||
};
|
||||
|
||||
/** \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 FINAL_UNLESS_WITH_TESTS : public LinkService
|
||||
, protected virtual GenericLinkServiceCounters
|
||||
class GenericLinkService NFD_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
|
||||
{
|
||||
public:
|
||||
constexpr
|
||||
Options() noexcept
|
||||
{
|
||||
}
|
||||
|
||||
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.
|
||||
*
|
||||
@@ -140,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.
|
||||
*
|
||||
@@ -148,97 +152,112 @@ 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.
|
||||
*
|
||||
* 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
|
||||
* being set with canOverrideMtuTo().
|
||||
*/
|
||||
ssize_t overrideMtu = std::numeric_limits<ssize_t>::max();
|
||||
|
||||
uint64_t C = 10000000;
|
||||
size_t vqSize = 20;
|
||||
};
|
||||
|
||||
/** \brief counters provided by GenericLinkService
|
||||
/** \brief %Counters provided by GenericLinkService.
|
||||
*/
|
||||
using Counters = GenericLinkServiceCounters;
|
||||
|
||||
explicit
|
||||
GenericLinkService(const Options& options = {});
|
||||
|
||||
/** \brief get Options used by GenericLinkService
|
||||
/** \brief Get the options used by GenericLinkService.
|
||||
*/
|
||||
const Options&
|
||||
getOptions() const;
|
||||
getOptions() const
|
||||
{
|
||||
return m_options;
|
||||
}
|
||||
|
||||
/** \brief sets Options used by GenericLinkService
|
||||
/** \brief Sets the options used by GenericLinkService.
|
||||
*/
|
||||
void
|
||||
setOptions(const Options& options);
|
||||
|
||||
const Counters&
|
||||
getCounters() const OVERRIDE_WITH_TESTS_ELSE_FINAL;
|
||||
getCounters() const NFD_OVERRIDE_WITH_TESTS_ELSE_FINAL
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
PROTECTED_WITH_TESTS_ELSE_PRIVATE: // send path
|
||||
/** \brief request an IDLE packet to transmit pending service fields
|
||||
ssize_t
|
||||
getEffectiveMtu() const NFD_OVERRIDE_WITH_TESTS_ELSE_FINAL;
|
||||
|
||||
/** \brief Whether MTU can be overridden to the specified value.
|
||||
*
|
||||
* If the transport MTU is unlimited, then this will always return false.
|
||||
*/
|
||||
bool
|
||||
canOverrideMtuTo(ssize_t mtu) const;
|
||||
|
||||
NFD_PROTECTED_WITH_TESTS_ELSE_PRIVATE: // send path
|
||||
/** \brief Request an IDLE packet to transmit pending service fields.
|
||||
*/
|
||||
void
|
||||
requestIdlePacket(const EndpointId& endpointId);
|
||||
requestIdlePacket();
|
||||
|
||||
/** \brief send an LpPacket to \p endpointId
|
||||
/** \brief Send an LpPacket.
|
||||
*/
|
||||
void
|
||||
sendLpPacket(lp::Packet&& pkt, const EndpointId& endpointId);
|
||||
sendLpPacket(lp::Packet&& pkt);
|
||||
|
||||
/** \brief send Interest
|
||||
void
|
||||
doSendInterest(const Interest& interest) NFD_OVERRIDE_WITH_TESTS_ELSE_FINAL;
|
||||
|
||||
void
|
||||
doSendData(const Data& data) NFD_OVERRIDE_WITH_TESTS_ELSE_FINAL;
|
||||
|
||||
void
|
||||
doSendNack(const ndn::lp::Nack& nack) NFD_OVERRIDE_WITH_TESTS_ELSE_FINAL;
|
||||
|
||||
/** \brief Assign consecutive sequence numbers to LpPackets.
|
||||
*/
|
||||
void
|
||||
doSendInterest(const Interest& interest, const EndpointId& endpointId) OVERRIDE_WITH_TESTS_ELSE_FINAL;
|
||||
|
||||
/** \brief send Data
|
||||
*/
|
||||
void
|
||||
doSendData(const Data& data, const EndpointId& endpointId) OVERRIDE_WITH_TESTS_ELSE_FINAL;
|
||||
|
||||
/** \brief send Nack
|
||||
*/
|
||||
void
|
||||
doSendNack(const ndn::lp::Nack& nack, const EndpointId& endpointId) OVERRIDE_WITH_TESTS_ELSE_FINAL;
|
||||
assignSequences(std::vector<lp::Packet>& pkts);
|
||||
|
||||
private: // send path
|
||||
/** \brief encode link protocol fields from tags onto an outgoing LpPacket
|
||||
/** \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 endpointId destination endpoint to which LpPacket will be sent
|
||||
* \param isInterest whether the network layer packet is an Interest
|
||||
*/
|
||||
void
|
||||
sendNetPacket(lp::Packet&& pkt, const EndpointId& endpointId, bool isInterest);
|
||||
sendNetPacket(lp::Packet&& pkt, bool isInterest);
|
||||
|
||||
/** \brief assign a sequence number to an LpPacket
|
||||
*/
|
||||
void
|
||||
assignSequence(lp::Packet& pkt);
|
||||
|
||||
/** \brief assign consecutive sequence numbers to LpPackets
|
||||
*/
|
||||
void
|
||||
assignSequences(std::vector<lp::Packet>& pkts);
|
||||
|
||||
/** \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
|
||||
checkCongestionLevel(lp::Packet& pkt);
|
||||
|
||||
private: // receive path
|
||||
/** \brief receive Packet from Transport
|
||||
*/
|
||||
void
|
||||
doReceivePacket(const Block& packet, const EndpointId& endpoint) OVERRIDE_WITH_TESTS_ELSE_FINAL;
|
||||
doReceivePacket(const Block& packet, const EndpointId& endpoint) NFD_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
|
||||
@@ -249,7 +268,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
|
||||
@@ -262,7 +281,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
|
||||
@@ -275,7 +294,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
|
||||
@@ -288,35 +307,26 @@ private: // receive path
|
||||
void
|
||||
decodeNack(const Block& netPkt, const lp::Packet& firstPkt, const EndpointId& endpointId);
|
||||
|
||||
PROTECTED_WITH_TESTS_ELSE_PRIVATE:
|
||||
NFD_PROTECTED_WITH_TESTS_ELSE_PRIVATE:
|
||||
Options m_options;
|
||||
LpFragmenter m_fragmenter;
|
||||
LpReassembler m_reassembler;
|
||||
LpReliability m_reliability;
|
||||
lp::Sequence m_lastSeqNo;
|
||||
|
||||
PUBLIC_WITH_TESTS_ELSE_PRIVATE:
|
||||
NFD_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
|
||||
/// Time to mark next packet due to send queue congestion
|
||||
time::steady_clock::TimePoint m_nextMarkTime;
|
||||
time::steady_clock::time_point m_nextMarkTime;
|
||||
/// number of marked packets in the current incident of congestion
|
||||
size_t m_nMarkedSinceInMarkingState;
|
||||
|
||||
friend class LpReliability;
|
||||
GlobalSP globalSp;
|
||||
bool canScheduler = true;
|
||||
std::function<void(std::shared_ptr<VirtualQueueItem>)> sendPacketCallback;
|
||||
|
||||
friend LpReliability;
|
||||
};
|
||||
|
||||
inline const GenericLinkService::Options&
|
||||
GenericLinkService::getOptions() const
|
||||
{
|
||||
return m_options;
|
||||
}
|
||||
|
||||
inline const GenericLinkService::Counters&
|
||||
GenericLinkService::getCounters() const
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
} // namespace nfd::face
|
||||
|
||||
#endif // NFD_DAEMON_FACE_GENERIC_LINK_SERVICE_HPP
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2022, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -28,8 +28,7 @@
|
||||
#include "internal-transport.hpp"
|
||||
#include "common/global.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
namespace nfd::face {
|
||||
|
||||
std::tuple<shared_ptr<Face>, shared_ptr<ndn::Face>>
|
||||
makeInternalFace(ndn::KeyChain& clientKeyChain)
|
||||
@@ -46,8 +45,7 @@ makeInternalFace(ndn::KeyChain& clientKeyChain)
|
||||
|
||||
auto clientFace = make_shared<ndn::Face>(clientTransport, getGlobalIoService(), clientKeyChain);
|
||||
|
||||
return std::make_tuple(face, clientFace);
|
||||
return {face, clientFace};
|
||||
}
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
} // namespace nfd::face
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/**
|
||||
* Copyright (c) 2014-2015, Regents of the University of California,
|
||||
/*
|
||||
* Copyright (c) 2014-2022, 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 {
|
||||
namespace face {
|
||||
namespace nfd::face {
|
||||
|
||||
/** \brief make a pair of forwarder-side face and client-side face
|
||||
* that are connected with each other
|
||||
/** \brief Make a pair of forwarder-side face and client-side face
|
||||
* that are connected to 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,7 +45,6 @@ namespace face {
|
||||
std::tuple<shared_ptr<Face>, shared_ptr<ndn::Face>>
|
||||
makeInternalFace(ndn::KeyChain& clientKeyChain);
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
} // namespace nfd::face
|
||||
|
||||
#endif // NFD_DAEMON_FACE_INTERNAL_FACE_HPP
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2023, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -26,8 +26,9 @@
|
||||
#include "internal-transport.hpp"
|
||||
#include "common/global.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
#include <boost/asio/post.hpp>
|
||||
|
||||
namespace nfd::face {
|
||||
|
||||
NFD_LOG_MEMBER_INIT(InternalForwarderTransport, InternalForwarderTransport);
|
||||
NFD_LOG_MEMBER_INIT(InternalClientTransport, InternalClientTransport);
|
||||
@@ -48,14 +49,14 @@ InternalForwarderTransport::InternalForwarderTransport(const FaceUri& localUri,
|
||||
void
|
||||
InternalForwarderTransport::receivePacket(const Block& packet)
|
||||
{
|
||||
getGlobalIoService().post([this, packet] {
|
||||
boost::asio::post(getGlobalIoService(), [this, packet] {
|
||||
NFD_LOG_FACE_TRACE("Received: " << packet.size() << " bytes");
|
||||
receive(packet);
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
InternalForwarderTransport::doSend(const Block& packet, const EndpointId&)
|
||||
InternalForwarderTransport::doSend(const Block& packet)
|
||||
{
|
||||
NFD_LOG_FACE_TRACE("Sending to " << m_peer);
|
||||
|
||||
@@ -106,7 +107,7 @@ InternalClientTransport::connectToForwarder(InternalForwarderTransport* forwarde
|
||||
void
|
||||
InternalClientTransport::receivePacket(const Block& packet)
|
||||
{
|
||||
getGlobalIoService().post([this, packet] {
|
||||
boost::asio::post(getGlobalIoService(), [this, packet] {
|
||||
NFD_LOG_TRACE("Received: " << packet.size() << " bytes");
|
||||
if (m_receiveCallback) {
|
||||
m_receiveCallback(packet);
|
||||
@@ -123,15 +124,4 @@ InternalClientTransport::send(const Block& wire)
|
||||
m_forwarder->receivePacket(wire);
|
||||
}
|
||||
|
||||
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
|
||||
} // namespace nfd::face
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2023, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -30,22 +30,23 @@
|
||||
|
||||
#include <ndn-cxx/transport/transport.hpp>
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
namespace nfd::face {
|
||||
|
||||
/** \brief Abstracts a transport that can be paired with another.
|
||||
/**
|
||||
* \brief Abstracts a transport that can be paired with another.
|
||||
*/
|
||||
class InternalTransportBase
|
||||
{
|
||||
public:
|
||||
virtual
|
||||
~InternalTransportBase() = default;
|
||||
|
||||
virtual void
|
||||
receivePacket(const Block& packet) = 0;
|
||||
|
||||
protected:
|
||||
~InternalTransportBase() = default;
|
||||
};
|
||||
|
||||
/** \brief Implements a forwarder-side transport that can be paired with another transport.
|
||||
/**
|
||||
* \brief Implements a forwarder-side transport that can be paired with another transport.
|
||||
*/
|
||||
class InternalForwarderTransport final : public Transport, public InternalTransportBase
|
||||
{
|
||||
@@ -57,7 +58,7 @@ public:
|
||||
ndn::nfd::LinkType linkType = ndn::nfd::LINK_TYPE_POINT_TO_POINT);
|
||||
|
||||
void
|
||||
setPeer(InternalTransportBase* peer)
|
||||
setPeer(InternalTransportBase* peer) noexcept
|
||||
{
|
||||
m_peer = peer;
|
||||
}
|
||||
@@ -71,7 +72,7 @@ protected:
|
||||
|
||||
private:
|
||||
void
|
||||
doSend(const Block& packet, const EndpointId& endpoint) final;
|
||||
doSend(const Block& packet) final;
|
||||
|
||||
private:
|
||||
NFD_LOG_MEMBER_DECL();
|
||||
@@ -79,7 +80,8 @@ private:
|
||||
InternalTransportBase* m_peer = nullptr;
|
||||
};
|
||||
|
||||
/** \brief Implements a client-side transport that can be paired with an InternalForwarderTransport.
|
||||
/**
|
||||
* \brief Implements a client-side transport that can be paired with an InternalForwarderTransport.
|
||||
*/
|
||||
class InternalClientTransport final : public ndn::Transport, public InternalTransportBase
|
||||
{
|
||||
@@ -101,10 +103,7 @@ public:
|
||||
receivePacket(const Block& packet) final;
|
||||
|
||||
void
|
||||
send(const Block& wire) final;
|
||||
|
||||
void
|
||||
send(const Block& header, const Block& payload) final;
|
||||
send(const Block& block) final;
|
||||
|
||||
void
|
||||
close() final
|
||||
@@ -128,7 +127,6 @@ private:
|
||||
signal::ScopedConnection m_fwTransportStateConn;
|
||||
};
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
} // namespace nfd::face
|
||||
|
||||
#endif // NFD_DAEMON_FACE_INTERNAL_TRANSPORT_HPP
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2022, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -26,23 +26,14 @@
|
||||
#include "link-service.hpp"
|
||||
#include "face.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
namespace nfd::face {
|
||||
|
||||
NFD_LOG_INIT(LinkService);
|
||||
|
||||
LinkService::LinkService()
|
||||
: m_face(nullptr)
|
||||
, m_transport(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
LinkService::~LinkService()
|
||||
{
|
||||
}
|
||||
LinkService::~LinkService() = default;
|
||||
|
||||
void
|
||||
LinkService::setFaceAndTransport(Face& face, Transport& transport)
|
||||
LinkService::setFaceAndTransport(Face& face, Transport& transport) noexcept
|
||||
{
|
||||
BOOST_ASSERT(m_face == nullptr);
|
||||
BOOST_ASSERT(m_transport == nullptr);
|
||||
@@ -52,36 +43,36 @@ LinkService::setFaceAndTransport(Face& face, Transport& transport)
|
||||
}
|
||||
|
||||
void
|
||||
LinkService::sendInterest(const Interest& interest, const EndpointId& endpoint)
|
||||
LinkService::sendInterest(const Interest& interest)
|
||||
{
|
||||
BOOST_ASSERT(m_transport != nullptr);
|
||||
NFD_LOG_FACE_TRACE(__func__);
|
||||
|
||||
++this->nOutInterests;
|
||||
|
||||
doSendInterest(interest, endpoint);
|
||||
doSendInterest(interest);
|
||||
}
|
||||
|
||||
void
|
||||
LinkService::sendData(const Data& data, const EndpointId& endpoint)
|
||||
LinkService::sendData(const Data& data)
|
||||
{
|
||||
BOOST_ASSERT(m_transport != nullptr);
|
||||
NFD_LOG_FACE_TRACE(__func__);
|
||||
|
||||
++this->nOutData;
|
||||
|
||||
doSendData(data, endpoint);
|
||||
doSendData(data);
|
||||
}
|
||||
|
||||
void
|
||||
LinkService::sendNack(const ndn::lp::Nack& nack, const EndpointId& endpoint)
|
||||
LinkService::sendNack(const ndn::lp::Nack& nack)
|
||||
{
|
||||
BOOST_ASSERT(m_transport != nullptr);
|
||||
NFD_LOG_FACE_TRACE(__func__);
|
||||
|
||||
++this->nOutNacks;
|
||||
|
||||
doSendNack(nack, endpoint);
|
||||
doSendNack(nack);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -117,7 +108,7 @@ LinkService::receiveNack(const ndn::lp::Nack& nack, const EndpointId& endpoint)
|
||||
void
|
||||
LinkService::notifyDroppedInterest(const Interest& interest)
|
||||
{
|
||||
++this->nDroppedInterests;
|
||||
++this->nInterestsExceededRetx;
|
||||
onDroppedInterest(interest);
|
||||
}
|
||||
|
||||
@@ -135,5 +126,4 @@ operator<<(std::ostream& os, const FaceLogHelper<LinkService>& flh)
|
||||
return os;
|
||||
}
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
} // namespace nfd::face
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2022, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -30,199 +30,199 @@
|
||||
#include "transport.hpp"
|
||||
#include "common/counter.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
namespace nfd::face {
|
||||
|
||||
/** \brief counters provided by LinkService
|
||||
* \note The type name 'LinkServiceCounters' is implementation detail.
|
||||
* Use 'LinkService::Counters' in public API.
|
||||
/** \brief Counters provided by LinkService.
|
||||
* \note The type name LinkServiceCounters is an 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 nDroppedInterests;
|
||||
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 part of a Face
|
||||
* \sa Face
|
||||
/**
|
||||
* \brief The upper half of a Face.
|
||||
* \sa Face, Transport
|
||||
*/
|
||||
class LinkService : protected virtual LinkServiceCounters, noncopyable
|
||||
{
|
||||
public:
|
||||
/** \brief counters provided by LinkService
|
||||
/**
|
||||
* \brief %Counters provided by LinkService.
|
||||
*/
|
||||
typedef LinkServiceCounters Counters;
|
||||
using Counters = LinkServiceCounters;
|
||||
|
||||
public:
|
||||
LinkService();
|
||||
|
||||
virtual
|
||||
~LinkService();
|
||||
|
||||
/** \brief set Face and Transport for LinkService
|
||||
* \pre setFaceAndTransport has not been called
|
||||
/**
|
||||
* \brief Set Face and Transport for this LinkService.
|
||||
* \pre setFaceAndTransport() has not been called.
|
||||
*/
|
||||
void
|
||||
setFaceAndTransport(Face& face, Transport& transport);
|
||||
setFaceAndTransport(Face& face, Transport& transport) noexcept;
|
||||
|
||||
/** \return Face to which this LinkService is attached
|
||||
/**
|
||||
* \brief Returns the Face to which this LinkService is attached.
|
||||
*/
|
||||
const Face*
|
||||
getFace() const;
|
||||
getFace() const noexcept
|
||||
{
|
||||
return m_face;
|
||||
}
|
||||
|
||||
/** \return Transport to which this LinkService is attached
|
||||
/**
|
||||
* \brief Returns the Transport to which this LinkService is attached.
|
||||
*/
|
||||
const Transport*
|
||||
getTransport() const;
|
||||
getTransport() const noexcept
|
||||
{
|
||||
return m_transport;
|
||||
}
|
||||
|
||||
/** \return Transport to which this LinkService is attached
|
||||
/**
|
||||
* \brief Returns the Transport to which this LinkService is attached.
|
||||
*/
|
||||
Transport*
|
||||
getTransport();
|
||||
getTransport() noexcept
|
||||
{
|
||||
return m_transport;
|
||||
}
|
||||
|
||||
virtual const Counters&
|
||||
getCounters() const;
|
||||
getCounters() const
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
virtual ssize_t
|
||||
getEffectiveMtu() const;
|
||||
|
||||
public: // upper interface to be used by forwarding
|
||||
/** \brief Send Interest to \p endpoint
|
||||
* \pre setTransport has been called
|
||||
/** \brief Send Interest.
|
||||
* \pre setFaceAndTransport() has been called.
|
||||
*/
|
||||
void
|
||||
sendInterest(const Interest& interest, const EndpointId& endpoint);
|
||||
sendInterest(const Interest& interest);
|
||||
|
||||
/** \brief Send Data to \p endpoint
|
||||
* \pre setTransport has been called
|
||||
/** \brief Send Data.
|
||||
* \pre setFaceAndTransport() has been called.
|
||||
*/
|
||||
void
|
||||
sendData(const Data& data, const EndpointId& endpoint);
|
||||
sendData(const Data& data);
|
||||
|
||||
/** \brief Send Nack to \p endpoint
|
||||
* \pre setTransport has been called
|
||||
/** \brief Send Nack.
|
||||
* \pre setFaceAndTransport() has been called.
|
||||
*/
|
||||
void
|
||||
sendNack(const ndn::lp::Nack& nack, const EndpointId& endpoint);
|
||||
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 to \p endpoint
|
||||
/** \brief Send a lower-layer packet via Transport.
|
||||
*/
|
||||
void
|
||||
sendPacket(const Block& packet, const EndpointId& endpoint);
|
||||
sendPacket(const Block& packet);
|
||||
|
||||
protected:
|
||||
void
|
||||
notifyDroppedInterest(const Interest& packet);
|
||||
|
||||
private: // upper interface to be overridden in subclass (send path entrypoint)
|
||||
/** \brief performs LinkService specific operations to send an Interest to \p endpoint
|
||||
/** \brief Performs LinkService specific operations to send an Interest.
|
||||
*/
|
||||
virtual void
|
||||
doSendInterest(const Interest& interest, const EndpointId& endpoint) = 0;
|
||||
doSendInterest(const Interest& interest) = 0;
|
||||
|
||||
/** \brief performs LinkService specific operations to send a Data to \p endpoint
|
||||
/** \brief Performs LinkService specific operations to send a Data.
|
||||
*/
|
||||
virtual void
|
||||
doSendData(const Data& data, const EndpointId& endpoint) = 0;
|
||||
doSendData(const Data& data) = 0;
|
||||
|
||||
/** \brief performs LinkService specific operations to send a Nack to \p endpoint
|
||||
/** \brief Performs LinkService specific operations to send a Nack.
|
||||
*/
|
||||
virtual void
|
||||
doSendNack(const lp::Nack& nack, const EndpointId& endpoint) = 0;
|
||||
doSendNack(const lp::Nack& nack) = 0;
|
||||
|
||||
private: // lower interface to be overridden in subclass
|
||||
virtual void
|
||||
doReceivePacket(const Block& packet, const EndpointId& endpoint) = 0;
|
||||
|
||||
private:
|
||||
Face* m_face;
|
||||
Transport* m_transport;
|
||||
Face* m_face = nullptr;
|
||||
Transport* m_transport = nullptr;
|
||||
};
|
||||
|
||||
inline const Face*
|
||||
LinkService::getFace() const
|
||||
inline ssize_t
|
||||
LinkService::getEffectiveMtu() 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;
|
||||
return m_transport->getMtu();
|
||||
}
|
||||
|
||||
inline void
|
||||
@@ -232,23 +232,22 @@ LinkService::receivePacket(const Block& packet, const EndpointId& endpoint)
|
||||
}
|
||||
|
||||
inline void
|
||||
LinkService::sendPacket(const Block& packet, const EndpointId& endpoint)
|
||||
LinkService::sendPacket(const Block& packet)
|
||||
{
|
||||
m_transport->send(packet, endpoint);
|
||||
m_transport->send(packet);
|
||||
}
|
||||
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, const FaceLogHelper<LinkService>& flh);
|
||||
|
||||
template<typename T>
|
||||
typename std::enable_if<std::is_base_of<LinkService, T>::value &&
|
||||
!std::is_same<LinkService, T>::value, std::ostream&>::type
|
||||
std::enable_if_t<std::is_base_of_v<LinkService, T> && !std::is_same_v<LinkService, T>,
|
||||
std::ostream&>
|
||||
operator<<(std::ostream& os, const FaceLogHelper<T>& flh)
|
||||
{
|
||||
return os << FaceLogHelper<LinkService>(flh.obj);
|
||||
}
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
} // namespace nfd::face
|
||||
|
||||
#endif // NFD_DAEMON_FACE_LINK_SERVICE_HPP
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2018, Regents of the University of California,
|
||||
* Copyright (c) 2014-2023, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -26,10 +26,9 @@
|
||||
#include "lp-fragmenter.hpp"
|
||||
#include "link-service.hpp"
|
||||
|
||||
#include <ndn-cxx/encoding/tlv.hpp>
|
||||
#include <ndn-cxx/lp/fields.hpp>
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
namespace nfd::face {
|
||||
|
||||
NFD_LOG_INIT(LpFragmenter);
|
||||
|
||||
@@ -39,18 +38,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.
|
||||
*/
|
||||
static const size_t MAX_SINGLE_FRAG_OVERHEAD =
|
||||
constexpr 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.
|
||||
*/
|
||||
static const size_t MAX_FRAG_OVERHEAD =
|
||||
constexpr size_t MAX_FRAG_OVERHEAD =
|
||||
1 + 9 + // LpPacket TLV-TYPE and TLV-LENGTH
|
||||
1 + 1 + 8 + // Sequence TLV
|
||||
1 + 1 + 8 + // FragIndex TLV
|
||||
@@ -86,18 +85,17 @@ 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 std::make_tuple(true, std::vector<lp::Packet>{packet});
|
||||
return {true, {packet}};
|
||||
}
|
||||
|
||||
ndn::Buffer::const_iterator netPktBegin, netPktEnd;
|
||||
std::tie(netPktBegin, netPktEnd) = packet.get<lp::FragmentField>();
|
||||
auto [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 Block& packetWire = packet.wireEncode();
|
||||
const auto& packetWire = packet.wireEncode();
|
||||
if (packetWire.type() == lp::tlv::LpPacket) {
|
||||
for (const Block& element : packetWire.elements()) {
|
||||
for (const auto& element : packetWire.elements()) {
|
||||
if (element.type() != lp::tlv::Fragment) {
|
||||
firstHeaderSize += element.size();
|
||||
}
|
||||
@@ -107,7 +105,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 std::make_tuple(false, std::vector<lp::Packet>{});
|
||||
return {false, {}};
|
||||
}
|
||||
size_t firstPayloadSize = std::min(netPktSize, mtu - firstHeaderSize - MAX_FRAG_OVERHEAD);
|
||||
size_t payloadSize = mtu - MAX_FRAG_OVERHEAD;
|
||||
@@ -117,7 +115,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 std::make_tuple(false, std::vector<lp::Packet>{});
|
||||
return {false, {}};
|
||||
}
|
||||
|
||||
// populate fragments
|
||||
@@ -139,7 +137,7 @@ LpFragmenter::fragmentPacket(const lp::Packet& packet, size_t mtu)
|
||||
}
|
||||
BOOST_ASSERT(fragIndex == fragCount);
|
||||
|
||||
return std::make_tuple(true, frags);
|
||||
return {true, frags};
|
||||
}
|
||||
|
||||
std::ostream&
|
||||
@@ -154,5 +152,4 @@ operator<<(std::ostream& os, const FaceLogHelper<LpFragmenter>& flh)
|
||||
return os;
|
||||
}
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
} // namespace nfd::face
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2022, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -30,20 +30,19 @@
|
||||
|
||||
#include <ndn-cxx/lp/packet.hpp>
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
namespace nfd::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;
|
||||
};
|
||||
@@ -51,7 +50,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);
|
||||
@@ -63,7 +62,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
|
||||
@@ -80,7 +79,6 @@ private:
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, const FaceLogHelper<LpFragmenter>& flh);
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
} // namespace nfd::face
|
||||
|
||||
#endif // NFD_DAEMON_FACE_LP_FRAGMENTER_HPP
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2023, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -24,13 +24,14 @@
|
||||
*/
|
||||
|
||||
#include "lp-reassembler.hpp"
|
||||
#include "link-service.hpp"
|
||||
#include "common/global.hpp"
|
||||
#include "link-service.hpp"
|
||||
|
||||
#include <ndn-cxx/lp/fields.hpp>
|
||||
|
||||
#include <numeric>
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
namespace nfd::face {
|
||||
|
||||
NFD_LOG_INIT(LpReassembler);
|
||||
|
||||
@@ -41,12 +42,10 @@ LpReassembler::LpReassembler(const LpReassembler::Options& options, const LinkSe
|
||||
}
|
||||
|
||||
std::tuple<bool, Block, lp::Packet>
|
||||
LpReassembler::receiveFragment(EndpointId remoteEndpoint, const lp::Packet& packet)
|
||||
LpReassembler::receiveFragment(const 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;
|
||||
@@ -59,29 +58,29 @@ LpReassembler::receiveFragment(EndpointId remoteEndpoint, const lp::Packet& pack
|
||||
|
||||
if (fragIndex >= fragCount) {
|
||||
NFD_LOG_FACE_WARN("reassembly error, FragIndex>=FragCount: DROP");
|
||||
return FALSE_RETURN;
|
||||
return {false, {}, {}};
|
||||
}
|
||||
|
||||
if (fragCount > m_options.nMaxFragments) {
|
||||
NFD_LOG_FACE_WARN("reassembly error, FragCount over limit: DROP");
|
||||
return FALSE_RETURN;
|
||||
return {false, {}, {}};
|
||||
}
|
||||
|
||||
// check for fast path
|
||||
if (fragIndex == 0 && fragCount == 1) {
|
||||
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);
|
||||
auto frag = packet.get<lp::FragmentField>();
|
||||
Block netPkt({frag.first, frag.second});
|
||||
return {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;
|
||||
return {false, {}, {}};
|
||||
}
|
||||
|
||||
lp::Sequence messageIdentifier = packet.get<lp::SequenceField>() - fragIndex;
|
||||
Key key = std::make_tuple(remoteEndpoint, messageIdentifier);
|
||||
Key key(remoteEndpoint, messageIdentifier);
|
||||
|
||||
// add to PartialPacket
|
||||
PartialPacket& pp = m_partialPackets[key];
|
||||
@@ -93,13 +92,13 @@ LpReassembler::receiveFragment(EndpointId remoteEndpoint, const lp::Packet& pack
|
||||
else {
|
||||
if (fragCount != pp.fragCount) {
|
||||
NFD_LOG_FACE_WARN("reassembly error, FragCount changed: DROP");
|
||||
return FALSE_RETURN;
|
||||
return {false, {}, {}};
|
||||
}
|
||||
}
|
||||
|
||||
if (pp.fragments[fragIndex].has<lp::SequenceField>()) {
|
||||
NFD_LOG_FACE_TRACE("fragment already received: DROP");
|
||||
return FALSE_RETURN;
|
||||
return {false, {}, {}};
|
||||
}
|
||||
|
||||
pp.fragments[fragIndex] = packet;
|
||||
@@ -110,13 +109,13 @@ LpReassembler::receiveFragment(EndpointId remoteEndpoint, const lp::Packet& pack
|
||||
Block reassembled = doReassembly(key);
|
||||
lp::Packet firstFrag(std::move(pp.fragments[0]));
|
||||
m_partialPackets.erase(key);
|
||||
return std::make_tuple(true, reassembled, firstFrag);
|
||||
return {true, reassembled, firstFrag};
|
||||
}
|
||||
|
||||
// set drop timer
|
||||
pp.dropTimer = getScheduler().schedule(m_options.reassemblyTimeout, [=] { timeoutPartialPacket(key); });
|
||||
|
||||
return FALSE_RETURN;
|
||||
return {false, {}, {}};
|
||||
}
|
||||
|
||||
Block
|
||||
@@ -126,21 +125,17 @@ 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 {
|
||||
ndn::Buffer::const_iterator fragBegin, fragEnd;
|
||||
std::tie(fragBegin, fragEnd) = pkt.get<lp::FragmentField>();
|
||||
auto [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) {
|
||||
ndn::Buffer::const_iterator fragBegin, fragEnd;
|
||||
std::tie(fragBegin, fragEnd) = frag.get<lp::FragmentField>();
|
||||
auto [fragBegin, fragEnd] = frag.get<lp::FragmentField>();
|
||||
it = std::copy(fragBegin, fragEnd, it);
|
||||
}
|
||||
|
||||
return Block(&*(fragBuffer.cbegin()), std::distance(fragBuffer.cbegin(), fragBuffer.cend()));
|
||||
return Block(fragBuffer);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -167,5 +162,4 @@ operator<<(std::ostream& os, const FaceLogHelper<LpReassembler>& flh)
|
||||
return os;
|
||||
}
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
} // namespace nfd::face
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2023, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -29,27 +29,28 @@
|
||||
#include "face-common.hpp"
|
||||
|
||||
#include <ndn-cxx/lp/packet.hpp>
|
||||
#include <ndn-cxx/lp/sequence.hpp>
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
namespace nfd::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 +58,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 +70,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,24 +80,26 @@ public:
|
||||
* \throw tlv::Error packet is malformed
|
||||
*/
|
||||
std::tuple<bool, Block, lp::Packet>
|
||||
receiveFragment(EndpointId remoteEndpoint, const lp::Packet& packet);
|
||||
receiveFragment(const EndpointId& remoteEndpoint, const lp::Packet& packet);
|
||||
|
||||
/** \brief count of partial packets
|
||||
/** \brief Count of partial packets.
|
||||
*/
|
||||
size_t
|
||||
size() const;
|
||||
|
||||
/** \brief signals before a partial packet is dropped due to timeout
|
||||
/**
|
||||
* \brief Notifies before a partial packet is dropped due to timeout.
|
||||
*
|
||||
* 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.
|
||||
* 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.
|
||||
*/
|
||||
signal::Signal<LpReassembler, EndpointId, size_t> beforeTimeout;
|
||||
|
||||
private:
|
||||
/** \brief holds all fragments of packet until reassembled
|
||||
/**
|
||||
* \brief Holds all fragments of a packet until reassembled.
|
||||
*/
|
||||
struct PartialPacket
|
||||
{
|
||||
@@ -106,12 +109,13 @@ private:
|
||||
scheduler::ScopedEventId dropTimer;
|
||||
};
|
||||
|
||||
/** \brief index key for PartialPackets
|
||||
/**
|
||||
* \brief Index key for PartialPackets.
|
||||
*/
|
||||
typedef std::tuple<
|
||||
EndpointId, // remoteEndpoint
|
||||
lp::Sequence // message identifier (sequence of the first fragment)
|
||||
> Key;
|
||||
using Key = std::tuple<
|
||||
EndpointId, // remote endpoint
|
||||
lp::Sequence // message identifier (sequence number of the first fragment)
|
||||
>;
|
||||
|
||||
Block
|
||||
doReassembly(const Key& key);
|
||||
@@ -146,7 +150,6 @@ LpReassembler::size() const
|
||||
return m_partialPackets.size();
|
||||
}
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
} // namespace nfd::face
|
||||
|
||||
#endif // NFD_DAEMON_FACE_LP_REASSEMBLER_HPP
|
||||
+102
-38
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2023, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -24,12 +24,15 @@
|
||||
*/
|
||||
|
||||
#include "lp-reliability.hpp"
|
||||
#include "common/global.hpp"
|
||||
#include "generic-link-service.hpp"
|
||||
#include "transport.hpp"
|
||||
#include "common/global.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
#include <ndn-cxx/lp/fields.hpp>
|
||||
|
||||
namespace nfd::face {
|
||||
|
||||
NFD_LOG_INIT(LpReliability);
|
||||
|
||||
LpReliability::LpReliability(const LpReliability::Options& options, GenericLinkService* linkService)
|
||||
: m_options(options)
|
||||
@@ -71,17 +74,22 @@ LpReliability::handleOutgoing(std::vector<lp::Packet>& frags, lp::Packet&& pkt,
|
||||
netPkt->unackedFrags.reserve(frags.size());
|
||||
|
||||
for (lp::Packet& frag : frags) {
|
||||
// Non-IDLE packets are required to have assigned Sequence numbers with LpReliability enabled
|
||||
BOOST_ASSERT(frag.has<lp::SequenceField>());
|
||||
|
||||
// Assign TxSequence number
|
||||
lp::Sequence txSeq = assignTxSequence(frag);
|
||||
|
||||
// Store LpPacket for future retransmissions
|
||||
unackedFragsIt = m_unackedFrags.emplace_hint(unackedFragsIt,
|
||||
std::piecewise_construct,
|
||||
std::forward_as_tuple(txSeq),
|
||||
std::forward_as_tuple(frag));
|
||||
unackedFragsIt = m_unackedFrags.try_emplace(unackedFragsIt, txSeq, frag);
|
||||
unackedFragsIt->second.sendTime = sendTime;
|
||||
unackedFragsIt->second.rtoTimer = getScheduler().schedule(m_rttEst.getEstimatedRto(),
|
||||
[=] { onLpPacketLost(txSeq); });
|
||||
auto rto = m_rttEst.getEstimatedRto();
|
||||
lp::Sequence seq = frag.get<lp::SequenceField>();
|
||||
NFD_LOG_FACE_TRACE("transmitting seq=" << seq << ", txseq=" << txSeq << ", rto=" <<
|
||||
time::duration_cast<time::milliseconds>(rto).count() << "ms");
|
||||
unackedFragsIt->second.rtoTimer = getScheduler().schedule(rto, [=] {
|
||||
onLpPacketLost(txSeq, true);
|
||||
});
|
||||
unackedFragsIt->second.netPkt = netPkt;
|
||||
|
||||
if (m_unackedFrags.size() == 1) {
|
||||
@@ -93,18 +101,20 @@ LpReliability::handleOutgoing(std::vector<lp::Packet>& frags, lp::Packet&& pkt,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
LpReliability::processIncomingPacket(const lp::Packet& pkt)
|
||||
{
|
||||
BOOST_ASSERT(m_options.isEnabled);
|
||||
|
||||
bool isDuplicate = false;
|
||||
auto now = time::steady_clock::now();
|
||||
|
||||
// Extract and parse Acks
|
||||
for (lp::Sequence ackSeq : pkt.list<lp::AckField>()) {
|
||||
auto fragIt = m_unackedFrags.find(ackSeq);
|
||||
for (lp::Sequence ackTxSeq : pkt.list<lp::AckField>()) {
|
||||
auto fragIt = m_unackedFrags.find(ackTxSeq);
|
||||
if (fragIt == m_unackedFrags.end()) {
|
||||
// Ignore an Ack for an unknown TxSequence number
|
||||
NFD_LOG_FACE_DEBUG("received ack for unknown txseq=" << ackTxSeq);
|
||||
continue;
|
||||
}
|
||||
auto& frag = fragIt->second;
|
||||
@@ -113,12 +123,19 @@ LpReliability::processIncomingPacket(const lp::Packet& pkt)
|
||||
frag.rtoTimer.cancel();
|
||||
|
||||
if (frag.retxCount == 0) {
|
||||
NFD_LOG_FACE_TRACE("received ack for seq=" << frag.pkt.get<lp::SequenceField>() << ", txseq=" <<
|
||||
ackTxSeq << ", retx=0, rtt=" <<
|
||||
time::duration_cast<time::milliseconds>(now - frag.sendTime).count() << "ms");
|
||||
// This sequence had no retransmissions, so use it to estimate the RTO
|
||||
m_rttEst.addMeasurement(now - frag.sendTime);
|
||||
}
|
||||
else {
|
||||
NFD_LOG_FACE_TRACE("received ack for seq=" << frag.pkt.get<lp::SequenceField>() << ", txseq=" <<
|
||||
ackTxSeq << ", retx=" << frag.retxCount);
|
||||
}
|
||||
|
||||
// Look for frags with TxSequence numbers < ackSeq (allowing for wraparound) and consider them
|
||||
// lost if a configurable number of Acks containing greater TxSequence numbers have been
|
||||
// Look for frags with TxSequence numbers < ackTxSeq (allowing for wraparound) and consider
|
||||
// them lost if a configurable number of Acks containing greater TxSequence numbers have been
|
||||
// received.
|
||||
auto lostLpPackets = findLostLpPackets(fragIt);
|
||||
|
||||
@@ -135,8 +152,8 @@ LpReliability::processIncomingPacket(const lp::Packet& pkt)
|
||||
// Resend or fail fragments considered lost. Potentially increment the start of the window.
|
||||
for (lp::Sequence txSeq : lostLpPackets) {
|
||||
if (removedLpPackets.find(txSeq) == removedLpPackets.end()) {
|
||||
auto removedThisTxSeq = onLpPacketLost(txSeq);
|
||||
for (auto removedTxSeq : removedThisTxSeq) {
|
||||
auto removedTxSeqs = onLpPacketLost(txSeq, false);
|
||||
for (auto removedTxSeq : removedTxSeqs) {
|
||||
removedLpPackets.insert(removedTxSeq);
|
||||
}
|
||||
}
|
||||
@@ -145,9 +162,29 @@ LpReliability::processIncomingPacket(const lp::Packet& pkt)
|
||||
|
||||
// If packet has Fragment and TxSequence fields, extract TxSequence and add to AckQueue
|
||||
if (pkt.has<lp::FragmentField>() && pkt.has<lp::TxSequenceField>()) {
|
||||
NFD_LOG_FACE_TRACE("queueing ack for remote txseq=" << pkt.get<lp::TxSequenceField>());
|
||||
m_ackQueue.push(pkt.get<lp::TxSequenceField>());
|
||||
|
||||
// Check for received frames with duplicate Sequences
|
||||
if (pkt.has<lp::SequenceField>()) {
|
||||
lp::Sequence pktSequence = pkt.get<lp::SequenceField>();
|
||||
isDuplicate = m_recentRecvSeqs.count(pktSequence) > 0;
|
||||
// Check for recent received Sequences to remove
|
||||
auto now = time::steady_clock::now();
|
||||
auto rto = m_rttEst.getEstimatedRto();
|
||||
while (!m_recentRecvSeqsQueue.empty() &&
|
||||
now > m_recentRecvSeqs[m_recentRecvSeqsQueue.front()] + rto) {
|
||||
m_recentRecvSeqs.erase(m_recentRecvSeqsQueue.front());
|
||||
m_recentRecvSeqsQueue.pop();
|
||||
}
|
||||
m_recentRecvSeqs.try_emplace(pktSequence, now);
|
||||
m_recentRecvSeqsQueue.push(pktSequence);
|
||||
}
|
||||
|
||||
startIdleAckTimer();
|
||||
}
|
||||
|
||||
return !isDuplicate;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -164,7 +201,7 @@ LpReliability::piggyback(lp::Packet& pkt, ssize_t mtu)
|
||||
remainingSpace -= pktSize;
|
||||
|
||||
while (!m_ackQueue.empty()) {
|
||||
lp::Sequence ackSeq = m_ackQueue.front();
|
||||
lp::Sequence ackTxSeq = m_ackQueue.front();
|
||||
// Ack size = Ack TLV-TYPE (3 octets) + TLV-LENGTH (1 octet) + lp::Sequence (8 octets)
|
||||
const ssize_t ackSize = tlv::sizeOfVarNumber(lp::tlv::Ack) +
|
||||
tlv::sizeOfVarNumber(sizeof(lp::Sequence)) +
|
||||
@@ -174,7 +211,9 @@ LpReliability::piggyback(lp::Packet& pkt, ssize_t mtu)
|
||||
break;
|
||||
}
|
||||
|
||||
pkt.add<lp::AckField>(ackSeq);
|
||||
NFD_LOG_FACE_TRACE("piggybacking ack for remote txseq=" << ackTxSeq);
|
||||
|
||||
pkt.add<lp::AckField>(ackTxSeq);
|
||||
m_ackQueue.pop();
|
||||
remainingSpace -= ackSize;
|
||||
}
|
||||
@@ -185,7 +224,7 @@ LpReliability::assignTxSequence(lp::Packet& frag)
|
||||
{
|
||||
lp::Sequence txSeq = ++m_lastTxSeqNo;
|
||||
frag.set<lp::TxSequenceField>(txSeq);
|
||||
if (m_unackedFrags.size() > 0 && m_lastTxSeqNo == m_firstUnackedFrag->first) {
|
||||
if (!m_unackedFrags.empty() && m_lastTxSeqNo == m_firstUnackedFrag->first) {
|
||||
NDN_THROW(std::length_error("TxSequence range exceeded"));
|
||||
}
|
||||
return m_lastTxSeqNo;
|
||||
@@ -201,7 +240,7 @@ LpReliability::startIdleAckTimer()
|
||||
|
||||
m_idleAckTimer = getScheduler().schedule(m_options.idleAckTimerPeriod, [this] {
|
||||
while (!m_ackQueue.empty()) {
|
||||
m_linkService->requestIdlePacket(0);
|
||||
m_linkService->requestIdlePacket();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -222,6 +261,8 @@ LpReliability::findLostLpPackets(LpReliability::UnackedFrags::iterator ackIt)
|
||||
|
||||
auto& unackedFrag = it->second;
|
||||
unackedFrag.nGreaterSeqAcks++;
|
||||
NFD_LOG_FACE_TRACE("received ack=" << ackIt->first << " before=" << it->first <<
|
||||
", before count=" << unackedFrag.nGreaterSeqAcks);
|
||||
|
||||
if (unackedFrag.nGreaterSeqAcks >= m_options.seqNumLossThreshold) {
|
||||
lostLpPackets.push_back(it->first);
|
||||
@@ -232,7 +273,7 @@ LpReliability::findLostLpPackets(LpReliability::UnackedFrags::iterator ackIt)
|
||||
}
|
||||
|
||||
std::vector<lp::Sequence>
|
||||
LpReliability::onLpPacketLost(lp::Sequence txSeq)
|
||||
LpReliability::onLpPacketLost(lp::Sequence txSeq, bool isTimeout)
|
||||
{
|
||||
BOOST_ASSERT(m_unackedFrags.count(txSeq) > 0);
|
||||
auto txSeqIt = m_unackedFrags.find(txSeq);
|
||||
@@ -241,9 +282,19 @@ LpReliability::onLpPacketLost(lp::Sequence txSeq)
|
||||
txFrag.rtoTimer.cancel();
|
||||
auto netPkt = txFrag.netPkt;
|
||||
std::vector<lp::Sequence> removedThisTxSeq;
|
||||
lp::Sequence seq = txFrag.pkt.get<lp::SequenceField>();
|
||||
|
||||
if (isTimeout) {
|
||||
NFD_LOG_FACE_TRACE("rto timer expired for seq=" << seq << ", txseq=" << txSeq);
|
||||
}
|
||||
else { // lost due to out-of-order TxSeqs
|
||||
NFD_LOG_FACE_TRACE("seq=" << seq << ", txseq=" << txSeq <<
|
||||
" considered lost from acks for more recent txseqs");
|
||||
}
|
||||
|
||||
// Check if maximum number of retransmissions exceeded
|
||||
if (txFrag.retxCount >= m_options.maxRetx) {
|
||||
NFD_LOG_FACE_DEBUG("seq=" << seq << " exceeded allowed retransmissions: DROP");
|
||||
// Delete all LpPackets of NetPkt from m_unackedFrags (except this one)
|
||||
for (size_t i = 0; i < netPkt->unackedFrags.size(); i++) {
|
||||
if (netPkt->unackedFrags[i] != txSeqIt) {
|
||||
@@ -257,12 +308,11 @@ LpReliability::onLpPacketLost(lp::Sequence txSeq)
|
||||
// Notify strategy of dropped Interest (if any)
|
||||
if (netPkt->isInterest) {
|
||||
BOOST_ASSERT(netPkt->pkt.has<lp::FragmentField>());
|
||||
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));
|
||||
auto frag = netPkt->pkt.get<lp::FragmentField>();
|
||||
onDroppedInterest(Interest(Block({frag.first, frag.second})));
|
||||
}
|
||||
|
||||
// Delete this LpPacket from m_unackedFrags
|
||||
removedThisTxSeq.push_back(txSeqIt->first);
|
||||
deleteUnackedFrag(txSeqIt);
|
||||
}
|
||||
@@ -272,13 +322,10 @@ LpReliability::onLpPacketLost(lp::Sequence txSeq)
|
||||
netPkt->didRetx = true;
|
||||
|
||||
// Move fragment to new TxSequence mapping
|
||||
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 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& newTxFrag = newTxFragIt->second;
|
||||
newTxFrag.retxCount = txFrag.retxCount + 1;
|
||||
newTxFrag.netPkt = netPkt;
|
||||
@@ -292,11 +339,17 @@ LpReliability::onLpPacketLost(lp::Sequence txSeq)
|
||||
deleteUnackedFrag(txSeqIt);
|
||||
|
||||
// Retransmit fragment
|
||||
m_linkService->sendLpPacket(lp::Packet(newTxFrag.pkt), 0);
|
||||
m_linkService->sendLpPacket(lp::Packet(newTxFrag.pkt));
|
||||
|
||||
auto rto = m_rttEst.getEstimatedRto();
|
||||
NFD_LOG_FACE_TRACE("retransmitting seq=" << seq << ", txseq=" << newTxSeq << ", retx=" <<
|
||||
txFrag.retxCount << ", rto=" <<
|
||||
time::duration_cast<time::milliseconds>(rto).count() << "ms");
|
||||
|
||||
// Start RTO timer for this sequence
|
||||
newTxFrag.rtoTimer = getScheduler().schedule(m_rttEst.getEstimatedRto(),
|
||||
[=] { onLpPacketLost(newTxSeq); });
|
||||
newTxFrag.rtoTimer = getScheduler().schedule(rto, [=] {
|
||||
onLpPacketLost(newTxSeq, true);
|
||||
});
|
||||
}
|
||||
|
||||
return removedThisTxSeq;
|
||||
@@ -362,5 +415,16 @@ LpReliability::NetPkt::NetPkt(lp::Packet&& pkt, bool isInterest)
|
||||
{
|
||||
}
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, const FaceLogHelper<LpReliability>& flh)
|
||||
{
|
||||
if (flh.obj.getLinkService() == nullptr) {
|
||||
os << "[id=0,local=unknown,remote=unknown] ";
|
||||
}
|
||||
else {
|
||||
os << FaceLogHelper<LinkService>(*flh.obj.getLinkService());
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
} // namespace nfd::face
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2022, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -26,7 +26,7 @@
|
||||
#ifndef NFD_DAEMON_FACE_LP_RELIABILITY_HPP
|
||||
#define NFD_DAEMON_FACE_LP_RELIABILITY_HPP
|
||||
|
||||
#include "core/common.hpp"
|
||||
#include "face-common.hpp"
|
||||
|
||||
#include <ndn-cxx/lp/packet.hpp>
|
||||
#include <ndn-cxx/lp/sequence.hpp>
|
||||
@@ -34,44 +34,49 @@
|
||||
|
||||
#include <queue>
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
namespace nfd::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);
|
||||
@@ -83,7 +88,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
|
||||
@@ -91,26 +96,26 @@ 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
|
||||
*/
|
||||
void
|
||||
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);
|
||||
|
||||
PUBLIC_WITH_TESTS_ELSE_PRIVATE:
|
||||
NFD_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
|
||||
class UnackedFrag;
|
||||
class NetPkt;
|
||||
using UnackedFrags = std::map<lp::Sequence, UnackedFrag>;
|
||||
|
||||
PUBLIC_WITH_TESTS_ELSE_PRIVATE:
|
||||
/** \brief assign TxSequence number to a fragment
|
||||
/** \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
|
||||
@@ -118,7 +123,7 @@ 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
|
||||
@@ -127,22 +132,22 @@ PUBLIC_WITH_TESTS_ELSE_PRIVATE:
|
||||
void
|
||||
startIdleAckTimer();
|
||||
|
||||
/** \brief find and mark as lost fragments where a configurable number of Acks
|
||||
* (\p m_options.seqNumLossThreshold) have been received for greater TxSequence numbers
|
||||
/** \brief Find and mark as lost fragments where a configurable number of Acks
|
||||
* (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);
|
||||
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.
|
||||
@@ -151,7 +156,7 @@ 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,
|
||||
@@ -161,8 +166,9 @@ PUBLIC_WITH_TESTS_ELSE_PRIVATE:
|
||||
void
|
||||
deleteUnackedFrag(UnackedFrags::iterator fragIt);
|
||||
|
||||
PUBLIC_WITH_TESTS_ELSE_PRIVATE:
|
||||
/** \brief contains a sent fragment that has not been acknowledged and associated data
|
||||
NFD_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
|
||||
/**
|
||||
* \brief Contains a sent fragment that has not been acknowledged and associated data.
|
||||
*/
|
||||
class UnackedFrag
|
||||
{
|
||||
@@ -173,13 +179,14 @@ PUBLIC_WITH_TESTS_ELSE_PRIVATE:
|
||||
public:
|
||||
lp::Packet pkt;
|
||||
scheduler::ScopedEventId rtoTimer;
|
||||
time::steady_clock::TimePoint sendTime;
|
||||
time::steady_clock::time_point 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
|
||||
{
|
||||
@@ -193,29 +200,25 @@ 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::queue<lp::Sequence> m_recentRecvSeqsQueue;
|
||||
lp::Sequence m_lastTxSeqNo;
|
||||
scheduler::ScopedEventId m_idleAckTimer;
|
||||
ndn::util::RttEstimator m_rttEst;
|
||||
};
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, const FaceLogHelper<LpReliability>& flh);
|
||||
|
||||
} // namespace nfd::face
|
||||
|
||||
#endif // NFD_DAEMON_FACE_LP_RELIABILITY_HPP
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2023, 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,8 +43,7 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
namespace nfd::face {
|
||||
|
||||
NFD_LOG_INIT(MulticastEthernetTransport);
|
||||
|
||||
@@ -66,20 +65,19 @@ MulticastEthernetTransport::MulticastEthernetTransport(const ndn::net::NetworkIn
|
||||
NFD_LOG_FACE_DEBUG("Creating transport");
|
||||
|
||||
char filter[110];
|
||||
// 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());
|
||||
// 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());
|
||||
m_pcap.setPacketFilter(filter);
|
||||
|
||||
BOOST_ASSERT(m_destAddress.isMulticast());
|
||||
if (!m_destAddress.isBroadcast())
|
||||
if (!m_destAddress.isBroadcast()) {
|
||||
joinMulticastGroup();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -105,8 +103,7 @@ MulticastEthernetTransport::joinMulticastGroup()
|
||||
|
||||
#if defined(__APPLE__) || defined(__FreeBSD__)
|
||||
// see bug #2327
|
||||
using boost::asio::ip::udp;
|
||||
udp::socket sock(getGlobalIoService(), udp::v4());
|
||||
boost::asio::ip::udp::socket sock(getGlobalIoService(), boost::asio::ip::udp::v4());
|
||||
int fd = sock.native_handle();
|
||||
|
||||
// Differences between Linux and the BSDs (including macOS):
|
||||
@@ -147,5 +144,4 @@ MulticastEthernetTransport::joinMulticastGroup()
|
||||
NDN_THROW(Error("Failed to join multicast group"));
|
||||
}
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
} // namespace nfd::face
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2017, Regents of the University of California,
|
||||
* Copyright (c) 2014-2023, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -28,17 +28,16 @@
|
||||
|
||||
#include "ethernet-transport.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
namespace nfd::face {
|
||||
|
||||
/**
|
||||
* @brief A multicast Transport that uses raw Ethernet II frames
|
||||
* @brief A multicast Transport that uses raw Ethernet II frames.
|
||||
*/
|
||||
class MulticastEthernetTransport final : public EthernetTransport
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Creates an Ethernet-based transport for multicast communication
|
||||
* @brief Creates an Ethernet-based transport for multicast communication.
|
||||
*/
|
||||
MulticastEthernetTransport(const ndn::net::NetworkInterface& localEndpoint,
|
||||
const ethernet::Address& mcastAddress,
|
||||
@@ -46,7 +45,7 @@ public:
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Enables receiving frames addressed to our MAC multicast group
|
||||
* @brief Enables receiving frames addressed to our MAC multicast group.
|
||||
*/
|
||||
void
|
||||
joinMulticastGroup();
|
||||
@@ -57,7 +56,6 @@ private:
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
} // namespace nfd::face
|
||||
|
||||
#endif // NFD_DAEMON_FACE_MULTICAST_ETHERNET_TRANSPORT_HPP
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2023, 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/privilege-helper.hpp"
|
||||
|
||||
#include <boost/functional/hash.hpp>
|
||||
#include <boost/asio/ip/multicast.hpp>
|
||||
#include <boost/asio/ip/v6_only.hpp>
|
||||
|
||||
#ifdef __linux__
|
||||
#include <cerrno> // for errno
|
||||
@@ -37,14 +38,15 @@
|
||||
#include <sys/socket.h> // for setsockopt()
|
||||
#endif // __linux__
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
namespace nfd::face {
|
||||
|
||||
NFD_LOG_MEMBER_INIT_SPECIALIZED((DatagramTransport<boost::asio::ip::udp, Multicast>), MulticastUdpTransport);
|
||||
namespace ip = boost::asio::ip;
|
||||
|
||||
MulticastUdpTransport::MulticastUdpTransport(const protocol::endpoint& multicastGroup,
|
||||
protocol::socket&& recvSocket,
|
||||
protocol::socket&& sendSocket,
|
||||
NFD_LOG_MEMBER_INIT_SPECIALIZED((DatagramTransport<ip::udp, Multicast>), MulticastUdpTransport);
|
||||
|
||||
MulticastUdpTransport::MulticastUdpTransport(const ip::udp::endpoint& multicastGroup,
|
||||
ip::udp::socket&& recvSocket,
|
||||
ip::udp::socket&& sendSocket,
|
||||
ndn::nfd::LinkType linkType)
|
||||
: DatagramTransport(std::move(recvSocket))
|
||||
, m_multicastGroup(multicastGroup)
|
||||
@@ -57,7 +59,7 @@ MulticastUdpTransport::MulticastUdpTransport(const protocol::endpoint& multicast
|
||||
this->setLinkType(linkType);
|
||||
this->setMtu(udp::computeMtu(m_sendSocket.local_endpoint()));
|
||||
|
||||
protocol::socket::send_buffer_size sendBufferSizeOption;
|
||||
boost::asio::socket_base::send_buffer_size sendBufferSizeOption;
|
||||
boost::system::error_code error;
|
||||
m_sendSocket.get_option(sendBufferSizeOption);
|
||||
if (error) {
|
||||
@@ -82,7 +84,7 @@ MulticastUdpTransport::getSendQueueLength()
|
||||
}
|
||||
|
||||
void
|
||||
MulticastUdpTransport::doSend(const Block& packet, const EndpointId&)
|
||||
MulticastUdpTransport::doSend(const Block& packet)
|
||||
{
|
||||
NFD_LOG_FACE_TRACE(__func__);
|
||||
|
||||
@@ -131,34 +133,26 @@ bindToDevice(int fd, const std::string& ifname)
|
||||
}
|
||||
|
||||
void
|
||||
MulticastUdpTransport::openRxSocket(protocol::socket& sock,
|
||||
const protocol::endpoint& multicastGroup,
|
||||
const boost::asio::ip::address& localAddress,
|
||||
const shared_ptr<const ndn::net::NetworkInterface>& netif)
|
||||
MulticastUdpTransport::openRxSocket(ip::udp::socket& sock,
|
||||
const ip::udp::endpoint& multicastGroup,
|
||||
const ip::address& localAddress,
|
||||
const ndn::net::NetworkInterface* netif)
|
||||
{
|
||||
BOOST_ASSERT(!sock.is_open());
|
||||
|
||||
sock.open(multicastGroup.protocol());
|
||||
sock.set_option(protocol::socket::reuse_address(true));
|
||||
sock.set_option(boost::asio::socket_base::reuse_address(true));
|
||||
|
||||
if (multicastGroup.address().is_v4()) {
|
||||
BOOST_ASSERT(localAddress.is_v4());
|
||||
sock.bind(multicastGroup);
|
||||
sock.set_option(boost::asio::ip::multicast::join_group(multicastGroup.address().to_v4(),
|
||||
localAddress.to_v4()));
|
||||
sock.set_option(ip::multicast::join_group(multicastGroup.address().to_v4(), localAddress.to_v4()));
|
||||
}
|
||||
else {
|
||||
BOOST_ASSERT(localAddress.is_v6());
|
||||
sock.set_option(boost::asio::ip::v6_only(true));
|
||||
#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()));
|
||||
BOOST_ASSERT(multicastGroup.address().to_v6().scope_id() != 0);
|
||||
sock.set_option(ip::v6_only(true));
|
||||
sock.bind(multicastGroup);
|
||||
sock.set_option(ip::multicast::join_group(multicastGroup.address().to_v6()));
|
||||
}
|
||||
|
||||
if (netif)
|
||||
@@ -166,46 +160,28 @@ MulticastUdpTransport::openRxSocket(protocol::socket& sock,
|
||||
}
|
||||
|
||||
void
|
||||
MulticastUdpTransport::openTxSocket(protocol::socket& sock,
|
||||
const protocol::endpoint& localEndpoint,
|
||||
const shared_ptr<const ndn::net::NetworkInterface>& netif,
|
||||
MulticastUdpTransport::openTxSocket(ip::udp::socket& sock,
|
||||
const ip::udp::endpoint& localEndpoint,
|
||||
const ndn::net::NetworkInterface* netif,
|
||||
bool enableLoopback)
|
||||
{
|
||||
BOOST_ASSERT(!sock.is_open());
|
||||
|
||||
sock.open(localEndpoint.protocol());
|
||||
sock.set_option(protocol::socket::reuse_address(true));
|
||||
sock.set_option(boost::asio::ip::multicast::enable_loopback(enableLoopback));
|
||||
sock.set_option(boost::asio::socket_base::reuse_address(true));
|
||||
sock.set_option(ip::multicast::enable_loopback(enableLoopback));
|
||||
|
||||
if (localEndpoint.address().is_v4()) {
|
||||
sock.bind(localEndpoint);
|
||||
if (!localEndpoint.address().is_unspecified())
|
||||
sock.set_option(boost::asio::ip::multicast::outbound_interface(localEndpoint.address().to_v4()));
|
||||
sock.set_option(ip::multicast::outbound_interface(localEndpoint.address().to_v4()));
|
||||
}
|
||||
else {
|
||||
sock.set_option(boost::asio::ip::v6_only(true));
|
||||
sock.set_option(ip::v6_only(true));
|
||||
sock.bind(localEndpoint);
|
||||
if (netif)
|
||||
sock.set_option(boost::asio::ip::multicast::outbound_interface(netif->getIndex()));
|
||||
sock.set_option(ip::multicast::outbound_interface(netif->getIndex()));
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
} // namespace nfd::face
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2023, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -28,23 +28,15 @@
|
||||
|
||||
#include "datagram-transport.hpp"
|
||||
|
||||
#include <boost/asio/ip/udp.hpp>
|
||||
#include <ndn-cxx/net/network-interface.hpp>
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
namespace nfd::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
|
||||
* \brief A Transport that communicates on a UDP multicast group.
|
||||
*/
|
||||
class MulticastUdpTransport final : public DatagramTransport<boost::asio::ip::udp, Multicast>
|
||||
{
|
||||
@@ -56,45 +48,50 @@ public:
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Creates a UDP-based transport for multicast communication
|
||||
* \brief Creates a UDP-based transport for multicast communication.
|
||||
* \param multicastGroup multicast group
|
||||
* \param recvSocket socket used to receive multicast packets
|
||||
* \param sendSocket socket used to send to the multicast group
|
||||
* \param linkType either `ndn::nfd::LINK_TYPE_MULTI_ACCESS` or `ndn::nfd::LINK_TYPE_AD_HOC`
|
||||
*/
|
||||
MulticastUdpTransport(const protocol::endpoint& multicastGroup,
|
||||
protocol::socket&& recvSocket,
|
||||
protocol::socket&& sendSocket,
|
||||
MulticastUdpTransport(const boost::asio::ip::udp::endpoint& multicastGroup,
|
||||
boost::asio::ip::udp::socket&& recvSocket,
|
||||
boost::asio::ip::udp::socket&& sendSocket,
|
||||
ndn::nfd::LinkType linkType);
|
||||
|
||||
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 shared_ptr<const ndn::net::NetworkInterface>& netif = nullptr);
|
||||
openRxSocket(boost::asio::ip::udp::socket& sock,
|
||||
const boost::asio::ip::udp::endpoint& multicastGroup,
|
||||
const boost::asio::ip::address& localAddress = {},
|
||||
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 shared_ptr<const ndn::net::NetworkInterface>& netif = nullptr,
|
||||
openTxSocket(boost::asio::ip::udp::socket& sock,
|
||||
const boost::asio::ip::udp::endpoint& localEndpoint,
|
||||
const ndn::net::NetworkInterface* netif = nullptr,
|
||||
bool enableLoopback = false);
|
||||
|
||||
private:
|
||||
void
|
||||
doSend(const Block& packet, const EndpointId& endpoint) final;
|
||||
doSend(const Block& packet) final;
|
||||
|
||||
void
|
||||
doClose() final;
|
||||
|
||||
private:
|
||||
protocol::endpoint m_multicastGroup;
|
||||
protocol::socket m_sendSocket;
|
||||
boost::asio::ip::udp::endpoint m_multicastGroup;
|
||||
boost::asio::ip::udp::socket m_sendSocket;
|
||||
};
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
} // namespace nfd::face
|
||||
|
||||
#endif // NFD_DAEMON_FACE_MULTICAST_UDP_TRANSPORT_HPP
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2022, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -27,8 +27,7 @@
|
||||
#include "face-system.hpp"
|
||||
#include "common/logger.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
namespace nfd::face {
|
||||
|
||||
NFD_LOG_INIT(NetdevBound);
|
||||
|
||||
@@ -46,9 +45,7 @@ NetdevBound::processConfig(OptionalConfigSection configSection,
|
||||
std::vector<Rule> rules;
|
||||
if (configSection) {
|
||||
int ruleIndex = 0;
|
||||
for (const auto& pair : *configSection) {
|
||||
const std::string& key = pair.first;
|
||||
const ConfigSection& value = pair.second;
|
||||
for (const auto& [key, value] : *configSection) {
|
||||
if (key == "rule") {
|
||||
rules.push_back(parseRule(ruleIndex++, value));
|
||||
}
|
||||
@@ -94,9 +91,7 @@ NetdevBound::parseRule(int index, const ConfigSection& confRule) const
|
||||
|
||||
bool hasWhitelist = false;
|
||||
bool hasBlacklist = false;
|
||||
for (const auto& pair : confRule) {
|
||||
const std::string& key = pair.first;
|
||||
const ConfigSection& value = pair.second;
|
||||
for (const auto& [key, value] : confRule) {
|
||||
if (key == "remote") {
|
||||
try {
|
||||
rule.remotes.emplace_back(value.get_value<std::string>());
|
||||
@@ -145,5 +140,4 @@ NetdevBound::parseRule(int index, const ConfigSection& confRule) const
|
||||
return rule;
|
||||
}
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
} // namespace nfd::face
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2023, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -26,14 +26,14 @@
|
||||
#ifndef NFD_DAEMON_FACE_NETDEV_BOUND_HPP
|
||||
#define NFD_DAEMON_FACE_NETDEV_BOUND_HPP
|
||||
|
||||
#include "network-predicate.hpp"
|
||||
#include "protocol-factory.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
namespace nfd::face {
|
||||
|
||||
class FaceSystem;
|
||||
|
||||
/** \brief manages netdev-bound faces
|
||||
/** \brief Manages netdev-bound faces.
|
||||
*/
|
||||
class NetdevBound : noncopyable
|
||||
{
|
||||
@@ -55,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);
|
||||
|
||||
PUBLIC_WITH_TESTS_ELSE_PRIVATE:
|
||||
NFD_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
|
||||
struct Rule
|
||||
{
|
||||
std::vector<FaceUri> remotes;
|
||||
@@ -71,7 +71,7 @@ PUBLIC_WITH_TESTS_ELSE_PRIVATE:
|
||||
Rule
|
||||
parseRule(int index, const ConfigSection& confRule) const;
|
||||
|
||||
PUBLIC_WITH_TESTS_ELSE_PRIVATE:
|
||||
NFD_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
|
||||
const FaceSystem& m_faceSystem;
|
||||
FaceCreatedCallback m_addFace;
|
||||
shared_ptr<ndn::net::NetworkMonitor> m_netmon;
|
||||
@@ -82,7 +82,6 @@ PUBLIC_WITH_TESTS_ELSE_PRIVATE:
|
||||
std::map<Key, shared_ptr<Face>> m_faces;
|
||||
};
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
} // namespace nfd::face
|
||||
|
||||
#endif // NFD_DAEMON_FACE_NETDEV_BOUND_HPP
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2023, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -29,16 +29,15 @@
|
||||
|
||||
#include <fnmatch.h>
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
namespace nfd::face {
|
||||
|
||||
NetworkPredicateBase::NetworkPredicateBase()
|
||||
{
|
||||
this->clear();
|
||||
}
|
||||
|
||||
NetworkPredicateBase::~NetworkPredicateBase() = default;
|
||||
|
||||
void
|
||||
NetworkPredicateBase::clear()
|
||||
{
|
||||
@@ -162,13 +161,6 @@ IpAddressPredicate::isRuleValid(const std::string& key, const std::string& value
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
NetworkPredicateBase::operator==(const NetworkPredicateBase& other) const
|
||||
{
|
||||
return this->m_whitelist == other.m_whitelist &&
|
||||
this->m_blacklist == other.m_blacklist;
|
||||
}
|
||||
|
||||
static bool
|
||||
doesMatchPattern(const std::string& ifname, const std::string& pattern)
|
||||
{
|
||||
@@ -198,8 +190,10 @@ 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(), bind(&doesNetifMatchRule, std::cref(netif), _1)) &&
|
||||
std::none_of(m_blacklist.begin(), m_blacklist.end(), bind(&doesNetifMatchRule, std::cref(netif), _1));
|
||||
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); });
|
||||
}
|
||||
|
||||
static bool
|
||||
@@ -219,9 +213,10 @@ 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(), bind(&doesAddressMatchRule, std::cref(address), _1)) &&
|
||||
std::none_of(m_blacklist.begin(), m_blacklist.end(), bind(&doesAddressMatchRule, std::cref(address), _1));
|
||||
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); });
|
||||
}
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
} // namespace nfd::face
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2023, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -28,21 +28,20 @@
|
||||
|
||||
#include "core/common.hpp"
|
||||
|
||||
#include <boost/operators.hpp>
|
||||
#include <boost/property_tree/ptree_fwd.hpp>
|
||||
|
||||
#include <ndn-cxx/net/network-interface.hpp>
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
namespace nfd::face {
|
||||
|
||||
class NetworkPredicateBase
|
||||
class NetworkPredicateBase : private boost::equality_comparable<NetworkPredicateBase>
|
||||
{
|
||||
public:
|
||||
NetworkPredicateBase();
|
||||
|
||||
virtual
|
||||
~NetworkPredicateBase();
|
||||
|
||||
/**
|
||||
* \brief Set the whitelist to "*" and clear the blacklist
|
||||
* \brief Set the whitelist to "*" and clear the blacklist.
|
||||
*/
|
||||
void
|
||||
clear();
|
||||
@@ -57,14 +56,24 @@ public:
|
||||
assign(std::initializer_list<std::pair<std::string, std::string>> whitelist,
|
||||
std::initializer_list<std::pair<std::string, std::string>> blacklist);
|
||||
|
||||
bool
|
||||
operator==(const NetworkPredicateBase& other) const;
|
||||
protected:
|
||||
// Explicitly declare the following four special member functions
|
||||
// to avoid -Wdeprecated-copy-with-dtor warnings from clang.
|
||||
|
||||
bool
|
||||
operator!=(const NetworkPredicateBase& other) const
|
||||
{
|
||||
return !this->operator==(other);
|
||||
}
|
||||
NetworkPredicateBase(const NetworkPredicateBase&) = delete;
|
||||
|
||||
NetworkPredicateBase(NetworkPredicateBase&&) = default;
|
||||
|
||||
NetworkPredicateBase&
|
||||
operator=(const NetworkPredicateBase&) = delete;
|
||||
|
||||
NetworkPredicateBase&
|
||||
operator=(NetworkPredicateBase&&) = default;
|
||||
|
||||
// NetworkPredicateBase is not supposed to be used polymorphically, so we make the destructor
|
||||
// protected to prevent deletion of derived objects through a pointer to the base class,
|
||||
// which would be UB when the destructor is non-virtual.
|
||||
~NetworkPredicateBase() = default;
|
||||
|
||||
private:
|
||||
virtual bool
|
||||
@@ -79,7 +88,15 @@ private:
|
||||
void
|
||||
parseList(std::set<std::string>& set, std::initializer_list<std::pair<std::string, std::string>> list);
|
||||
|
||||
PUBLIC_WITH_TESTS_ELSE_PROTECTED:
|
||||
private: // non-member operators (hidden friends)
|
||||
friend bool
|
||||
operator==(const NetworkPredicateBase& lhs, const NetworkPredicateBase& rhs)
|
||||
{
|
||||
return lhs.m_whitelist == rhs.m_whitelist &&
|
||||
lhs.m_blacklist == rhs.m_blacklist;
|
||||
}
|
||||
|
||||
NFD_PUBLIC_WITH_TESTS_ELSE_PROTECTED:
|
||||
std::set<std::string> m_whitelist;
|
||||
std::set<std::string> m_blacklist;
|
||||
};
|
||||
@@ -94,7 +111,7 @@ PUBLIC_WITH_TESTS_ELSE_PROTECTED:
|
||||
* ndn::net::NetworkInterface is accepted if it matches any entry in the whitelist and none of
|
||||
* the entries in the blacklist.
|
||||
*/
|
||||
class NetworkInterfacePredicate : public NetworkPredicateBase
|
||||
class NetworkInterfacePredicate final : public NetworkPredicateBase
|
||||
{
|
||||
public:
|
||||
bool
|
||||
@@ -116,7 +133,7 @@ private:
|
||||
* 2001:db8:2::/64`) or a wildcard (`*`) that matches all IP addresses. An IP address is
|
||||
* accepted if it matches any entry in the whitelist and none of the entries in the blacklist.
|
||||
*/
|
||||
class IpAddressPredicate : public NetworkPredicateBase
|
||||
class IpAddressPredicate final : public NetworkPredicateBase
|
||||
{
|
||||
public:
|
||||
bool
|
||||
@@ -130,7 +147,6 @@ private:
|
||||
isRuleValid(const std::string& key, const std::string& value) final;
|
||||
};
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
} // namespace nfd::face
|
||||
|
||||
#endif // NFD_DAEMON_FACE_NETWORK_PREDICATE_HPP
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2022, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -27,8 +27,7 @@
|
||||
#include "null-link-service.hpp"
|
||||
#include "null-transport.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
namespace nfd::face {
|
||||
|
||||
shared_ptr<Face>
|
||||
makeNullFace(const FaceUri& uri)
|
||||
@@ -39,5 +38,4 @@ makeNullFace(const FaceUri& uri)
|
||||
make_unique<NullTransport>(uri, uri, ndn::nfd::FACE_SCOPE_LOCAL));
|
||||
}
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
} // namespace nfd::face
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/**
|
||||
* Copyright (c) 2014-2015, Regents of the University of California,
|
||||
/*
|
||||
* Copyright (c) 2014-2022, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -28,15 +28,14 @@
|
||||
|
||||
#include "face.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
namespace nfd::face {
|
||||
|
||||
/** \return a Face that has no underlying transport and drops every packet
|
||||
/**
|
||||
* \brief Returns a Face that has no underlying transport and drops every packet.
|
||||
*/
|
||||
shared_ptr<Face>
|
||||
makeNullFace(const FaceUri& uri = FaceUri("null://"));
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
} // namespace nfd::face
|
||||
|
||||
#endif // NFD_DAEMON_FACE_NULL_FACE_HPP
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2022, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -28,8 +28,7 @@
|
||||
|
||||
#include "link-service.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
namespace nfd::face {
|
||||
|
||||
/** \brief A LinkService that drops every packet.
|
||||
*/
|
||||
@@ -37,17 +36,17 @@ class NullLinkService final : public LinkService
|
||||
{
|
||||
private:
|
||||
void
|
||||
doSendInterest(const Interest&, const EndpointId&) final
|
||||
doSendInterest(const Interest&) final
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
doSendData(const Data&, const EndpointId&) final
|
||||
doSendData(const Data&) final
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
doSendNack(const lp::Nack&, const EndpointId&) final
|
||||
doSendNack(const lp::Nack&) final
|
||||
{
|
||||
}
|
||||
|
||||
@@ -57,7 +56,6 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
} // namespace nfd::face
|
||||
|
||||
#endif // NFD_DAEMON_FACE_NULL_LINK_SERVICE_HPP
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2022, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -25,8 +25,7 @@
|
||||
|
||||
#include "null-transport.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
namespace nfd::face {
|
||||
|
||||
NFD_LOG_INIT(NullTransport);
|
||||
|
||||
@@ -43,5 +42,4 @@ NullTransport::NullTransport(const FaceUri& localUri, const FaceUri& remoteUri,
|
||||
NFD_LOG_FACE_DEBUG("Creating transport");
|
||||
}
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
} // namespace nfd::face
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2022, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -28,12 +28,11 @@
|
||||
|
||||
#include "transport.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
namespace nfd::face {
|
||||
|
||||
/** \brief A Transport that drops every packet.
|
||||
*/
|
||||
class NullTransport FINAL_UNLESS_WITH_TESTS : public Transport
|
||||
class NullTransport NFD_FINAL_UNLESS_WITH_TESTS : public Transport
|
||||
{
|
||||
public:
|
||||
explicit
|
||||
@@ -44,19 +43,18 @@ public:
|
||||
|
||||
protected:
|
||||
void
|
||||
doClose() OVERRIDE_WITH_TESTS_ELSE_FINAL
|
||||
doClose() NFD_OVERRIDE_WITH_TESTS_ELSE_FINAL
|
||||
{
|
||||
setState(TransportState::CLOSED);
|
||||
}
|
||||
|
||||
private:
|
||||
void
|
||||
doSend(const Block&, const EndpointId&) OVERRIDE_WITH_TESTS_ELSE_FINAL
|
||||
doSend(const Block&) NFD_OVERRIDE_WITH_TESTS_ELSE_FINAL
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
} // namespace nfd::face
|
||||
|
||||
#endif // NFD_DAEMON_FACE_NULL_TRANSPORT_HPP
|
||||
+22
-17
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2022, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -26,6 +26,8 @@
|
||||
#include "pcap-helper.hpp"
|
||||
#include "ethernet-protocol.hpp"
|
||||
|
||||
#include "common/privilege-helper.hpp"
|
||||
|
||||
#include <pcap/pcap.h>
|
||||
#include <unistd.h>
|
||||
|
||||
@@ -33,11 +35,9 @@
|
||||
#define PCAP_NETMASK_UNKNOWN 0xffffffff
|
||||
#endif
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
namespace nfd::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()
|
||||
PcapHelper::~PcapHelper() noexcept
|
||||
{
|
||||
close();
|
||||
}
|
||||
@@ -63,9 +63,15 @@ PcapHelper::~PcapHelper()
|
||||
void
|
||||
PcapHelper::activate(int dlt)
|
||||
{
|
||||
int ret = pcap_activate(m_pcap);
|
||||
if (ret < 0)
|
||||
NDN_THROW(Error("pcap_activate: " + std::string(pcap_statustostr(ret))));
|
||||
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)));
|
||||
|
||||
if (pcap_set_datalink(m_pcap, dlt) < 0)
|
||||
NDN_THROW(Error("pcap_set_datalink: " + getLastError()));
|
||||
@@ -75,7 +81,7 @@ PcapHelper::activate(int dlt)
|
||||
}
|
||||
|
||||
void
|
||||
PcapHelper::close()
|
||||
PcapHelper::close() noexcept
|
||||
{
|
||||
if (m_pcap) {
|
||||
pcap_close(m_pcap);
|
||||
@@ -96,7 +102,7 @@ PcapHelper::getFd() const
|
||||
}
|
||||
|
||||
std::string
|
||||
PcapHelper::getLastError() const
|
||||
PcapHelper::getLastError() const noexcept
|
||||
{
|
||||
return pcap_geterr(m_pcap);
|
||||
}
|
||||
@@ -124,20 +130,19 @@ PcapHelper::setPacketFilter(const char* filter) const
|
||||
NDN_THROW(Error("pcap_setfilter: " + getLastError()));
|
||||
}
|
||||
|
||||
std::tuple<const uint8_t*, size_t, std::string>
|
||||
PcapHelper::readNextPacket() const
|
||||
std::tuple<span<const uint8_t>, std::string>
|
||||
PcapHelper::readNextPacket() const noexcept
|
||||
{
|
||||
pcap_pkthdr* header;
|
||||
const uint8_t* packet;
|
||||
|
||||
int ret = pcap_next_ex(m_pcap, &header, &packet);
|
||||
if (ret < 0)
|
||||
return std::make_tuple(nullptr, 0, getLastError());
|
||||
return {span<uint8_t>{}, getLastError()};
|
||||
else if (ret == 0)
|
||||
return std::make_tuple(nullptr, 0, "timed out");
|
||||
return {span<uint8_t>{}, "Nothing to read"};
|
||||
else
|
||||
return std::make_tuple(packet, header->caplen, "");
|
||||
return {{packet, header->caplen}, ""};
|
||||
}
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
} // namespace nfd::face
|
||||
+18
-25
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/**
|
||||
* Copyright (c) 2014-2017, Regents of the University of California,
|
||||
/*
|
||||
* Copyright (c) 2014-2022, 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 HAVE_LIBPCAP
|
||||
#ifndef NFD_HAVE_LIBPCAP
|
||||
#error "Cannot include this file when libpcap is not available"
|
||||
#endif
|
||||
|
||||
@@ -36,8 +36,7 @@
|
||||
struct pcap;
|
||||
typedef pcap pcap_t;
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
namespace nfd::face {
|
||||
|
||||
/**
|
||||
* @brief Helper class for dealing with libpcap handles.
|
||||
@@ -48,11 +47,7 @@ public:
|
||||
class Error : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
explicit
|
||||
Error(const std::string& what)
|
||||
: std::runtime_error(what)
|
||||
{
|
||||
}
|
||||
using std::runtime_error::runtime_error;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -63,7 +58,7 @@ public:
|
||||
explicit
|
||||
PcapHelper(const std::string& interfaceName);
|
||||
|
||||
~PcapHelper();
|
||||
~PcapHelper() noexcept;
|
||||
|
||||
/**
|
||||
* @brief Start capturing packets.
|
||||
@@ -79,7 +74,7 @@ public:
|
||||
* @sa pcap_close(3pcap)
|
||||
*/
|
||||
void
|
||||
close();
|
||||
close() noexcept;
|
||||
|
||||
/**
|
||||
* @brief Obtain a file descriptor that can be used in calls such as select(2) and poll(2).
|
||||
@@ -98,7 +93,7 @@ public:
|
||||
* @sa pcap_geterr(3pcap)
|
||||
*/
|
||||
std::string
|
||||
getLastError() const;
|
||||
getLastError() const noexcept;
|
||||
|
||||
/**
|
||||
* @brief Get the number of packets dropped by the kernel, as reported by libpcap.
|
||||
@@ -120,27 +115,25 @@ public:
|
||||
|
||||
/**
|
||||
* @brief Read the next packet captured on the interface.
|
||||
* @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.
|
||||
* @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.
|
||||
* @sa pcap_next_ex(3pcap)
|
||||
*/
|
||||
std::tuple<const uint8_t*, size_t, std::string>
|
||||
readNextPacket() const;
|
||||
std::tuple<span<const uint8_t>, std::string>
|
||||
readNextPacket() const noexcept;
|
||||
|
||||
operator pcap_t*() const
|
||||
operator pcap_t*() const noexcept
|
||||
{
|
||||
return m_pcap;
|
||||
}
|
||||
|
||||
private:
|
||||
pcap_t* m_pcap;
|
||||
pcap_t* m_pcap = nullptr;
|
||||
};
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
} // namespace nfd::face
|
||||
|
||||
#endif // NFD_DAEMON_FACE_PCAP_HELPER_HPP
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2022, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -28,8 +28,7 @@
|
||||
#include <boost/range/adaptor/map.hpp>
|
||||
#include <boost/range/algorithm/copy.hpp>
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
namespace nfd::face {
|
||||
|
||||
ProtocolFactory::Registry&
|
||||
ProtocolFactory::getRegistry()
|
||||
@@ -129,5 +128,4 @@ ProtocolFactory::doGetChannels() const
|
||||
return {};
|
||||
}
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
} // namespace nfd::face
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2022, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -33,15 +33,16 @@
|
||||
#include <boost/range/adaptor/map.hpp>
|
||||
#include <boost/range/algorithm/copy.hpp>
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
namespace nfd::face {
|
||||
|
||||
/** \brief Parameters to ProtocolFactory constructor
|
||||
/**
|
||||
* \brief Parameters to ProtocolFactory constructor.
|
||||
*
|
||||
* 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.
|
||||
* 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.
|
||||
*/
|
||||
struct ProtocolFactoryCtorParams
|
||||
{
|
||||
@@ -49,44 +50,52 @@ struct ProtocolFactoryCtorParams
|
||||
shared_ptr<ndn::net::NetworkMonitor> netmon;
|
||||
};
|
||||
|
||||
/** \brief Provides support for an underlying protocol
|
||||
* \sa FaceSystem
|
||||
/**
|
||||
* \brief Provides support for an underlying protocol.
|
||||
*
|
||||
* 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.
|
||||
* 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
|
||||
*/
|
||||
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())
|
||||
{
|
||||
Registry& registry = getRegistry();
|
||||
BOOST_ASSERT(registry.count(id) == 0);
|
||||
registry[id] = [] (const CtorParams& p) { return make_unique<PF>(p); };
|
||||
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);
|
||||
}
|
||||
|
||||
/** \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.
|
||||
*/
|
||||
static std::set<std::string>
|
||||
[[nodiscard]] 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
|
||||
{
|
||||
@@ -101,18 +110,20 @@ public:
|
||||
~ProtocolFactory() = 0;
|
||||
|
||||
#ifdef DOXYGEN
|
||||
/** \brief Get id for this protocol factory
|
||||
/**
|
||||
* \brief Get the ID of 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
|
||||
getProvidedSchemes() const noexcept
|
||||
{
|
||||
return providedSchemes;
|
||||
}
|
||||
@@ -133,7 +144,7 @@ public:
|
||||
struct CreateFaceRequest
|
||||
{
|
||||
FaceUri remoteUri;
|
||||
optional<FaceUri> localUri;
|
||||
std::optional<FaceUri> localUri;
|
||||
FaceParams params;
|
||||
};
|
||||
|
||||
@@ -246,8 +257,7 @@ protected:
|
||||
shared_ptr<ndn::net::NetworkMonitor> netmon;
|
||||
};
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
} // namespace nfd::face
|
||||
|
||||
/** \brief Registers a protocol factory
|
||||
*
|
||||
|
||||
@@ -0,0 +1,505 @@
|
||||
#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;
|
||||
}
|
||||
bool hasCleanFlow = false;
|
||||
for (auto it = this->virtualQueues.begin(); it != this->virtualQueues.end();)
|
||||
{
|
||||
if (it->second->recvBits == 0 && it->second->empty())
|
||||
{
|
||||
this->totalWeight -= it->second->weight;
|
||||
this->virtualQueues.erase(it++); // here is the key
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
item.second->penaltyFactor = 0.5;
|
||||
item.second->size = 20;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (item.second->gredyTimes > 0)
|
||||
{
|
||||
item.second->gredyTimes--;
|
||||
}
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
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)
|
||||
{
|
||||
for (auto &queue : this->queues)
|
||||
{
|
||||
if (queue->getRemainBandwidthRate(queue->originAvaliableBandwidth) < 0.2)
|
||||
{
|
||||
queue->updateAvailableBandwidth(
|
||||
queue->getWeight() * remain * 1.0 / totalHightSpeedFlowWeight +
|
||||
queue->originAvaliableBandwidth);
|
||||
}
|
||||
else
|
||||
{
|
||||
queue->updateAvailableBandwidth(queue->originAvaliableBandwidth);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
auto objectRate = this->getQueueByTos(serviceClass)->getObjectRateByFlowKey(key);
|
||||
auto targetRate = data.getTargetRate();
|
||||
if (!targetRate || *targetRate > objectRate)
|
||||
{
|
||||
data.setTargetRate(objectRate);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,338 @@
|
||||
#ifndef NS_QUEUES_HPP
|
||||
#define NS_QUEUES_HPP
|
||||
#include <deque>
|
||||
#include <unordered_map>
|
||||
#include <memory>
|
||||
#include "common/global.hpp"
|
||||
#include "link-service.hpp"
|
||||
#include <ndn-cxx/lp/tags.hpp>
|
||||
#include "TokenBucket.hpp"
|
||||
#include <iostream>
|
||||
namespace nfd
|
||||
{
|
||||
namespace face
|
||||
{
|
||||
class VirtualQueue;
|
||||
struct VirtualQueueItem
|
||||
{
|
||||
int seq;
|
||||
std::shared_ptr<const Interest> item;
|
||||
EndpointId endpointId;
|
||||
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, const EndpointId &endpointId,
|
||||
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 = 5;
|
||||
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, const EndpointId &endpointId);
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
getScheduler().schedule(time::nanoseconds(1000000 * this->calObjectRateInterval),
|
||||
[this]
|
||||
{ this->calObjectRate(false); });
|
||||
}
|
||||
std::shared_ptr<VirtualQueueItem> scheduleNext();
|
||||
bool appendInterest(const Interest &interest, const EndpointId &endpointId);
|
||||
void receiveInterest(const Interest &interest);
|
||||
void calObjectRate(bool getCurrentRateOnly);
|
||||
std::shared_ptr<WDRRQueue> getQueueByTos(int tosValue);
|
||||
void assignObjectRate(const Data &data);
|
||||
|
||||
private:
|
||||
DelaySensitiveServiceSP delaySensitiveServiceSp;
|
||||
WFQQueue wfqQueue;
|
||||
int calObjectRateInterval = 100;
|
||||
uint32_t availableBandwidth;
|
||||
size_t interestBytes = 0;
|
||||
};
|
||||
}
|
||||
}
|
||||
#endif // NS_QUEUES_HPP
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2018, Regents of the University of California,
|
||||
* Copyright (c) 2014-2022, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -33,8 +33,7 @@
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
namespace nfd::face {
|
||||
|
||||
ssize_t
|
||||
getTxQueueLength(int fd)
|
||||
@@ -53,5 +52,4 @@ getTxQueueLength(int fd)
|
||||
return queueLength;
|
||||
}
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
} // namespace nfd::face
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2018, Regents of the University of California,
|
||||
* Copyright (c) 2014-2022, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -28,10 +28,9 @@
|
||||
|
||||
#include "core/common.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
namespace nfd::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
|
||||
@@ -42,7 +41,6 @@ namespace face {
|
||||
ssize_t
|
||||
getTxQueueLength(int fd);
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
} // namespace nfd::face
|
||||
|
||||
#endif // NFD_DAEMON_FACE_SOCKET_UTILS_HPP
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2023, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -32,22 +32,26 @@
|
||||
|
||||
#include <queue>
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
#include <boost/asio/defer.hpp>
|
||||
#include <boost/asio/write.hpp>
|
||||
|
||||
/** \brief Implements Transport for stream-based protocols.
|
||||
namespace nfd::face {
|
||||
|
||||
/**
|
||||
* \brief Implements a Transport for stream-based protocols.
|
||||
*
|
||||
* \tparam Protocol a stream-based protocol in Boost.Asio
|
||||
* \tparam Protocol a stream-based protocol in Boost.Asio
|
||||
*/
|
||||
template<class Protocol>
|
||||
class StreamTransport : public Transport
|
||||
{
|
||||
public:
|
||||
typedef Protocol protocol;
|
||||
using protocol = Protocol;
|
||||
|
||||
/** \brief Construct stream transport.
|
||||
/**
|
||||
* \brief Construct stream transport.
|
||||
*
|
||||
* \param socket Protocol-specific socket for the created transport
|
||||
* \param socket Protocol-specific socket for the created transport
|
||||
*/
|
||||
explicit
|
||||
StreamTransport(typename protocol::socket&& socket);
|
||||
@@ -63,7 +67,7 @@ protected:
|
||||
deferredClose();
|
||||
|
||||
void
|
||||
doSend(const Block& packet, const EndpointId& endpoint) override;
|
||||
doSend(const Block& packet) override;
|
||||
|
||||
void
|
||||
sendFromQueue();
|
||||
@@ -143,12 +147,12 @@ StreamTransport<T>::doClose()
|
||||
// Use the non-throwing variants and ignore errors, if any.
|
||||
boost::system::error_code error;
|
||||
m_socket.cancel(error);
|
||||
m_socket.shutdown(protocol::socket::shutdown_both, error);
|
||||
m_socket.shutdown(boost::asio::socket_base::shutdown_both, error);
|
||||
}
|
||||
|
||||
// Ensure that the Transport stays alive at least until
|
||||
// all pending handlers are dispatched
|
||||
getGlobalIoService().post([this] { deferredClose(); });
|
||||
boost::asio::defer(getGlobalIoService(), [this] { deferredClose(); });
|
||||
|
||||
// Some bug or feature of Boost.Asio (see https://redmine.named-data.net/issues/1856):
|
||||
//
|
||||
@@ -180,7 +184,7 @@ StreamTransport<T>::deferredClose()
|
||||
|
||||
template<class T>
|
||||
void
|
||||
StreamTransport<T>::doSend(const Block& packet, const EndpointId&)
|
||||
StreamTransport<T>::doSend(const Block& packet)
|
||||
{
|
||||
NFD_LOG_FACE_TRACE(__func__);
|
||||
|
||||
@@ -244,16 +248,17 @@ 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 (m_receiveBufferSize - offset > 0) {
|
||||
while (offset < bufferView.size()) {
|
||||
Block element;
|
||||
std::tie(isOk, element) = Block::fromBuffer(m_receiveBuffer + offset, m_receiveBufferSize - offset);
|
||||
std::tie(isOk, element) = Block::fromBuffer(bufferView.subspan(offset));
|
||||
if (!isOk)
|
||||
break;
|
||||
|
||||
offset += element.size();
|
||||
BOOST_ASSERT(offset <= m_receiveBufferSize);
|
||||
BOOST_ASSERT(offset <= bufferView.size());
|
||||
|
||||
this->receive(element);
|
||||
}
|
||||
@@ -332,7 +337,6 @@ StreamTransport<T>::getSendQueueBytes() const
|
||||
return m_sendQueueBytes;
|
||||
}
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
} // namespace nfd::face
|
||||
|
||||
#endif // NFD_DAEMON_FACE_STREAM_TRANSPORT_HPP
|
||||
+38
-35
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2023, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -29,19 +29,19 @@
|
||||
#include "tcp-transport.hpp"
|
||||
#include "common/global.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
#include <boost/asio/ip/v6_only.hpp>
|
||||
|
||||
NFD_LOG_INIT(TcpChannel);
|
||||
namespace nfd::face {
|
||||
|
||||
namespace ip = boost::asio::ip;
|
||||
|
||||
NFD_LOG_INIT(TcpChannel);
|
||||
|
||||
TcpChannel::TcpChannel(const tcp::Endpoint& localEndpoint, bool wantCongestionMarking,
|
||||
DetermineFaceScopeFromAddress determineFaceScope)
|
||||
: m_localEndpoint(localEndpoint)
|
||||
, m_acceptor(getGlobalIoService())
|
||||
, m_socket(getGlobalIoService())
|
||||
, m_wantCongestionMarking(wantCongestionMarking)
|
||||
, m_acceptor(getGlobalIoService())
|
||||
, m_determineFaceScope(std::move(determineFaceScope))
|
||||
{
|
||||
setUri(FaceUri(m_localEndpoint));
|
||||
@@ -51,7 +51,7 @@ TcpChannel::TcpChannel(const tcp::Endpoint& localEndpoint, bool wantCongestionMa
|
||||
void
|
||||
TcpChannel::listen(const FaceCreatedCallback& onFaceCreated,
|
||||
const FaceCreationFailedCallback& onAcceptFailed,
|
||||
int backlog/* = tcp::acceptor::max_connections*/)
|
||||
int backlog)
|
||||
{
|
||||
if (isListening()) {
|
||||
NFD_LOG_CHAN_WARN("Already listening");
|
||||
@@ -59,7 +59,7 @@ TcpChannel::listen(const FaceCreatedCallback& onFaceCreated,
|
||||
}
|
||||
|
||||
m_acceptor.open(m_localEndpoint.protocol());
|
||||
m_acceptor.set_option(ip::tcp::acceptor::reuse_address(true));
|
||||
m_acceptor.set_option(boost::asio::socket_base::reuse_address(true));
|
||||
if (m_localEndpoint.address().is_v6()) {
|
||||
m_acceptor.set_option(ip::v6_only(true));
|
||||
}
|
||||
@@ -98,10 +98,19 @@ TcpChannel::connect(const tcp::Endpoint& remoteEndpoint,
|
||||
void
|
||||
TcpChannel::createFace(ip::tcp::socket&& socket,
|
||||
const FaceParams& params,
|
||||
const FaceCreatedCallback& onFaceCreated)
|
||||
const FaceCreatedCallback& onFaceCreated,
|
||||
const FaceCreationFailedCallback& onFaceCreationFailed)
|
||||
{
|
||||
shared_ptr<Face> face;
|
||||
tcp::Endpoint remoteEndpoint = socket.remote_endpoint();
|
||||
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;
|
||||
}
|
||||
|
||||
auto it = m_channelFaces.find(remoteEndpoint);
|
||||
if (it == m_channelFaces.end()) {
|
||||
@@ -129,6 +138,7 @@ TcpChannel::createFace(ip::tcp::socket&& socket,
|
||||
socket.remote_endpoint().address());
|
||||
auto transport = make_unique<TcpTransport>(std::move(socket), params.persistency, faceScope);
|
||||
face = make_shared<Face>(std::move(linkService), std::move(transport));
|
||||
face->setChannel(weak_from_this());
|
||||
|
||||
m_channelFaces[remoteEndpoint] = face;
|
||||
connectFaceClosedSignal(*face, [this, remoteEndpoint] { m_channelFaces.erase(remoteEndpoint); });
|
||||
@@ -139,7 +149,7 @@ TcpChannel::createFace(ip::tcp::socket&& socket,
|
||||
NFD_LOG_CHAN_TRACE("Reusing existing face for " << remoteEndpoint);
|
||||
|
||||
boost::system::error_code error;
|
||||
socket.shutdown(ip::tcp::socket::shutdown_both, error);
|
||||
socket.shutdown(boost::asio::socket_base::shutdown_both, error);
|
||||
socket.close(error);
|
||||
}
|
||||
|
||||
@@ -152,31 +162,25 @@ void
|
||||
TcpChannel::accept(const FaceCreatedCallback& onFaceCreated,
|
||||
const FaceCreationFailedCallback& onAcceptFailed)
|
||||
{
|
||||
m_acceptor.async_accept(m_socket, [=] (const auto& e) { this->handleAccept(e, onFaceCreated, onAcceptFailed); });
|
||||
}
|
||||
|
||||
void
|
||||
TcpChannel::handleAccept(const boost::system::error_code& error,
|
||||
const FaceCreatedCallback& onFaceCreated,
|
||||
const FaceCreationFailedCallback& onAcceptFailed)
|
||||
{
|
||||
if (error) {
|
||||
if (error != boost::asio::error::operation_aborted) {
|
||||
NFD_LOG_CHAN_DEBUG("Accept failed: " << error.message());
|
||||
if (onAcceptFailed)
|
||||
onAcceptFailed(500, "Accept failed: " + error.message());
|
||||
m_acceptor.async_accept([=] (const boost::system::error_code& error, ip::tcp::socket socket) {
|
||||
if (error) {
|
||||
if (error != boost::asio::error::operation_aborted) {
|
||||
NFD_LOG_CHAN_DEBUG("Accept failed: " << error.message());
|
||||
if (onAcceptFailed)
|
||||
onAcceptFailed(500, "Accept failed: " + error.message());
|
||||
}
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
NFD_LOG_CHAN_TRACE("Incoming connection from " << m_socket.remote_endpoint());
|
||||
NFD_LOG_CHAN_TRACE("Incoming connection from " << socket.remote_endpoint());
|
||||
|
||||
FaceParams params;
|
||||
params.persistency = ndn::nfd::FACE_PERSISTENCY_ON_DEMAND;
|
||||
createFace(std::move(m_socket), params, onFaceCreated);
|
||||
FaceParams params;
|
||||
params.persistency = ndn::nfd::FACE_PERSISTENCY_ON_DEMAND;
|
||||
createFace(std::move(socket), params, onFaceCreated, onAcceptFailed);
|
||||
|
||||
// prepare accepting the next connection
|
||||
accept(onFaceCreated, onAcceptFailed);
|
||||
// prepare accepting the next connection
|
||||
accept(onFaceCreated, onAcceptFailed);
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
@@ -200,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);
|
||||
createFace(std::move(*socket), params, onFaceCreated, onConnectFailed);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -218,5 +222,4 @@ TcpChannel::handleConnectTimeout(const tcp::Endpoint& remoteEndpoint,
|
||||
onConnectFailed(504, "Connection timed out");
|
||||
}
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
} // namespace nfd::face
|
||||
+22
-29
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2023, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -28,51 +28,50 @@
|
||||
|
||||
#include "channel.hpp"
|
||||
|
||||
namespace nfd {
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
|
||||
namespace tcp {
|
||||
typedef boost::asio::ip::tcp::endpoint Endpoint;
|
||||
} // namespace tcp
|
||||
namespace nfd::tcp {
|
||||
using Endpoint = boost::asio::ip::tcp::endpoint;
|
||||
} // namespace nfd::tcp
|
||||
|
||||
namespace face {
|
||||
namespace nfd::face {
|
||||
|
||||
using DetermineFaceScopeFromAddress = std::function<ndn::nfd::FaceScope(const boost::asio::ip::address& local,
|
||||
const boost::asio::ip::address& remote)>;
|
||||
|
||||
/**
|
||||
* \brief Class implementing TCP-based channel to create faces
|
||||
* \brief Class implementing a TCP-based channel to create faces.
|
||||
*
|
||||
* Channel can create faces as a response to incoming TCP
|
||||
* connections (TcpChannel::listen needs to be called for that
|
||||
* to work) or explicitly after using TcpChannel::connect method.
|
||||
* The channel can create faces as a response to incoming TCP connections (TcpChannel::listen()
|
||||
* needs to be called for that to work) or explicitly by using TcpChannel::connect().
|
||||
*/
|
||||
class TcpChannel : public Channel
|
||||
class TcpChannel final : public Channel
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* \brief Create TCP channel for the local endpoint
|
||||
* \brief Create a TCP channel for the specified \p localEndpoint.
|
||||
*
|
||||
* To enable creation faces upon incoming connections,
|
||||
* one needs to explicitly call TcpChannel::listen method.
|
||||
* To enable the creation of faces upon incoming connections, one needs to
|
||||
* explicitly call listen().
|
||||
*/
|
||||
TcpChannel(const tcp::Endpoint& localEndpoint, bool wantCongestionMarking,
|
||||
DetermineFaceScopeFromAddress determineFaceScope);
|
||||
|
||||
bool
|
||||
isListening() const override
|
||||
isListening() const final
|
||||
{
|
||||
return m_acceptor.is_open();
|
||||
}
|
||||
|
||||
size_t
|
||||
size() const override
|
||||
size() const final
|
||||
{
|
||||
return m_channelFaces.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Enable listening on the local endpoint, accept connections,
|
||||
* and create faces when remote host makes a connection
|
||||
* and create faces when remote host makes a connection.
|
||||
* \param onFaceCreated Callback to notify successful creation of the face
|
||||
* \param onAcceptFailed Callback to notify when channel fails (accept call
|
||||
* returns an error)
|
||||
@@ -82,10 +81,10 @@ public:
|
||||
void
|
||||
listen(const FaceCreatedCallback& onFaceCreated,
|
||||
const FaceCreationFailedCallback& onAcceptFailed,
|
||||
int backlog = boost::asio::ip::tcp::acceptor::max_connections);
|
||||
int backlog = boost::asio::socket_base::max_listen_connections);
|
||||
|
||||
/**
|
||||
* \brief Create a face by establishing a TCP connection to \p remoteEndpoint
|
||||
* \brief Create a face by establishing a TCP connection to \p remoteEndpoint.
|
||||
*/
|
||||
void
|
||||
connect(const tcp::Endpoint& remoteEndpoint,
|
||||
@@ -98,17 +97,13 @@ private:
|
||||
void
|
||||
createFace(boost::asio::ip::tcp::socket&& socket,
|
||||
const FaceParams& params,
|
||||
const FaceCreatedCallback& onFaceCreated);
|
||||
const FaceCreatedCallback& onFaceCreated,
|
||||
const FaceCreationFailedCallback& onFaceCreationFailed);
|
||||
|
||||
void
|
||||
accept(const FaceCreatedCallback& onFaceCreated,
|
||||
const FaceCreationFailedCallback& onAcceptFailed);
|
||||
|
||||
void
|
||||
handleAccept(const boost::system::error_code& error,
|
||||
const FaceCreatedCallback& onFaceCreated,
|
||||
const FaceCreationFailedCallback& onAcceptFailed);
|
||||
|
||||
void
|
||||
handleConnect(const boost::system::error_code& error,
|
||||
const tcp::Endpoint& remoteEndpoint,
|
||||
@@ -125,14 +120,12 @@ private:
|
||||
|
||||
private:
|
||||
const tcp::Endpoint m_localEndpoint;
|
||||
const bool m_wantCongestionMarking;
|
||||
boost::asio::ip::tcp::acceptor m_acceptor;
|
||||
boost::asio::ip::tcp::socket m_socket;
|
||||
std::map<tcp::Endpoint, shared_ptr<Face>> m_channelFaces;
|
||||
bool m_wantCongestionMarking;
|
||||
DetermineFaceScopeFromAddress m_determineFaceScope;
|
||||
};
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
} // namespace nfd::face
|
||||
|
||||
#endif // NFD_DAEMON_FACE_TCP_CHANNEL_HPP
|
||||
+15
-14
@@ -1,6 +1,6 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2019, Regents of the University of California,
|
||||
* Copyright (c) 2014-2023, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
@@ -25,8 +25,9 @@
|
||||
|
||||
#include "tcp-factory.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
namespace nfd::face {
|
||||
|
||||
namespace ip = boost::asio::ip;
|
||||
|
||||
@@ -151,31 +152,31 @@ TcpFactory::doCreateFace(const CreateFaceRequest& req,
|
||||
const FaceCreationFailedCallback& onFailure)
|
||||
{
|
||||
if (req.localUri) {
|
||||
NFD_LOG_TRACE("Cannot create unicast TCP face with LocalUri");
|
||||
NFD_LOG_TRACE("createFace: unsupported LocalUri");
|
||||
onFailure(406, "Unicast TCP faces cannot be created with a LocalUri");
|
||||
return;
|
||||
}
|
||||
|
||||
if (req.params.persistency == ndn::nfd::FACE_PERSISTENCY_ON_DEMAND) {
|
||||
NFD_LOG_TRACE("createFace does not support FACE_PERSISTENCY_ON_DEMAND");
|
||||
NFD_LOG_TRACE("createFace: unsupported FacePersistency");
|
||||
onFailure(406, "Outgoing TCP faces do not support on-demand persistency");
|
||||
return;
|
||||
}
|
||||
|
||||
tcp::Endpoint endpoint(ip::address::from_string(req.remoteUri.getHost()),
|
||||
tcp::Endpoint endpoint(ip::make_address(req.remoteUri.getHost()),
|
||||
boost::lexical_cast<uint16_t>(req.remoteUri.getPort()));
|
||||
|
||||
// a canonical tcp4/tcp6 FaceUri cannot have a multicast address
|
||||
BOOST_ASSERT(!endpoint.address().is_multicast());
|
||||
|
||||
if (req.params.wantLocalFields && !endpoint.address().is_loopback()) {
|
||||
NFD_LOG_TRACE("createFace cannot create non-local face with local fields enabled");
|
||||
NFD_LOG_TRACE("createFace: cannot create non-local face with local fields enabled");
|
||||
onFailure(406, "Local fields can only be enabled on faces with local scope");
|
||||
return;
|
||||
}
|
||||
|
||||
if (req.params.mtu) {
|
||||
NFD_LOG_TRACE("createFace cannot create a TCP face with an overridden MTU");
|
||||
NFD_LOG_TRACE("createFace: cannot create TCP face with overridden MTU");
|
||||
onFailure(406, "TCP faces do not support MTU overrides");
|
||||
return;
|
||||
}
|
||||
@@ -200,8 +201,9 @@ TcpFactory::createChannel(const tcp::Endpoint& endpoint)
|
||||
if (it != m_channels.end())
|
||||
return it->second;
|
||||
|
||||
auto channel = make_shared<TcpChannel>(endpoint, m_wantCongestionMarking,
|
||||
bind(&TcpFactory::determineFaceScopeFromAddresses, this, _1, _2));
|
||||
auto channel = make_shared<TcpChannel>(endpoint, m_wantCongestionMarking, [this] (auto&&... args) {
|
||||
return determineFaceScopeFromAddresses(std::forward<decltype(args)>(args)...);
|
||||
});
|
||||
m_channels[endpoint] = channel;
|
||||
return channel;
|
||||
}
|
||||
@@ -213,8 +215,8 @@ TcpFactory::doGetChannels() const
|
||||
}
|
||||
|
||||
ndn::nfd::FaceScope
|
||||
TcpFactory::determineFaceScopeFromAddresses(const boost::asio::ip::address& localAddress,
|
||||
const boost::asio::ip::address& remoteAddress) const
|
||||
TcpFactory::determineFaceScopeFromAddresses(const ip::address& localAddress,
|
||||
const ip::address& remoteAddress) const
|
||||
{
|
||||
if (m_local(localAddress) && m_local(remoteAddress)) {
|
||||
return ndn::nfd::FACE_SCOPE_LOCAL;
|
||||
@@ -222,5 +224,4 @@ TcpFactory::determineFaceScopeFromAddresses(const boost::asio::ip::address& loca
|
||||
return ndn::nfd::FACE_SCOPE_NON_LOCAL;
|
||||
}
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
} // namespace nfd::face
|
||||
Loaded 100 of 570 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user