Compare commits

...
68 Commits
Author SHA1 Message Date
SunnyQjm 9bc57b880b feat: Add qsccp sched 2023-12-03 17:57:24 +08:00
Varun Patil 9b877c3a23 docker: add HOME environment variable and default config
Change-Id: I82b8d46ba74dc648786c23e68a1d1498c893108a
2023-11-18 18:20:28 -08:00
Varun Patil 23135a4cdd Add Dockerfile for nfd-status-http-server
Change-Id: I87349b2cf351c7323d8511677ce7f4a31d944387
2023-11-18 20:21:24 -05:00
Varun PatilandJunxiao Shi 6ba08cd5cb Add initial Dockerfile and CI workflow
Co-authored-by: Junxiao Shi <git@mail1.yoursunny.com>
Change-Id: Ib8341b61edef9be4e4c5f43836ff936c3c063010
2023-11-18 17:18:25 -05:00
Davide Pesavento e277f8b9e8 tools: switch to Face::getIoContext()
Change-Id: I6be4c682d62e1061af45052d2141b9e5b9e897c5
2023-11-11 17:14:02 -05:00
Davide Pesavento 9a63bf22d0 face: add missing includes
Change-Id: I2d855f71310e824205d37d892749c3eab9f5b3c3
2023-11-11 17:12:51 -05:00
Davide Pesavento ef6a528ae0 tests: randomize port used in multicast transport tests
Change-Id: I6030317ad10cf6f3c81f29c2a3898b41a1982c0e
2023-11-03 16:50:10 -04:00
Davide Pesavento 05bd6c2d69 docs: update list of supported platforms
Change-Id: I6aad1f19b593e707e0468e24b160bf3e769376d7
2023-10-31 21:45:25 -04:00
Davide Pesavento a9ec67c52b tests: expand test coverage of EthernetFactory and UdpFactory
Change-Id: I469ac8682502ca7a0e360703b462bfb119eaedf1
2023-10-23 21:00:03 -04:00
Davide Pesavento d7083a507f tests: refactor EthernetFixture
Also, use BOOST_TEST_INFO_SCOPE in a few places.

Change-Id: I113f326207825949ed9d3d22ade0654976d49b76
2023-10-19 17:51:16 -04:00
Davide Pesavento c5a9f81fce face: more robust handling of multicast face creation errors
Refs: #5030, #5297
Change-Id: I3ca985498d9d3756cbff94873063f3734bcea288
2023-10-19 02:12:05 -04:00
Davide Pesavento 0a05f7aea6 build: disable -Wnon-virtual-dtor compiler warning
It's overkill and suffers from annoying false positives that
prevent us from applying the "protected non-virtual destructor"
idiom in several perfectly valid cases. See for instance the
GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102168

The -Wdelete-non-virtual-dtor warning (included in -Wall) is
the preferred alternative and is enough to catch the unsafe
cases without false positives.

Partially reverts 847de408cb

Change-Id: I46ee1f01e7d4e2b125c2c534c6550824ba1de4c0
2023-10-16 20:50:03 -04:00
Davide Pesavento c0df94ed10 face: minor code cleanups
Change-Id: I154d2ad4dfd9e12e1fa9756f74884286b31298e4
2023-10-08 19:26:55 -04:00
awlane 9c36a65b11 face: handle PcapHelper::Error when applying multicast configuration
When the network interface state is changed, NFD reconfigures its
multicast ethernet faces. The code responsible for this is prone to
a TOCTOU race condition, e.g., if an interface is quickly brought up
and then down again. This currently raises an uncaught exception when
we try to set a packet filter for that interface.

Prevent this issue by catching PcapHelper errors in the same manner
as we catch EthernetTransport errors, and skip creating the face.

Refs: #5297
Change-Id: I9f91ac7c42dec06de34128cb34d6de8bb57e8cf5
2023-10-08 16:52:06 -04:00
Davide Pesavento 1e0c88e184 face: use async_wait operation instead of async_read with null_buffers
Change-Id: I2914e7f8fbd1b9a9e1fa8113d53700e7d6184464
2023-10-05 03:52:52 -04:00
Davide Pesavento 9bf64cc60d face: use new-style async_accept API
Change-Id: Id9de72c0922ec9ea13e5b1d9ded27dd7edf67e38
2023-10-05 02:12:02 -04:00
Davide Pesavento d91fe6d921 core+face: avoid deprecated Boost.Asio interfaces
Change-Id: I07ec286531edf63f258babe1561b4da2a88edd10
2023-10-04 21:40:02 -04:00
Davide Pesavento 5d64263dcb daemon: use asio::defer() instead of asio::post() where appropriate
Change-Id: I24d0fab6499d6430dd500ca157daa87f48960d15
2023-10-03 00:36:08 -04:00
Davide Pesavento a9e1ab2664 build: require boost >= 1.71.0
Refs: #5276
Change-Id: Ie428541639dcf1113acfb9e9d0a80f9be87d6cd3
2023-10-02 22:42:02 -04:00
Davide Pesavento 910232fce0 build: use python f-strings
Change-Id: I955739ac40508642509521760c1bc75286c94f30
2023-09-08 14:20:02 -04:00
Davide Pesavento decaf509b4 tools: modernize nfd-status-http-server and improve error handling
Change-Id: I5715c35f79d7dcd8dbefed328ebb625e9150a846
2023-08-30 22:50:03 -04:00
Davide Pesavento 8f0b8b6063 Simplify some code with Boost.Operators
Change-Id: Ic873bcbaf6be00d5c35601cfc8090df534d815ee
2023-08-29 21:04:08 -04:00
Davide Pesavento 11f1fd8340 build: update waf to version 2.0.26
Change-Id: I896871a312983ff36f1784aa53484c5edf95ebda
2023-08-19 01:50:04 -04:00
Davide Pesavento bf2e67fb14 build: enable a few more compiler warnings
Refactor default-compiler-flags.py to reduce duplication

Change-Id: I627b05257c2eec5c3ada9994bcd2b9a9be362157
2023-08-07 17:06:02 -04:00
Davide Pesavento 5b15e2fe97 build: decrease level of debug information produced by default
Refs: #5279
Change-Id: I537ff2a0a2e411279922823ae46cb7fee6586670
2023-08-07 16:35:35 -04:00
Davide Pesavento 95afc6d8a4 fw: increment nOutNacks when sending a Nack from onInterestLoop
Also expand test coverage of all forwarder counters

Change-Id: I6948af05aca1b5589e2f1c8a1f23c002d39d0ec0
2023-08-02 21:20:05 -04:00
Alex LaneandDavide Pesavento 653eb07e29 fw: refactor strategy logging and improve ASF probe logging
Bring strategy logging in line with format from 6bf94c0.
This should also marginally improve performance when log level is raised.

Refs: #5262, #5267
Co-authored-by: Davide Pesavento <davidepesa@gmail.com>
Change-Id: I6493b6476f3d0c6ae5562b66abfa46f6c6f4903d
2023-07-28 14:14:11 -04:00
Alex Lane 6bf94c02f5 fw: add Interest nonce to Forwarder logging where appropriate
Refs: #5262
Change-Id: Id3675fe1adb973d403f1e2ba386e9a4ec686c7b6
2023-06-08 02:42:02 -04:00
Davide Pesavento 191a7a24e6 core+daemon: declare all equality operators as hidden friends
Change-Id: Id832ee1fb16fb6742879c8b87f56002f94745103
2023-05-17 22:50:32 -04:00
Davide Pesavento ae43030f6f Further reduce the use of std::bind()
And also avoid deprecated ndn-cxx type aliases

Change-Id: I87e903b9671a3cf1c1b9ab30d4594d595c3c6da9
2023-05-11 01:50:11 -04:00
Davide Pesavento 63b3ae818f tools: fix compilation with latest ndn-cxx
Change-Id: Ifded624f3256452be98f288f9193dd26e464cd36
2023-03-27 14:05:04 -04:00
Davide Pesavento 4064127b97 mgmt+tools: add missing includes
Change-Id: I53aeaa6b223b616c170697662d02a028cea67400
2023-03-16 13:31:12 -04:00
Davide Pesavento d6ea0b1e0e tests: use std::nullopt
Change-Id: I7efdc8076c1bc4ced11dd3bdab7f199609009545
2023-03-13 22:54:15 -04:00
Davide Pesavento c5e3e7a55d build: drop official support for Ubuntu 18.04 and macOS 10.15
Increase the minimum required version of clang to 7.0 on linux, because
older versions fail to compile libstdc++'s implementation of std::variant

Change-Id: I6320973cbe3ff00faa8a36cd0e7ddf564c20d965
2023-03-07 21:25:27 -05:00
Davide Pesavento bf4c131f82 docs: update several URLs to point to docs.named-data.net
Change-Id: I4bab897f17e2b929675119198c9eab0309b6cc3e
2023-02-23 20:32:01 -05:00
Davide Pesavento 39c67f6291 build: switch source archive to xz compression
And a few minor README improvements

Change-Id: Iae8dc8fb3f5ac53296ffdadc8d2b893d13b8e684
2023-02-15 00:26:26 -05:00
Davide Pesavento 269b702f3d ci: adopt reusable workflows from named-data/actions
Change-Id: Iefd142d82f56a6fb83c5039565b6eba83c6e6445
2023-02-12 16:14:56 -05:00
Davide Pesavento 3bc8e19a89 Prepare release 22.12
Refs: #5250
Change-Id: I6b9a3daab498cbffb78a108207e92bc2596be378
2022-12-31 01:40:11 -05:00
Davide Pesavento 0b0156887b face: put the pcap handle in non-blocking mode
This prevents NFD from getting stuck in pcap_next_ex()
when the network interface goes down

Change-Id: I5760fcc7c950b46aecb7619bd889508ee24133aa
2022-12-12 22:01:28 -05:00
Davide Pesavento 6b78a53cf7 build: update waf to version 2.0.24
Change-Id: I57b597fb5933e46b55979ad6b1a62a7fd40c645d
2022-12-02 18:24:16 -05:00
Ikko Ashimine a68af8129e docs: fix typo in release-notes-22.02.rst
accomodate -> accommodate

Closes: https://github.com/named-data/NFD/pull/11
Change-Id: Ibad215a723cd51881760d2e43c05694a0e8928fe
2022-11-25 22:15:12 -05:00
Davide Pesavento a42efcb408 ci: add Xcode 14.1
Change-Id: I8415fb1375da16813a69fa7a03bf37a7b0efc8b7
2022-11-15 02:43:16 -05:00
Davide Pesavento aa9e3b2148 docs: fix capitalization in doxygen comments
Change-Id: Ibf5ee5119d12d60d382b0acef8dfd08277c18fcb
2022-10-29 21:45:24 -04:00
Davide Pesavento b83d3df256 mgmt: finalize migration to the new signed Interest format
Change-Id: I6d3fe1bd092fa80e185d36746a42c188ab00a60e
2022-10-13 09:45:33 -04:00
Davide Pesavento 6d6f207661 mgmt: rename extractRequester() and support signed Interest v0.3
Change-Id: I6bb6635896fa1b9fa54beb70b902c5a35831dc9c
2022-10-13 08:55:42 -04:00
Davide Pesavento 9bfdaef62d build: link with lld if available
Change-Id: Ie390c511c711508b6bb8c326a9a62fb1eca291c5
2022-10-05 17:38:44 -04:00
Davide Pesavento 20d94f67f8 Use inline on all namespace-scope constants defined in headers
Change-Id: Ic61f8d26f59fdc2895415ca47065c02d6eec28ed
2022-09-26 03:30:53 -04:00
Davide Pesavento 36184f6893 docs: restore exception handling in conf.py
Change-Id: Ie6408385e821e509e964bcea001a39f8cfdc5da0
2022-09-25 03:48:58 -04:00
Davide Pesavento 6cc9541220 docs: simplify conf.py and fix compatibility with upcoming Sphinx 6.0
Change-Id: Iacf4a72d30babc4a7c3fab0fea619a798eff2df1
2022-09-20 19:10:55 -04:00
Davide Pesavento 279af1ceac tests: fix UDP multicast transport tests with IPv6
A valid scope id is always required on the multicast address

Change-Id: Ic676fcde0ee50daf75eb38c137e3cb917f43699f
2022-08-29 20:18:32 -04:00
Teng Liang d94b7b3b24 face: reimplement EndpointId with std::variant
Refs: #5041
Change-Id: Ib8aced49a7aa14b137fb06de4a0ae8b979f07587
2022-08-24 19:38:47 -04:00
Davide Pesavento e541d1b250 build+ci: support macOS on arm64
Refs: #5135
Change-Id: I86f1955366df12cfb8b3e6f9d5e9f202778cc211
2022-08-18 20:50:05 -04:00
Davide Pesavento 4791fcb8ba ci: refresh GitHub Actions matrix
* Add ubuntu-22.04, remove 18.04
 * Add macos-12, remove 10.15

Change-Id: I775ea45661259ba1353e3f6ee0c602abee58acbd
2022-08-14 17:40:05 -04:00
Davide Pesavento 72517b5510 ci: auto-detect the OS instead of relying on NODE_LABELS
And remove WAF_JOBS: waf already defaults to the number of available
CPUs, which is appropriate in most cases, and we can always use the
built-in JOBS variable to override it where necessary.

Change-Id: I555dda0ccc48ee791271dbdaf4225cd1cfec4f3d
2022-08-13 18:50:55 -04:00
Davide Pesavento 20cafa8715 tests: minor code cleanups
Change-Id: I9759ba4b7eb467d4d1df4b379efad91bc4f5cc3a
2022-07-25 01:15:03 -04:00
Davide Pesavento 2150da8ee5 build+docs: support CentOS Stream 9, drop CentOS 8
Refs: #5181
Change-Id: I2d8bc595bad047ceaa78bd3729848491b843e83d
2022-07-08 18:18:51 -04:00
Davide Pesavento 990620ac3b nfdc: merge canonizer.hpp and find-face.hpp into face-helpers.hpp
Change-Id: I19ca5cbce8cab54e61eb7af0a32c33c3aa73faf1
2022-06-13 16:33:25 -04:00
Davide Pesavento a9b09b6994 build: make precompiled headers more useful
This can reduce the compilation time of a release
build (without tests) by more than 40%

Refs: #5212
Change-Id: I977aff0c0c7becbfee8a8b55605b81d0c014829b
2022-06-13 16:30:11 -04:00
Davide Pesavento 9a28c3f752 fw+table: workaround bogus doxygen warnings
Change-Id: I0a093658f4b27620ba9731a0640ca71c3d03360a
2022-06-11 21:52:05 -04:00
Davide Pesavento e422f9e1e9 Refactor and modernize namespace declarations
Move all unit tests to namespace nfd::tests

Delete unused header core/algorithm.hpp

Change-Id: I5591f0c5f3bb5db67f8b45fae95471f8a555ca68
2022-06-11 20:10:26 -04:00
Davide Pesavento a3a7a4e330 Use more C++17 features
Mainly structured bindings, inline variables, and class template
argument deduction, plus many more smaller things.

Change-Id: I810d17e0adb470426e4e30c898e03b3140ad052f
2022-06-04 20:26:02 -04:00
Davide Pesavento b7bfcb904a build: switch to C++17
Change-Id: Ie68020a04b7e20b74778b6d0370544ded55c5e26
2022-05-23 03:42:32 -04:00
Junxiao Shi 4b84a2c9be tests: expect certificate name in KeyLocator
Also, delete unused KeyChainFixture::makeCert function.

refs #5112

Change-Id: I59b1ca81fca0481a37126270c447f639080ec75f
2022-04-28 03:17:05 +00:00
Davide Pesavento 6153eafa62 ci: require gcovr 5.1 for code coverage reports
Stop passing `-j`, it wasn't very useful and it's broken in gcovr 5.1

Change-Id: I17ffb97c2dc9cd8db7c900fbbd4ab5f8f92184dd
2022-04-19 19:45:03 -04:00
Ashlesh Gawande 1ef93d0316 fw: add strategy parameters to configure exponential retx suppression
Supported by ASF, BestRoute, and Multicast strategies

Refs: #4924
Change-Id: I215d9212d90b93fa622cc65278703dc5198d0c9d
2022-04-08 00:27:27 -04:00
Davide Pesavento deb5427bb4 daemon+tests: avoid deprecated ndn-cxx functions
Change-Id: Idfa341629919d63fac140eda0b465f8f8abd38e6
2022-03-11 18:51:05 -05:00
Davide Pesavento 1b22a8c156 tests: drop redundant calls to Interest::setCanBePrefix(false)
Change-Id: I6afd1028ab370633c64a74ab4310396dab3c8a03
2022-03-07 21:23:23 -05:00
Davide Pesavento c52cd5eec1 build: align minimum build dependencies with ndn-cxx
* boost 1.65.1
 * gcc 7.4
 * clang 6.0
 * Xcode 10.0 (11.3 or later recommended)

Change-Id: I5e41f2a70d6c510dcb889a083a51504121b4627d
2022-03-05 20:40:54 -05:00
514 changed files with 8716 additions and 8517 deletions

No files matched your search

+8
View File
@@ -0,0 +1,8 @@
Dockerfile
/build/
.waf-*-*/
.waf3-*-*/
.lock-waf*
/VERSION.info
+10 -57
View File
@@ -3,66 +3,19 @@ on:
push:
paths-ignore:
- 'docs/**'
- '*.conf.sample*'
- '*.md'
- '.mailmap'
workflow_dispatch:
permissions:
contents: read
permissions: {}
jobs:
linux:
name: ${{ matrix.compiler }} on ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
compiler: [g++-8, g++-9, g++-10, g++-11,
clang++-7, clang++-8, clang++-9, clang++-10, clang++-11, clang++-12]
os: [ubuntu-20.04]
include:
- compiler: g++-7
os: ubuntu-18.04
- compiler: clang++-5.0
os: ubuntu-18.04
- compiler: clang++-6.0
os: ubuntu-18.04
runs-on: ${{ matrix.os }}
env:
CXX: ${{ matrix.compiler }}
NODE_LABELS: Linux Ubuntu
WAF_JOBS: 2
steps:
- name: Install C++ compiler
run: |
sudo apt-get -qy install ${CXX/clang++/clang}
${CXX} --version
- name: Checkout
uses: actions/checkout@v2
- name: Build and test
run: ./.jenkins
macos:
name: Xcode ${{ matrix.xcode }} on ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
xcode: ['11.3', '11.7', '12.4']
os: [macos-10.15]
include:
- xcode: '12.5'
os: macos-11
- xcode: '13.2'
os: macos-11
runs-on: ${{ matrix.os }}
env:
NODE_LABELS: OSX
WAF_JOBS: 3
steps:
- name: Set up Xcode
uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: ${{ matrix.xcode }}
- name: Checkout
uses: actions/checkout@v2
- name: Build and test
run: ./.jenkins
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
+81
View File
@@ -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 }}
+17 -33
View File
@@ -1,40 +1,24 @@
name: Docs
on:
push:
paths-ignore:
- '*.md'
- '.mailmap'
workflow_dispatch:
inputs:
skip-deploy:
description: 'Skip deployment?'
required: true
type: boolean
permissions:
contents: read
permissions: {}
jobs:
build:
strategy:
fail-fast: false
matrix:
os: [macos-11, ubuntu-20.04]
runs-on: ${{ matrix.os }}
env:
JOB_NAME: Docs
WAF_JOBS: 3
steps:
- name: Checkout
uses: actions/checkout@v2
with:
submodules: true
- name: Install dependencies
run: |
case ${RUNNER_OS} in
Linux) export NODE_LABELS="Linux Ubuntu" ;;
macOS) export NODE_LABELS="OSX" ;;
esac
find .jenkins.d/ -type f -name '[1-9]*.sh' -exec chmod -x '{}' +
./.jenkins
- name: Build documentation
run: |
./waf --color=yes configure
./waf --color=yes build --targets=version.hpp
./waf --color=yes build --targets=manpages
./waf --color=yes docs
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
+33 -7
View File
@@ -1,13 +1,39 @@
#!/usr/bin/env bash
set -e
source .jenkins.d/util.sh
set -eo pipefail
case $(uname) in
Linux)
if [[ -e /etc/os-release ]]; then
source /etc/os-release
else
source /usr/lib/os-release
fi
export ID VERSION_ID
export ID_LIKE="${ID} ${ID_LIKE} linux"
export PATH="${HOME}/.local/bin${PATH:+:}${PATH}"
;;
Darwin)
# Emulate a subset of os-release(5)
export ID=macos
export VERSION_ID=$(sw_vers -productVersion)
export PATH="/usr/local/bin${PATH:+:}${PATH}"
if [[ -x /opt/homebrew/bin/brew ]]; then
eval "$(/opt/homebrew/bin/brew shellenv)"
elif [[ -x /usr/local/bin/brew ]]; then
eval "$(/usr/local/bin/brew shellenv)"
fi
;;
esac
if has Linux $NODE_LABELS; then
export PATH="${HOME}/.local/bin${PATH:+:}${PATH}"
fi
export CACHE_DIR=${CACHE_DIR:-/tmp}
export WAF_JOBS=${WAF_JOBS:-1}
[[ $JOB_NAME == *"code-coverage" ]] && export DISABLE_ASAN=yes
if [[ $JOB_NAME == *"code-coverage" ]]; then
export DISABLE_ASAN=yes
export DISABLE_HEADERS_CHECK=yes
fi
# 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
+30 -42
View File
@@ -1,52 +1,40 @@
#!/usr/bin/env bash
set -ex
set -eo pipefail
if has OSX $NODE_LABELS; then
FORMULAE=(boost openssl pkg-config)
if [[ $JOB_NAME == *"Docs" ]]; then
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)
fi
PIP_PKGS+=(sphinx sphinxcontrib-doxylink)
;;
esac
set -x
if [[ $ID == macos ]]; then
if [[ -n $GITHUB_ACTIONS ]]; then
# GitHub Actions runners have a large number of pre-installed
# Homebrew packages. Don't waste time upgrading all of them.
brew list --versions "${FORMULAE[@]}" || brew update
for FORMULA in "${FORMULAE[@]}"; do
brew list --versions "$FORMULA" || brew install "$FORMULA"
done
# Ensure /usr/local/opt/openssl exists
brew reinstall openssl
else
brew update
brew upgrade
brew install "${FORMULAE[@]}"
brew cleanup
export HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1
fi
if [[ $JOB_NAME == *"Docs" ]]; then
pip3 install --upgrade --upgrade-strategy=eager sphinx sphinxcontrib-doxylink
fi
elif has Ubuntu $NODE_LABELS; then
brew update
brew install --formula "${FORMULAE[@]}"
elif [[ $ID_LIKE == *debian* ]]; then
sudo apt-get -qq update
sudo apt-get -qy install build-essential pkg-config python3-minimal \
libboost-all-dev libssl-dev libsqlite3-dev \
libpcap-dev libsystemd-dev
case $JOB_NAME in
*code-coverage)
sudo apt-get -qy install lcov python3-pip
pip3 install --user --upgrade --upgrade-strategy=eager 'gcovr~=5.0'
;;
*Docs)
sudo apt-get -qy install doxygen graphviz python3-pip
pip3 install --user --upgrade --upgrade-strategy=eager sphinx sphinxcontrib-doxylink
;;
esac
elif has CentOS-8 $NODE_LABELS; then
sudo dnf config-manager --enable powertools
sudo dnf -y install gcc-c++ libasan pkgconf-pkg-config python3 \
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 (( ${#PIP_PKGS[@]} )); then
pip3 install --user --upgrade --upgrade-strategy=eager "${PIP_PKGS[@]}"
fi
+8 -13
View File
@@ -1,11 +1,11 @@
#!/usr/bin/env bash
set -ex
set -exo pipefail
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
@@ -35,21 +35,16 @@ sudo rm -f /usr/local/lib{,64}/pkgconfig/libndn-cxx.pc
pushd ndn-cxx >/dev/null
if has CentOS-8 $NODE_LABELS; then
# https://bugzilla.redhat.com/show_bug.cgi?id=1721553
PCH="--without-pch"
fi
./waf --color=yes configure --disable-static --enable-shared --without-osx-keychain $PCH
./waf --color=yes build -j$WAF_JOBS
sudo_preserve_env PATH -- ./waf --color=yes install
./waf --color=yes configure --without-osx-keychain
./waf --color=yes build
sudo ./waf --color=yes install
popd >/dev/null
popd >/dev/null
if has CentOS-8 $NODE_LABELS; then
if [[ $ID_LIKE == *fedora* ]]; then
sudo tee /etc/ld.so.conf.d/ndn.conf >/dev/null <<< /usr/local/lib64
fi
if has Linux $NODE_LABELS; then
if [[ $ID_LIKE == *linux* ]]; then
sudo ldconfig
fi
+8 -10
View File
@@ -1,8 +1,5 @@
#!/usr/bin/env bash
set -ex
git submodule sync
git submodule update --init
set -eo pipefail
if [[ -z $DISABLE_ASAN ]]; then
ASAN="--with-sanitizer=address"
@@ -10,22 +7,23 @@ fi
if [[ $JOB_NAME == *"code-coverage" ]]; then
COVERAGE="--with-coverage"
fi
if has CentOS-8 $NODE_LABELS; then
# https://bugzilla.redhat.com/show_bug.cgi?id=1721553
if [[ -n $DISABLE_PCH ]]; then
PCH="--without-pch"
fi
set -x
if [[ $JOB_NAME != *"code-coverage" && $JOB_NAME != *"limited-build" ]]; then
# Build in release mode with tests and without precompiled headers
./waf --color=yes configure --with-tests --without-pch
./waf --color=yes build -j$WAF_JOBS
./waf --color=yes build
# Cleanup
./waf --color=yes distclean
# Build in release mode without tests, but with "other tests"
./waf --color=yes configure --with-other-tests $PCH
./waf --color=yes build -j$WAF_JOBS
./waf --color=yes build
# Cleanup
./waf --color=yes distclean
@@ -33,9 +31,9 @@ fi
# Build in debug mode with tests
./waf --color=yes configure --debug --with-tests $ASAN $COVERAGE $PCH
./waf --color=yes build -j$WAF_JOBS
./waf --color=yes build
# (tests will be run against the debug version)
# Install
sudo_preserve_env PATH -- ./waf --color=yes install
sudo ./waf --color=yes install
+10 -13
View File
@@ -1,14 +1,5 @@
#!/usr/bin/env bash
set -ex
# Prepare environment
rm -rf ~/.ndn
if has OSX $NODE_LABELS; then
security unlock-keychain -p named-data
fi
ndnsec key-gen "/tmp/jenkins/$NODE_NAME" | ndnsec cert-install -
set -eo pipefail
# https://github.com/google/sanitizers/wiki/AddressSanitizerFlags
ASAN_OPTIONS="color=always"
@@ -22,6 +13,7 @@ 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
@@ -30,6 +22,11 @@ ut_log_args() {
echo --logger=HRF,test_suite,stdout:XML,all,build/xunit-log${1:+-$1}.xml
}
set -x
# Prepare environment
rm -rf ~/.ndn
# First run all tests as unprivileged user
./build/unit-tests-core $(ut_log_args core)
./build/unit-tests-daemon $(ut_log_args daemon)
@@ -37,9 +34,9 @@ ut_log_args() {
./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)
+4 -5
View File
@@ -1,18 +1,17 @@
#!/usr/bin/env bash
set -ex
set -exo pipefail
if [[ $JOB_NAME == *"code-coverage" ]]; then
# Generate an XML report (Cobertura format) and a detailed HTML report using gcovr
# Note: trailing slashes are important in the paths below. Do not remove them!
gcovr -j$WAF_JOBS \
--object-directory build \
gcovr --object-directory build \
--exclude tests/ \
--exclude websocketpp/ \
--exclude-throw-branches \
--exclude-unreachable-branches \
--print-summary \
--cobertura build/coverage.xml \
--html-details build/gcovr/ \
--xml build/coverage.xml
--print-summary
# Generate a detailed HTML report using lcov
lcov --quiet \
+24 -16
View File
@@ -1,28 +1,36 @@
# CONTINUOUS INTEGRATION SCRIPTS
# Continuous Integration Scripts
## Environment Variables Used in Build Scripts
## Environment Variables
- `NODE_LABELS`: space-separated list of platform properties. The included values are used by
the build scripts to select the proper behavior for different operating systems and versions.
- `ID`: 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 normally contain `[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.
Example values:
Examples:
- `[OS_TYPE]`: `Linux`, `OSX`
- `[DISTRO_TYPE]`: `Ubuntu`, `CentOS`
- `[DISTRO_VERSION]`: `Ubuntu-16.04`, `Ubuntu-18.04`, `CentOS-8`, `OSX-10.14`, `OSX-10.15`
- On CentOS, `ID_LIKE="centos rhel fedora linux"`
- On Ubuntu, `ID_LIKE="ubuntu debian linux"`
- `JOB_NAME`: optional variable that defines the type of build job. Depending on the job type,
the build scripts can perform different tasks.
- `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`.
Possible values:
- `JOB_NAME`: defines the type of the current CI job. Depending on the job type, the CI
scripts can perform different tasks.
Supported values:
- empty: default build task
- `code-coverage`: debug build with tests and code coverage analysis (Ubuntu Linux is assumed)
- `code-coverage`: 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`: directory containing cached files from previous builds, e.g., a compiled
version of ndn-cxx. If not set, `/tmp` is used.
- `WAF_JOBS`: number of parallel build threads used by waf, defaults to 1.
- `DISABLE_ASAN`: disable building with AddressSanitizer. This is automatically set for
the `code-coverage` job type.
[os-release(5)]: https://www.freedesktop.org/software/systemd/man/os-release.html
-39
View File
@@ -1,39 +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}
}
export -f has
sudo_preserve_env() {
local saved_xtrace
[[ $- == *x* ]] && saved_xtrace=-x || saved_xtrace=+x
set +x
local vars=()
while [[ $# -gt 0 ]]; do
local arg=$1
shift
case ${arg} in
--) break ;;
*) vars+=("${arg}=${!arg}") ;;
esac
done
set ${saved_xtrace}
sudo env "${vars[@]}" "$@"
}
export -f sudo_preserve_env
+9 -7
View File
@@ -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>
+2 -2
View File
@@ -54,8 +54,8 @@ from waflib import Utils, Logs, Errors
from waflib.Configure import conf
from waflib.TaskGen import feature, after_method
BOOST_LIBS = ['/usr/lib', '/usr/local/lib', '/opt/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 = '''
+91 -78
View File
@@ -3,10 +3,12 @@
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 (-Og)')
def configure(conf):
conf.start_msg('Checking C++ compiler version')
@@ -16,23 +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 7.4.0.')
elif ccver < (7, 4, 0):
warnmsg = ('Using a version of gcc older than 7.4.0 is not '
'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 Utils.unversioned_sys_platform() == 'darwin' and ccver < (9, 0, 0):
errmsg = ('The version of Xcode you are using is too old.\n'
'The minimum supported Xcode version is 9.0.')
elif ccver < (4, 0, 0):
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 4.0.')
'The minimum supported clang version is 7.0.')
conf.flags = ClangFlags()
else:
warnmsg = '%s compiler is unsupported' % cxx
warnmsg = f'{cxx} compiler is unsupported'
conf.flags = CompilerFlags()
if errmsg:
@@ -44,7 +50,7 @@ def configure(conf):
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)
@@ -52,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
@@ -74,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
@@ -93,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
@@ -113,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"""
@@ -129,99 +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'] += ['-Og',
'-g3',
'-pedantic',
'-Wall',
'-Wextra',
'-Werror',
'-Wcatch-value=2',
'-Wextra-semi',
'-Wnon-virtual-dtor',
'-Wno-error=deprecated-declarations', # Bug #3795
'-Wno-error=maybe-uninitialized', # Bug #1615
'-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',
'-Wcatch-value=2',
'-Wextra-semi',
'-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',
'-Wredundant-tags',
]
if platform.machine() == 'armv7l' and self.getCompilerVersion(conf) >= (7, 1, 0):
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',
'-Wredundant-tags',
]
if platform.machine() == 'armv7l' and self.getCompilerVersion(conf) >= (7, 1, 0):
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)
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
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',
'-Wundefined-func-template',
'-Wno-unused-local-typedef', # Bugs #2657 and #3209
]
if self.getCompilerVersion(conf) < (6, 0, 0):
flags['CXXFLAGS'] += ['-Wno-missing-braces'] # Bug #4721
flags = super().getDebugFlags(conf)
flags['CXXFLAGS'] += self.__cxxFlags
return flags
def getOptimizedFlags(self, conf):
flags = super(ClangFlags, self).getOptimizedFlags(conf)
flags['CXXFLAGS'] += ['-fcolor-diagnostics',
'-Wundefined-func-template',
'-Wno-unused-local-typedef', # Bugs #2657 and #3209
]
if self.getCompilerVersion(conf) < (6, 0, 0):
flags['CXXFLAGS'] += ['-Wno-missing-braces'] # Bug #4721
flags = super().getOptimizedFlags(conf)
flags['CXXFLAGS'] += self.__cxxFlags
return flags
+6 -5
View File
@@ -1,12 +1,12 @@
# NFD Authors
The following lists maintainers, primary developers, and all much-appreciated contributors to NFD in alphabetic order.
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/master/CONTRIBUTING.md.
If you would like to become a contributor to the official repository, please follow the recommendations in <https://github.com/named-data/.github/blob/main/CONTRIBUTING.md>.
* Jerald Paul Abraham <https://cs.arizona.edu/~jeraldabraham>
* ***(Maintainer)*** Alexander Afanasyev <https://users.cs.fiu.edu/~afanasyev>
* Syed Obai Amin <http://obaidamin.weebly.com>
* 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>
@@ -19,6 +19,7 @@ If you would like to become a contributor to the official repository, please fol
* 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>
@@ -31,7 +32,7 @@ If you would like to become a contributor to the official repository, please fol
* Eric Newberry <https://ericnewberry.com>
* Ju Pan <https://cs-jupan.com>
* João Pereira <http://website.jpereira.co.uk>
* Davide Pesavento <https://github.com/Pesa>
* ***(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>
@@ -55,7 +56,7 @@ If you would like to become a contributor to the official repository, please fol
* Patrick Crowley <https://www.arl.wustl.edu/~pcrowley>
* Christos Papadopoulos <https://www.cs.colostate.edu/~christos>
* Giovanni Pau <http://www.cs.ucla.edu/~gpau/Giovanni_Paus_Home_Page/Home.html>
* 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>
+1 -1
View File
@@ -3,7 +3,7 @@ message: If you use NFD in your research, please cite it as below.
license: GPL-3.0-or-later
repository-code: "https://github.com/named-data/NFD"
title: Named Data Networking Forwarding Daemon
url: "https://named-data.net/doc/NFD/"
url: "https://docs.named-data.net/NFD/"
preferred-citation:
authors:
- name: Named Data Networking Project Team
+4 -5
View File
@@ -9,10 +9,10 @@ NFD relies on third-party software, licensed under the following licenses:
- The Boost libraries are licensed under the
[Boost Software License 1.0](https://www.boost.org/users/license.html)
- CityHash is licensed under 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
View File
@@ -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"]
+7 -9
View File
@@ -1,7 +1,7 @@
# Notes for NFD developers
If you are new to the NDN software community, please read the
[Contributor's Guide](https://github.com/named-data/.github/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,7 +59,7 @@ 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
The [Boost.Test framework](https://www.boost.org/doc/libs/1_65_1/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:
@@ -94,4 +92,4 @@ or `-p` to show a progress bar:
There are many more command line options available, information about which can be obtained
either from the command line using the `--help` switch, or online on the
[Boost.Test website](https://www.boost.org/doc/libs/1_65_1/libs/test/doc/html/index.html).
[Boost.Test website](https://www.boost.org/doc/libs/1_71_0/libs/test/doc/html/boost_test/runtime_config.html).
+20 -15
View File
@@ -1,14 +1,20 @@
# NFD - Named Data Networking Forwarding Daemon
<div align="center">
[<img alt height="65" src="docs/named_data_theme/static/ndn-logo.svg"/>](https://named-data.net/)
# NFD: Named Data Networking Forwarding Daemon
</div>
[![CI](https://github.com/named-data/NFD/actions/workflows/ci.yml/badge.svg)](https://github.com/named-data/NFD/actions/workflows/ci.yml)
[![Docs](https://github.com/named-data/NFD/actions/workflows/docs.yml/badge.svg)](https://github.com/named-data/NFD/actions/workflows/docs.yml)
![Language](https://img.shields.io/badge/C%2B%2B-14-blue)
![Language](https://img.shields.io/badge/C%2B%2B-17-blue)
![Latest version](https://img.shields.io/github/v/tag/named-data/NFD?label=Latest%20version)
## 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/).
@@ -28,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
@@ -44,13 +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](https://github.com/named-data/.github/blob/master/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 a free and open-source software package licensed under the GPL version 3 and
is the centerpiece of our committement to making NDN's core technology free and open
to all Internet users and developers. For more information about licensing, refer to
[`COPYING.md`](COPYING.md).
NFD is free software distributed under the GNU General Public License version 3.
See [`COPYING.md`](COPYING.md) for details.
-1
View File
@@ -1 +0,0 @@
docs/release-notes-latest.rst
-58
View File
@@ -1,58 +0,0 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2014-2015, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
* Washington University in St. Louis,
* Beijing Institute of Technology,
* The University of Memphis.
*
* This file is part of NFD (Named Data Networking Forwarding Daemon).
* See AUTHORS.md for complete list of NFD authors and contributors.
*
* NFD is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Foundation,
* either version 3 of the License, or (at your option) any later version.
*
* NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef NFD_CORE_ALGORITHM_HPP
#define NFD_CORE_ALGORITHM_HPP
#include "common.hpp"
#include <boost/concept/requires.hpp>
namespace nfd {
/** \brief finds the last element satisfying a predicate
* \tparam It BidirectionalIterator
* \tparam Pred UnaryPredicate
*
* \return Iterator to the last element satisfying the condition,
* or \p last if no such element is found.
*
* Complexity: at most \p last-first invocations of \p p
*/
template<typename It, typename Pred>
BOOST_CONCEPT_REQUIRES(
((boost::BidirectionalIterator<It>))
((boost::UnaryPredicate<Pred, typename std::iterator_traits<It>::value_type>)),
(It)
)
find_last_if(It first, It last, Pred p)
{
std::reverse_iterator<It> firstR(first), lastR(last);
auto found = std::find_if(lastR, firstR, p);
return found == firstR ? last : std::prev(found.base());
}
} // namespace nfd
#endif // NFD_CORE_ALGORITHM_HPP
+10 -15
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, Regents of the University of California,
* Copyright (c) 2014-2023, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -50,11 +50,11 @@
#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>
@@ -66,24 +66,18 @@
#include <ndn-cxx/net/face-uri.hpp>
#include <ndn-cxx/util/backports.hpp>
#include <ndn-cxx/util/exception.hpp>
#include <ndn-cxx/util/optional.hpp>
#include <ndn-cxx/util/scheduler.hpp>
#include <ndn-cxx/util/signal.hpp>
#include <ndn-cxx/util/span.hpp>
#include <ndn-cxx/util/time.hpp>
#include <boost/asio.hpp>
#include <boost/assert.hpp>
#include <boost/core/noncopyable.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/property_tree/ptree.hpp>
namespace nfd {
using std::size_t;
using boost::noncopyable;
using std::shared_ptr;
using std::unique_ptr;
using std::weak_ptr;
@@ -94,13 +88,13 @@ using std::static_pointer_cast;
using std::dynamic_pointer_cast;
using std::const_pointer_cast;
using std::to_string;
using namespace std::string_literals;
using namespace std::string_view_literals;
using boost::noncopyable;
using ndn::optional;
using ndn::nullopt;
using ndn::span;
using ndn::to_string;
using ndn::Block;
using ndn::Data;
using ndn::FaceUri;
@@ -118,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
View File
@@ -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
View File
@@ -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&
+3 -2
View File
@@ -26,8 +26,9 @@
#ifndef NFD_CORE_VERSION_HPP
#define NFD_CORE_VERSION_HPP
// NFD version follows Semantic Versioning 2.0.0 based on year and month of the release
// 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 the VERSION variable in the top-level wscript.
+4 -4
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2019, Regents of the University of California,
* Copyright (c) 2014-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
+19 -14
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2021, Regents of the University of California,
* Copyright (c) 2014-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,12 +110,12 @@ 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>();
auto value = node.get_value_optional<T>();
// Unsigned logic is workaround for https://redmine.named-data.net/issues/4489
if (value &&
(std::is_signed<T>() || node.get_value<std::string>().find("-") == std::string::npos)) {
(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>() +
@@ -125,14 +130,14 @@ public: // parse helpers
}
/**
* \brief check that a value is within the inclusive range [min, max]
* \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<T>::value, "T must be an integral type");
static_assert(std::is_integral_v<T>);
if (value < min || value > max) {
NDN_THROW(Error("Invalid value '" + to_string(value) + "' for option '" + key +
@@ -142,7 +147,7 @@ public: // parse helpers
}
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
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2019, Regents of the University of California,
* Copyright (c) 2014-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
+19 -31
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2021, Regents of the University of California,
* Copyright (c) 2014-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&
@@ -55,46 +55,34 @@ 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
+15 -20
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2021 Regents of the University of California,
* Copyright (c) 2014-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);
/** \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);
setRibIoService(boost::asio::io_context* ribIo);
#ifdef NFD_WITH_TESTS
/** \brief Destroy the global io_service instance.
/**
* \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();
+7 -5
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2021, Regents of the University of California,
* Copyright (c) 2014-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 {
std::forward<F>(f)();
std::invoke(std::forward<F>(f));
}
catch (...) {
drop();
+42
View File
@@ -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;
}
}
}
}
+34
View File
@@ -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
+5 -7
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2021, Regents of the University of California,
* Copyright (c) 2014-2022, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -26,19 +26,18 @@
#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)
Channel::setDefaultMtu(size_t mtu) noexcept
{
m_defaultMtu = mtu;
}
@@ -53,5 +52,4 @@ connectFaceClosedSignal(Face& face, std::function<void()> f)
});
}
} // namespace face
} // namespace nfd
} // namespace nfd::face
+13 -12
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2021, Regents of the University of California,
* Copyright (c) 2014-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
@@ -45,35 +44,38 @@ public:
~Channel();
const FaceUri&
getUri() const
getUri() const noexcept
{
return m_uri;
}
/** \brief Returns the default MTU for all faces created by this channel
/**
* \brief Returns the default MTU for all faces created by this channel.
*/
size_t
getDefaultMtu() const
getDefaultMtu() const noexcept
{
return m_defaultMtu;
}
/** \brief Returns whether the channel is listening
/**
* \brief Returns whether the channel is listening.
*/
virtual bool
isListening() const = 0;
/** \brief Returns the number of faces in the channel
/**
* \brief Returns the number of faces in the channel.
*/
virtual size_t
size() const = 0;
protected:
void
setUri(const FaceUri& uri);
setUri(const FaceUri& uri) noexcept;
void
setDefaultMtu(size_t mtu);
setDefaultMtu(size_t mtu) noexcept;
private:
FaceUri m_uri;
@@ -99,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
+20 -25
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, Regents of the University of California,
* Copyright (c) 2014-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:
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);
@@ -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,7 +152,7 @@ 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);
});
}
@@ -178,9 +180,7 @@ DatagramTransport<T, U>::receiveDatagram(span<const uint8_t> buffer,
NFD_LOG_FACE_TRACE("Received: " << buffer.size() << " bytes from " << m_sender);
bool isOk = false;
Block element;
std::tie(isOk, element) = Block::fromBuffer(buffer);
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
@@ -193,7 +193,10 @@ DatagramTransport<T, U>::receiveDatagram(span<const uint8_t> buffer,
}
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>
@@ -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
+12 -17
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, Regents of the University of California,
* Copyright (c) 2014-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,19 +120,15 @@ EthernetChannel::handleRead(const boost::system::error_code& error,
return;
}
span<const uint8_t> pkt;
std::string err;
std::tie(pkt, err) = m_pcap.readNextPacket();
auto [pkt, readErr] = m_pcap.readNextPacket();
if (pkt.empty()) {
NFD_LOG_CHAN_WARN("Read error: " << err);
NFD_LOG_CHAN_WARN("Read error: " << readErr);
}
else {
const ether_header* eh;
std::tie(eh, err) = ethernet::checkFrameHeader(pkt, 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);
@@ -207,7 +203,7 @@ EthernetChannel::createFace(const ethernet::Address& remoteEndpoint,
auto transport = make_unique<UnicastEthernetTransport>(*m_localEndpoint, remoteEndpoint,
params.persistency, m_idleFaceTimeout);
auto face = make_shared<Face>(std::move(linkService), std::move(transport));
face->setChannel(shared_from_this()); // use weak_from_this() in C++17
face->setChannel(weak_from_this());
m_channelFaces[remoteEndpoint] = face;
connectFaceClosedSignal(*face, [this, remoteEndpoint] {
@@ -238,5 +234,4 @@ EthernetChannel::updateFilter()
m_pcap.setPacketFilter(filter.data());
}
} // namespace face
} // namespace nfd
} // namespace nfd::face
+12 -17
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, Regents of the University of California,
* Copyright (c) 2014-2023, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -30,35 +30,31 @@
#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 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);
@@ -76,7 +72,7 @@ public:
}
/**
* \brief Create a unicast Ethernet face toward \p remoteEndpoint
* \brief Create a unicast Ethernet face toward \p remoteEndpoint.
*/
void
connect(const ethernet::Address& remoteEndpoint,
@@ -85,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.
@@ -137,7 +133,6 @@ private:
#endif
};
} // namespace face
} // namespace nfd
} // namespace nfd::face
#endif // NFD_DAEMON_FACE_ETHERNET_CHANNEL_HPP
+36 -35
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2020, 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,14 +184,14 @@ 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;
}
@@ -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;
@@ -258,7 +257,9 @@ EthernetFactory::createMulticastFace(const ndn::net::NetworkInterface& netif,
connectFaceClosedSignal(*face, [this, key] { m_mcastFaces.erase(key); });
auto channelIt = m_channels.find(netif.getName());
face->setChannel(channelIt != m_channels.end() ? channelIt->second : nullptr);
if (channelIt != m_channels.end()) {
face->setChannel(channelIt->second);
}
return face;
}
@@ -270,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;
}
@@ -304,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;
}
@@ -324,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;
@@ -332,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;
}
@@ -362,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);
@@ -377,5 +379,4 @@ EthernetFactory::applyConfig(const FaceSystem::ConfigContext&)
}
}
} // namespace face
} // namespace nfd
} // namespace nfd::face
+19 -18
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2021, Regents of the University of California,
* Copyright (c) 2014-2023, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -28,11 +28,12 @@
#include "protocol-factory.hpp"
#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 final : public ProtocolFactory
{
@@ -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,15 +67,13 @@ 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) final;
@@ -87,14 +86,16 @@ private:
std::vector<shared_ptr<const Channel>>
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
+2 -4
View File
@@ -27,8 +27,7 @@
#include <boost/endian/conversion.hpp>
namespace nfd {
namespace ethernet {
namespace nfd::ethernet {
std::tuple<const ether_header*, std::string>
checkFrameHeader(span<const uint8_t> packet, const Address& localAddr, const Address& destAddr)
@@ -57,5 +56,4 @@ checkFrameHeader(span<const uint8_t> packet, const Address& localAddr, const Add
return {eh, ""};
}
} // namespace ethernet
} // namespace nfd
} // namespace nfd::ethernet
+2 -4
View File
@@ -31,15 +31,13 @@
#include <ndn-cxx/net/ethernet.hpp>
#include <net/ethernet.h>
namespace nfd {
namespace ethernet {
namespace nfd::ethernet {
using namespace ndn::ethernet;
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
+14 -29
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, Regents of the University of California,
* Copyright (c) 2014-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);
@@ -90,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);
});
}
@@ -149,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
@@ -168,19 +166,15 @@ EthernetTransport::handleRead(const boost::system::error_code& error)
return;
}
span<const uint8_t> pkt;
std::string err;
std::tie(pkt, err) = m_pcap.readNextPacket();
auto [pkt, readErr] = m_pcap.readNextPacket();
if (pkt.empty()) {
NFD_LOG_FACE_WARN("Read error: " << err);
NFD_LOG_FACE_DEBUG("Read error: " << readErr);
}
else {
const ether_header* eh;
std::tie(eh, err) = ethernet::checkFrameHeader(pkt, 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);
@@ -204,9 +198,7 @@ EthernetTransport::receivePayload(span<const uint8_t> payload, const ethernet::A
{
NFD_LOG_FACE_TRACE("Received: " << payload.size() << " bytes from " << sender);
bool isOk = false;
Block element;
std::tie(isOk, element) = Block::fromBuffer(payload);
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
@@ -214,13 +206,7 @@ EthernetTransport::receivePayload(span<const uint8_t> payload, const ethernet::A
}
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
@@ -236,5 +222,4 @@ EthernetTransport::handleError(const std::string& errorMessage)
doClose();
}
} // namespace face
} // namespace nfd
} // namespace nfd::face
+7 -8
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, Regents of the University of California,
* Copyright (c) 2014-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,7 +48,7 @@ public:
};
/**
* @brief Processes the payload of an incoming frame
* @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
*/
@@ -82,7 +82,7 @@ private:
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);
@@ -113,7 +113,6 @@ private:
#endif
};
} // namespace face
} // namespace nfd
} // namespace nfd::face
#endif // NFD_DAEMON_FACE_ETHERNET_TRANSPORT_HPP
+32 -28
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2020, 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,36 +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 Minimum MTU that may be set
/**
* \brief Minimum MTU that may be set.
*
* This is done to ensure the NDNLPv2 fragmentation feature functions properly.
* This is done to ensure the NDNLPv2 fragmentation feature functions properly.
*/
const ssize_t MIN_MTU = 64;
inline constexpr ssize_t MIN_MTU = 64;
/** \brief Identifies a remote endpoint on the link.
/**
* \brief Identifies a remote endpoint on the link.
*
* This ID is only meaningful in the context of the same Transport.
* Incoming packets from the same remote endpoint have the same EndpointId,
* and incoming packets from different remote endpoints have different EndpointIds.
* This ID is only meaningful in the context of the same Transport.
* Incoming packets from the same remote endpoint have the same EndpointId,
* and incoming packets from different remote endpoints have different EndpointIds.
*
* Typically, a point-to-point Transport has only one meaningful EndpointId (usually 0).
* Typically, a point-to-point Transport has only one meaningful EndpointId,
* represented by `std::monostate`.
*/
using EndpointId = uint64_t;
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.
*
@@ -78,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;
@@ -128,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 */
+3 -5
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2020, 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-counters.hpp"
namespace nfd {
namespace face {
namespace nfd::face {
FaceCounters::FaceCounters(const LinkService::Counters& linkServiceCounters,
const Transport::Counters& transportCounters)
@@ -46,5 +45,4 @@ FaceCounters::FaceCounters(const LinkService::Counters& linkServiceCounters,
{
}
} // namespace face
} // namespace nfd
} // namespace nfd::face
+8 -10
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2020, 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);
@@ -81,11 +80,11 @@ public:
const ByteCounter& nInBytes;
const ByteCounter& nOutBytes;
/** \brief count of incoming Interests dropped due to HopLimit == 0
/** \brief Count of incoming Interests dropped due to HopLimit == 0.
*/
PacketCounter nInHopLimitZero;
/** \brief count of outgoing Interests dropped due to HopLimit == 0 on non-local faces
/** \brief Count of outgoing Interests dropped due to HopLimit == 0 on non-local faces.
*/
PacketCounter nOutHopLimitZero;
@@ -94,7 +93,6 @@ private:
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
+15 -12
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2021, Regents of the University of California,
* Copyright (c) 2014-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(Face& face, EndpointId endpoint)
: 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
+10 -16
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2021, Regents of the University of California,
* Copyright (c) 2014-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;
@@ -120,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");
@@ -166,5 +161,4 @@ FaceSystem::processConfig(const ConfigSection& configSection, bool isDryRun, con
}
}
} // namespace face
} // namespace nfd
} // namespace nfd::face
+19 -16
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2021, Regents of the University of California,
* Copyright (c) 2014-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
{
@@ -110,13 +113,13 @@ private:
const std::string& filename);
NFD_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
/** \brief config section name => protocol factory
/** \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.
*/
+3 -6
View File
@@ -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
+63 -62
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2021, Regents of the University of California,
* Copyright (c) 2014-2022, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -36,11 +36,12 @@ namespace face {
class Channel;
/** \brief indicates the state of a face
/**
* \brief Indicates the state of a face.
*/
typedef TransportState FaceState;
using FaceState = TransportState;
/** \brief generalization of a network interface
/** \brief Generalization of a network interface.
*
* A face generalizes a network interface.
* It provides best-effort network-layer packet delivery services
@@ -57,12 +58,18 @@ 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();
}
/** \brief Request that the face be closed
/** \brief Request that the face be closed.
*
* This operation is effective only if face is in the UP or DOWN state; otherwise, it has no effect.
* The face will change state to CLOSING, and then perform a cleanup procedure.
@@ -75,115 +82,133 @@ public:
close();
public: // upper interface connected to forwarding
/** \brief send Interest
/** \brief Send Interest.
*/
void
sendInterest(const Interest& interest);
/** \brief send Data
/** \brief Send Data.
*/
void
sendData(const Data& data);
/** \brief send Nack
/** \brief Send Nack.
*/
void
sendNack(const lp::Nack& nack);
/** \brief signals on Interest received
/** \brief Signals on Interest received.
*/
signal::Signal<LinkService, Interest, EndpointId>& afterReceiveInterest;
/** \brief signals on Data received
/** \brief Signals on Data received.
*/
signal::Signal<LinkService, Data, EndpointId>& afterReceiveData;
/** \brief signals on Nack received
/** \brief Signals on Nack received.
*/
signal::Signal<LinkService, lp::Nack, EndpointId>& afterReceiveNack;
/** \brief signals on Interest dropped by reliability system for exceeding allowed number of retx
/** \brief Signals on Interest dropped by reliability system for exceeding allowed number of retx.
*/
signal::Signal<LinkService, Interest>& onDroppedInterest;
public: // properties
/** \return face ID
/**
* \brief Returns the face ID.
*/
FaceId
getId() const;
getId() const noexcept
{
return m_id;
}
/** \brief sets face ID
* \note Normally, this should only be invoked by FaceTable.
/**
* \brief Sets the face ID.
* \note Normally, this should only be invoked by FaceTable.
*/
void
setId(FaceId id);
setId(FaceId id) noexcept
{
m_id = id;
}
/** \return a FaceUri representing local endpoint
/**
* \brief Returns a FaceUri representing the local endpoint.
*/
FaceUri
getLocalUri() const;
/** \return a FaceUri representing remote endpoint
/**
* \brief Returns a FaceUri representing the remote endpoint.
*/
FaceUri
getRemoteUri() const;
/** \return whether face is local or non-local for scope control purpose
/**
* \brief Returns whether the face is local or non-local for scope control purposes.
*/
ndn::nfd::FaceScope
getScope() const;
/** \return face persistency setting
/**
* \brief Returns the current persistency setting of the face.
*/
ndn::nfd::FacePersistency
getPersistency() const;
/** \brief changes face persistency setting
/**
* \brief Changes the face persistency setting.
*/
void
setPersistency(ndn::nfd::FacePersistency persistency);
/** \return whether face is point-to-point or multi-access
/**
* \brief Returns the link type of the face (point-to-point, multi-access, ...).
*/
ndn::nfd::LinkType
getLinkType() const;
/** \brief Returns face effective MTU
/**
* \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.
* This function is a wrapper. The effective MTU of a face is determined by the link service.
*/
ssize_t
getMtu() const;
/** \return face state
/**
* \brief Returns the face state.
*/
FaceState
getState() const;
/** \brief signals after face state changed
/**
* \brief Signals after face state changed.
*/
signal::Signal<Transport, FaceState/*old*/, FaceState/*new*/>& afterStateChange;
/** \return expiration time of the face
* \retval time::steady_clock::TimePoint::max() the face has an indefinite lifetime
/**
* \brief Returns the expiration time of the face.
* \retval time::steady_clock::time_point::max() The face has an indefinite lifetime.
*/
time::steady_clock::TimePoint
time::steady_clock::time_point
getExpirationTime() const;
const FaceCounters&
getCounters() const
getCounters() const noexcept
{
return m_counters;
}
FaceCounters&
getCounters()
getCounters() noexcept
{
return m_counters;
}
/**
* \brief Get channel on which face was created (unicast) or the associated channel (multicast)
* \brief Get channel on which face was created (unicast) or the associated channel (multicast).
*/
weak_ptr<Channel>
getChannel() const
@@ -192,7 +217,7 @@ public: // properties
}
/**
* \brief Set channel on which face was created (unicast) or the associated channel (multicast)
* \brief Set channel on which face was created (unicast) or the associated channel (multicast).
*/
void
setChannel(weak_ptr<Channel> channel)
@@ -201,25 +226,13 @@ public: // properties
}
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
{
return m_service.get();
}
inline Transport*
Face::getTransport() const
{
return m_transport.get();
}
inline void
Face::close()
{
@@ -244,18 +257,6 @@ Face::sendNack(const lp::Nack& nack)
m_service->sendNack(nack);
}
inline FaceId
Face::getId() const
{
return m_id;
}
inline void
Face::setId(FaceId id)
{
m_id = id;
}
inline FaceUri
Face::getLocalUri() const
{
@@ -304,7 +305,7 @@ 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();
+68 -14
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2021, Regents of the University of California,
* Copyright (c) 2014-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);
@@ -47,10 +47,41 @@ GenericLinkService::GenericLinkService(const GenericLinkService::Options& option
, m_lastSeqNo(-2)
, m_nextMarkTime(time::steady_clock::time_point::max())
, m_nMarkedSinceInMarkingState(0)
, globalSp(options.C * 0.99, options.vqSize)
{
m_reassembler.beforeTimeout.connect([this] (auto&&...) { ++nReassemblyTimeouts; });
m_reliability.onDroppedInterest.connect([this] (const auto& i) { notifyDroppedInterest(i); });
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
@@ -115,19 +146,46 @@ GenericLinkService::sendLpPacket(lp::Packet&& pkt)
void
GenericLinkService::doSendInterest(const Interest& interest)
{
lp::Packet lpPacket(interest.wireEncode());
if (interest.getName().getPrefix(1).toUri() == "/localhost") {
const Block &block = interest.wireEncode();
// // std::cout << "interest wireEncode size: " << block.size() << std::endl;
lp::Packet lpPacket(block);
// // std::cout << "lppacket size before encode lp fields: " << lpPacket.wireEncode().size() << std::endl;
encodeLpFields(interest, lpPacket);
// // std::cout << "lppacket size after encode lp fields: " << lpPacket.wireEncode().size() << std::endl;
this->sendNetPacket(std::move(lpPacket), true);
} else {
this->globalSp.appendInterest(interest);
if (this->canScheduler) {
this->sendPacketCallback(nullptr);
}
//if (!success) {
// // send Nack
// lp::Nack nack(interest);
// nack.setReason(lp::NackReason::CONGESTION);
// if (this->nwfq.canMark(nack)) {
// // 拥塞标记
// nack.getInterest().setTag(make_shared<lp::CongestionMarkTag>(1));
// }
// this->receiveNack(nack, endpointId);
//}
}
// lp::Packet lpPacket(interest.wireEncode());
encodeLpFields(interest, lpPacket);
// encodeLpFields(interest, lpPacket);
this->sendNetPacket(std::move(lpPacket), true);
// this->sendNetPacket(std::move(lpPacket), true);
}
void
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), false);
}
@@ -312,10 +370,7 @@ 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);
}
@@ -510,5 +565,4 @@ GenericLinkService::decodeNack(const Block& netPkt, const lp::Packet& firstPkt,
this->receiveNack(nack, endpointId);
}
} // namespace face
} // namespace nfd
} // namespace nfd::face
+68 -67
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2021, Regents of the University of California,
* Copyright (c) 2014-2022, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -30,74 +30,75 @@
#include "lp-fragmenter.hpp"
#include "lp-reassembler.hpp"
#include "lp-reliability.hpp"
#include "queues.hpp"
namespace nfd {
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 LpPackets dropped due to duplicate Sequence numbers
/** \brief Count of LpPackets dropped due to duplicate Sequence numbers.
*/
PacketCounter nDuplicateSequence;
/** \brief count of outgoing LpPackets that were marked with congestion marks
/** \brief Count of outgoing LpPackets that were marked with congestion marks.
*/
PacketCounter nCongestionMarked;
};
/** \brief GenericLinkService is a LinkService that implements the NDNLPv2 protocol
* \sa https://redmine.named-data.net/projects/nfd/wiki/NDNLPv2
/**
* \brief GenericLinkService is a LinkService that implements the NDNLPv2 protocol.
* \sa https://redmine.named-data.net/projects/nfd/wiki/NDNLPv2
*/
class GenericLinkService NFD_FINAL_UNLESS_WITH_TESTS : public LinkService
, protected virtual GenericLinkServiceCounters
{
public:
/** \brief Options that control the behavior of GenericLinkService
/** \brief %Options that control the behavior of GenericLinkService.
*/
class Options
{
@@ -107,35 +108,35 @@ public:
}
public:
/** \brief enables encoding of IncomingFaceId, and decoding of NextHopFaceId and CachePolicy
/** \brief Enables encoding of IncomingFaceId, and decoding of NextHopFaceId and CachePolicy.
*/
bool allowLocalFields = false;
/** \brief enables fragmentation
/** \brief Enables fragmentation.
*/
bool allowFragmentation = false;
/** \brief options for fragmentation
/** \brief Options for fragmentation.
*/
LpFragmenter::Options fragmenterOptions;
/** \brief enables reassembly
/** \brief Enables reassembly.
*/
bool allowReassembly = false;
/** \brief options for reassembly
/** \brief Options for reassembly.
*/
LpReassembler::Options reassemblerOptions;
/** \brief options for reliability
/** \brief Options for reliability.
*/
LpReliability::Options reliabilityOptions;
/** \brief enables send queue congestion detection and marking
/** \brief Enables send queue congestion detection and marking.
*/
bool allowCongestionMarking = false;
/** \brief starting value for congestion marking interval
/** \brief Starting value for congestion marking interval.
*
* Packets are marked if the queue size stays above THRESHOLD for at least one INTERVAL.
*
@@ -143,7 +144,7 @@ public:
*/
time::nanoseconds baseCongestionMarkingInterval = 100_ms;
/** \brief default congestion threshold in bytes
/** \brief Default congestion threshold in bytes.
*
* Packets are marked if the queue size stays above THRESHOLD for at least one INTERVAL.
*
@@ -151,45 +152,54 @@ public:
*/
size_t defaultCongestionThreshold = 65536;
/** \brief enables self-learning forwarding support
/** \brief Enables self-learning forwarding support.
*/
bool allowSelfLearning = true;
/** \brief overrides MTU provided by Transport
/** \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 the override MTU are values >= MIN_MTU, which can be validated before
* 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 NFD_OVERRIDE_WITH_TESTS_ELSE_FINAL;
getCounters() const NFD_OVERRIDE_WITH_TESTS_ELSE_FINAL
{
return *this;
}
ssize_t
getEffectiveMtu() const NFD_OVERRIDE_WITH_TESTS_ELSE_FINAL;
/** \brief Whether MTU can be overridden to the specified value
/** \brief Whether MTU can be overridden to the specified value.
*
* If the transport MTU is unlimited, then this will always return false.
*/
@@ -197,12 +207,12 @@ public:
canOverrideMtuTo(ssize_t mtu) const;
NFD_PROTECTED_WITH_TESTS_ELSE_PRIVATE: // send path
/** \brief request an IDLE packet to transmit pending service fields
/** \brief Request an IDLE packet to transmit pending service fields.
*/
void
requestIdlePacket();
/** \brief send an LpPacket
/** \brief Send an LpPacket.
*/
void
sendLpPacket(lp::Packet&& pkt);
@@ -216,28 +226,28 @@ NFD_PROTECTED_WITH_TESTS_ELSE_PRIVATE: // send path
void
doSendNack(const ndn::lp::Nack& nack) NFD_OVERRIDE_WITH_TESTS_ELSE_FINAL;
/** \brief assign consecutive sequence numbers to LpPackets
/** \brief Assign consecutive sequence numbers to LpPackets.
*/
void
assignSequences(std::vector<lp::Packet>& pkts);
private: // send path
/** \brief encode link protocol fields from tags onto an outgoing LpPacket
/** \brief Encode link protocol fields from tags onto an outgoing LpPacket.
* \param netPkt network-layer packet to extract tags from
* \param lpPacket LpPacket to add link protocol fields to
*/
void
encodeLpFields(const ndn::PacketBase& netPkt, lp::Packet& lpPacket);
/** \brief send a complete network layer packet
/** \brief Send a complete network layer packet.
* \param pkt LpPacket containing a complete network layer packet
* \param isInterest whether the network layer packet is an Interest
*/
void
sendNetPacket(lp::Packet&& pkt, bool isInterest);
/** \brief if the send queue is found to be congested, add a congestion mark to the packet
* according to CoDel
/** \brief If the send queue is found to be congested, add a congestion mark to the packet
* according to CoDel.
* \sa https://tools.ietf.org/html/rfc8289
*/
void
@@ -247,7 +257,7 @@ private: // receive path
void
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
@@ -258,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
@@ -271,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
@@ -284,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
@@ -306,26 +316,17 @@ NFD_PROTECTED_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
+4 -6
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2019, Regents of the University of California,
* Copyright (c) 2014-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
+8 -9
View File
@@ -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
+7 -7
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, Regents of the University of California,
* Copyright (c) 2014-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,7 +49,7 @@ 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);
});
@@ -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,5 +124,4 @@ InternalClientTransport::send(const Block& wire)
m_forwarder->receivePacket(wire);
}
} // namespace face
} // namespace nfd
} // namespace nfd::face
+13 -12
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, Regents of the University of California,
* Copyright (c) 2014-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;
}
@@ -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
{
@@ -125,7 +127,6 @@ private:
signal::ScopedConnection m_fwTransportStateConn;
};
} // namespace face
} // namespace nfd
} // namespace nfd::face
#endif // NFD_DAEMON_FACE_INTERNAL_TRANSPORT_HPP
+5 -15
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2020, 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);
@@ -135,5 +126,4 @@ operator<<(std::ostream& os, const FaceLogHelper<LinkService>& flh)
return os;
}
} // namespace face
} // namespace nfd
} // namespace nfd::face
+67 -77
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2020, 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,147 +30,162 @@
#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 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
* \pre setTransport has been called
/** \brief Send Interest.
* \pre setFaceAndTransport() has been called.
*/
void
sendInterest(const Interest& interest);
/** \brief Send Data
* \pre setTransport has been called
/** \brief Send Data.
* \pre setFaceAndTransport() has been called.
*/
void
sendData(const Data& data);
/** \brief Send Nack
* \pre setTransport has been called
/** \brief Send Nack.
* \pre setFaceAndTransport() has been called.
*/
void
sendNack(const ndn::lp::Nack& nack);
/** \brief signals on Interest received
/** \brief Signals on Interest received.
*/
signal::Signal<LinkService, Interest, EndpointId> afterReceiveInterest;
/** \brief signals on Data received
/** \brief Signals on Data received.
*/
signal::Signal<LinkService, Data, EndpointId> afterReceiveData;
/** \brief signals on Nack received
/** \brief Signals on Nack received.
*/
signal::Signal<LinkService, lp::Nack, EndpointId> afterReceiveNack;
/** \brief signals on Interest dropped by reliability system for exceeding allowed number of retx
/** \brief Signals on Interest dropped by reliability system for exceeding allowed number of retx.
*/
signal::Signal<LinkService, Interest> onDroppedInterest;
public: // lower interface to be invoked by Transport
/** \brief performs LinkService specific operations to receive a lower-layer packet
/** \brief Performs LinkService specific operations to receive a lower-layer packet.
*/
void
receivePacket(const Block& packet, const EndpointId& endpoint);
protected: // upper interface to be invoked in subclass (receive path termination)
/** \brief delivers received Interest to forwarding
/** \brief Delivers received Interest to forwarding.
*/
void
receiveInterest(const Interest& interest, const EndpointId& endpoint);
/** \brief delivers received Data to forwarding
/** \brief Delivers received Data to forwarding.
*/
void
receiveData(const Data& data, const EndpointId& endpoint);
/** \brief delivers received Nack to forwarding
/** \brief Delivers received Nack to forwarding.
*/
void
receiveNack(const lp::Nack& nack, const EndpointId& endpoint);
protected: // lower interface to be invoked in subclass (send path termination)
/** \brief send a lower-layer packet via Transport
/** \brief Send a lower-layer packet via Transport.
*/
void
sendPacket(const Block& packet);
@@ -180,17 +195,17 @@ protected:
notifyDroppedInterest(const Interest& packet);
private: // upper interface to be overridden in subclass (send path entrypoint)
/** \brief performs LinkService specific operations to send an Interest
/** \brief Performs LinkService specific operations to send an Interest.
*/
virtual void
doSendInterest(const Interest& interest) = 0;
/** \brief performs LinkService specific operations to send a Data
/** \brief Performs LinkService specific operations to send a Data.
*/
virtual void
doSendData(const Data& data) = 0;
/** \brief performs LinkService specific operations to send a Nack
/** \brief Performs LinkService specific operations to send a Nack.
*/
virtual void
doSendNack(const lp::Nack& nack) = 0;
@@ -200,34 +215,10 @@ private: // lower interface to be overridden in subclass
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
{
return m_face;
}
inline const Transport*
LinkService::getTransport() const
{
return m_transport;
}
inline Transport*
LinkService::getTransport()
{
return m_transport;
}
inline const LinkService::Counters&
LinkService::getCounters() const
{
return *this;
}
inline ssize_t
LinkService::getEffectiveMtu() const
{
@@ -250,14 +241,13 @@ 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
+17 -20
View File
@@ -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
+8 -10
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2019, Regents of the University of California,
* Copyright (c) 2014-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
+18 -23
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, Regents of the University of California,
* Copyright (c) 2014-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,12 +58,12 @@ 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
@@ -77,10 +76,11 @@ LpReassembler::receiveFragment(EndpointId remoteEndpoint, const lp::Packet& pack
// 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];
@@ -92,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;
@@ -109,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
@@ -125,20 +125,16 @@ 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);
}
@@ -166,5 +162,4 @@ operator<<(std::ostream& os, const FaceLogHelper<LpReassembler>& flh)
return os;
}
} // namespace face
} // namespace nfd
} // namespace nfd::face
+28 -25
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2019, Regents of the University of California,
* Copyright (c) 2014-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
+12 -18
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, Regents of the University of California,
* Copyright (c) 2014-2023, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -24,12 +24,13 @@
*/
#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);
@@ -80,10 +81,7 @@ LpReliability::handleOutgoing(std::vector<lp::Packet>& frags, lp::Packet&& pkt,
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;
auto rto = m_rttEst.getEstimatedRto();
lp::Sequence seq = frag.get<lp::SequenceField>();
@@ -179,7 +177,7 @@ LpReliability::processIncomingPacket(const lp::Packet& pkt)
m_recentRecvSeqs.erase(m_recentRecvSeqsQueue.front());
m_recentRecvSeqsQueue.pop();
}
m_recentRecvSeqs.emplace(pktSequence, now);
m_recentRecvSeqs.try_emplace(pktSequence, now);
m_recentRecvSeqsQueue.push(pktSequence);
}
@@ -324,13 +322,10 @@ LpReliability::onLpPacketLost(lp::Sequence txSeq, bool isTimeout)
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;
@@ -432,5 +427,4 @@ operator<<(std::ostream& os, const FaceLogHelper<LpReliability>& flh)
return os;
}
} // namespace face
} // namespace nfd
} // namespace nfd::face
+40 -43
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2021, Regents of the University of California,
* Copyright (c) 2014-2022, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -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,16 +96,16 @@ public:
void
handleOutgoing(std::vector<lp::Packet>& frags, lp::Packet&& pkt, bool isInterest);
/** \brief extract and parse all Acks and add Ack for contained Fragment (if any) to AckQueue
/** \brief Extract and parse all Acks and add Ack for contained Fragment (if any) to AckQueue.
* \param pkt incoming LpPacket
* \return whether incoming LpPacket is new and not a duplicate
*/
bool
processIncomingPacket(const lp::Packet& pkt);
/** \brief called by GenericLinkService to attach Acks onto an outgoing LpPacket
/** \brief Called by GenericLinkService to attach Acks onto an outgoing LpPacket.
* \param pkt outgoing LpPacket to attach Acks to
* \param mtu MTU of the Transport
* \param mtu MTU of the transport
*/
void
piggyback(lp::Packet& pkt, ssize_t mtu);
@@ -110,8 +115,7 @@ NFD_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
class NetPkt;
using UnackedFrags = std::map<lp::Sequence, UnackedFrag>;
NFD_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
@@ -119,7 +123,7 @@ NFD_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
lp::Sequence
assignTxSequence(lp::Packet& frag);
/** \brief start the idle Ack timer
/** \brief Start the idle Ack timer.
*
* This timer requests an IDLE packet to acknowledge pending fragments not already piggybacked.
* It is called regularly on a period configured in Options::idleAckTimerPeriod. This allows Acks
@@ -128,22 +132,22 @@ NFD_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, 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.
@@ -152,7 +156,7 @@ NFD_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
void
onLpPacketAcknowledged(UnackedFrags::iterator fragIt);
/** \brief delete a fragment from UnackedFrags and advance acknowledge window if necessary
/** \brief Delete a fragment from UnackedFrags and advance acknowledge window if necessary.
* \param fragIt iterator to an UnackedFrag, must be dereferencable
* \post fragIt is not in m_unackedFrags
* \post if was equal to m_firstUnackedFrag,
@@ -163,7 +167,8 @@ NFD_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
deleteUnackedFrag(UnackedFrags::iterator fragIt);
NFD_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
/** \brief contains a sent fragment that has not been acknowledged and associated data
/**
* \brief Contains a sent fragment that has not been acknowledged and associated data.
*/
class UnackedFrag
{
@@ -174,13 +179,14 @@ NFD_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
{
@@ -194,24 +200,16 @@ NFD_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
bool didRetx;
};
public:
/// TxSequence TLV-TYPE (3 octets) + TLV-LENGTH (1 octet) + lp::Sequence (8 octets)
static constexpr size_t RESERVED_HEADER_SPACE = tlv::sizeOfVarNumber(lp::tlv::TxSequence) +
tlv::sizeOfVarNumber(sizeof(lp::Sequence)) +
sizeof(lp::Sequence);
NFD_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::TimePoint> m_recentRecvSeqs;
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;
@@ -221,7 +219,6 @@ NFD_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
std::ostream&
operator<<(std::ostream& os, const FaceLogHelper<LpReliability>& flh);
} // namespace face
} // namespace nfd
} // namespace nfd::face
#endif // NFD_DAEMON_FACE_LP_RELIABILITY_HPP
+14 -18
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2019, Regents of the University of California,
* Copyright (c) 2014-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
+6 -8
View File
@@ -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
+30 -54
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2021, Regents of the University of California,
* Copyright (c) 2014-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) {
@@ -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 NFD_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
+24 -27
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2020, 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,30 +48,36 @@ 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:
@@ -90,11 +88,10 @@ private:
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
+5 -11
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2019, Regents of the University of California,
* Copyright (c) 2014-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
+6 -7
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2021, Regents of the University of California,
* Copyright (c) 2014-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,7 +55,7 @@ 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,
@@ -82,7 +82,6 @@ NFD_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
+5 -14
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2021, Regents of the University of California,
* Copyright (c) 2014-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)
{
@@ -227,5 +219,4 @@ IpAddressPredicate::operator()(const boost::asio::ip::address& address) const
[&address] (const auto& rule) { return doesAddressMatchRule(address, rule); });
}
} // namespace face
} // namespace nfd
} // namespace nfd::face
+35 -19
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2021, Regents of the University of California,
* Copyright (c) 2014-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,6 +88,14 @@ private:
void
parseList(std::set<std::string>& set, std::initializer_list<std::pair<std::string, std::string>> list);
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 @@ NFD_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
+3 -5
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2019, Regents of the University of California,
* Copyright (c) 2014-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
+6 -7
View File
@@ -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
+3 -5
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2020, 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.
*/
@@ -57,7 +56,6 @@ private:
}
};
} // namespace face
} // namespace nfd
} // namespace nfd::face
#endif // NFD_DAEMON_FACE_NULL_LINK_SERVICE_HPP
+3 -5
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2019, Regents of the University of California,
* Copyright (c) 2014-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
+3 -5
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2021, Regents of the University of California,
* Copyright (c) 2014-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 "transport.hpp"
namespace nfd {
namespace face {
namespace nfd::face {
/** \brief A Transport that drops every packet.
*/
@@ -56,7 +55,6 @@ private:
}
};
} // namespace face
} // namespace nfd
} // namespace nfd::face
#endif // NFD_DAEMON_FACE_NULL_TRANSPORT_HPP
+8 -7
View File
@@ -35,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);
@@ -57,7 +55,7 @@ PcapHelper::PcapHelper(const std::string& interfaceName)
pcap_set_buffer_size(m_pcap, 4 * 1024 * 1024);
}
PcapHelper::~PcapHelper()
PcapHelper::~PcapHelper() noexcept
{
close();
}
@@ -71,6 +69,10 @@ PcapHelper::activate(int dlt)
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()));
@@ -138,10 +140,9 @@ PcapHelper::readNextPacket() const noexcept
if (ret < 0)
return {span<uint8_t>{}, getLastError()};
else if (ret == 0)
return {span<uint8_t>{}, "timed out"};
return {span<uint8_t>{}, "Nothing to read"};
else
return {{packet, header->caplen}, ""};
}
} // namespace face
} // namespace nfd
} // namespace nfd::face
+5 -11
View File
@@ -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.
@@ -136,10 +131,9 @@ public:
}
private:
pcap_t* m_pcap;
pcap_t* m_pcap = nullptr;
};
} // namespace face
} // namespace nfd
} // namespace nfd::face
#endif // NFD_DAEMON_FACE_PCAP_HELPER_HPP
+3 -5
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2019, Regents of the University of California,
* Copyright (c) 2014-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
+41 -31
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2019, Regents of the University of California,
* Copyright (c) 2014-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
*
+505
View File
@@ -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);
}
}
}
}
+338
View File
@@ -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
+3 -5
View File
@@ -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
+4 -6
View File
@@ -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
+14 -11
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, Regents of the University of California,
* Copyright (c) 2014-2023, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -32,12 +32,15 @@
#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
@@ -45,9 +48,10 @@ class StreamTransport : public Transport
public:
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);
@@ -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):
//
@@ -333,7 +337,6 @@ StreamTransport<T>::getSendQueueBytes() const
return m_sendQueueBytes;
}
} // namespace face
} // namespace nfd
} // namespace nfd::face
#endif // NFD_DAEMON_FACE_STREAM_TRANSPORT_HPP
+26 -33
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, Regents of the University of California,
* Copyright (c) 2014-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));
}
@@ -138,7 +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(shared_from_this()); // use weak_from_this() in C++17
face->setChannel(weak_from_this());
m_channelFaces[remoteEndpoint] = face;
connectFaceClosedSignal(*face, [this, remoteEndpoint] { m_channelFaces.erase(remoteEndpoint); });
@@ -149,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);
}
@@ -162,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, onAcceptFailed);
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
@@ -228,5 +222,4 @@ TcpChannel::handleConnectTimeout(const tcp::Endpoint& remoteEndpoint,
onConnectFailed(504, "Connection timed out");
}
} // namespace face
} // namespace nfd
} // namespace nfd::face
+17 -25
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, Regents of the University of California,
* Copyright (c) 2014-2023, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -28,32 +28,31 @@
#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 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);
@@ -72,7 +71,7 @@ public:
/**
* \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,
@@ -105,11 +104,6 @@ private:
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,
@@ -126,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
+12 -12
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2021, Regents of the University of California,
* Copyright (c) 2014-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;
}
@@ -214,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;
@@ -223,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
+9 -11
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2021, Regents of the University of California,
* Copyright (c) 2014-2023, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -27,12 +27,13 @@
#define NFD_DAEMON_FACE_TCP_FACTORY_HPP
#include "protocol-factory.hpp"
#include "network-predicate.hpp"
#include "tcp-channel.hpp"
namespace nfd {
namespace face {
namespace nfd::face {
/** \brief Protocol factory for TCP over IPv4 and IPv6
/**
* \brief Protocol factory for TCP over IPv4 and IPv6.
*/
class TcpFactory final : public ProtocolFactory
{
@@ -43,22 +44,20 @@ public:
using ProtocolFactory::ProtocolFactory;
/**
* \brief Create TCP-based channel using tcp::Endpoint
* \brief Create TCP-based channel using tcp::Endpoint.
*
* tcp::Endpoint is really an alias for boost::asio::ip::tcp::endpoint.
* tcp::Endpoint is an alias for boost::asio::ip::tcp::endpoint.
*
* 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 TcpChannel object, an exception
* \return Always a valid pointer to a TcpChannel object, an exception
* is thrown if it cannot be created.
*/
shared_ptr<TcpChannel>
createChannel(const tcp::Endpoint& localEndpoint);
private:
/** \brief process face_system.tcp config section
*/
void
doProcessConfig(OptionalConfigSection configSection,
FaceSystem::ConfigContext& context) final;
@@ -83,7 +82,6 @@ NFD_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
IpAddressPredicate m_local;
};
} // namespace face
} // namespace nfd
} // namespace nfd::face
#endif // NFD_DAEMON_FACE_TCP_FACTORY_HPP
+15 -23
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2019, Regents of the University of California,
* Copyright (c) 2014-2023, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -26,26 +26,25 @@
#include "tcp-transport.hpp"
#include "common/global.hpp"
#include <boost/asio/defer.hpp>
#if defined(__linux__)
#include <linux/sockios.h>
#include <sys/ioctl.h>
#endif
namespace nfd {
namespace face {
namespace nfd::face {
NFD_LOG_MEMBER_INIT_SPECIALIZED(StreamTransport<boost::asio::ip::tcp>, TcpTransport);
namespace ip = boost::asio::ip;
time::milliseconds TcpTransport::s_initialReconnectWait = 1_s;
time::milliseconds TcpTransport::s_maxReconnectWait = 5_min;
float TcpTransport::s_reconnectWaitMultiplier = 2.0f;
NFD_LOG_MEMBER_INIT_SPECIALIZED(StreamTransport<ip::tcp>, TcpTransport);
TcpTransport::TcpTransport(protocol::socket&& socket,
TcpTransport::TcpTransport(ip::tcp::socket&& socket,
ndn::nfd::FacePersistency persistency,
ndn::nfd::FaceScope faceScope)
: StreamTransport(std::move(socket))
, m_remoteEndpoint(m_socket.remote_endpoint())
, m_nextReconnectWait(s_initialReconnectWait)
, m_nextReconnectWait(INITIAL_RECONNECT_DELAY)
{
this->setLocalUri(FaceUri(m_socket.local_endpoint()));
this->setRemoteUri(FaceUri(m_socket.remote_endpoint()));
@@ -110,7 +109,7 @@ TcpTransport::handleError(const boost::system::error_code& error)
m_socket.cancel(ec);
// do this asynchronously because there could be some callbacks still pending
getGlobalIoService().post([this] { reconnect(); });
boost::asio::defer(getGlobalIoService(), [this] { reconnect(); });
}
else {
StreamTransport::handleError(error);
@@ -133,13 +132,7 @@ TcpTransport::reconnect()
BOOST_ASSERT(getState() == TransportState::DOWN);
// recreate the socket
m_socket = protocol::socket(
#if BOOST_VERSION >= 107000
m_socket.get_executor()
#else
m_socket.get_io_service()
#endif // BOOST_VERSION >= 107000
);
m_socket = ip::tcp::socket(m_socket.get_executor());
this->resetReceiveBuffer();
this->resetSendQueue();
@@ -165,7 +158,7 @@ TcpTransport::handleReconnect(const boost::system::error_code& error)
}
m_reconnectEvent.cancel();
m_nextReconnectWait = s_initialReconnectWait;
m_nextReconnectWait = INITIAL_RECONNECT_DELAY;
this->setLocalUri(FaceUri(m_socket.local_endpoint()));
NFD_LOG_FACE_TRACE("TCP connection reestablished");
@@ -182,11 +175,11 @@ TcpTransport::handleReconnectTimeout()
// exponentially back off the reconnection timer
m_nextReconnectWait =
std::min(time::duration_cast<time::milliseconds>(m_nextReconnectWait * s_reconnectWaitMultiplier),
s_maxReconnectWait);
std::min(time::duration_cast<time::milliseconds>(m_nextReconnectWait * RECONNECT_DELAY_MULTIPLIER),
MAX_RECONNECT_DELAY);
// do this asynchronously because there could be some callbacks still pending
getGlobalIoService().post([this] { reconnect(); });
boost::asio::defer(getGlobalIoService(), [this] { reconnect(); });
}
void
@@ -196,5 +189,4 @@ TcpTransport::doClose()
StreamTransport::doClose();
}
} // namespace face
} // namespace nfd
} // namespace nfd::face
+20 -19
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2021, Regents of the University of California,
* Copyright (c) 2014-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 "stream-transport.hpp"
namespace nfd {
namespace face {
#include <boost/asio/ip/tcp.hpp>
namespace nfd::face {
NFD_LOG_MEMBER_DECL_SPECIALIZED(StreamTransport<boost::asio::ip::tcp>);
/**
* \brief A Transport that communicates on a connected TCP socket
* \brief A Transport that communicates on a connected TCP socket.
*
* When persistency is set to permanent, whenever the TCP connection is severed, the transport
* state is set to DOWN, and the connection is retried periodically with exponential backoff
@@ -43,7 +44,9 @@ NFD_LOG_MEMBER_DECL_SPECIALIZED(StreamTransport<boost::asio::ip::tcp>);
class TcpTransport NFD_FINAL_UNLESS_WITH_TESTS : public StreamTransport<boost::asio::ip::tcp>
{
public:
TcpTransport(protocol::socket&& socket, ndn::nfd::FacePersistency persistency, ndn::nfd::FaceScope faceScope);
TcpTransport(boost::asio::ip::tcp::socket&& socket,
ndn::nfd::FacePersistency persistency,
ndn::nfd::FaceScope faceScope);
ssize_t
getSendQueueLength() final;
@@ -72,31 +75,29 @@ NFD_PROTECTED_WITH_TESTS_ELSE_PRIVATE:
handleReconnectTimeout();
NFD_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
/** \brief how long to wait before the first reconnection attempt after the TCP connection has been severed
/**
* \brief Delay before the first reconnection attempt after the TCP connection has been severed.
*/
static time::milliseconds s_initialReconnectWait;
static constexpr time::milliseconds INITIAL_RECONNECT_DELAY = 1_s;
/** \brief maximum amount of time to wait before a reconnection attempt
/**
* \brief Maximum amount of time to wait before a reconnection attempt.
*/
static time::milliseconds s_maxReconnectWait;
static constexpr time::milliseconds MAX_RECONNECT_DELAY = 5_min;
/** \brief multiplier for the exponential backoff of the reconnection timer
/**
* \brief Multiplier for the exponential backoff of the reconnection timer.
*/
static float s_reconnectWaitMultiplier;
static constexpr float RECONNECT_DELAY_MULTIPLIER = 2.0f;
private:
typename protocol::endpoint m_remoteEndpoint;
boost::asio::ip::tcp::endpoint m_remoteEndpoint;
/** \note valid only when persistency is set to permanent
*/
// The following members are valid only when the persistency is set to permanent
scheduler::ScopedEventId m_reconnectEvent;
/** \note valid only when persistency is set to permanent
*/
time::milliseconds m_nextReconnectWait;
};
} // namespace face
} // namespace nfd
} // namespace nfd::face
#endif // NFD_DAEMON_FACE_TCP_TRANSPORT_HPP
+6 -19
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2020, 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,8 +26,7 @@
#include "transport.hpp"
#include "face.hpp"
namespace nfd {
namespace face {
namespace nfd::face {
NFD_LOG_INIT(Transport);
@@ -50,23 +49,12 @@ operator<<(std::ostream& os, TransportState state)
}
}
Transport::Transport()
: m_face(nullptr)
, m_service(nullptr)
, m_scope(ndn::nfd::FACE_SCOPE_NONE)
, m_persistency(ndn::nfd::FACE_PERSISTENCY_NONE)
, m_linkType(ndn::nfd::LINK_TYPE_NONE)
, m_mtu(MTU_INVALID)
, m_sendQueueCapacity(QUEUE_UNSUPPORTED)
, m_state(TransportState::UP)
, m_expirationTime(time::steady_clock::TimePoint::max())
{
}
Transport::Transport() = default;
Transport::~Transport() = default;
void
Transport::setFaceAndLinkService(Face& face, LinkService& service)
Transport::setFaceAndLinkService(Face& face, LinkService& service) noexcept
{
BOOST_ASSERT(m_face == nullptr);
BOOST_ASSERT(m_service == nullptr);
@@ -123,7 +111,7 @@ Transport::receive(const Block& packet, const EndpointId& endpoint)
}
void
Transport::setMtu(ssize_t mtu)
Transport::setMtu(ssize_t mtu) noexcept
{
BOOST_ASSERT(mtu == MTU_UNLIMITED || mtu >= 0);
@@ -235,5 +223,4 @@ operator<<(std::ostream& os, const FaceLogHelper<Transport>& flh)
return os;
}
} // namespace face
} // namespace nfd
} // namespace nfd::face
+177 -212
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2020, 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,10 @@
#include "face-common.hpp"
#include "common/counter.hpp"
namespace nfd {
namespace face {
namespace nfd::face {
/** \brief Indicates the state of a transport.
/**
* \brief Indicates the state of a transport.
*/
enum class TransportState {
NONE,
@@ -53,7 +53,7 @@ operator<<(std::ostream& os, TransportState state);
class TransportCounters
{
public:
/** \brief count of incoming packets
/** \brief Count of incoming packets.
*
* A 'packet' typically means a top-level TLV block.
* For a datagram-based transport, an incoming packet that cannot be parsed as TLV
@@ -61,14 +61,14 @@ public:
*/
PacketCounter nInPackets;
/** \brief count of outgoing packets
/** \brief Count of outgoing packets.
*
* A 'packet' typically means a top-level TLV block.
* This counter is incremented only if transport is UP.
*/
PacketCounter nOutPackets;
/** \brief total incoming bytes
/** \brief Total incoming bytes.
*
* This counter includes headers imposed by NFD (such as NDNLP),
* but excludes overhead of underlying protocol (such as IP header).
@@ -77,7 +77,7 @@ public:
*/
ByteCounter nInBytes;
/** \brief total outgoing bytes
/** \brief Total outgoing bytes.
*
* This counter includes headers imposed by NFD (such as NDNLP),
* but excludes overhead of underlying protocol (such as IP header).
@@ -86,24 +86,29 @@ public:
ByteCounter nOutBytes;
};
/** \brief indicates the transport has no limit on payload size
/**
* \brief Indicates that the transport has no limit on payload size.
*/
const ssize_t MTU_UNLIMITED = -1;
inline constexpr ssize_t MTU_UNLIMITED = -1;
/** \brief (for internal use) indicates MTU field is unset
/**
* \brief (for internal use) Indicates that the MTU field is unset.
*/
const ssize_t MTU_INVALID = -2;
inline constexpr ssize_t MTU_INVALID = -2;
/** \brief indicates that the transport does not support reading the queue capacity/length
/**
* \brief Indicates that the transport does not support reading the queue capacity/length.
*/
const ssize_t QUEUE_UNSUPPORTED = -1;
inline constexpr ssize_t QUEUE_UNSUPPORTED = -1;
/** \brief indicates that the transport was unable to retrieve the queue capacity/length
/**
* \brief Indicates that the transport was unable to retrieve the queue capacity/length.
*/
const ssize_t QUEUE_ERROR = -2;
inline constexpr ssize_t QUEUE_ERROR = -2;
/** \brief The lower half of a Face.
* \sa Face
/**
* \brief The lower half of a Face.
* \sa Face, LinkService
*/
class Transport : protected virtual TransportCounters, noncopyable
{
@@ -127,32 +132,48 @@ public:
~Transport();
public:
/** \brief set Face and LinkService for Transport
* \pre setFaceAndLinkService has not been called
/**
* \brief Set Face and LinkService for this transport.
* \pre setFaceAndLinkService() has not been called.
*/
void
setFaceAndLinkService(Face& face, LinkService& service);
setFaceAndLinkService(Face& face, LinkService& service) noexcept;
/** \return Face to which this Transport is attached
/**
* \brief Returns the Face to which this transport is attached.
*/
const Face*
getFace() const;
getFace() const noexcept
{
return m_face;
}
/** \return LinkService to which this Transport is attached
/**
* \brief Returns the LinkService to which this transport is attached.
*/
const LinkService*
getLinkService() const;
getLinkService() const noexcept
{
return m_service;
}
/** \return LinkService to which this Transport is attached
/**
* \brief Returns the LinkService to which this transport is attached.
*/
LinkService*
getLinkService();
getLinkService() noexcept
{
return m_service;
}
virtual const Counters&
getCounters() const;
getCounters() const
{
return *this;
}
public: // upper interface
/** \brief Request the transport to be closed
/** \brief Request the transport to be closed.
*
* This operation is effective only if transport is in UP or DOWN state,
* otherwise it has no effect.
@@ -163,7 +184,7 @@ public: // upper interface
void
close();
/** \brief Send a link-layer packet
/** \brief Send a link-layer packet.
* \param packet the packet to be sent, must be a valid and well-formed TLV block
* \note This operation has no effect if getState() is neither UP nor DOWN
* \warning Behavior is undefined if packet size exceeds the MTU limit
@@ -172,85 +193,125 @@ public: // upper interface
send(const Block& packet);
public: // static properties
/** \return a FaceUri representing local endpoint
/**
* \brief Returns a FaceUri representing the local endpoint.
*/
FaceUri
getLocalUri() const;
getLocalUri() const noexcept
{
return m_localUri;
}
/** \return a FaceUri representing remote endpoint
/**
* \brief Returns a FaceUri representing the remote endpoint.
*/
FaceUri
getRemoteUri() const;
getRemoteUri() const noexcept
{
return m_remoteUri;
}
/** \return whether face is local or non-local for scope control purpose
/**
* \brief Returns whether the transport is local or non-local for scope control purposes.
*/
ndn::nfd::FaceScope
getScope() const;
getScope() const noexcept
{
return m_scope;
}
/** \return face persistency setting
/**
* \brief Returns the current persistency setting of the transport.
*/
ndn::nfd::FacePersistency
getPersistency() const;
getPersistency() const noexcept
{
return m_persistency;
}
/** \brief check whether the face persistency can be changed to \p newPersistency
/**
* \brief Check whether the persistency can be changed to \p newPersistency.
*
* This function serves as the external API, and invokes the protected function
* canChangePersistencyToImpl to perform further checks if \p newPersistency differs
* from the current persistency.
* This function serves as the external API, and invokes the protected function
* canChangePersistencyToImpl() to perform further checks if \p newPersistency differs
* from the current persistency.
*
* \return true if the change can be performed, false otherwise
* \return true if the change can be performed, false otherwise
*/
bool
canChangePersistencyTo(ndn::nfd::FacePersistency newPersistency) const;
/** \brief changes face persistency setting
/**
* \brief Changes the persistency setting of the transport.
*/
void
setPersistency(ndn::nfd::FacePersistency newPersistency);
/** \return the link type of the transport
/**
* \brief Returns the link type of the transport.
*/
ndn::nfd::LinkType
getLinkType() const;
getLinkType() const noexcept
{
return m_linkType;
}
/** \return maximum payload size
* \retval MTU_UNLIMITED transport has no limit on payload size
/**
* \brief Returns the maximum payload size.
* \retval MTU_UNLIMITED The transport has no limit on payload size.
*
* This size is the maximum packet size that can be sent or received through this transport.
* This size is the maximum packet size that can be sent or received through this transport.
*
* For a datagram-based transport, this is typically the Maximum Transmission Unit (MTU),
* after the overhead of headers introduced by the transport has been accounted for.
* For a stream-based transport, this is typically unlimited (MTU_UNLIMITED).
* For a datagram-based transport, this is typically the Maximum Transmission Unit (MTU),
* after the overhead of headers introduced by the transport has been accounted for.
* For a stream-based transport, this is typically unlimited (MTU_UNLIMITED).
*/
ssize_t
getMtu() const;
getMtu() const noexcept
{
return m_mtu;
}
/** \return capacity of the send queue (in bytes)
* \retval QUEUE_UNSUPPORTED transport does not support queue capacity retrieval
* \retval QUEUE_ERROR transport was unable to retrieve the queue capacity
/**
* \brief Returns the capacity of the send queue (in bytes).
* \retval QUEUE_UNSUPPORTED The transport does not support queue capacity retrieval.
* \retval QUEUE_ERROR The transport was unable to retrieve the queue capacity.
*/
ssize_t
getSendQueueCapacity() const;
getSendQueueCapacity() const noexcept
{
return m_sendQueueCapacity;
}
public: // dynamic properties
/** \return transport state
/**
* \brief Returns the current transport state.
*/
TransportState
getState() const;
getState() const noexcept
{
return m_state;
}
/** \brief signals when transport state changes
/**
* \brief Signals when the transport state changes.
*/
signal::Signal<Transport, TransportState/*old*/, TransportState/*new*/> afterStateChange;
/** \return expiration time of the transport
* \retval time::steady_clock::TimePoint::max() the transport has indefinite lifetime
/**
* \brief Returns the expiration time of the transport.
* \retval time::steady_clock::time_point::max() The transport has an indefinite lifetime.
*/
time::steady_clock::TimePoint
getExpirationTime() const;
time::steady_clock::time_point
getExpirationTime() const noexcept
{
return m_expirationTime;
}
/** \return current send queue length of the transport (in octets)
* \retval QUEUE_UNSUPPORTED transport does not support queue length retrieval
* \retval QUEUE_ERROR transport was unable to retrieve the queue length
/**
* \brief Returns the current send queue length of the transport (in octets).
* \retval QUEUE_UNSUPPORTED The transport does not support queue length retrieval.
* \retval QUEUE_ERROR The transport was unable to retrieve the queue length.
*/
virtual ssize_t
getSendQueueLength()
@@ -259,34 +320,50 @@ public: // dynamic properties
}
protected: // upper interface to be invoked by subclass
/** \brief Pass a received link-layer packet to the upper layer for further processing
* \param packet the received packet, must be a valid and well-formed TLV block
* \param endpoint the source endpoint
* \warning Behavior is undefined if packet size exceeds the MTU limit
/**
* \brief Pass a received link-layer packet to the upper layer for further processing.
* \param packet The received packet, must be a valid and well-formed TLV block
* \param endpoint The source endpoint, optional for unicast transports
* \warning Behavior is undefined if packet size exceeds the MTU limit.
*/
void
receive(const Block& packet, const EndpointId& endpoint = 0);
receive(const Block& packet, const EndpointId& endpoint = {});
protected: // properties to be set by subclass
void
setLocalUri(const FaceUri& uri);
setLocalUri(const FaceUri& uri) noexcept
{
m_localUri = uri;
}
void
setRemoteUri(const FaceUri& uri);
setRemoteUri(const FaceUri& uri) noexcept
{
m_remoteUri = uri;
}
void
setScope(ndn::nfd::FaceScope scope);
setScope(ndn::nfd::FaceScope scope) noexcept
{
m_scope = scope;
}
void
setLinkType(ndn::nfd::LinkType linkType);
setLinkType(ndn::nfd::LinkType linkType) noexcept
{
m_linkType = linkType;
}
void
setMtu(ssize_t mtu);
setMtu(ssize_t mtu) noexcept;
void
setSendQueueCapacity(ssize_t sendQueueCapacity);
setSendQueueCapacity(ssize_t sendQueueCapacity) noexcept
{
m_sendQueueCapacity = sendQueueCapacity;
}
/** \brief set transport state
/** \brief Set transport state.
*
* Only the following transitions are valid:
* UP->DOWN, DOWN->UP, UP/DOWN->CLOSING/FAILED, CLOSING/FAILED->CLOSED
@@ -297,10 +374,13 @@ protected: // properties to be set by subclass
setState(TransportState newState);
void
setExpirationTime(const time::steady_clock::TimePoint& expirationTime);
setExpirationTime(const time::steady_clock::time_point& expirationTime) noexcept
{
m_expirationTime = expirationTime;
}
protected: // to be overridden by subclass
/** \brief invoked by canChangePersistencyTo to perform the check
/** \brief Invoked by canChangePersistencyTo to perform the check.
*
* Base class implementation returns false.
*
@@ -309,7 +389,7 @@ protected: // to be overridden by subclass
virtual bool
canChangePersistencyToImpl(ndn::nfd::FacePersistency newPersistency) const;
/** \brief invoked after the persistency has been changed
/** \brief Invoked after the persistency has been changed.
*
* The base class implementation does nothing.
* When overridden in a subclass, the function should update internal states
@@ -318,9 +398,9 @@ protected: // to be overridden by subclass
virtual void
afterChangePersistency(ndn::nfd::FacePersistency oldPersistency);
/** \brief performs Transport specific operations to close the transport
/** \brief Performs Transport specific operations to close the transport.
*
* This is invoked once by \p close() after changing state to CLOSING.
* This is invoked once by close() after changing state to CLOSING.
* It will not be invoked by Transport class if the transport is already CLOSING or CLOSED.
*
* When the cleanup procedure is complete, this method should change state to CLOSED.
@@ -330,7 +410,7 @@ protected: // to be overridden by subclass
doClose() = 0;
private: // to be overridden by subclass
/** \brief performs Transport specific operations to send a packet
/** \brief Performs Transport specific operations to send a packet.
* \param packet the packet to be sent, can be assumed to be valid and well-formed
* \pre transport state is either UP or DOWN
*/
@@ -338,145 +418,30 @@ private: // to be overridden by subclass
doSend(const Block& packet) = 0;
private:
Face* m_face;
LinkService* m_service;
Face* m_face = nullptr;
LinkService* m_service = nullptr;
FaceUri m_localUri;
FaceUri m_remoteUri;
ndn::nfd::FaceScope m_scope;
ndn::nfd::FacePersistency m_persistency;
ndn::nfd::LinkType m_linkType;
ssize_t m_mtu;
ssize_t m_sendQueueCapacity;
TransportState m_state;
time::steady_clock::TimePoint m_expirationTime;
ndn::nfd::FaceScope m_scope = ndn::nfd::FACE_SCOPE_NONE;
ndn::nfd::FacePersistency m_persistency = ndn::nfd::FACE_PERSISTENCY_NONE;
ndn::nfd::LinkType m_linkType = ndn::nfd::LINK_TYPE_NONE;
ssize_t m_mtu = MTU_INVALID;
ssize_t m_sendQueueCapacity = QUEUE_UNSUPPORTED;
TransportState m_state = TransportState::UP;
time::steady_clock::time_point m_expirationTime = time::steady_clock::time_point::max();
};
inline const Face*
Transport::getFace() const
{
return m_face;
}
inline const LinkService*
Transport::getLinkService() const
{
return m_service;
}
inline LinkService*
Transport::getLinkService()
{
return m_service;
}
inline const Transport::Counters&
Transport::getCounters() const
{
return *this;
}
inline FaceUri
Transport::getLocalUri() const
{
return m_localUri;
}
inline void
Transport::setLocalUri(const FaceUri& uri)
{
m_localUri = uri;
}
inline FaceUri
Transport::getRemoteUri() const
{
return m_remoteUri;
}
inline void
Transport::setRemoteUri(const FaceUri& uri)
{
m_remoteUri = uri;
}
inline ndn::nfd::FaceScope
Transport::getScope() const
{
return m_scope;
}
inline void
Transport::setScope(ndn::nfd::FaceScope scope)
{
m_scope = scope;
}
inline ndn::nfd::FacePersistency
Transport::getPersistency() const
{
return m_persistency;
}
inline ndn::nfd::LinkType
Transport::getLinkType() const
{
return m_linkType;
}
inline void
Transport::setLinkType(ndn::nfd::LinkType linkType)
{
m_linkType = linkType;
}
inline ssize_t
Transport::getMtu() const
{
return m_mtu;
}
inline ssize_t
Transport::getSendQueueCapacity() const
{
return m_sendQueueCapacity;
}
inline void
Transport::setSendQueueCapacity(ssize_t sendQueueCapacity)
{
m_sendQueueCapacity = sendQueueCapacity;
}
inline TransportState
Transport::getState() const
{
return m_state;
}
inline time::steady_clock::TimePoint
Transport::getExpirationTime() const
{
return m_expirationTime;
}
inline void
Transport::setExpirationTime(const time::steady_clock::TimePoint& expirationTime)
{
m_expirationTime = expirationTime;
}
std::ostream&
operator<<(std::ostream& os, const FaceLogHelper<Transport>& flh);
template<typename T>
typename std::enable_if<std::is_base_of<Transport, T>::value &&
!std::is_same<Transport, T>::value, std::ostream&>::type
std::enable_if_t<std::is_base_of_v<Transport, T> && !std::is_same_v<Transport, T>,
std::ostream&>
operator<<(std::ostream& os, const FaceLogHelper<T>& flh)
{
return os << FaceLogHelper<Transport>(flh.obj);
}
} // namespace face
} // namespace nfd
} // namespace nfd::face
#endif // NFD_DAEMON_FACE_TRANSPORT_HPP
+12 -13
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2022, Regents of the University of California,
* Copyright (c) 2014-2023, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -29,13 +29,14 @@
#include "unicast-udp-transport.hpp"
#include "common/global.hpp"
namespace nfd {
namespace face {
#include <boost/asio/ip/v6_only.hpp>
NFD_LOG_INIT(UdpChannel);
namespace nfd::face {
namespace ip = boost::asio::ip;
NFD_LOG_INIT(UdpChannel);
UdpChannel::UdpChannel(const udp::Endpoint& localEndpoint,
time::nanoseconds idleTimeout,
bool wantCongestionMarking,
@@ -82,7 +83,7 @@ UdpChannel::listen(const FaceCreatedCallback& onFaceCreated,
}
m_socket.open(m_localEndpoint.protocol());
m_socket.set_option(ip::udp::socket::reuse_address(true));
m_socket.set_option(boost::asio::socket_base::reuse_address(true));
if (m_localEndpoint.address().is_v6()) {
m_socket.set_option(ip::v6_only(true));
}
@@ -96,10 +97,9 @@ void
UdpChannel::waitForNewPeer(const FaceCreatedCallback& onFaceCreated,
const FaceCreationFailedCallback& onReceiveFailed)
{
m_socket.async_receive_from(boost::asio::buffer(m_receiveBuffer), m_remoteEndpoint,
[=] (auto&&... args) {
this->handleNewPeer(std::forward<decltype(args)>(args)..., onFaceCreated, onReceiveFailed);
});
m_socket.async_receive_from(boost::asio::buffer(m_receiveBuffer), m_remoteEndpoint, [=] (auto&&... args) {
handleNewPeer(std::forward<decltype(args)>(args)..., onFaceCreated, onReceiveFailed);
});
}
void
@@ -159,7 +159,7 @@ UdpChannel::createFace(const udp::Endpoint& remoteEndpoint,
// else, create a new face
ip::udp::socket socket(getGlobalIoService(), m_localEndpoint.protocol());
socket.set_option(ip::udp::socket::reuse_address(true));
socket.set_option(boost::asio::socket_base::reuse_address(true));
socket.bind(m_localEndpoint);
socket.connect(remoteEndpoint);
@@ -189,7 +189,7 @@ UdpChannel::createFace(const udp::Endpoint& remoteEndpoint,
auto transport = make_unique<UnicastUdpTransport>(std::move(socket), params.persistency,
m_idleFaceTimeout);
auto face = make_shared<Face>(std::move(linkService), std::move(transport));
face->setChannel(shared_from_this()); // use weak_from_this() in C++17
face->setChannel(weak_from_this());
m_channelFaces[remoteEndpoint] = face;
connectFaceClosedSignal(*face, [this, remoteEndpoint] { m_channelFaces.erase(remoteEndpoint); });
@@ -197,5 +197,4 @@ UdpChannel::createFace(const udp::Endpoint& remoteEndpoint,
return {true, face};
}
} // namespace face
} // namespace nfd
} // namespace nfd::face
Loaded 100 of 514 files, more files were not shown because too many files have changed in this diff. Show more