Compare commits

...
66 Commits
Author SHA1 Message Date
Alexander Afanasyev a46d41df0e Prepare release 0.6.3
Change-Id: I004e5609f26186ad270bbe5f2015052a7c2be89a
Refs: #4727
2018-09-18 08:52:46 -07:00
Md Ashiqur Rahman 922330b1e0 ci: add support for CentOS 7
refs: #4610

Change-Id: I699bbbe1f59dd3bd0fe23e94de28b44613833ce6
2018-09-16 12:30:57 -04:00
Teng Liang bce3cb528b tests: adapt to lp::PrefixAnnouncementHeader
Change-Id: Ic1bfeb76010955426b421f9239d9bbc987e2f316
refs: #4280
2018-09-16 09:23:54 -07:00
Davide Pesavento 7015694293 tests: use "daemon" user/group in Test{PrivilegeHelper,GeneralConfigSection}
Change-Id: I40ff8317a11e8fb88555f6c85dae3430295ac435
Refs: #3403
2018-09-15 18:40:21 -04:00
Davide Pesavento 69692abf50 build+ci: sync compilation flags and Travis-CI matrix with ndn-cxx
Change-Id: I49c7069bf1fcc1bf89c91a5f92cd830730a32a87
Refs: #4721
2018-09-11 18:11:23 -04:00
Chavoosh Ghasemi 32e7609edf table: Make LRU the default CS replacement policy
Change-Id: I01fe000544da9df860437ffc8869bc6b20e844c0
refs: #4728
2018-09-11 11:47:37 -07:00
Junxiao Shi d47cd63b1b rib: put PrefixAnnouncement in Route and RibEntry
refs #4650

Change-Id: I03a846cd6e013d52f080bd7b092cd392b0284f88
2018-09-11 03:10:00 +00:00
Teng Liang f59e58f202 core: add a facility to execute functions on the main io_service
Change-Id: I38e5f4ad5ed6798a14e0075fb7a14b792f8b2413
refs: #4683
2018-09-10 12:42:01 -07:00
Junxiao Shi 5200904303 rib: change FIB mocking mechanism
Previously, RIB test suites mock FIB updates by invoking RibManager
or Rib's private methods from a callback. In this commit, Rib class
exposes a `mockFibResponse` function variable, so that test cases
can directly specify FibUpdater's response without needing to invoke
private methods. This further allows replacing these private methods
with lambdas.

Also, logic for beginning RibUpdateBatch is abstracted out of control
command handlers, in preparation for PrefixAnnouncement-based RIB
update functions.

refs #4683

Change-Id: I0c95d8daa1458c704c7352a7809e6bed69134642
2018-09-10 12:33:56 +00:00
Davide Pesavento dda258af14 ci: introduce helper to preserve select env variables under sudo
Change-Id: Ia5db4b50e07a40c2eb256182a721c990c5b53382
Refs: #4610
2018-09-09 19:21:42 -07:00
Davide Pesavento 3e7fc83c12 face: add missing out-of-class definition of Transport::MIN_MTU
Also fix a type mismatch in Transport::m_sendQueueCapacity

Change-Id: I5b316917f5088587aefaa1bbb67efe017b77c155
2018-09-08 14:21:22 -04:00
Ashlesh Gawande f84bac5a7a rib: fix initialization error in Service
refs #4723

Change-Id: Ibfe313a3e2f1b0e57ee81661aa387397101228f9
2018-08-27 07:39:31 +00:00
Junxiao Shi f4cfed1a61 rib: move config parsing to Service class
This commit also de-duplicates code in Service class constructors
and reduces usage of unique_ptrs.

refs #4650

Change-Id: Ibbf454841b76ffe4d569b51fef3b1d06f7d2fdfc
2018-08-22 23:26:29 +00:00
Davide Pesavento 9f8b10e350 rib: change object ownership
rib::Service instead of RibManager now owns Controller,
Rib, FibUpdater, AutoPrefixPropagator, Readvertise objects.
RibManager is only responsible for serving RIB management
commands and datasets.

refs #4650

Change-Id: Idb99cdc6cb97b3e3c1bc56685b3ca121b062c7f5
2018-08-22 08:45:37 +00:00
Teng Liang 04d5ce685d rib: make Service globally accessible via get() static function
Change-Id: I2101fb81a613d301acbce7f26e062caa692c5e29
Refs: #4683
2018-08-11 00:54:18 +08:00
Teng Liang 952d6fd3d7 core: add a facility to execute functions on the RIB io_service
refs #4279

Change-Id: I29222053348e5d1737d47c85a59d29280b4b791b
2018-08-05 14:12:14 -04:00
Junxiao Shi b53fe6444b docs: improve ndn-autoconfig man page
refs #4201

Change-Id: I544d7ac9b71ab28ada11b47c852a3de681ed8b4c
2018-07-25 11:45:35 -06:00
Junxiao Shi a4d7fe0f22 tools: implement 'nfdc cs erase' command
refs #4318

Change-Id: If4dc401a3efff44a5bf4b3074d21797f8384cf9f
2018-07-20 06:51:41 -06:00
Davide Pesavento 457f135980 face+tools: use Boost.Endian for endianness conversions
Change-Id: Ia9c8777cc16130ace9f1ca478624d71e6a11fadd
2018-07-14 17:17:38 -04:00
Davide Pesavento d657d53eea build: require clang >= 3.6
Also fix an unused lambda capture warning with clang >= 5.0

Change-Id: I29c56cdf560da4a44efa038d4e65d868975aab6e
2018-06-26 21:16:10 -07:00
Eric Newberry 359135cfb2 tests: check against new SegmentFetcher error messages
refs #4364

Change-Id: I543930d76a01ef1eeef611fb589eb722342b5a86
2018-06-26 21:02:12 -07:00
Eric Newberry 4f8dd96fbf tools: add mtu option to 'nfdc face create'
refs #4789

Change-Id: I9e31c5fb460ee99199332ffb6fadc9f0f33125e9
2018-06-20 22:16:57 -07:00
Eric Newberry 812d615717 mgmt+face: allow MTU of datagram faces to be overridden
refs #4005

Change-Id: I01d98b88cdee41b633f6fb9a5600088efe8de749
2018-06-19 16:28:29 -07:00
Davide Pesavento e4b2238b33 Improve and simplify code with modern C++ features
Change-Id: I83bf5513c2a1f90ba5a59e93c473306864b27d94
2018-06-11 20:26:47 -04:00
Davide Pesavento 1705744468 tests: stop using deprecated {get,set}FinalBlockId
Change-Id: Ibe3f7b394487773139ec4e17d2b87ca8cb06504a
2018-06-06 16:25:04 -04:00
Davide Pesavento c0822fa4a5 build: switch to C++14
Change-Id: I7a32dad01e74ef5b7c5f37a5464d0b17a7882c61
Refs: #3076
2018-06-06 16:24:22 -04:00
Nick Gordon 7b8e797c32 docs: minor changes to the contributing guide
refs: #4475

Change-Id: I7e1e43e5f0990b7f1a9ff7e3463ebe620e92fe4e
2018-05-24 10:20:50 -04:00
Davide Pesavento 9c33b90fd3 core+face+tools: use asio::ip::address::from_string directly
The compatibility wrappers in ndn-cxx are no longer needed
and will be deprecated soon.

Change-Id: I394164c11dfe776f1d5a6f7c0dceffe9ce6ad85f
2018-05-22 18:22:49 -04:00
Davide Pesavento 5f35f64d9a build: require gcc >= 5.3 and boost >= 1.58
This effectively drops support for all versions of Ubuntu older than 16.04

Change-Id: If1c96cc697d38a94588f126a89d13ec8e582702d
Refs: #4462
2018-05-10 20:33:57 -04:00
Davide Pesavento a3148081ce core: reimplement logging using ndn-cxx's facility
Change-Id: Ifc7c5d70a61ad405dc1f1adfa522a2c0ad1586ab
Refs: #4580
2018-05-05 23:04:22 -04:00
Alexander Afanasyev 782a1d1621 Prepare release 0.6.2
Change-Id: I50c8479efa4fff6244f50555d8ff552530bc4509
Refs: #4564
2018-05-03 15:00:14 -04:00
Davide Pesavento 67f797f9a3 ci: add gcc-8 to Travis-CI build matrix
Change-Id: Ibf4ea92af716c44c5a91e704c605b2b811f3122e
2018-04-28 14:51:27 -04:00
Junxiao Shi 21e0193e5c face: piggyback Ack field with fixed-width encoding
refs #4403

Change-Id: I4b0123d20aea058581774d467452553724fddc61
2018-04-21 10:39:05 +00:00
Davide Pesavento e34a2825f1 core: silence truncation warning in LoggerTimestamp's operator<<
Change-Id: I85882bf5589fbdb8239deec285509c123740ec25
Refs: #4365
2018-04-20 13:10:18 -04:00
Davide Pesavento 45898d2215 tools: fix compilation with Boost 1.67
Change-Id: Ia2bdaa0c78757a03796acf64b15c781ec9fa6c0e
Refs: #4584
2018-04-19 12:32:40 -04:00
Junxiao Shi bd72431945 mgmt: implement cs/erase command
refs #4318

Change-Id: I2c8180cde940cc378a219f9aaecae71cd3b0b28c
2018-04-17 02:23:48 +00:00
Davide Pesavento 87fc0f8d6f core: drop std::function and ndn::Exclude from common.hpp, add ndn::optional
Change-Id: Ie3983d8b6f9929430efd8ada8d942e3f95755cd4
2018-04-12 14:23:40 -04:00
Davide Pesavento 981db808cb Delete core/asserts.hpp and use ndn-cxx's util/concepts.hpp instead
Change-Id: I13a3460c1c3a90ea0fdca3d8212267353f72af4f
2018-04-11 19:24:54 -04:00
Davide Pesavento 1cb619e63b docs: fully qualify types documented via doxygen's \class command
Change-Id: I38594e4d358078d3c6dc7c588695c4b299a44895
2018-04-11 19:24:48 -04:00
Alexander Afanasyev ded17426c6 face: Configurable IP subnets for "local" TCP faces
Change-Id: Idaddfe4b2c304b552d2e132235f4c3d3e6c2ebcb
Refs: #4546
2018-04-11 19:23:41 -04:00
Alexander Afanasyev e4d745d41f core: Add IpAddressPredicate for white-/blacklisting IP address subnets
Change-Id: I9f67c4bcbc55e8a8de0bb70812c5562ba083c948
Refs: #4546
2018-04-10 19:28:07 -04:00
Teng Liang 43bb2315ea fw: introduce afterReceiveData strategy trigger
Change-Id: Ia805f1bd48f481c9b903b6ce5c388dd66fbbb7d1
refs: #4290
2018-04-10 05:30:36 -07:00
Alexander Afanasyev 3bdc1decf6 core: Add support for IPv6 subnets in Network::isValidCidr
This change effectively adds support for IPv6 subnets in white-/blacklists
of NetworkInterfacePredicate

Change-Id: I1962100329d398b4659c4d1a4a0975fa354af026
Refs: #4546
2018-04-09 19:25:14 +00:00
Junxiao Shi 30c37ab9bf table: add Cs::erase method
This commit also corrects CS's description in Doxygen.

refs #4318

Change-Id: Ie8854a2e2b59a072b98603c0cc31768bb84ea6d2
2018-04-09 14:26:47 +00:00
Eric Newberry c14a8acf39 build: find Boost lib architecture automatically
refs #4573

Change-Id: Ie58f18c0634a837b303e290018f8a9a5bb71f5c7
2018-04-07 16:32:43 -07:00
Eric Newberry 971d9621ce face: correctly handle removed fragments in LpReliability
refs #4479

Change-Id: Id5d1aa231ddfc10a14859ef819f6dde0a4111501
2018-04-02 18:37:29 -07:00
Eric Newberry 3406dc9742 docs: only use sphinxcontrib-doxylink on Python 3
refs #4553

Change-Id: I001d1fddc13994f8a522251a439cad0467bd8c58
2018-03-25 14:35:18 -07:00
Teng Liang 85a36632a7 fw: introduce afterContentStoreHit strategy trigger
Change-Id: I71ca9e21467d2296203eb9686bff7647b1140271
refs: #4290
2018-03-22 21:57:06 -07:00
Junxiao Shi 7a36ac7d9d tools: include CS config in 'nfdc cs info'
Also, ForwarderGeneralModule::formatItemText now uses ItemAttributes.

refs #4050

Change-Id: I1b2bde29b82e4b3910d87b41efd90e273052b18d
2018-03-21 15:23:22 +00:00
Junxiao Shi 057d149fda table: enforce NameTree max depth universally
refs #4262

Change-Id: Ia9b04a89c12cd09aa244201b513cc1808c0c473f
2018-03-20 17:14:18 +00:00
Teng Liang 7003e0bc66 fw: replace straggler timer with per-strategy decision
remove onInterestReject pipeline

refs: #4200

Change-Id: I184d7ef7f732efda3d1066eef6cd89e36a6a8802
2018-03-20 00:26:15 -07:00
Davide Pesavento 3cf75dc10b mgmt: prevent potential nullptr dereference in FaceManager
Change-Id: Ice622f2b51a3be448dc1c211dc4f80d967db14c6
Refs: #4548
2018-03-17 00:38:03 -04:00
Davide Pesavento 068a71d6f0 ci: update .travis.yml
Change-Id: I0bb8694ccbef65ec124def2aafcd772c8dd058c7
2018-03-15 00:52:34 -04:00
Davide Pesavento 0064c1dd91 build: update waf to version 2.0.6
Major cleanup of all build scripts

Change-Id: I6904f034d40adc66366fdf08749900ffb31c68d9
2018-03-08 20:16:30 -05:00
Junxiao Shi cdf7845986 tools: add 'nfdc cs config' command
refs #4050

Change-Id: Ifc49b78a286b1947452d3d7917b5937b95d1bfe5
2018-03-03 07:37:47 -08:00
Junxiao Shi 8dc473a724 tools: simplify on/off attribute printing
refs #4004

Change-Id: Idb666ff4dbeddc37f1cb10710ba3d75f7fe8bdb5
2018-03-03 07:35:50 -08:00
Teng Liang 6f09ab6cde fw+table: add isSatisfied and dataFreshnessPeriod to PIT entry
Change-Id: I00731028131139164adca342d0a0fd7d3af0709a
refs: #4290
2018-03-02 23:22:32 -07:00
Davide Pesavento cfb1a315ed mgmt: eliminate FaceManager::setConfigFile()
Change-Id: Ib39b05a969345448b3719047093577df31d2bf8a
Refs: #3904
2018-03-01 01:35:36 -05:00
Teng Liang 63086448bf fw: remove onInterestUnsatisfied pipeline stage
Change-Id: Ic008bb26b87db176bac8d51230e53f923b19e5d2
refs: 4290
2018-02-27 13:20:11 -07:00
Davide Pesavento 47456e7d98 daemon: log more detailed build info at startup
Change-Id: Ie0a96a3871c24879d6bb2afdd8544da9724253a2
2018-02-25 19:54:14 -05:00
Davide Pesavento b922c8891c tools: ignore URL query string in nfd-status-http-server
Change-Id: I5e071b7f036a0ef4e9a6e8b6a1eaf637aa5ad92e
2018-02-25 19:51:52 -05:00
Davide Pesavento 9e5b8af1f5 tools: fix a couple of HTML/CSS validation errors in the status page
Also update reset.css and text.css from the Unsemantic project
https://github.com/nathansmith/unsemantic/tree/master/assets/stylesheets

Change-Id: I8f6292461f13902d39b511399515b3efdf50c8c5
2018-02-25 19:50:12 -05:00
Davide Pesavento 6a88b5f435 tools: use CSS to paint table rows with alternating colors in the status page
Change-Id: I04416437e2b18b452bde2f478084090f92003a85
2018-02-25 19:49:04 -05:00
Davide Pesavento d9c520bed9 tools: fix listing of face flags in HTML status page
Change-Id: I288615eb8379979b0e3eb9599e1adb1d06478814
2018-02-24 14:49:14 -05:00
Davide Pesavento d214744ab8 tools: alias 'nfdc cs' to 'nfdc cs info'
Change-Id: Ied1d34a84110ee0b6488d35d56fb1caecaf14117
Refs: #4498
2018-02-20 21:39:09 -05:00
Davide Pesavento 2a58815ee3 tools: extend nfdc help to cover more cases
Change-Id: I0cd182c8635b15c8ffb750c913e14fa99e595d45
Refs: #4503
2018-02-20 21:34:00 -05:00
293 changed files with 6458 additions and 5372 deletions

No files matched your search

+30 -9
View File
@@ -1,9 +1,30 @@
.DS*
.waf-1*
.waf3-*
.lock*
*.pyc
*.pyo
build/
VERSION
unit-tests.conf
# Emacs
*~
\#*\#
/.emacs.desktop
/.emacs.desktop.lock
*.elc
.\#*
# Visual Studio Code
.vscode/
# macOS
.DS_Store
.AppleDouble
.LSOverride
._*
# Waf build system
/build/
.waf-*-*/
.waf3-*-*/
.lock-waf*
# Compiled python code
__pycache__/
*.py[cod]
# Other
/unit-tests.conf
/VERSION
+15
View File
@@ -32,3 +32,18 @@ if has Ubuntu $NODE_LABELS; then
sudo easy_install --upgrade gcovr
fi
fi
if has CentOS $NODE_LABELS; then
sudo yum -y install yum-utils pkgconfig libpcap-devel \
openssl-devel libtranslit-icu \
python-devel sqlite-devel \
devtoolset-7-libasan-devel \
devtoolset-7-liblsan-devel
sudo yum -y groupinstall 'Development Tools'
svn checkout https://github.com/cmscaltech/sandie-ndn/trunk/packaging/RPMS/x86_64
sudo rpm -U --force x86_64/boost-license*
sudo rpm -U --force x86_64/boost-doc-html*
sudo rpm -U --force x86_64/libboost*
sudo rpm -U --force x86_64/boost-devel*
fi
+3 -3
View File
@@ -37,14 +37,14 @@ fi
sudo rm -f /usr/local/bin/ndnsec*
sudo rm -fr /usr/local/include/ndn-cxx
sudo rm -f /usr/local/lib/libndn-cxx*
sudo rm -f /usr/local/lib/pkgconfig/libndn-cxx.pc
sudo rm -f /usr/local/lib{,64}/libndn-cxx*
sudo rm -f /usr/local/lib{,64}/pkgconfig/libndn-cxx.pc
pushd ndn-cxx >/dev/null
./waf configure --color=yes --enable-shared --disable-static --without-osx-keychain
./waf build --color=yes -j${WAF_JOBS:-1}
sudo env "PATH=$PATH" ./waf install --color=yes
sudo_preserve_env PATH -- ./waf install --color=yes
popd >/dev/null
popd >/dev/null
+4 -4
View File
@@ -17,7 +17,7 @@ elif [[ -z $DISABLE_ASAN ]]; then
fi
# Cleanup
sudo env "PATH=$PATH" ./waf --color=yes distclean
sudo_preserve_env PATH -- ./waf --color=yes distclean
if [[ $JOB_NAME != *"code-coverage" && $JOB_NAME != *"limited-build" ]]; then
# Configure/build in optimized mode with tests
@@ -25,14 +25,14 @@ if [[ $JOB_NAME != *"code-coverage" && $JOB_NAME != *"limited-build" ]]; then
./waf --color=yes build -j${WAF_JOBS:-1}
# Cleanup
sudo env "PATH=$PATH" ./waf --color=yes distclean
sudo_preserve_env PATH -- ./waf --color=yes distclean
# Configure/build in optimized mode without tests, but with "other tests"
./waf --color=yes configure --with-other-tests
./waf --color=yes build -j${WAF_JOBS:-1}
# Cleanup
sudo env "PATH=$PATH" ./waf --color=yes distclean
sudo_preserve_env PATH -- ./waf --color=yes distclean
fi
# Configure/build in debug mode with tests and without precompiled headers
@@ -42,4 +42,4 @@ fi
# (tests will be run against debug version)
# Install
sudo env "PATH=$PATH" ./waf --color=yes install
sudo_preserve_env PATH -- ./waf --color=yes install
+9 -4
View File
@@ -41,6 +41,9 @@ ASAN_OPTIONS+=":strict_string_checks=true"
ASAN_OPTIONS+=":strip_path_prefix=${PWD}/"
export ASAN_OPTIONS
export BOOST_TEST_BUILD_INFO=1
export BOOST_TEST_COLOR_OUTPUT=1
# First run all tests as unprivileged user
./build/unit-tests-core $(ut_log_args core)
./build/unit-tests-daemon $(ut_log_args daemon)
@@ -48,7 +51,9 @@ export ASAN_OPTIONS
./build/unit-tests-tools $(ut_log_args tools)
# Then use sudo to run those tests that need superuser powers
sudo -E ./build/unit-tests-core -t TestPrivilegeHelper $(ut_log_args core-privilege)
sudo -E ./build/unit-tests-daemon -t Face/*Ethernet* $(ut_log_args daemon-ethernet)
sudo -E ./build/unit-tests-daemon -t Face/TestUdpFactory $(ut_log_args daemon-udp-factory)
sudo -E ./build/unit-tests-daemon -t Mgmt/TestGeneralConfigSection/UserAndGroupConfig,NoUserConfig $(ut_log_args daemon-user-config)
sudo_preserve_env ASAN_OPTIONS BOOST_TEST_COLOR_OUTPUT -- \
./build/unit-tests-core -t TestPrivilegeHelper $(ut_log_args core-privilege)
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 -- \
./build/unit-tests-daemon -t Face/TestUdpFactory $(ut_log_args daemon-udp)
+2 -2
View File
@@ -13,13 +13,13 @@ Environment Variables Used in Build Scripts
* `[OS_TYPE]`: `Linux`
* `[DISTRO_TYPE]`: `Ubuntu`
* `[DISTRO_VERSION]`: `Ubuntu-14.04`, `Ubuntu-16.04`
* `[DISTRO_VERSION]`: `Ubuntu-16.04`, `Ubuntu-18.04`
Possible values for OS X / macOS:
* `[OS_TYPE]`: `OSX`
* `[DISTRO_TYPE]`: `OSX` (can be absent)
* `[DISTRO_VERSION]`: `OSX-10.10`, `OSX-10.11`, `OSX-10.12`
* `[DISTRO_VERSION]`: `OSX-10.11`, `OSX-10.12`, `OSX-10.13`
- `JOB_NAME`: optional variable to define type of the job. Depending on the defined job type,
the build scripts can perform different tasks.
+19
View File
@@ -16,3 +16,22 @@ has() {
set ${saved_xtrace}
return ${ret}
}
sudo_preserve_env() {
local saved_xtrace
[[ $- == *x* ]] && saved_xtrace=-x || saved_xtrace=+x
set +x
local vars=()
while [[ $# -gt 0 ]]; do
local arg=$1
shift
case ${arg} in
--) break ;;
*) vars+=("${arg}=${!arg}") ;;
esac
done
set ${saved_xtrace}
sudo env "${vars[@]}" "$@"
}
+40 -57
View File
@@ -1,5 +1,5 @@
language: cpp
dist: trusty
dist: xenial
sudo: required
env:
global:
@@ -10,101 +10,84 @@ matrix:
include:
# Linux/gcc
# https://launchpad.net/~ubuntu-toolchain-r/+archive/ubuntu/test/+packages
- os: linux
env: COMPILER=g++-4.8
- os: linux
env: COMPILER=g++-4.9
addons:
apt:
sources: ubuntu-toolchain-r-test
packages: g++-4.9
- os: linux
env: COMPILER=g++-5
addons:
apt:
sources: ubuntu-toolchain-r-test
packages: g++-5
- os: linux
env: COMPILER=g++-6
addons:
apt:
sources: ubuntu-toolchain-r-test
packages: g++-6
- os: linux
env: COMPILER=g++-7
addons:
apt:
sources: ubuntu-toolchain-r-test
packages: g++-7
- os: linux
env: COMPILER=g++-8
# Linux/clang
# https://apt.llvm.org/
- os: linux
env: COMPILER=clang++-3.5
addons:
apt:
packages: clang-3.5
- os: linux
env: COMPILER=clang++-3.6
addons:
apt:
packages: clang-3.6
- os: linux
env: COMPILER=clang++-3.7 DISABLE_ASAN=yes
addons:
apt:
sources: ["llvm-toolchain-precise-3.7", "ubuntu-toolchain-r-test"]
packages: clang-3.7
- os: linux
env: COMPILER=clang++-3.8
addons:
apt:
sources: ["llvm-toolchain-precise-3.8", "ubuntu-toolchain-r-test"]
packages: clang-3.8
- os: linux
env: COMPILER=clang++-3.9 DISABLE_ASAN=yes
addons:
apt:
sources: ["llvm-toolchain-trusty-3.9", "ubuntu-toolchain-r-test"]
packages: clang-3.9
env: COMPILER=clang++-3.9
- os: linux
env: COMPILER=clang++-4.0
addons:
apt:
sources: ["llvm-toolchain-trusty-4.0", "ubuntu-toolchain-r-test"]
packages: clang-4.0
- os: linux
env: COMPILER=clang++-5.0
addons:
apt:
sources: ["llvm-toolchain-trusty-5.0", "ubuntu-toolchain-r-test"]
packages: clang-5.0
- os: linux
env: COMPILER=clang++-6.0
addons:
apt:
sources: ["llvm-toolchain-trusty", "ubuntu-toolchain-r-test"]
packages: clang-6.0
- os: linux
env: COMPILER=clang++-7
- os: linux
env: COMPILER=clang++-8
# macOS/clang
# https://docs.travis-ci.com/user/osx-ci-environment/#OS-X-Version
# https://docs.travis-ci.com/user/reference/osx/#OS-X-Version
- os: osx
osx_image: xcode7.3
env: OSX_VERSION=10.11
- os: osx
osx_image: xcode8
env: OSX_VERSION=10.11
- os: osx
osx_image: xcode8.3
env: OSX_VERSION=10.12
- os: osx
osx_image: xcode9.2
env: OSX_VERSION=10.12
- os: osx
osx_image: xcode9.4
env: OSX_VERSION=10.13
- os: osx
osx_image: xcode10
env: OSX_VERSION=10.13
allow_failures:
- env: COMPILER=clang++-6.0
- env: COMPILER=clang++-3.6
- env: COMPILER=clang++-3.7 DISABLE_ASAN=yes
- env: COMPILER=clang++-8
fast_finish: true
install: |
case ${COMPILER} in
g++-[6789])
travis_retry sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
travis_retry sudo apt-get -qq update
travis_retry sudo apt-get -qy install "${COMPILER}"
;;
clang++-*)
CLANG_VERSION=${COMPILER/clang++}
if [[ ${CLANG_VERSION} != "-3."* ]]; then
travis_retry wget -nv -O - "https://apt.llvm.org/llvm-snapshot.gpg.key" | sudo apt-key add -
travis_retry sudo add-apt-repository -y "deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial${CLANG_VERSION/-8} main"
fi
travis_retry sudo apt-get -qq update
travis_retry sudo apt-get -qy install "clang${CLANG_VERSION}"
;;
esac
before_script:
- if [[ ${TRAVIS_OS_NAME} == linux ]]; then export NODE_LABELS="Linux Ubuntu Ubuntu-14.04"; fi
- if [[ ${TRAVIS_OS_NAME} == linux ]]; then export NODE_LABELS="Linux Ubuntu Ubuntu-16.04"; fi
- if [[ ${TRAVIS_OS_NAME} == osx ]]; then export NODE_LABELS="OSX OSX-${OSX_VERSION}"; fi
- if [[ -n ${COMPILER} ]]; then export CXX=${COMPILER}; fi
- ${CXX:-c++} --version
-23
View File
@@ -1,23 +0,0 @@
# -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
#
# Copyright (c) 2014, Regents of the University of California
#
# GPL 3.0 license, see the COPYING.md file for more information
from waflib import Configure
BOOST_ASIO_HAS_KQUEUE_CHECK = '''
#include <boost/asio.hpp>
#if defined(BOOST_ASIO_HAS_KQUEUE) and BOOST_VERSION == 105600
#error "Ethernet face support cannot be enabled on this platform with boost 1.56"
#endif
'''
@Configure.conf
def check_asio_pcap_support(conf):
# https://svn.boost.org/trac/boost/ticket/10367
if conf.check_cxx(msg='Checking if Ethernet face support can be enabled',
fragment=BOOST_ASIO_HAS_KQUEUE_CHECK,
features='cxx', use='BOOST', mandatory=False):
conf.define('HAVE_ASIO_PCAP_SUPPORT', 1)
conf.env['HAVE_ASIO_PCAP_SUPPORT'] = True
+6 -2
View File
@@ -54,8 +54,7 @@ from waflib import Utils, Logs, Errors
from waflib.Configure import conf
from waflib.TaskGen import feature, after_method
BOOST_LIBS = ['/usr/lib/x86_64-linux-gnu', '/usr/lib/i386-linux-gnu',
'/usr/lib', '/usr/local/lib', '/opt/local/lib', '/sw/lib', '/lib']
BOOST_LIBS = ['/usr/lib', '/usr/local/lib', '/opt/local/lib', '/sw/lib', '/lib']
BOOST_INCLUDES = ['/usr/include', '/usr/local/include', '/opt/local/include', '/sw/include']
BOOST_VERSION_FILE = 'boost/version.hpp'
BOOST_VERSION_CODE = '''
@@ -404,6 +403,11 @@ def check_boost(self, *k, **kw):
var = kw.get('uselib_store', 'BOOST')
self.find_program('dpkg-architecture', var='DPKG_ARCHITECTURE', mandatory=False)
if self.env.DPKG_ARCHITECTURE:
deb_host_multiarch = self.cmd_and_log([self.env.DPKG_ARCHITECTURE[0], '-qDEB_HOST_MULTIARCH'])
BOOST_LIBS.insert(0, '/usr/lib/%s' % deb_host_multiarch.strip())
self.start_msg('Checking boost includes')
self.env['INCLUDES_%s' % var] = inc = self.boost_get_includes(**params)
versions = self.boost_get_version(inc)
+4 -4
View File
@@ -1,15 +1,15 @@
# -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
from waflib import TaskGen, Logs
from waflib import TaskGen
def options(opt):
opt.add_option('--with-coverage', action='store_true', default=False, dest='with_coverage',
help='''Set compiler flags for gcc to enable code coverage information''')
opt.add_option('--with-coverage', action='store_true', default=False,
help='Add compiler flags to enable code coverage information')
def configure(conf):
if conf.options.with_coverage:
if not conf.options.debug:
conf.fatal("Code coverage flags require debug mode compilation (add --debug)")
conf.fatal('Code coverage flags require debug mode compilation (add --debug)')
conf.check_cxx(cxxflags=['-fprofile-arcs', '-ftest-coverage', '-fPIC'],
linkflags=['-fprofile-arcs'], uselib_store='GCOV', mandatory=True)
+32 -34
View File
@@ -1,44 +1,45 @@
# -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
from waflib import Logs, Configure, Utils
from waflib import Configure, Logs, Utils
def options(opt):
opt.add_option('--debug', '--with-debug', action='store_true', default=False, dest='debug',
help='''Compile in debugging mode with minimal optimizations (-O0 or -Og)''')
opt.add_option('--debug', '--with-debug', action='store_true', default=False,
help='Compile in debugging mode with minimal optimizations (-O0 or -Og)')
def configure(conf):
conf.start_msg('Checking C++ compiler version')
cxx = conf.env['CXX_NAME'] # CXX_NAME is the generic name of the compiler
ccver = tuple(int(i) for i in conf.env['CC_VERSION'])
cxx = conf.env.CXX_NAME # generic name of the compiler
ccver = tuple(int(i) for i in conf.env.CC_VERSION)
ccverstr = '.'.join(conf.env.CC_VERSION)
errmsg = ''
warnmsg = ''
if cxx == 'gcc':
if ccver < (4, 8, 2):
if ccver < (5, 3, 0):
errmsg = ('The version of gcc you are using is too old.\n'
'The minimum supported gcc version is 4.8.2.')
'The minimum supported gcc version is 5.3.0.')
conf.flags = GccFlags()
elif cxx == 'clang':
if ccver < (3, 4, 0):
if ccver < (3, 6, 0):
errmsg = ('The version of clang you are using is too old.\n'
'The minimum supported clang version is 3.4.0.')
'The minimum supported clang version is 3.6.0.')
conf.flags = ClangFlags()
else:
warnmsg = 'Note: %s compiler is unsupported' % cxx
conf.flags = CompilerFlags()
if errmsg:
conf.end_msg('.'.join(conf.env['CC_VERSION']), color='RED')
conf.end_msg(ccverstr, color='RED')
conf.fatal(errmsg)
elif warnmsg:
conf.end_msg('.'.join(conf.env['CC_VERSION']), color='YELLOW')
conf.end_msg(ccverstr, color='YELLOW')
Logs.warn(warnmsg)
else:
conf.end_msg('.'.join(conf.env['CC_VERSION']))
conf.end_msg(ccverstr)
conf.areCustomCxxflagsPresent = (len(conf.env.CXXFLAGS) > 0)
# General flags are always applied (e.g., selecting C++11 mode)
# General flags are always applied (e.g., selecting C++ language standard)
generalFlags = conf.flags.getGeneralFlags(conf)
conf.add_supported_cxxflags(generalFlags['CXXFLAGS'])
conf.add_supported_linkflags(generalFlags['LINKFLAGS'])
@@ -53,10 +54,10 @@ def check_compiler_flags(conf):
extraFlags = conf.flags.getDebugFlags(conf)
if conf.areCustomCxxflagsPresent:
missingFlags = [x for x in extraFlags['CXXFLAGS'] if x not in conf.env.CXXFLAGS]
if len(missingFlags) > 0:
Logs.warn("Selected debug mode, but CXXFLAGS is set to a custom value '%s'"
% " ".join(conf.env.CXXFLAGS))
Logs.warn("Default flags '%s' are not activated" % " ".join(missingFlags))
if missingFlags:
Logs.warn('Selected debug mode, but CXXFLAGS is set to a custom value "%s"'
% ' '.join(conf.env.CXXFLAGS))
Logs.warn('Default flags "%s" will not be used' % ' '.join(missingFlags))
else:
extraFlags = conf.flags.getOptimizedFlags(conf)
@@ -106,6 +107,9 @@ def add_supported_linkflags(self, linkflags):
class CompilerFlags(object):
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': []}
@@ -124,7 +128,7 @@ class GccBasicFlags(CompilerFlags):
"""
def getGeneralFlags(self, conf):
flags = super(GccBasicFlags, self).getGeneralFlags(conf)
flags['CXXFLAGS'] += ['-std=c++11']
flags['CXXFLAGS'] += ['-std=c++14']
return flags
def getDebugFlags(self, conf):
@@ -160,25 +164,19 @@ class GccBasicFlags(CompilerFlags):
class GccFlags(GccBasicFlags):
def getDebugFlags(self, conf):
flags = super(GccFlags, self).getDebugFlags(conf)
version = tuple(int(i) for i in conf.env['CC_VERSION'])
if version < (5, 1, 0):
flags['CXXFLAGS'] += ['-Wno-missing-field-initializers']
flags['CXXFLAGS'] += ['-fdiagnostics-color'] # gcc >= 4.9
flags['CXXFLAGS'] += ['-fdiagnostics-color']
return flags
def getOptimizedFlags(self, conf):
flags = super(GccFlags, self).getOptimizedFlags(conf)
version = tuple(int(i) for i in conf.env['CC_VERSION'])
if version < (5, 1, 0):
flags['CXXFLAGS'] += ['-Wno-missing-field-initializers']
flags['CXXFLAGS'] += ['-fdiagnostics-color'] # gcc >= 4.9
flags['CXXFLAGS'] += ['-fdiagnostics-color']
return flags
class ClangFlags(GccBasicFlags):
def getGeneralFlags(self, conf):
flags = super(ClangFlags, self).getGeneralFlags(conf)
version = tuple(int(i) for i in conf.env['CC_VERSION'])
if Utils.unversioned_sys_platform() == 'darwin' and version >= (9, 0, 0): # Bug #4296
if Utils.unversioned_sys_platform() == 'darwin' and self.getCompilerVersion(conf) >= (9, 0, 0):
# Bug #4296
flags['CXXFLAGS'] += [['-isystem', '/usr/local/include'], # for Homebrew
['-isystem', '/opt/local/include']] # for MacPorts
return flags
@@ -188,15 +186,13 @@ class ClangFlags(GccBasicFlags):
flags['CXXFLAGS'] += ['-fcolor-diagnostics',
'-Wextra-semi',
'-Wundefined-func-template',
'-Wno-error=deprecated-register',
'-Wno-error=infinite-recursion', # Bug #3358
'-Wno-error=keyword-macro', # Bug #3235
'-Wno-error=unneeded-internal-declaration', # Bug #1588
'-Wno-unused-local-typedef', # Bugs #2657 and #3209
]
version = tuple(int(i) for i in conf.env['CC_VERSION'])
version = self.getCompilerVersion(conf)
if version < (3, 9, 0) or (Utils.unversioned_sys_platform() == 'darwin' and version < (8, 1, 0)):
flags['CXXFLAGS'] += ['-Wno-unknown-pragmas']
if version < (6, 0, 0):
flags['CXXFLAGS'] += ['-Wno-missing-braces'] # Bug #4721
return flags
def getOptimizedFlags(self, conf):
@@ -206,7 +202,9 @@ class ClangFlags(GccBasicFlags):
'-Wundefined-func-template',
'-Wno-unused-local-typedef', # Bugs #2657 and #3209
]
version = tuple(int(i) for i in conf.env['CC_VERSION'])
version = self.getCompilerVersion(conf)
if version < (3, 9, 0) or (Utils.unversioned_sys_platform() == 'darwin' and version < (8, 1, 0)):
flags['CXXFLAGS'] += ['-Wno-unknown-pragmas']
if version < (6, 0, 0):
flags['CXXFLAGS'] += ['-Wno-missing-braces'] # Bug #4721
return flags
+5 -5
View File
@@ -4,10 +4,10 @@ from waflib import Options, Logs
from waflib.Configure import conf
def addDependencyOptions(self, opt, name, extraHelp=''):
opt.add_option('--with-%s' % name, type='string', default=None,
dest='with_%s' % name,
opt.add_option('--with-%s' % name, metavar='PATH',
help='Path to %s, e.g., /usr/local %s' % (name, extraHelp))
setattr(Options.OptionsContext, "addDependencyOptions", addDependencyOptions)
setattr(Options.OptionsContext, 'addDependencyOptions', addDependencyOptions)
@conf
def checkDependency(self, name, **kw):
@@ -18,8 +18,8 @@ def checkDependency(self, name, **kw):
kw['mandatory'] = kw.get('mandatory', True)
if root:
isOk = self.check_cxx(includes="%s/include" % root,
libpath="%s/lib" % root,
isOk = self.check_cxx(includes='%s/include' % root,
libpath='%s/lib' % root,
**kw)
else:
isOk = self.check_cxx(**kw)
+5 -10
View File
@@ -52,7 +52,7 @@ Note that precompiled header must have multiple inclusion guards. If the guards
"""
import os
from waflib import Task, TaskGen, Logs, Utils
from waflib import Task, TaskGen, Utils
from waflib.Tools import c_preproc, cxx
@@ -67,11 +67,6 @@ def options(opt):
def configure(conf):
if (conf.options.with_pch and conf.env['COMPILER_CXX'] in PCH_COMPILER_OPTIONS.keys()):
if Utils.unversioned_sys_platform() == "darwin" and conf.env['CXX_NAME'] == 'clang':
version = tuple(int(i) for i in conf.env['CC_VERSION'])
if version < (6, 1, 0):
# Issue #2804
return
conf.env.WITH_PCH = True
flags = PCH_COMPILER_OPTIONS[conf.env['COMPILER_CXX']]
conf.env.CXXPCH_F = flags[0]
@@ -95,8 +90,8 @@ def apply_pch(self):
if getattr(self, 'name', None):
try:
task = self.bld.pch_tasks[self.name]
self.bld.fatal("Duplicated 'pch' task with name %r" % self.name)
task = self.bld.pch_tasks["%s.%s" % (self.name, self.idx)]
self.bld.fatal("Duplicated 'pch' task with name %r" % "%s.%s" % (self.name, self.idx))
except KeyError:
pass
@@ -109,7 +104,7 @@ def apply_pch(self):
self.pch_task = task
if getattr(self, 'name', None):
self.bld.pch_tasks[self.name] = task
self.bld.pch_tasks["%s.%s" % (self.name, self.idx)] = task
@TaskGen.feature('cxx')
@TaskGen.after_method('process_source', 'propagate_uselib_vars')
@@ -134,7 +129,7 @@ def add_pch(self):
x.env.append_value('CXXFLAGS', self.env['CXXPCH_F'] + [pch.target])
class gchx(Task.Task):
run_str = '${CXX} ${ARCH_ST:ARCH} ${CXXFLAGS} ${CPPFLAGS} ${CXXPCH_FLAGS} ${FRAMEWORKPATH_ST:FRAMEWORKPATH} ${CPPPATH_ST:INCPATHS} ${DEFINES_ST:DEFINES} ${CXXPCH_F:SRC} ${CXX_SRC_F}${SRC[0].abspath()} ${CXX_TGT_F}${TGT[0].abspath()}'
run_str = '${CXX} ${ARCH_ST:ARCH} ${CXXFLAGS} ${CXXPCH_FLAGS} ${FRAMEWORKPATH_ST:FRAMEWORKPATH} ${CPPPATH_ST:INCPATHS} ${DEFINES_ST:DEFINES} ${CXXPCH_F:SRC} ${CXX_SRC_F}${SRC[0].abspath()} ${CXX_TGT_F}${TGT[0].abspath()} ${CPPFLAGS}'
scan = c_preproc.scan
color = 'BLUE'
ext_out=['.h']
-19
View File
@@ -1,19 +0,0 @@
# -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
#
# Copyright (c) 2014, Regents of the University of California
#
# GPL 3.0 license, see the COPYING.md file for more information
from waflib import Configure
IS_MOVE_CONSTRUCTIBLE_CHECK = '''
#include <type_traits>
static_assert(std::is_move_constructible<int>::value, "");
'''
def configure(conf):
if conf.check_cxx(msg='Checking for std::is_move_constructible',
fragment=IS_MOVE_CONSTRUCTIBLE_CHECK,
features='cxx', mandatory=False):
conf.define('HAVE_IS_MOVE_CONSTRUCTIBLE', 1)
conf.env['HAVE_IS_MOVE_CONSTRUCTIBLE'] = True
+5 -4
View File
@@ -1,6 +1,6 @@
# -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
#
# Copyright (c) 2014, Regents of the University of California
# Copyright (c) 2014-2018, Regents of the University of California
#
# GPL 3.0 license, see the COPYING.md file for more information
@@ -15,8 +15,9 @@ BOOST_ASIO_HAS_LOCAL_SOCKETS_CHECK = '''
def addUnixOptions(self, opt):
opt.add_option('--force-unix-socket', action='store_true', default=False,
dest='force_unix_socket', help='''Forcefully enable Unix sockets support''')
setattr(Options.OptionsContext, "addUnixOptions", addUnixOptions)
help='Forcefully enable Unix sockets support')
setattr(Options.OptionsContext, 'addUnixOptions', addUnixOptions)
def configure(conf):
def boost_asio_has_local_sockets():
@@ -26,4 +27,4 @@ def configure(conf):
if conf.options.force_unix_socket or boost_asio_has_local_sockets():
conf.define('HAVE_UNIX_SOCKETS', 1)
conf.env['HAVE_UNIX_SOCKETS'] = True
conf.env.HAVE_UNIX_SOCKETS = True
+14 -17
View File
@@ -6,7 +6,8 @@ import re
def addWebsocketOptions(self, opt):
opt.add_option('--without-websocket', action='store_false', default=True,
dest='with_websocket', help='Disable WebSocket face support')
setattr(Options.OptionsContext, "addWebsocketOptions", addWebsocketOptions)
setattr(Options.OptionsContext, 'addWebsocketOptions', addWebsocketOptions)
@Configure.conf
def checkWebsocket(self, **kw):
@@ -15,7 +16,7 @@ def checkWebsocket(self, **kw):
isMandatory = kw.get('mandatory', True)
self.start_msg('Checking for WebSocket includes')
self.start_msg('Checking for WebSocket++ includes')
try:
websocketDir = self.path.find_dir('websocketpp/websocketpp')
@@ -24,40 +25,36 @@ def checkWebsocket(self, **kw):
versionFile = websocketDir.find_node('version.hpp')
if not websocketDir:
raise Errors.WafError('Corrupted: WebSocket version file not found')
raise Errors.WafError('WebSocket++ version file not found')
try:
txt = versionFile.read()
except (OSError, IOError):
raise Errors.WafError('Corrupted: cannot read WebSocket version file')
raise Errors.WafError('Cannot read WebSocket++ version file')
version = [None, None, None]
# Looking for the following:
# static int const major_version = 0;
# static int const minor_version = 7;
# static int const patch_version = 0;
version = [None, None, None]
majorVersion = re.compile('^static int const major_version = (\\d+);$', re.M)
version[0] = majorVersion.search(txt)
minorVersion = re.compile('^static int const minor_version = (\\d+);$', re.M)
version[1] = minorVersion.search(txt)
patchVersion = re.compile('^static int const patch_version = (\\d+);$', re.M)
version[2] = patchVersion.search(txt)
if not version[0] or not version[1] or not version[2]:
raise Errors.WafError('Corrupted: cannot detect websocket version')
raise Errors.WafError('Cannot detect WebSocket++ version')
self.env['WEBSOCKET_VERSION'] = [i.group(1) for i in version]
self.env.WEBSOCKET_VERSION = [i.group(1) for i in version]
# todo: version checking, if necessary
self.end_msg('.'.join(self.env['WEBSOCKET_VERSION']))
self.end_msg('.'.join(self.env.WEBSOCKET_VERSION))
self.env['INCLUDES_WEBSOCKET'] = websocketDir.parent.abspath()
self.env['HAVE_WEBSOCKET'] = True
self.env.INCLUDES_WEBSOCKET = websocketDir.parent.abspath()
self.env.HAVE_WEBSOCKET = True
self.define('HAVE_WEBSOCKET', 1)
self.define('_WEBSOCKETPP_CPP11_STL_', 1)
@@ -65,12 +62,12 @@ def checkWebsocket(self, **kw):
if isMandatory:
self.end_msg(str(error), color='RED')
Logs.warn('If you are using git NFD repository, checkout websocketpp submodule: ')
Logs.warn(' git submodule init && git submodule update')
Logs.warn(' git submodule update --init')
Logs.warn('Otherwise, manually download and extract websocketpp library:')
Logs.warn(' mkdir websocketpp')
Logs.warn(' curl -L https://github.com/zaphoyd/websocketpp/archive/0.7.0.tar.gz > websocket.tar.gz')
Logs.warn(' tar zxf websocket.tar.gz -C websocketpp/ --strip 1')
Logs.warn(' tar xf websocket.tar.gz -C websocketpp/ --strip 1')
Logs.warn('Alternatively, WebSocket support can be disabled with --without-websocket')
self.fatal("The configuration failed")
self.fatal('The configuration failed')
else:
self.end_msg(str(error))
+9 -5
View File
@@ -139,7 +139,7 @@ There is a
for Python. It applies many of the provisions from the C++ guide, in
addition to some other Python-specific things.
Some NDN projects are writtin in JavaScript, and there is a [style guide](https://named-data.net/codebase/platform/documentation/ndn-platform-development-guidelines/cpp-code-guidelines/) for that language, too.
Some NDN projects are written in JavaScript, and there is a [style guide](https://named-data.net/codebase/platform/documentation/ndn-platform-development-guidelines/cpp-code-guidelines/) for that language, too.
#### Commit Messages ####
@@ -151,7 +151,7 @@ understand the timeline of a project. Commit messages should:
they change. A good rule of thumb is a maximum length of 65
characters.
- If including a body, leave a blank line between the first line and
the rest, and ensure that it's no longer than 72 characters.
the rest, and ensure that each line is no longer than 72 characters.
- Include Redmine issue numbers. The exact syntax is given below.
- Be written in an imperative mood. E.g. `"Make foo a bar"` and not
`"Foo is now a bar"`
@@ -162,6 +162,10 @@ To explain, the anatomy of a typical commit message is like this:
docs: write contributing guide and code of conduct
This commit adds a guide that may be useful for new-comers to NDN in
becoming productive contributors. This commit also adds a code of
conduct.
refs: #3898
Change-Id: Ife89360305027dba9020f0b298793c1121ae1fd6c
@@ -315,7 +319,7 @@ Once you have a commit message you are happy with, simply run `git
push HEAD:refs/for/master`.
**Note:** Gerrit separates commits into patch sets by the unique
`Change-Id`s. As a result, it is important that you either:
`Change-Id`s. As a result, you must either:
* Squash your various commits into one with `git rebase -i
<initial commit>`, ensuring that the ultimate `Change-Id` in the
@@ -470,8 +474,8 @@ repetitive, you have a few options:
* Git has an alias system that you can use to specify certain
commands. For example, you can use `git config --global alias.pg
"push origin HEAD:refs/for/master"` to make `git pg` push to Gerrit. You
can [learn about git aliases.](https://githowto.com/aliases)
"push origin HEAD:refs/for/master"` to make `git pg` push to
Gerrit. [Learn about git aliases here.](https://githowto.com/aliases)
* If using Linux or macOS, it is relatively simple to create a shell
alias: `alias gs="git status"` for example, or `alias gitpush="git
+2 -2
View File
@@ -60,7 +60,7 @@ The simplest way to run tests, is just to run the compiled binary without any pa
# Run NFD RIB management tests
./build/unit-tests-rib
However, [Boost.Test framework](http://www.boost.org/doc/libs/1_54_0/libs/test/doc/html/index.html)
However, [Boost.Test framework](https://www.boost.org/doc/libs/1_58_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:
@@ -93,5 +93,5 @@ or `-p` to show progress bar:
There are many more command line options available, information about
which can be obtained either from the command line using `--help`
switch, or online on [Boost.Test library](http://www.boost.org/doc/libs/1_54_0/libs/test/doc/html/index.html)
switch, or online on [Boost.Test library](https://www.boost.org/doc/libs/1_58_0/libs/test/doc/html/index.html)
website.
-67
View File
@@ -1,67 +0,0 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2014-2016, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
* Washington University in St. Louis,
* Beijing Institute of Technology,
* The University of Memphis.
*
* This file is part of NFD (Named Data Networking Forwarding Daemon).
* See AUTHORS.md for complete list of NFD authors and contributors.
*
* NFD is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Foundation,
* either version 3 of the License, or (at your option) any later version.
*
* NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef NFD_CORE_ASSERTS_HPP
#define NFD_CORE_ASSERTS_HPP
#include "common.hpp"
#include <boost/concept/assert.hpp>
#include <boost/concept_check.hpp>
#include <type_traits>
namespace nfd {
namespace detail {
// As of Boost 1.54.0, the internal implementation of BOOST_CONCEPT_ASSERT does not allow
// multiple assertions on the same line, so we have to combine multiple concepts together.
template<typename T>
class StlForwardIteratorConcept : public boost::ForwardIterator<T>
, public boost::DefaultConstructible<T>
{
};
} // namespace detail
} // namespace nfd
/** \brief assert T is default constructible
* \sa http://en.cppreference.com/w/cpp/concept/DefaultConstructible
*/
#define NFD_ASSERT_DEFAULT_CONSTRUCTIBLE(T) \
static_assert(std::is_default_constructible<T>::value, \
#T " must be default-constructible"); \
BOOST_CONCEPT_ASSERT((boost::DefaultConstructible<T>))
/** \brief assert T is a forward iterator
* \sa http://en.cppreference.com/w/cpp/concept/ForwardIterator
* \note A forward iterator should be default constructible, but boost::ForwardIterator follows
* SGI standard which doesn't require DefaultConstructible, so a separate check is needed.
*/
#define NFD_ASSERT_FORWARD_ITERATOR(T) \
BOOST_CONCEPT_ASSERT((::nfd::detail::StlForwardIteratorConcept<T>)); \
static_assert(std::is_default_constructible<T>::value, \
#T " must be default-constructible")
#endif // NFD_CORE_ASSERTS_HPP
+6 -8
View File
@@ -46,10 +46,10 @@
#include <cstdint>
#include <functional>
#include <limits>
#include <list>
#include <map>
#include <memory>
#include <set>
#include <stdexcept>
#include <string>
#include <unordered_map>
#include <unordered_set>
@@ -59,7 +59,6 @@
#include <ndn-cxx/data.hpp>
#include <ndn-cxx/delegation.hpp>
#include <ndn-cxx/delegation-list.hpp>
#include <ndn-cxx/exclude.hpp>
#include <ndn-cxx/interest.hpp>
#include <ndn-cxx/name.hpp>
#include <ndn-cxx/encoding/block.hpp>
@@ -85,25 +84,24 @@ using std::shared_ptr;
using std::unique_ptr;
using std::weak_ptr;
using std::make_shared;
using ndn::make_unique;
using std::enable_shared_from_this;
using std::make_unique;
using std::static_pointer_cast;
using std::dynamic_pointer_cast;
using std::const_pointer_cast;
using std::function;
using std::bind;
using std::ref;
using std::cref;
using namespace std::string_literals;
using ndn::optional;
using ndn::nullopt;
using ndn::to_string;
using ndn::Block;
using ndn::Data;
using ndn::Delegation;
using ndn::DelegationList;
using ndn::Exclude;
using ndn::FaceUri;
using ndn::Interest;
using ndn::Name;
+10 -11
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-2018, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -34,24 +34,23 @@ namespace nfd {
/** \brief a config file section
*/
typedef boost::property_tree::ptree ConfigSection;
using ConfigSection = boost::property_tree::ptree;
/** \brief an optional config file section
*/
typedef boost::optional<const ConfigSection&> OptionalConfigSection;
using OptionalConfigSection = boost::optional<const ConfigSection&>;
/** \brief callback to process a config file section
*/
typedef function<void(const ConfigSection& section,
bool isDryRun,
const std::string& filename)> ConfigSectionHandler;
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
*/
typedef function<void(const std::string& filename,
const std::string& sectionName,
const ConfigSection& section,
bool isDryRun)> UnknownConfigSectionHandler;
using UnknownConfigSectionHandler = std::function<void(const std::string& filename,
const std::string& sectionName,
const ConfigSection& section,
bool isDryRun)>;
/** \brief configuration file parsing utility
*/
+42 -3
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-2018, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -34,8 +34,9 @@ void
resetGlobalScheduler();
} // namespace scheduler
static boost::thread_specific_ptr<boost::asio::io_service> g_ioService;
static boost::asio::io_service* g_mainIoService = nullptr;
static boost::asio::io_service* g_ribIoService = nullptr;
boost::asio::io_service&
getGlobalIoService()
@@ -53,4 +54,42 @@ resetGlobalIoService()
g_ioService.reset();
}
void
setMainIoService(boost::asio::io_service* mainIo)
{
g_mainIoService = mainIo;
}
void
setRibIoService(boost::asio::io_service* ribIo)
{
g_ribIoService = ribIo;
}
boost::asio::io_service&
getMainIoService()
{
BOOST_ASSERT(g_mainIoService != nullptr);
return *g_mainIoService;
}
boost::asio::io_service&
getRibIoService()
{
BOOST_ASSERT(g_ribIoService != nullptr);
return *g_ribIoService;
}
void
runOnMainIoService(const std::function<void()>& f)
{
getMainIoService().post(f);
}
void
runOnRibIoService(const std::function<void()>& f)
{
getRibIoService().post(f);
}
} // namespace nfd
+29 -7
View File
@@ -1,11 +1,11 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2014 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
/*
* Copyright (c) 2014-2018 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
*
* This file is part of NFD (Named Data Networking Forwarding Daemon).
* See AUTHORS.md for complete list of NFD authors and contributors.
@@ -34,6 +34,28 @@ namespace nfd {
boost::asio::io_service&
getGlobalIoService();
void
setMainIoService(boost::asio::io_service* 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);
boost::asio::io_service&
getMainIoService();
boost::asio::io_service&
getRibIoService();
#ifdef WITH_TESTS
/** \brief delete the global io_service instance
*
+96
View File
@@ -0,0 +1,96 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2018, 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/>.
*/
#include "log-config-section.hpp"
#include <ndn-cxx/util/logger.hpp>
#include <ndn-cxx/util/logging.hpp>
namespace nfd {
namespace log {
static ndn::util::LogLevel
parseLogLevel(const ConfigSection& item, const std::string& key)
{
try {
return ndn::util::parseLogLevel(item.get_value<std::string>());
}
catch (const std::invalid_argument& e) {
BOOST_THROW_EXCEPTION(ConfigFile::Error("Invalid setting for log." + key + ": " + e.what()));
}
}
static void
onConfig(const ConfigSection& section, bool isDryRun, const std::string&)
{
// log
// {
// ; default_level specifies the logging level for modules
// ; that are not explicitly named. All debugging levels
// ; listed above the selected value are enabled.
//
// default_level INFO
//
// ; You may also override the default for specific modules:
//
// FibManager DEBUG
// Forwarder WARN
// }
auto defaultLevel = ndn::util::LogLevel::INFO;
auto item = section.get_child_optional("default_level");
if (item) {
defaultLevel = parseLogLevel(*item, "default_level");
}
if (!isDryRun) {
// default_level applies only to NFD loggers
ndn::util::Logging::setLevel("nfd.*", defaultLevel);
}
for (const auto& i : section) {
if (i.first == "default_level") {
// do nothing
}
else {
auto level = parseLogLevel(i.second, i.first);
if (!isDryRun) {
if (i.first.find('.') == std::string::npos)
// backward compat: assume unqualified logger names refer to NFD loggers
ndn::util::Logging::setLevel("nfd." + i.first, level);
else
ndn::util::Logging::setLevel(i.first, level);
}
}
}
}
void
setConfigFile(ConfigFile& config)
{
config.addSectionHandler("log", &onConfig);
}
} // namespace log
} // namespace nfd
+40
View File
@@ -0,0 +1,40 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2018, 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_LOG_CONFIG_SECTION_HPP
#define NFD_CORE_LOG_CONFIG_SECTION_HPP
#include "config-file.hpp"
namespace nfd {
namespace log {
void
setConfigFile(ConfigFile& config);
} // namespace log
} // namespace nfd
#endif // NFD_CORE_LOG_CONFIG_SECTION_HPP
-228
View File
@@ -1,228 +0,0 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2017, 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/>.
*/
#include "logger-factory.hpp"
#include <ndn-cxx/util/logging.hpp>
#include <boost/algorithm/string/case_conv.hpp>
#include <boost/range/adaptor/map.hpp>
#include <iostream>
#ifdef HAVE_CUSTOM_LOGGER
#error "This file should not be compiled when custom logger is used"
#endif
namespace nfd {
NFD_LOG_INIT("LoggerFactory");
LoggerFactory&
LoggerFactory::getInstance()
{
static LoggerFactory globalLoggerFactory;
return globalLoggerFactory;
}
LoggerFactory::LoggerFactory()
: m_defaultLevel(LOG_INFO)
{
m_levelNames["NONE"] = LOG_NONE;
m_levelNames["ERROR"] = LOG_ERROR;
m_levelNames["WARN"] = LOG_WARN;
m_levelNames["INFO"] = LOG_INFO;
m_levelNames["DEBUG"] = LOG_DEBUG;
m_levelNames["TRACE"] = LOG_TRACE;
m_levelNames["ALL"] = LOG_ALL;
// Let ndn-cxx logging facility initialize Boost.Log backend,
// so that only one sink is attached to Boost.Log core.
ndn::util::Logging::setDestination(std::clog);
}
LoggerFactory::~LoggerFactory()
{
ndn::util::Logging::flush();
}
void
LoggerFactory::setConfigFile(ConfigFile& config)
{
config.addSectionHandler("log", bind(&LoggerFactory::onConfig, this, _1, _2, _3));
}
LogLevel
LoggerFactory::parseLevel(const std::string& level)
{
std::string upperLevel = boost::to_upper_copy(level);
// std::cerr << "parsing level: " << upperLevel << std::endl;;
// std::cerr << "# levels: " << m_levelNames.size() << std::endl;
// std::cerr << m_levelNames.begin()->first << std::endl;
LevelMap::const_iterator levelIt = m_levelNames.find(upperLevel);
if (levelIt != m_levelNames.end()) {
return levelIt->second;
}
try {
uint32_t levelNo = boost::lexical_cast<uint32_t>(level);
if ((boost::lexical_cast<uint32_t>(LOG_NONE) <= levelNo &&
levelNo <= boost::lexical_cast<uint32_t>(LOG_TRACE)) ||
levelNo == LOG_ALL) {
return static_cast<LogLevel>(levelNo);
}
}
catch (const boost::bad_lexical_cast& error) {
}
BOOST_THROW_EXCEPTION(LoggerFactory::Error("Unsupported logging level \"" + level + "\""));
}
LogLevel
LoggerFactory::extractLevel(const ConfigSection& item, const std::string& key)
{
std::string levelString;
try {
levelString = item.get_value<std::string>();
}
catch (const boost::property_tree::ptree_error& error) {
}
if (levelString.empty()) {
BOOST_THROW_EXCEPTION(LoggerFactory::Error("No logging level found for option \"" + key + "\""));
}
return parseLevel(levelString);
}
void
LoggerFactory::onConfig(const ConfigSection& section,
bool isDryRun,
const std::string& filename)
{
// log
// {
// ; default_level specifies the logging level for modules
// ; that are not explicitly named. All debugging levels
// ; listed above the selected value are enabled.
//
// default_level INFO
//
// ; You may also override the default for specific modules:
//
// FibManager DEBUG
// Forwarder WARN
// }
if (!isDryRun) {
ConfigSection::const_assoc_iterator item = section.find("default_level");
if (item != section.not_found()) {
LogLevel level = extractLevel(item->second, "default_level");
setDefaultLevel(level);
}
else {
setDefaultLevel(LOG_INFO);
}
}
for (const auto& i : section) {
LogLevel level = extractLevel(i.second, i.first);
if (i.first == "default_level") {
// do nothing
}
else {
std::unique_lock<std::mutex> lock(m_loggersGuard);
LoggerMap::iterator loggerIt = m_loggers.find(i.first);
if (loggerIt == m_loggers.end()) {
lock.unlock();
NFD_LOG_DEBUG("Failed to configure logging level for module \"" <<
i.first << "\" (module not found)");
}
else if (!isDryRun) {
loggerIt->second.setLogLevel(level);
lock.unlock();
NFD_LOG_DEBUG("Changing level for module " << i.first << " to " << level);
}
}
}
}
void
LoggerFactory::setDefaultLevel(LogLevel level)
{
// std::cerr << "changing to default_level " << level << std::endl;
std::lock_guard<std::mutex> lock(m_loggersGuard);
m_defaultLevel = level;
for (auto&& logger : m_loggers) {
// std::cerr << "changing " << i->first << " to default " << m_defaultLevel << std::endl;
logger.second.setLogLevel(m_defaultLevel);
}
}
void
LoggerFactory::flushBackend()
{
ndn::util::Logging::flush();
}
Logger&
LoggerFactory::create(const std::string& moduleName)
{
return LoggerFactory::getInstance().createLogger(moduleName);
}
Logger&
LoggerFactory::createLogger(const std::string& moduleName)
{
// std::cerr << "creating logger for " << moduleName
// << " with level " << m_defaultLevel << std::endl;
std::lock_guard<std::mutex> lock(m_loggersGuard);
std::pair<LoggerMap::iterator, bool> loggerIt =
m_loggers.insert(NameAndLogger(moduleName, Logger(moduleName, m_defaultLevel)));
return loggerIt.first->second;
}
std::list<std::string>
LoggerFactory::getModules() const
{
std::lock_guard<std::mutex> lock(m_loggersGuard);
std::list<std::string> modules;
for (const auto& loggerName : m_loggers | boost::adaptors::map_keys) {
modules.push_back(loggerName);
}
return modules;
}
} // namespace nfd
-126
View File
@@ -1,126 +0,0 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2014-2016, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
* Washington University in St. Louis,
* Beijing Institute of Technology,
* The University of Memphis.
*
* This file is part of NFD (Named Data Networking Forwarding Daemon).
* See AUTHORS.md for complete list of NFD authors and contributors.
*
* NFD is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Foundation,
* either version 3 of the License, or (at your option) any later version.
*
* NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef NFD_CORE_LOGGER_FACTORY_HPP
#define NFD_CORE_LOGGER_FACTORY_HPP
#include "common.hpp"
#ifdef HAVE_CUSTOM_LOGGER
#include "custom-logger-factory.hpp"
#else
#include "config-file.hpp"
#include "logger.hpp"
#include <mutex>
namespace nfd {
class LoggerFactory : noncopyable
{
public:
class Error : public std::runtime_error
{
public:
explicit
Error(const std::string& error)
: std::runtime_error(error)
{
}
};
static LoggerFactory&
getInstance();
void
setConfigFile(ConfigFile& config);
void
onConfig(const ConfigSection& section, bool isDryRun, const std::string& filename);
std::list<std::string>
getModules() const;
static Logger&
create(const std::string& moduleName);
PUBLIC_WITH_TESTS_ELSE_PRIVATE:
// these methods are used during unit-testing
LogLevel
getDefaultLevel() const;
void
setDefaultLevel(LogLevel level);
void
flushBackend();
private:
LoggerFactory();
~LoggerFactory();
Logger&
createLogger(const std::string& moduleName);
LogLevel
parseLevel(const std::string& level);
LogLevel
extractLevel(const ConfigSection& item, const std::string& key);
private:
typedef std::map<std::string, LogLevel> LevelMap;
typedef std::pair<std::string, LogLevel> NameAndLevel;
LevelMap m_levelNames;
typedef std::map<std::string, Logger> LoggerMap;
typedef std::pair<std::string, Logger> NameAndLogger;
LoggerMap m_loggers;
mutable std::mutex m_loggersGuard;
LogLevel m_defaultLevel;
};
inline LogLevel
LoggerFactory::getDefaultLevel() const
{
return m_defaultLevel;
}
} // namespace nfd
#endif // HAVE_CUSTOM_LOGGER
#endif // NFD_CORE_LOGGER_FACTORY_HPP
-70
View File
@@ -1,70 +0,0 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2014-2016, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
* Washington University in St. Louis,
* Beijing Institute of Technology,
* The University of Memphis.
*
* This file is part of NFD (Named Data Networking Forwarding Daemon).
* See AUTHORS.md for complete list of NFD authors and contributors.
*
* NFD is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Foundation,
* either version 3 of the License, or (at your option) any later version.
*
* NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*/
#include "logger.hpp"
#ifdef HAVE_CUSTOM_LOGGER
#error "This file should not be compiled when custom logger is used"
#endif
#include <ndn-cxx/util/time.hpp>
#include <cinttypes>
#include <stdio.h>
#include <type_traits>
namespace nfd {
Logger::Logger(const std::string& name, LogLevel level)
: m_moduleName(name)
, m_enabledLogLevel(level)
{
}
std::ostream&
operator<<(std::ostream& os, const LoggerTimestamp&)
{
using namespace ndn::time;
static const microseconds::rep ONE_SECOND = 1000000;
microseconds::rep microsecondsSinceEpoch = duration_cast<microseconds>(
system_clock::now().time_since_epoch()).count();
// 10 (whole seconds) + '.' + 6 (fraction) + '\0'
char buffer[10 + 1 + 6 + 1];
BOOST_ASSERT_MSG(microsecondsSinceEpoch / ONE_SECOND <= 9999999999L,
"whole seconds cannot fit in 10 characters");
static_assert(std::is_same<microseconds::rep, int_least64_t>::value,
"PRIdLEAST64 is incompatible with microseconds::rep");
// - std::snprintf not found in some environments
// http://redmine.named-data.net/issues/2299 for more information
snprintf(buffer, sizeof(buffer), "%" PRIdLEAST64 ".%06" PRIdLEAST64,
microsecondsSinceEpoch / ONE_SECOND,
microsecondsSinceEpoch % ONE_SECOND);
return os << buffer;
}
} // namespace nfd
+14 -141
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-2018, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -26,146 +26,19 @@
#ifndef NFD_CORE_LOGGER_HPP
#define NFD_CORE_LOGGER_HPP
#include "common.hpp"
#include <ndn-cxx/util/logger.hpp>
#ifdef HAVE_CUSTOM_LOGGER
#include "custom-logger.hpp"
#else
#include <boost/log/common.hpp>
#include <boost/log/sources/logger.hpp>
#define NFD_LOG_INIT(name) NDN_LOG_INIT(nfd.name)
#define NFD_LOG_MEMBER_DECL() NDN_LOG_MEMBER_DECL()
#define NFD_LOG_MEMBER_DECL_SPECIALIZED(cls) NDN_LOG_MEMBER_DECL_SPECIALIZED(cls)
#define NFD_LOG_MEMBER_INIT(cls, name) NDN_LOG_MEMBER_INIT(cls, nfd.name)
#define NFD_LOG_MEMBER_INIT_SPECIALIZED(cls, name) NDN_LOG_MEMBER_INIT_SPECIALIZED(cls, nfd.name)
namespace nfd {
/** \brief indicates a log level
* \note This type is internal. Logger should be accessed through NFD_LOG_* macros.
*/
enum LogLevel {
LOG_FATAL = -1, // fatal (will be logged unconditionally)
LOG_NONE = 0, // no messages
LOG_ERROR = 1, // serious error messages
LOG_WARN = 2, // warning messages
LOG_INFO = 3, // informational messages
LOG_DEBUG = 4, // debug messages
LOG_TRACE = 5, // trace messages (most verbose)
LOG_ALL = 255 // all messages
};
/** \brief provides logging for a module
* \note This type is internal. Logger should be accessed through NFD_LOG_* macros.
* \note This type is copyable because logger can be declared as a field of
* (usually template) classes, and shouldn't prevent those classes to be copyable.
*/
class Logger
{
public:
Logger(const std::string& name, LogLevel level);
bool
isEnabled(LogLevel level) const
{
return m_enabledLogLevel >= level;
}
void
setLogLevel(LogLevel level)
{
m_enabledLogLevel = level;
}
const std::string&
getName() const
{
return m_moduleName;
}
void
setName(const std::string& name)
{
m_moduleName = name;
}
public:
boost::log::sources::logger boostLogger;
private:
std::string m_moduleName;
LogLevel m_enabledLogLevel;
};
inline std::ostream&
operator<<(std::ostream& output, const Logger& logger)
{
output << logger.getName();
return output;
}
/**
* \brief a tag that writes a timestamp upon stream output
*/
struct LoggerTimestamp
{
};
/**
* \brief write a timestamp to \p os
* \note This function is thread-safe.
*/
std::ostream&
operator<<(std::ostream& os, const LoggerTimestamp&);
} // namespace nfd
#include "core/logger-factory.hpp"
namespace nfd {
#define NFD_LOG_INIT(name) \
static ::nfd::Logger& g_logger = ::nfd::LoggerFactory::create(name)
#define NFD_LOG_INCLASS_DECLARE() \
static ::nfd::Logger& g_logger
#define NFD_LOG_INCLASS_DEFINE(cls, name) \
::nfd::Logger& cls::g_logger = ::nfd::LoggerFactory::create(name)
#define NFD_LOG_INCLASS_TEMPLATE_DEFINE(cls, name) \
template<class T> \
::nfd::Logger& cls<T>::g_logger = ::nfd::LoggerFactory::create(name)
#define NFD_LOG_INCLASS_TEMPLATE_SPECIALIZATION_DEFINE(cls, specialization, name) \
template<> \
::nfd::Logger& cls<specialization>::g_logger = ::nfd::LoggerFactory::create(name)
#define NFD_LOG_INCLASS_2TEMPLATE_SPECIALIZATION_DEFINE(cls, s1, s2, name) \
template<> \
::nfd::Logger& cls<s1, s2>::g_logger = ::nfd::LoggerFactory::create(name)
#if (BOOST_VERSION >= 105900) && (BOOST_VERSION < 106000)
// workaround Boost bug 11549
#define NFD_BOOST_LOG(x) BOOST_LOG(x) << ""
#else
#define NFD_BOOST_LOG(x) BOOST_LOG(x)
#endif
#define NFD_LOG_LINE(msg, expression) \
::nfd::LoggerTimestamp{} << " "#msg": " << "[" << g_logger << "] " << expression
#define NFD_LOG(level, msg, expression) \
do { \
if (g_logger.isEnabled(::nfd::LOG_##level)) { \
NFD_BOOST_LOG(g_logger.boostLogger) << NFD_LOG_LINE(msg, expression); \
} \
} while (false)
#define NFD_LOG_TRACE(expression) NFD_LOG(TRACE, TRACE, expression)
#define NFD_LOG_DEBUG(expression) NFD_LOG(DEBUG, DEBUG, expression)
#define NFD_LOG_INFO(expression) NFD_LOG(INFO, INFO, expression)
#define NFD_LOG_WARN(expression) NFD_LOG(WARN, WARNING, expression)
#define NFD_LOG_ERROR(expression) NFD_LOG(ERROR, ERROR, expression)
#define NFD_LOG_FATAL(expression) NFD_LOG(FATAL, FATAL, expression)
} // namespace nfd
#endif // HAVE_CUSTOM_LOGGER
#define NFD_LOG_TRACE NDN_LOG_TRACE
#define NFD_LOG_DEBUG NDN_LOG_DEBUG
#define NFD_LOG_INFO NDN_LOG_INFO
#define NFD_LOG_WARN NDN_LOG_WARN
#define NFD_LOG_ERROR NDN_LOG_ERROR
#define NFD_LOG_FATAL NDN_LOG_FATAL
#endif // NFD_CORE_LOGGER_HPP
+7 -7
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-2018, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -72,10 +72,10 @@ public:
PUBLIC_WITH_TESTS_ELSE_PROTECTED: // registrations to the dispatcher
// difference from mgmt::ControlCommand: accepts nfd::ControlParameters
typedef function<void(const ControlCommand& command,
const Name& prefix, const Interest& interest,
const ControlParameters& parameters,
const ndn::mgmt::CommandContinuation done)> ControlCommandHandler;
using ControlCommandHandler = std::function<void(const ControlCommand& command,
const Name& prefix, const Interest& interest,
const ControlParameters& parameters,
const ndn::mgmt::CommandContinuation done)>;
template<typename Command>
void
@@ -161,7 +161,7 @@ ManagerBase::registerCommandHandler(const std::string& verb,
m_dispatcher.addControlCommand<ControlParameters>(
makeRelPrefix(verb),
makeAuthorization(verb),
bind(&ManagerBase::validateParameters, cref(*command), _1),
bind(&ManagerBase::validateParameters, std::cref(*command), _1),
bind(&ManagerBase::handleCommand, command, handler, _1, _2, _3, _4));
}
-138
View File
@@ -1,138 +0,0 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2017, 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/>.
*/
#include "network-interface-predicate.hpp"
#include "config-file.hpp"
#include "network.hpp"
#include <fnmatch.h>
namespace nfd {
NetworkInterfacePredicate::NetworkInterfacePredicate()
{
this->clear();
}
void
NetworkInterfacePredicate::clear()
{
m_whitelist = std::set<std::string>{"*"};
m_blacklist.clear();
}
static void
parseList(std::set<std::string>& set, const boost::property_tree::ptree& list, const std::string& section)
{
set.clear();
for (const auto& item : list) {
if (item.first == "*") {
// insert wildcard
set.insert(item.first);
}
else if (item.first == "ifname") {
// very basic sanity check for interface names
auto name = item.second.get_value<std::string>();
if (name.empty()) {
BOOST_THROW_EXCEPTION(ConfigFile::Error("Empty interface name in \"" + section + "\" section"));
}
set.insert(name);
}
else if (item.first == "ether") {
// validate ethernet address
auto addr = item.second.get_value<std::string>();
if (ndn::ethernet::Address::fromString(addr).isNull()) {
BOOST_THROW_EXCEPTION(ConfigFile::Error("Malformed ether address \"" + addr +
"\" in \"" + section + "\" section"));
}
set.insert(addr);
}
else if (item.first == "subnet") {
// example subnet: 10.0.0.0/8
auto cidr = item.second.get_value<std::string>();
if (!Network::isValidCidr(cidr)) {
BOOST_THROW_EXCEPTION(ConfigFile::Error("Malformed subnet declaration \"" + cidr +
"\" in \"" + section + "\" section"));
}
set.insert(cidr);
}
}
}
void
NetworkInterfacePredicate::parseWhitelist(const boost::property_tree::ptree& list)
{
parseList(m_whitelist, list, "whitelist");
}
void
NetworkInterfacePredicate::parseBlacklist(const boost::property_tree::ptree& list)
{
parseList(m_blacklist, list, "blacklist");
}
static bool
doesMatchPattern(const std::string& ifname, const std::string& pattern)
{
// use fnmatch(3) to provide unix glob-style matching for interface names
// fnmatch returns 0 if there is a match
return ::fnmatch(pattern.data(), ifname.data(), 0) == 0;
}
static bool
doesMatchRule(const ndn::net::NetworkInterface& netif, const std::string& rule)
{
// if '/' is in rule, this is a subnet, check if IP in subnet
if (rule.find('/') != std::string::npos) {
Network n = boost::lexical_cast<Network>(rule);
for (const auto& addr : netif.getNetworkAddresses()) {
if (n.doesContain(addr.getIp())) {
return true;
}
}
}
return rule == "*" ||
doesMatchPattern(netif.getName(), rule) ||
netif.getEthernetAddress().toString() == rule;
}
bool
NetworkInterfacePredicate::operator()(const ndn::net::NetworkInterface& netif) const
{
return std::any_of(m_whitelist.begin(), m_whitelist.end(), bind(&doesMatchRule, cref(netif), _1)) &&
std::none_of(m_blacklist.begin(), m_blacklist.end(), bind(&doesMatchRule, cref(netif), _1));
}
bool
NetworkInterfacePredicate::operator==(const NetworkInterfacePredicate& other) const
{
return this->m_whitelist == other.m_whitelist &&
this->m_blacklist == other.m_blacklist;
}
} // namespace nfd
-79
View File
@@ -1,79 +0,0 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2017, 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_NETWORK_INTERFACE_PREDICATE_HPP
#define NFD_CORE_NETWORK_INTERFACE_PREDICATE_HPP
#include "common.hpp"
#include <ndn-cxx/net/network-interface.hpp>
namespace nfd {
/**
* \brief Represents a predicate to accept or reject a NetworkInterfaceInfo.
*
* The predicate consists of a whitelist and a blacklist. Whitelist and blacklist can contain,
* in no particular order, interface names (e.g., ifname eth0), mac addresses
* (e.g., ether 85:3b:4d:d3:5f:c2), subnets (e.g., subnet 192.0.2.0/24) or a wildcard (*) that matches
* all interfaces. A NetworkInterfaceInfo is accepted if it matches any entry in the whitelist and none
* of the entries in the blacklist.
*/
class NetworkInterfacePredicate
{
public:
NetworkInterfacePredicate();
/**
* \brief Set the whitelist to "*" and clear the blacklist
*/
void
clear();
void
parseWhitelist(const boost::property_tree::ptree& list);
void
parseBlacklist(const boost::property_tree::ptree& list);
bool
operator()(const ndn::net::NetworkInterface& netif) const;
bool
operator==(const NetworkInterfacePredicate& other) const;
bool
operator!=(const NetworkInterfacePredicate& other) const
{
return !this->operator==(other);
}
private:
std::set<std::string> m_whitelist;
std::set<std::string> m_blacklist;
};
} // namespace nfd
#endif // NFD_CORE_NETWORK_INTERFACE_PREDICATE_HPP
+221
View File
@@ -0,0 +1,221 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2018, 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/>.
*/
#include "network-predicate.hpp"
#include "config-file.hpp"
#include "network.hpp"
#include <fnmatch.h>
namespace nfd {
NetworkPredicateBase::NetworkPredicateBase()
{
this->clear();
}
NetworkPredicateBase::~NetworkPredicateBase() = default;
void
NetworkPredicateBase::clear()
{
m_whitelist = std::set<std::string>{"*"};
m_blacklist.clear();
}
void
NetworkPredicateBase::parseList(std::set<std::string>& set, const boost::property_tree::ptree& list, const std::string& section)
{
set.clear();
for (const auto& item : list) {
if (item.first == "*") {
// insert wildcard
set.insert(item.first);
}
else {
if (!isRuleSupported(item.first)) {
BOOST_THROW_EXCEPTION(ConfigFile::Error("Unrecognized rule \"" + item.first + "\" in \"" + section + "\" section"));
}
auto value = item.second.get_value<std::string>();
if (!isRuleValid(item.first, value)) {
BOOST_THROW_EXCEPTION(ConfigFile::Error("Malformed " + item.first + " \"" + value + "\" in \"" + section + "\" section"));
}
set.insert(value);
}
}
}
void
NetworkPredicateBase::parseList(std::set<std::string>& set, std::initializer_list<std::pair<std::string, std::string>> list)
{
set.clear();
for (const auto& item : list) {
if (item.first == "*") {
// insert wildcard
set.insert(item.first);
}
else {
if (!isRuleSupported(item.first)) {
BOOST_THROW_EXCEPTION(std::runtime_error("Unrecognized rule \"" + item.first + "\""));
}
if (!isRuleValid(item.first, item.second)) {
BOOST_THROW_EXCEPTION(std::runtime_error("Malformed " + item.first + " \"" + item.second + "\""));
}
set.insert(item.second);
}
}
}
void
NetworkPredicateBase::parseWhitelist(const boost::property_tree::ptree& list)
{
parseList(m_whitelist, list, "whitelist");
}
void
NetworkPredicateBase::parseBlacklist(const boost::property_tree::ptree& list)
{
parseList(m_blacklist, list, "blacklist");
}
void
NetworkPredicateBase::assign(std::initializer_list<std::pair<std::string, std::string>> whitelist,
std::initializer_list<std::pair<std::string, std::string>> blacklist)
{
parseList(m_whitelist, whitelist);
parseList(m_blacklist, blacklist);
}
bool
NetworkInterfacePredicate::isRuleSupported(const std::string& key)
{
return key == "ifname" || key == "ether" || key == "subnet";
}
bool
NetworkInterfacePredicate::isRuleValid(const std::string& key, const std::string& value)
{
if (key == "ifname") {
// very basic sanity check for interface names
return !value.empty();
}
else if (key == "ether") {
// validate ethernet address
return !ndn::ethernet::Address::fromString(value).isNull();
}
else if (key == "subnet") {
// example subnet: 10.0.0.0/8
return Network::isValidCidr(value);
}
else {
BOOST_THROW_EXCEPTION(std::logic_error("Only supported rules are expected"));
}
}
bool
IpAddressPredicate::isRuleSupported(const std::string& key)
{
return key == "subnet";
}
bool
IpAddressPredicate::isRuleValid(const std::string& key, const std::string& value)
{
if (key == "subnet") {
// example subnet: 10.0.0.0/8
return Network::isValidCidr(value);
}
else {
BOOST_THROW_EXCEPTION(std::logic_error("Only supported rules are expected"));
}
}
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)
{
// use fnmatch(3) to provide unix glob-style matching for interface names
// fnmatch returns 0 if there is a match
return ::fnmatch(pattern.data(), ifname.data(), 0) == 0;
}
static bool
doesNetifMatchRule(const ndn::net::NetworkInterface& netif, const std::string& rule)
{
// if '/' is in rule, this is a subnet, check if IP in subnet
if (rule.find('/') != std::string::npos) {
Network n = boost::lexical_cast<Network>(rule);
for (const auto& addr : netif.getNetworkAddresses()) {
if (n.doesContain(addr.getIp())) {
return true;
}
}
}
return rule == "*" ||
doesMatchPattern(netif.getName(), rule) ||
netif.getEthernetAddress().toString() == rule;
}
bool
NetworkInterfacePredicate::operator()(const ndn::net::NetworkInterface& netif) const
{
return std::any_of(m_whitelist.begin(), m_whitelist.end(), bind(&doesNetifMatchRule, std::cref(netif), _1)) &&
std::none_of(m_blacklist.begin(), m_blacklist.end(), bind(&doesNetifMatchRule, std::cref(netif), _1));
}
static bool
doesAddressMatchRule(const boost::asio::ip::address& address, const std::string& rule)
{
// if '/' is in rule, this is a subnet, check if IP in subnet
if (rule.find('/') != std::string::npos) {
Network n = boost::lexical_cast<Network>(rule);
if (n.doesContain(address)) {
return true;
}
}
return rule == "*";
}
bool
IpAddressPredicate::operator()(const boost::asio::ip::address& address) const
{
return std::any_of(m_whitelist.begin(), m_whitelist.end(), bind(&doesAddressMatchRule, std::cref(address), _1)) &&
std::none_of(m_blacklist.begin(), m_blacklist.end(), bind(&doesAddressMatchRule, std::cref(address), _1));
}
} // namespace nfd
+133
View File
@@ -0,0 +1,133 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2018, 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_NETWORK_PREDICATE_HPP
#define NFD_CORE_NETWORK_PREDICATE_HPP
#include "common.hpp"
#include <ndn-cxx/net/network-interface.hpp>
namespace nfd {
class NetworkPredicateBase
{
public:
NetworkPredicateBase();
virtual
~NetworkPredicateBase();
/**
* \brief Set the whitelist to "*" and clear the blacklist
*/
void
clear();
void
parseWhitelist(const boost::property_tree::ptree& list);
void
parseBlacklist(const boost::property_tree::ptree& list);
void
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;
bool
operator!=(const NetworkPredicateBase& other) const
{
return !this->operator==(other);
}
private:
virtual bool
isRuleSupported(const std::string& key) = 0;
virtual bool
isRuleValid(const std::string& key, const std::string& value) = 0;
void
parseList(std::set<std::string>& set, const boost::property_tree::ptree& list, const std::string& section);
void
parseList(std::set<std::string>& set, std::initializer_list<std::pair<std::string, std::string>> list);
PUBLIC_WITH_TESTS_ELSE_PROTECTED:
std::set<std::string> m_whitelist;
std::set<std::string> m_blacklist;
};
/**
* \brief Represents a predicate to accept or reject a ndn::net::NetworkInterface.
*
* The predicate consists of a whitelist and a blacklist. Whitelist and blacklist can contain,
* in no particular order, interface names (e.g., `ifname eth0`), MAC addresses (e.g., `ether
* 85:3b:4d:d3:5f:c2`), IPv4 and IPv6 subnets (e.g., `subnet 192.0.2.0/24` or `subnet
* 2001:db8:2::/64`), or a wildcard (`*`) that matches all interfaces. A
* 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
{
public:
bool
operator()(const ndn::net::NetworkInterface& netif) const;
private:
bool
isRuleSupported(const std::string& key) final;
bool
isRuleValid(const std::string& key, const std::string& value) final;
};
/**
* \brief Represents a predicate to accept or reject an IP address.
*
* The predicate consists of a whitelist and a blacklist. Whitelist and blacklist can contain,
* in no particular order, IPv4 and IPv6 subnets (e.g., `subnet 192.0.2.0/24` or `subnet
* 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
{
public:
bool
operator()(const boost::asio::ip::address& address) const;
private:
bool
isRuleSupported(const std::string& key) final;
bool
isRuleValid(const std::string& key, const std::string& value) final;
};
} // namespace nfd
#endif // NFD_CORE_NETWORK_PREDICATE_HPP
+44 -24
View File
@@ -1,12 +1,12 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2017, Regents of the University of California,
* Copyright (c) 2014-2018, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
* Washington University in St. Louis,
* Beijing Institute of Technology,
* The University of Memphis
* 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.
@@ -25,9 +25,9 @@
#include "network.hpp"
#include <ndn-cxx/net/address-converter.hpp>
#include <boost/utility/value_init.hpp>
#include <algorithm>
#include <cctype>
namespace nfd {
@@ -66,28 +66,13 @@ Network::isValidCidr(const std::string& cidr)
return false;
}
boost::system::error_code invalidIp;
boost::asio::ip::address_v4::from_string(cidr.substr(0, pos), invalidIp);
if (invalidIp) {
return false;
}
auto prefixLenStr = cidr.substr(pos + 1);
if (!std::all_of(prefixLenStr.begin(), prefixLenStr.end(), ::isdigit)) {
return false;
}
int prefixLen = -1;
try {
prefixLen = boost::lexical_cast<int>(prefixLenStr);
boost::lexical_cast<Network>(cidr);
return true;
}
catch (const boost::bad_lexical_cast&) {
return false;
}
if (prefixLen < 0 || prefixLen > 32) {
return false;
}
return true;
}
std::ostream&
@@ -106,14 +91,44 @@ operator>>(std::istream& is, Network& network)
size_t position = networkStr.find('/');
if (position == std::string::npos) {
network.m_minAddress = ndn::ip::addressFromString(networkStr);
network.m_maxAddress = ndn::ip::addressFromString(networkStr);
try {
network.m_minAddress = ip::address::from_string(networkStr);
network.m_maxAddress = ip::address::from_string(networkStr);
}
catch (const boost::system::system_error&) {
is.setstate(std::ios::failbit);
return is;
}
}
else {
ip::address address = ndn::ip::addressFromString(networkStr.substr(0, position));
size_t mask = boost::lexical_cast<size_t>(networkStr.substr(position+1));
boost::system::error_code ec;
auto address = ip::address::from_string(networkStr.substr(0, position), ec);
if (ec) {
is.setstate(std::ios::failbit);
return is;
}
auto prefixLenStr = networkStr.substr(position + 1);
if (!std::all_of(prefixLenStr.begin(), prefixLenStr.end(),
[] (unsigned char c) { return std::isdigit(c); })) {
is.setstate(std::ios::failbit);
return is;
}
size_t mask;
try {
mask = boost::lexical_cast<size_t>(prefixLenStr);
}
catch (const boost::bad_lexical_cast&) {
is.setstate(std::ios::failbit);
return is;
}
if (address.is_v4()) {
if (mask > 32) {
is.setstate(std::ios::failbit);
return is;
}
ip::address_v4::bytes_type maskBytes = boost::initialized_value;
for (size_t i = 0; i < mask; i++) {
size_t byteId = i / 8;
@@ -134,6 +149,11 @@ operator>>(std::istream& is, Network& network)
network.m_maxAddress = ip::address_v4(max);
}
else {
if (mask > 128) {
is.setstate(std::ios::failbit);
return is;
}
ip::address_v6::bytes_type maskBytes = boost::initialized_value;
for (size_t i = 0; i < mask; i++) {
size_t byteId = i / 8;
+15 -11
View File
@@ -31,7 +31,7 @@
namespace nfd {
NFD_LOG_INIT("PrivilegeHelper");
NFD_LOG_INIT(PrivilegeHelper);
#ifdef HAVE_PRIVILEGE_DROP_AND_ELEVATE
uid_t PrivilegeHelper::s_normalUid = ::geteuid();
@@ -45,13 +45,13 @@ void
PrivilegeHelper::initialize(const std::string& userName, const std::string& groupName)
{
#ifdef HAVE_PRIVILEGE_DROP_AND_ELEVATE
static const size_t MAX_GROUP_BUFFER_SIZE = 16384; // 16kB
static const size_t MAX_GROUP_BUFFER_SIZE = 16384; // 16 KiB
static const size_t MAX_PASSWD_BUFFER_SIZE = 16384;
static const size_t FALLBACK_GROUP_BUFFER_SIZE = 1024;
static const size_t FALLBACK_PASSWD_BUFFER_SIZE = 1024;
NFD_LOG_TRACE("initializing privilege helper with user \"" << userName << "\""
NFD_LOG_TRACE("initializing with user \"" << userName << "\""
<< " group \"" << groupName << "\"");
// workflow from man getpwnam_r
@@ -62,21 +62,20 @@ PrivilegeHelper::initialize(const std::string& userName, const std::string& grou
if (groupSize == -1)
groupSize = FALLBACK_GROUP_BUFFER_SIZE;
std::vector<char> groupBuffer(groupSize);
std::vector<char> groupBuffer(static_cast<size_t>(groupSize));
struct group group;
struct group* groupResult = nullptr;
int errorCode = getgrnam_r(groupName.data(), &group,
&groupBuffer[0], groupBuffer.size(), &groupResult);
groupBuffer.data(), groupBuffer.size(), &groupResult);
while (errorCode == ERANGE) {
if (groupBuffer.size() * 2 > MAX_GROUP_BUFFER_SIZE)
throw Error("Cannot allocate large enough buffer for struct group");
groupBuffer.resize(groupBuffer.size() * 2);
errorCode = getgrnam_r(groupName.data(), &group,
&groupBuffer[0], groupBuffer.size(), &groupResult);
groupBuffer.data(), groupBuffer.size(), &groupResult);
}
if (errorCode != 0 || !groupResult)
@@ -91,21 +90,20 @@ PrivilegeHelper::initialize(const std::string& userName, const std::string& grou
if (passwdSize == -1)
passwdSize = FALLBACK_PASSWD_BUFFER_SIZE;
std::vector<char> passwdBuffer(passwdSize);
std::vector<char> passwdBuffer(static_cast<size_t>(passwdSize));
struct passwd passwd;
struct passwd* passwdResult = nullptr;
int errorCode = getpwnam_r(userName.data(), &passwd,
&passwdBuffer[0], passwdBuffer.size(), &passwdResult);
passwdBuffer.data(), passwdBuffer.size(), &passwdResult);
while (errorCode == ERANGE) {
if (passwdBuffer.size() * 2 > MAX_PASSWD_BUFFER_SIZE)
throw Error("Cannot allocate large enough buffer for struct passwd");
passwdBuffer.resize(passwdBuffer.size() * 2);
errorCode = getpwnam_r(userName.data(), &passwd,
&passwdBuffer[0], passwdBuffer.size(), &passwdResult);
passwdBuffer.data(), passwdBuffer.size(), &passwdResult);
}
if (errorCode != 0 || !passwdResult)
@@ -123,6 +121,9 @@ PrivilegeHelper::initialize(const std::string& userName, const std::string& grou
void
PrivilegeHelper::drop()
{
if (::geteuid() == s_normalUid && ::getegid() == s_normalGid)
return;
#ifdef HAVE_PRIVILEGE_DROP_AND_ELEVATE
NFD_LOG_TRACE("dropping to effective gid=" << s_normalGid);
if (::setegid(s_normalGid) != 0)
@@ -141,6 +142,9 @@ PrivilegeHelper::drop()
void
PrivilegeHelper::raise()
{
if (::geteuid() == s_privilegedUid && ::getegid() == s_privilegedGid)
return;
#ifdef HAVE_PRIVILEGE_DROP_AND_ELEVATE
NFD_LOG_TRACE("elevating to effective uid=" << s_privilegedUid);
if (::seteuid(s_privilegedUid) != 0)
+11 -11
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-2018, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -33,7 +33,7 @@ namespace nfd {
/**
* \brief implements the Mean-Deviation RTT estimator
*
* reference: ns3::RttMeanDeviation
* \sa ns3::RttMeanDeviation
*
* This RttEstimator algorithm is designed for TCP, which is a continuous stream.
* NDN Interest-Data traffic is not always a continuous stream,
@@ -43,18 +43,18 @@ namespace nfd {
class RttEstimator
{
public:
typedef time::microseconds Duration;
static Duration
getInitialRtt(void)
{
return time::seconds(1);
}
using Duration = time::microseconds;
RttEstimator(uint16_t maxMultiplier = 16,
Duration minRto = time::milliseconds(1),
Duration minRto = 1_ms,
double gain = 0.1);
static Duration
getInitialRtt()
{
return 1_s;
}
void
addMeasurement(Duration measure);
+14 -15
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-2018, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -27,6 +27,7 @@
#define NFD_CORE_SCHEDULER_HPP
#include "common.hpp"
#include <ndn-cxx/util/scheduler.hpp>
namespace nfd {
@@ -34,40 +35,40 @@ namespace scheduler {
using ndn::Scheduler;
/** \class EventId
* \brief Opaque type (shared_ptr) representing ID of a scheduled event
/** \class nfd::scheduler::EventId
* \brief Opaque handle for a scheduled event.
*/
using ndn::EventId;
using ndn::util::scheduler::EventCallback;
/** \brief schedule an event
/** \brief Schedule an event.
*/
EventId
schedule(time::nanoseconds after, const EventCallback& event);
/** \brief cancel a scheduled event
/** \brief Cancel a scheduled event.
*/
void
cancel(const EventId& eventId);
/** \brief cancels an event automatically upon destruction
/** \brief Cancels an event automatically upon destruction.
*/
class ScopedEventId : noncopyable
{
public:
ScopedEventId();
/** \brief implicit constructor from EventId
/** \brief Implicit constructor from EventId.
* \param event the event to be cancelled upon destruction
*/
ScopedEventId(const EventId& event);
/** \brief move constructor
/** \brief Move constructor.
*/
ScopedEventId(ScopedEventId&& other);
/** \brief assigns an event
/** \brief Assigns an event.
*
* If a different event has been assigned to this instance previously,
* that event will be cancelled immediately.
@@ -75,17 +76,16 @@ public:
ScopedEventId&
operator=(const EventId& event);
/** \brief cancels the event
/** \brief Cancels the event.
*/
~ScopedEventId();
/** \brief cancels the event manually
/** \brief Cancels the event manually.
*/
void
cancel();
/** \brief releases the event so that it won't be disconnected
* when this ScopedEventId is destructed
/** \brief Releases the event so that it won't be cancelled when this ScopedEventId is destructed.
*/
void
release();
@@ -95,7 +95,6 @@ private:
};
} // namespace scheduler
} // namespace nfd
#endif // NFD_CORE_SCHEDULER_HPP
+10 -20
View File
@@ -37,11 +37,11 @@ namespace face {
/** \brief Prototype for the callback that is invoked when a face is created
* (in response to an incoming connection or after a connection is established)
*/
using FaceCreatedCallback = function<void(const shared_ptr<Face>& face)>;
using FaceCreatedCallback = std::function<void(const shared_ptr<Face>& face)>;
/** \brief Prototype for the callback that is invoked when a face fails to be created
*/
using FaceCreationFailedCallback = function<void(uint32_t status, const std::string& reason)>;
using FaceCreationFailedCallback = std::function<void(uint32_t status, const std::string& reason)>;
/** \brief represent a channel that communicates on a local endpoint
* \sa FaceSystem
@@ -84,25 +84,15 @@ private:
* Parameters are passed as a struct rather than individually, so that a future change in the list
* of parameters does not require an update to the method signature in all subclasses.
*/
class FaceParams
struct FaceParams
{
public:
// get rid of this constructor and use aggregate init + NSDMIs when we switch to C++14
FaceParams() noexcept
: persistency(ndn::nfd::FACE_PERSISTENCY_PERSISTENT)
, wantLocalFields(false)
, wantLpReliability(false)
, wantCongestionMarking(boost::logic::indeterminate)
{
}
public:
ndn::nfd::FacePersistency persistency;
ndn::optional<time::nanoseconds> baseCongestionMarkingInterval;
ndn::optional<uint64_t> defaultCongestionThreshold;
bool wantLocalFields;
bool wantLpReliability;
boost::logic::tribool wantCongestionMarking;
ndn::nfd::FacePersistency persistency = ndn::nfd::FACE_PERSISTENCY_PERSISTENT;
optional<time::nanoseconds> baseCongestionMarkingInterval;
optional<uint64_t> defaultCongestionThreshold;
optional<ssize_t> mtu;
bool wantLocalFields = false;
bool wantLpReliability = false;
boost::logic::tribool wantCongestionMarking = boost::logic::indeterminate;
};
/** \brief invokes a callback when the face is closed
+16 -21
View File
@@ -72,12 +72,10 @@ protected:
doSend(Transport::Packet&& packet) override;
void
handleSend(const boost::system::error_code& error,
size_t nBytesSent, const Block& payload);
handleSend(const boost::system::error_code& error, size_t nBytesSent);
void
handleReceive(const boost::system::error_code& error,
size_t nBytesReceived);
handleReceive(const boost::system::error_code& error, size_t nBytesReceived);
void
processErrorCode(const boost::system::error_code& error);
@@ -95,7 +93,7 @@ protected:
typename protocol::socket m_socket;
typename protocol::endpoint m_sender;
NFD_LOG_INCLASS_DECLARE();
NFD_LOG_MEMBER_DECL();
private:
std::array<uint8_t, ndn::MAX_NDN_PACKET_SIZE> m_receiveBuffer;
@@ -120,9 +118,9 @@ DatagramTransport<T, U>::DatagramTransport(typename DatagramTransport::protocol:
}
m_socket.async_receive_from(boost::asio::buffer(m_receiveBuffer), m_sender,
bind(&DatagramTransport<T, U>::handleReceive, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
[this] (auto&&... args) {
this->handleReceive(std::forward<decltype(args)>(args)...);
});
}
template<class T, class U>
@@ -164,10 +162,10 @@ DatagramTransport<T, U>::doSend(Transport::Packet&& packet)
NFD_LOG_FACE_TRACE(__func__);
m_socket.async_send(boost::asio::buffer(packet.packet),
bind(&DatagramTransport<T, U>::handleSend, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred,
packet.packet));
// packet.packet is copied into the lambda to retain the underlying Buffer
[this, p = packet.packet] (auto&&... args) {
this->handleSend(std::forward<decltype(args)>(args)...);
});
}
template<class T, class U>
@@ -202,23 +200,20 @@ DatagramTransport<T, U>::receiveDatagram(const uint8_t* buffer, size_t nBytesRec
template<class T, class U>
void
DatagramTransport<T, U>::handleReceive(const boost::system::error_code& error,
size_t nBytesReceived)
DatagramTransport<T, U>::handleReceive(const boost::system::error_code& error, size_t nBytesReceived)
{
receiveDatagram(m_receiveBuffer.data(), nBytesReceived, error);
if (m_socket.is_open())
m_socket.async_receive_from(boost::asio::buffer(m_receiveBuffer), m_sender,
bind(&DatagramTransport<T, U>::handleReceive, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
[this] (auto&&... args) {
this->handleReceive(std::forward<decltype(args)>(args)...);
});
}
template<class T, class U>
void
DatagramTransport<T, U>::handleSend(const boost::system::error_code& error,
size_t nBytesSent, const Block& payload)
// 'payload' is unused; it's needed to retain the underlying Buffer
DatagramTransport<T, U>::handleSend(const boost::system::error_code& error, size_t nBytesSent)
{
if (error)
return processErrorCode(error);
@@ -266,7 +261,7 @@ DatagramTransport<T, U>::resetRecentlyReceived()
template<class T, class U>
Transport::EndpointId
DatagramTransport<T, U>::makeEndpointId(const typename protocol::endpoint& ep)
DatagramTransport<T, U>::makeEndpointId(const typename protocol::endpoint&)
{
return 0;
}
+6 -7
View File
@@ -35,7 +35,7 @@
namespace nfd {
namespace face {
NFD_LOG_INIT("EthernetChannel");
NFD_LOG_INIT(EthernetChannel);
EthernetChannel::EthernetChannel(shared_ptr<const ndn::net::NetworkInterface> localEndpoint,
time::nanoseconds idleTimeout)
@@ -65,7 +65,7 @@ EthernetChannel::connect(const ethernet::Address& remoteEndpoint,
catch (const boost::system::system_error& e) {
NFD_LOG_CHAN_DEBUG("Face creation for " << remoteEndpoint << " failed: " << e.what());
if (onConnectFailed)
onConnectFailed(504, std::string("Face creation failed: ") + e.what());
onConnectFailed(504, "Face creation failed: "s + e.what());
return;
}
@@ -102,9 +102,7 @@ EthernetChannel::asyncRead(const FaceCreatedCallback& onFaceCreated,
const FaceCreationFailedCallback& onReceiveFailed)
{
m_socket.async_read_some(boost::asio::null_buffers(),
bind(&EthernetChannel::handleRead, this,
boost::asio::placeholders::error,
onFaceCreated, onReceiveFailed));
[=] (const auto& e, auto) { this->handleRead(e, onFaceCreated, onReceiveFailed); });
}
void
@@ -172,7 +170,7 @@ EthernetChannel::processIncomingPacket(const uint8_t* packet, size_t length,
catch (const EthernetTransport::Error& e) {
NFD_LOG_CHAN_DEBUG("Face creation for " << sender << " failed: " << e.what());
if (onReceiveFailed)
onReceiveFailed(504, std::string("Face creation failed: ") + e.what());
onReceiveFailed(504, "Face creation failed: "s + e.what());
return;
}
@@ -205,7 +203,8 @@ EthernetChannel::createFace(const ethernet::Address& remoteEndpoint,
auto linkService = make_unique<GenericLinkService>(options);
auto transport = make_unique<UnicastEthernetTransport>(*m_localEndpoint, remoteEndpoint,
params.persistency, m_idleFaceTimeout);
params.persistency, m_idleFaceTimeout,
params.mtu);
auto face = make_shared<Face>(std::move(linkService), std::move(transport));
m_channelFaces[remoteEndpoint] = face;
+12 -6
View File
@@ -33,7 +33,7 @@
namespace nfd {
namespace face {
NFD_LOG_INIT("EthernetFactory");
NFD_LOG_INIT(EthernetFactory);
NFD_REGISTER_PROTOCOL_FACTORY(EthernetFactory);
const std::string&
@@ -46,11 +46,10 @@ EthernetFactory::getId()
EthernetFactory::EthernetFactory(const CtorParams& params)
: ProtocolFactory(params)
{
m_netifAddConn = netmon->onInterfaceAdded.connect(
[this] (const shared_ptr<const ndn::net::NetworkInterface>& netif) {
this->applyUnicastConfigToNetif(netif);
this->applyMcastConfigToNetif(*netif);
});
m_netifAddConn = netmon->onInterfaceAdded.connect([this] (const auto& netif) {
this->applyUnicastConfigToNetif(netif);
this->applyMcastConfigToNetif(*netif);
});
}
void
@@ -201,6 +200,13 @@ EthernetFactory::createFace(const CreateFaceRequest& req,
return;
}
if (req.params.mtu && *req.params.mtu < Transport::MIN_MTU) {
// The specified MTU must be greater than the minimum possible
NFD_LOG_TRACE("createFace cannot create a face with an MTU less than " << Transport::MIN_MTU);
onFailure(406, "MTU cannot be less than " + to_string(Transport::MIN_MTU));
return;
}
for (const auto& i : m_channels) {
if (i.first == localEndpoint) {
i.second->connect(remoteEndpoint, req.params, onCreated, onFailure);
+6 -5
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-2018, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -25,7 +25,7 @@
#include "ethernet-protocol.hpp"
#include <arpa/inet.h> // for ntohs()
#include <boost/endian/conversion.hpp>
namespace nfd {
namespace ethernet {
@@ -41,8 +41,9 @@ checkFrameHeader(const uint8_t* packet, size_t length,
// in some cases VLAN-tagged frames may survive the BPF filter,
// make sure we do not process those frames (see #3348)
if (ntohs(eh->ether_type) != ETHERTYPE_NDN)
return {nullptr, "Received frame with wrong ethertype: " + to_string(ntohs(eh->ether_type))};
uint16_t ethertype = boost::endian::big_to_native(eh->ether_type);
if (ethertype != ETHERTYPE_NDN)
return {nullptr, "Received frame with wrong ethertype: " + to_string(ethertype)};
#ifdef _DEBUG
Address shost(eh->ether_shost);
+7 -7
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-2018, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -29,13 +29,14 @@
#include <pcap/pcap.h>
#include <arpa/inet.h> // for htons()
#include <cstring> // for memcpy()
#include <cstring> // for memcpy()
#include <boost/endian/conversion.hpp>
namespace nfd {
namespace face {
NFD_LOG_INIT("EthernetTransport");
NFD_LOG_INIT(EthernetTransport);
EthernetTransport::EthernetTransport(const ndn::net::NetworkInterface& localEndpoint,
const ethernet::Address& remoteEndpoint)
@@ -101,7 +102,7 @@ EthernetTransport::sendPacket(const ndn::Block& block)
}
// construct and prepend the ethernet header
static uint16_t ethertype = htons(ethernet::ETHERTYPE_NDN);
uint16_t ethertype = boost::endian::native_to_big(ethernet::ETHERTYPE_NDN);
buffer.prependByteArray(reinterpret_cast<const uint8_t*>(&ethertype), ethernet::TYPE_LEN);
buffer.prependByteArray(m_srcAddress.data(), m_srcAddress.size());
buffer.prependByteArray(m_destAddress.data(), m_destAddress.size());
@@ -122,8 +123,7 @@ void
EthernetTransport::asyncRead()
{
m_socket.async_read_some(boost::asio::null_buffers(),
bind(&EthernetTransport::handleRead, this,
boost::asio::placeholders::error));
[this] (const auto& e, auto) { this->handleRead(e); });
}
void
+2 -2
View File
@@ -31,7 +31,7 @@
namespace nfd {
namespace face {
NFD_LOG_INIT("FaceSystem");
NFD_LOG_INIT(FaceSystem);
FaceSystem::FaceSystem(FaceTable& faceTable, shared_ptr<ndn::net::NetworkMonitor> netmon)
: m_faceTable(faceTable)
@@ -47,7 +47,7 @@ FaceSystem::FaceSystem(FaceTable& faceTable, shared_ptr<ndn::net::NetworkMonitor
ProtocolFactoryCtorParams
FaceSystem::makePFCtorParams()
{
auto addFace = bind(&FaceTable::add, &m_faceTable, _1);
auto addFace = [&ft = m_faceTable] (auto face) { ft.add(std::move(face)); };
return {addFace, m_netmon};
}
+1 -1
View File
@@ -28,7 +28,7 @@
#include "channel.hpp"
#include "core/config-file.hpp"
#include "core/network-interface-predicate.hpp"
#include "core/network-predicate.hpp"
#include <ndn-cxx/net/network-address.hpp>
#include <ndn-cxx/net/network-interface.hpp>
#include <ndn-cxx/net/network-monitor.hpp>
+2 -2
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-2018, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -68,7 +68,7 @@ class Face
#ifndef WITH_TESTS
final
#endif
: public enable_shared_from_this<Face>, noncopyable
: public std::enable_shared_from_this<Face>, noncopyable
{
public:
Face(unique_ptr<LinkService> service, unique_ptr<Transport> transport);
+4 -15
View File
@@ -32,21 +32,10 @@
namespace nfd {
namespace face {
NFD_LOG_INIT("GenericLinkService");
NFD_LOG_INIT(GenericLinkService);
constexpr uint32_t DEFAULT_CONGESTION_THRESHOLD_DIVISOR = 2;
GenericLinkService::Options::Options()
: allowLocalFields(false)
, allowFragmentation(false)
, allowReassembly(false)
, allowCongestionMarking(false)
, baseCongestionMarkingInterval(time::milliseconds(100)) // Interval from RFC 8289 (CoDel)
, defaultCongestionThreshold(65536) // This default value works well for a queue capacity of 200KiB
, allowSelfLearning(false)
{
}
GenericLinkService::GenericLinkService(const GenericLinkService::Options& options)
: m_options(options)
, m_fragmenter(m_options.fragmenterOptions, this)
@@ -57,8 +46,8 @@ GenericLinkService::GenericLinkService(const GenericLinkService::Options& option
, m_lastMarkTime(time::steady_clock::TimePoint::min())
, m_nMarkedSinceInMarkingState(0)
{
m_reassembler.beforeTimeout.connect(bind([this] { ++this->nReassemblyTimeouts; }));
m_reliability.onDroppedInterest.connect([this] (const Interest& i) { this->notifyDroppedInterest(i); });
m_reassembler.beforeTimeout.connect([this] (auto...) { ++this->nReassemblyTimeouts; });
m_reliability.onDroppedInterest.connect([this] (const auto& i) { this->notifyDroppedInterest(i); });
nReassembling.observe(&m_reassembler);
}
@@ -226,7 +215,7 @@ GenericLinkService::assignSequence(lp::Packet& pkt)
void
GenericLinkService::assignSequences(std::vector<lp::Packet>& pkts)
{
std::for_each(pkts.begin(), pkts.end(), bind(&GenericLinkService::assignSequence, this, _1));
std::for_each(pkts.begin(), pkts.end(), [this] (auto& pkt) { this->assignSequence(pkt); });
}
void
+17 -9
View File
@@ -98,16 +98,19 @@ public:
class Options
{
public:
Options();
constexpr
Options() noexcept
{
}
public:
/** \brief enables encoding of IncomingFaceId, and decoding of NextHopFaceId and CachePolicy
*/
bool allowLocalFields;
bool allowLocalFields = false;
/** \brief enables fragmentation
*/
bool allowFragmentation;
bool allowFragmentation = false;
/** \brief options for fragmentation
*/
@@ -115,7 +118,7 @@ public:
/** \brief enables reassembly
*/
bool allowReassembly;
bool allowReassembly = false;
/** \brief options for reassembly
*/
@@ -127,19 +130,23 @@ public:
/** \brief enables send queue congestion detection and marking
*/
bool allowCongestionMarking;
bool allowCongestionMarking = false;
/** \brief starting value for congestion marking interval
*
* The default value (100 ms) is taken from RFC 8289 (CoDel).
*/
time::nanoseconds baseCongestionMarkingInterval;
time::nanoseconds baseCongestionMarkingInterval = 100_ms;
/** \brief default congestion threshold in bytes
*
* The default value (64 KiB) works well for a queue capacity of 200 KiB.
*/
size_t defaultCongestionThreshold;
size_t defaultCongestionThreshold = 65536;
/** \brief enables self-learning forwarding support
*/
bool allowSelfLearning;
bool allowSelfLearning = false;
};
/** \brief counters provided by GenericLinkService
@@ -147,7 +154,7 @@ public:
using Counters = GenericLinkServiceCounters;
explicit
GenericLinkService(const Options& options = Options());
GenericLinkService(const Options& options = {});
/** \brief get Options used by GenericLinkService
*/
@@ -283,6 +290,7 @@ PROTECTED_WITH_TESTS_ELSE_PRIVATE:
PUBLIC_WITH_TESTS_ELSE_PRIVATE:
/// CongestionMark TLV-TYPE (3 octets) + CongestionMark TLV-LENGTH (1 octet) + sizeof(uint64_t)
static constexpr size_t CONGESTION_MARK_SIZE = 3 + 1 + sizeof(uint64_t);
/// Time to mark next packet due to send queue congestion
time::steady_clock::TimePoint m_nextMarkTime;
/// Time last packet was marked
+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-2018, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -29,11 +29,11 @@
namespace nfd {
namespace face {
NFD_LOG_INCLASS_DEFINE(InternalForwarderTransport, "InternalForwarderTransport");
NFD_LOG_MEMBER_INIT(InternalForwarderTransport, InternalForwarderTransport);
NFD_LOG_MEMBER_INIT(InternalClientTransport, InternalClientTransport);
InternalForwarderTransport::InternalForwarderTransport(
const FaceUri& localUri, const FaceUri& remoteUri,
ndn::nfd::FaceScope scope, ndn::nfd::LinkType linkType)
InternalForwarderTransport::InternalForwarderTransport(const FaceUri& localUri, const FaceUri& remoteUri,
ndn::nfd::FaceScope scope, ndn::nfd::LinkType linkType)
{
this->setLocalUri(localUri);
this->setRemoteUri(remoteUri);
@@ -71,8 +71,6 @@ InternalForwarderTransport::doClose()
this->setState(TransportState::CLOSED);
}
NFD_LOG_INCLASS_DEFINE(InternalClientTransport, "InternalClientTransport");
static void
asyncReceive(InternalTransportBase* recipient, const Block& packet)
{
+4 -3
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-2018, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -27,6 +27,7 @@
#define NFD_DAEMON_FACE_INTERNAL_TRANSPORT_HPP
#include "transport.hpp"
#include <ndn-cxx/transport/transport.hpp>
namespace nfd {
@@ -73,7 +74,7 @@ private:
doSend(Packet&& packet) override;
private:
NFD_LOG_INCLASS_DECLARE();
NFD_LOG_MEMBER_DECL();
};
/** \brief implements a client-side transport that can be paired with another
@@ -117,7 +118,7 @@ public:
send(const Block& header, const Block& payload) override;
private:
NFD_LOG_INCLASS_DECLARE();
NFD_LOG_MEMBER_DECL();
signal::ScopedConnection m_fwToClientTransmitConn;
signal::ScopedConnection m_clientToFwTransmitConn;
+2 -2
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-2018, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -29,7 +29,7 @@
namespace nfd {
namespace face {
NFD_LOG_INIT("LinkService");
NFD_LOG_INIT(LinkService);
LinkService::LinkService()
: m_face(nullptr)
+7 -11
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-2018, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -25,12 +25,13 @@
#include "lp-fragmenter.hpp"
#include "link-service.hpp"
#include <ndn-cxx/encoding/tlv.hpp>
namespace nfd {
namespace face {
NFD_LOG_INIT("LpFragmenter");
NFD_LOG_INIT(LpFragmenter);
static_assert(lp::tlv::LpPacket < 253, "LpPacket TLV-TYPE must fit in 1 octet");
static_assert(lp::tlv::Sequence < 253, "Sequence TLV-TYPE must fit in 1 octet");
@@ -56,11 +57,6 @@ static const size_t MAX_FRAG_OVERHEAD =
1 + 1 + 8 + // FragCount TLV
1 + 9; // Fragment TLV-TYPE and TLV-LENGTH
LpFragmenter::Options::Options()
: nMaxFragments(400)
{
}
LpFragmenter::LpFragmenter(const LpFragmenter::Options& options, const LinkService* linkService)
: m_options(options)
, m_linkService(linkService)
@@ -121,7 +117,7 @@ LpFragmenter::fragmentPacket(const lp::Packet& packet, size_t mtu)
// compute FragCount
if (fragCount > m_options.nMaxFragments) {
NFD_LOG_FACE_WARN("fragmentation error, FragCount over limit: DROP");
return std::make_pair(false, std::vector<lp::Packet>{});
return std::make_tuple(false, std::vector<lp::Packet>{});
}
// populate fragments
@@ -134,7 +130,7 @@ LpFragmenter::fragmentPacket(const lp::Packet& packet, size_t mtu)
lp::Packet& frag = frags[fragIndex];
frag.add<lp::FragIndexField>(fragIndex);
frag.add<lp::FragCountField>(fragCount);
frag.set<lp::FragmentField>(std::make_pair(fragBegin, fragEnd));
frag.set<lp::FragmentField>({fragBegin, fragEnd});
BOOST_ASSERT(frag.wireEncode().size() <= mtu);
++fragIndex;
@@ -143,7 +139,7 @@ LpFragmenter::fragmentPacket(const lp::Packet& packet, size_t mtu)
}
BOOST_ASSERT(fragIndex == fragCount);
return std::make_pair(true, frags);
return std::make_tuple(true, frags);
}
std::ostream&
+7 -10
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-2018, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -26,6 +26,7 @@
#ifndef NFD_DAEMON_FACE_LP_FRAGMENTER_HPP
#define NFD_DAEMON_FACE_LP_FRAGMENTER_HPP
#include "core/common.hpp"
#include "face-log.hpp"
#include <ndn-cxx/lp/packet.hpp>
@@ -36,26 +37,22 @@ namespace face {
class LinkService;
/** \brief fragments network-layer packets into NDNLPv2 link-layer packets
* \sa http://redmine.named-data.net/projects/nfd/wiki/NDNLPv2
* \sa https://redmine.named-data.net/projects/nfd/wiki/NDNLPv2
*/
class LpFragmenter
{
public:
/** \brief Options that control the behavior of LpFragmenter
*/
class Options
struct Options
{
public:
Options();
public:
/** \brief maximum number of fragments in a packet
*/
size_t nMaxFragments;
size_t nMaxFragments = 400;
};
explicit
LpFragmenter(const Options& options = Options(), const LinkService* linkService = nullptr);
LpFragmenter(const Options& options, const LinkService* linkService = nullptr);
/** \brief set options for fragmenter
*/
+7 -13
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-2018, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -25,18 +25,13 @@
#include "lp-reassembler.hpp"
#include "link-service.hpp"
#include <numeric>
namespace nfd {
namespace face {
NFD_LOG_INIT("LpReassembler");
LpReassembler::Options::Options()
: nMaxFragments(400)
, reassemblyTimeout(time::milliseconds(500))
{
}
NFD_LOG_INIT(LpReassembler);
LpReassembler::LpReassembler(const LpReassembler::Options& options, const LinkService* linkService)
: m_options(options)
@@ -118,8 +113,7 @@ LpReassembler::receiveFragment(Transport::EndpointId remoteEndpoint, const lp::P
}
// set drop timer
pp.dropTimer = scheduler::schedule(m_options.reassemblyTimeout,
bind(&LpReassembler::timeoutPartialPacket, this, key));
pp.dropTimer = scheduler::schedule(m_options.reassemblyTimeout, [=] { timeoutPartialPacket(key); });
return FALSE_RETURN;
}
@@ -129,7 +123,7 @@ LpReassembler::doReassembly(const Key& key)
{
PartialPacket& pp = m_partialPackets[key];
size_t payloadSize = std::accumulate(pp.fragments.begin(), pp.fragments.end(), 0,
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>();
@@ -137,7 +131,7 @@ LpReassembler::doReassembly(const Key& key)
});
ndn::Buffer fragBuffer(payloadSize);
ndn::Buffer::iterator it = fragBuffer.begin();
auto it = fragBuffer.begin();
for (const lp::Packet& frag : pp.fragments) {
ndn::Buffer::const_iterator fragBegin, fragEnd;
+7 -11
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-2018, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -38,32 +38,28 @@ namespace face {
class LinkService;
/** \brief reassembles fragmented network-layer packets
* \sa http://redmine.named-data.net/projects/nfd/wiki/NDNLPv2
* \sa https://redmine.named-data.net/projects/nfd/wiki/NDNLPv2
*/
class LpReassembler : noncopyable
{
public:
/** \brief Options that control the behavior of LpReassembler
*/
class Options
struct Options
{
public:
Options();
public:
/** \brief maximum number of fragments in a packet
*
* LpPackets with FragCount over this limit are dropped.
*/
size_t nMaxFragments;
size_t nMaxFragments = 400;
/** \brief timeout before a partially reassembled packet is dropped
*/
time::nanoseconds reassemblyTimeout;
time::nanoseconds reassemblyTimeout = 500_ms;
};
explicit
LpReassembler(const Options& options = Options(), const LinkService* linkService = nullptr);
LpReassembler(const Options& options, const LinkService* linkService = nullptr);
/** \brief set options for reassembler
*/
+35 -20
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-2018, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -39,13 +39,13 @@ LpReliability::LpReliability(const LpReliability::Options& options, GenericLinkS
{
BOOST_ASSERT(m_linkService != nullptr);
BOOST_ASSERT(m_options.idleAckTimerPeriod > time::nanoseconds::zero());
BOOST_ASSERT(m_options.idleAckTimerPeriod > 0_ns);
}
void
LpReliability::setOptions(const Options& options)
{
BOOST_ASSERT(options.idleAckTimerPeriod > time::nanoseconds::zero());
BOOST_ASSERT(options.idleAckTimerPeriod > 0_ns);
if (m_options.isEnabled && !options.isEnabled) {
this->stopIdleAckTimer();
@@ -81,8 +81,7 @@ LpReliability::handleOutgoing(std::vector<lp::Packet>& frags, lp::Packet&& pkt,
std::forward_as_tuple(txSeq),
std::forward_as_tuple(frag));
unackedFragsIt->second.sendTime = sendTime;
unackedFragsIt->second.rtoTimer =
scheduler::schedule(m_rto.computeRto(), bind(&LpReliability::onLpPacketLost, this, unackedFragsIt));
unackedFragsIt->second.rtoTimer = scheduler::schedule(m_rto.computeRto(), [=] { onLpPacketLost(txSeq); });
unackedFragsIt->second.netPkt = netPkt;
if (m_unackedFrags.size() == 1) {
@@ -127,9 +126,20 @@ LpReliability::processIncomingPacket(const lp::Packet& pkt)
// packet. Potentially increment the start of the window.
onLpPacketAcknowledged(fragIt);
// This set contains TxSequences that have been removed by onLpPacketLost below because they
// were part of a network packet that was removed due to a fragment exceeding retx, as well as
// any other TxSequences removed by onLpPacketLost. This prevents onLpPacketLost from being
// called later for an invalid iterator.
std::set<lp::Sequence> removedLpPackets;
// Resend or fail fragments considered lost. Potentially increment the start of the window.
for (UnackedFrags::iterator txSeqIt : lostLpPackets) {
this->onLpPacketLost(txSeqIt);
for (lp::Sequence txSeq : lostLpPackets) {
if (removedLpPackets.find(txSeq) == removedLpPackets.end()) {
auto removedThisTxSeq = this->onLpPacketLost(txSeq);
for (auto removedTxSeq : removedThisTxSeq) {
removedLpPackets.insert(removedTxSeq);
}
}
}
}
@@ -157,11 +167,10 @@ LpReliability::piggyback(lp::Packet& pkt, ssize_t mtu)
while (!m_ackQueue.empty()) {
lp::Sequence ackSeq = m_ackQueue.front();
// Ack Size = Ack Type (3 octets) + Ack Length (1 octet) + Value (1, 2, 4, or 8 octets)
ssize_t ackSize = tlv::sizeOfVarNumber(lp::tlv::Ack) +
tlv::sizeOfVarNumber(
tlv::sizeOfNonNegativeInteger(std::numeric_limits<lp::Sequence>::max())) +
tlv::sizeOfNonNegativeInteger(ackSeq);
// Ack size = Ack TLV-TYPE (3 octets) + TLV-LENGTH (1 octet) + uint64_t (8 octets)
const ssize_t ackSize = tlv::sizeOfVarNumber(lp::tlv::Ack) +
tlv::sizeOfVarNumber(sizeof(lp::Sequence)) +
sizeof(lp::Sequence);
if (ackSize > remainingSpace) {
break;
@@ -206,10 +215,10 @@ LpReliability::stopIdleAckTimer()
m_isIdleAckTimerRunning = false;
}
std::vector<LpReliability::UnackedFrags::iterator>
std::vector<lp::Sequence>
LpReliability::findLostLpPackets(LpReliability::UnackedFrags::iterator ackIt)
{
std::vector<UnackedFrags::iterator> lostLpPackets;
std::vector<lp::Sequence> lostLpPackets;
for (auto it = m_firstUnackedFrag; ; ++it) {
if (it == m_unackedFrags.end()) {
@@ -224,27 +233,30 @@ LpReliability::findLostLpPackets(LpReliability::UnackedFrags::iterator ackIt)
unackedFrag.nGreaterSeqAcks++;
if (unackedFrag.nGreaterSeqAcks >= m_options.seqNumLossThreshold) {
lostLpPackets.push_back(it);
lostLpPackets.push_back(it->first);
}
}
return lostLpPackets;
}
void
LpReliability::onLpPacketLost(UnackedFrags::iterator txSeqIt)
std::vector<lp::Sequence>
LpReliability::onLpPacketLost(lp::Sequence txSeq)
{
BOOST_ASSERT(m_unackedFrags.count(txSeqIt->first) > 0);
BOOST_ASSERT(m_unackedFrags.count(txSeq) > 0);
auto txSeqIt = m_unackedFrags.find(txSeq);
auto& txFrag = txSeqIt->second;
txFrag.rtoTimer.cancel();
auto netPkt = txFrag.netPkt;
std::vector<lp::Sequence> removedThisTxSeq;
// Check if maximum number of retransmissions exceeded
if (txFrag.retxCount >= m_options.maxRetx) {
// Delete all LpPackets of NetPkt from m_unackedFrags (except this one)
for (size_t i = 0; i < netPkt->unackedFrags.size(); i++) {
if (netPkt->unackedFrags[i] != txSeqIt) {
removedThisTxSeq.push_back(netPkt->unackedFrags[i]->first);
deleteUnackedFrag(netPkt->unackedFrags[i]);
}
}
@@ -260,6 +272,7 @@ LpReliability::onLpPacketLost(UnackedFrags::iterator txSeqIt)
onDroppedInterest(Interest(frag));
}
removedThisTxSeq.push_back(txSeqIt->first);
deleteUnackedFrag(txSeqIt);
}
else {
@@ -284,15 +297,17 @@ LpReliability::onLpPacketLost(UnackedFrags::iterator txSeqIt)
BOOST_ASSERT(fragInNetPkt != netPkt->unackedFrags.end());
*fragInNetPkt = newTxFragIt;
removedThisTxSeq.push_back(txSeqIt->first);
deleteUnackedFrag(txSeqIt);
// Retransmit fragment
m_linkService->sendLpPacket(lp::Packet(newTxFrag.pkt));
// Start RTO timer for this sequence
newTxFrag.rtoTimer = scheduler::schedule(m_rto.computeRto(),
bind(&LpReliability::onLpPacketLost, this, newTxFragIt));
newTxFrag.rtoTimer = scheduler::schedule(m_rto.computeRto(), [=] { onLpPacketLost(newTxSeq); });
}
return removedThisTxSeq;
}
void
+7 -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-2018, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -57,7 +57,7 @@ public:
/** \brief period between sending pending Acks in an IDLE packet
*/
time::nanoseconds idleAckTimerPeriod = time::milliseconds(5);
time::nanoseconds idleAckTimerPeriod = 5_ms;
/** \brief a fragment is considered lost if this number of fragments with greater sequence
* numbers are acknowledged
@@ -135,15 +135,16 @@ PUBLIC_WITH_TESTS_ELSE_PRIVATE:
/** \brief find and mark as lost fragments where a configurable number of Acks
* (\p m_options.seqNumLossThreshold) have been received for greater TxSequence numbers
* \param ackIt iterator pointing to acknowledged fragment
* \return vector containing iterators to fragments marked lost by this mechanism
* \return vector containing TxSequences of fragments marked lost by this mechanism
*/
std::vector<UnackedFrags::iterator>
std::vector<lp::Sequence>
findLostLpPackets(UnackedFrags::iterator ackIt);
/** \brief resend (or give up on) a lost fragment
* \return vector of the TxSequences of fragments removed due to a network packet being removed
*/
void
onLpPacketLost(UnackedFrags::iterator txSeqIt);
std::vector<lp::Sequence>
onLpPacketLost(lp::Sequence txSeq);
/** \brief remove the fragment with the given sequence number from the map of unacknowledged
* fragments, as well as its associated network packet (if any)
+2 -2
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-2018, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -46,7 +46,7 @@
namespace nfd {
namespace face {
NFD_LOG_INIT("MulticastEthernetTransport");
NFD_LOG_INIT(MulticastEthernetTransport);
MulticastEthernetTransport::MulticastEthernetTransport(const ndn::net::NetworkInterface& localEndpoint,
const ethernet::Address& mcastAddress,
+5 -6
View File
@@ -40,8 +40,7 @@
namespace nfd {
namespace face {
NFD_LOG_INCLASS_2TEMPLATE_SPECIALIZATION_DEFINE(DatagramTransport, MulticastUdpTransport::protocol,
Multicast, "MulticastUdpTransport");
NFD_LOG_MEMBER_INIT_SPECIALIZED((DatagramTransport<boost::asio::ip::udp, Multicast>), MulticastUdpTransport);
MulticastUdpTransport::MulticastUdpTransport(const protocol::endpoint& multicastGroup,
protocol::socket&& recvSocket,
@@ -88,10 +87,10 @@ MulticastUdpTransport::doSend(Transport::Packet&& packet)
NFD_LOG_FACE_TRACE(__func__);
m_sendSocket.async_send_to(boost::asio::buffer(packet.packet), m_multicastGroup,
bind(&MulticastUdpTransport::handleSend, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred,
packet.packet));
// packet.packet is copied into the lambda to retain the underlying Buffer
[this, p = packet.packet] (auto&&... args) {
this->handleSend(std::forward<decltype(args)>(args)...);
});
}
void
+2
View File
@@ -33,6 +33,8 @@
namespace nfd {
namespace face {
NFD_LOG_MEMBER_DECL_SPECIALIZED((DatagramTransport<boost::asio::ip::udp, Multicast>));
// Explicit specialization of makeEndpointId for the UDP multicast case.
// Note that this "shall be declared before the first use of the specialization
// that would cause an implicit instantiation to take place, in every translation
+2 -4
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-2018, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -43,14 +43,12 @@ PcapHelper::PcapHelper(const std::string& interfaceName)
if (!m_pcap)
BOOST_THROW_EXCEPTION(Error("pcap_create: " + std::string(errbuf)));
#ifdef HAVE_PCAP_SET_IMMEDIATE_MODE
// Enable "immediate mode", effectively disabling any read buffering in the kernel.
// This corresponds to the BIOCIMMEDIATE ioctl on BSD-like systems (including macOS)
// where libpcap uses a BPF device. On Linux this forces libpcap not to use TPACKET_V3,
// even if the kernel supports it, thus preventing bug #1511.
if (pcap_set_immediate_mode(m_pcap, 1) < 0)
BOOST_THROW_EXCEPTION(Error("pcap_set_immediate_mode failed"));
#endif
}
PcapHelper::~PcapHelper()
+1 -1
View File
@@ -137,7 +137,7 @@ public:
struct CreateFaceRequest
{
FaceUri remoteUri;
ndn::optional<FaceUri> localUri;
optional<FaceUri> localUri;
FaceParams params;
};
+3 -7
View File
@@ -97,7 +97,7 @@ protected:
protected:
typename protocol::socket m_socket;
NFD_LOG_INCLASS_DECLARE();
NFD_LOG_MEMBER_DECL();
private:
uint8_t m_receiveBuffer[ndn::MAX_NDN_PACKET_SIZE];
@@ -200,9 +200,7 @@ void
StreamTransport<T>::sendFromQueue()
{
boost::asio::async_write(m_socket, boost::asio::buffer(m_sendQueue.front()),
bind(&StreamTransport<T>::handleSend, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
[this] (auto&&... args) { this->handleSend(std::forward<decltype(args)>(args)...); });
}
template<class T>
@@ -232,9 +230,7 @@ StreamTransport<T>::startReceive()
m_socket.async_receive(boost::asio::buffer(m_receiveBuffer + m_receiveBufferSize,
ndn::MAX_NDN_PACKET_SIZE - m_receiveBufferSize),
bind(&StreamTransport<T>::handleReceive, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
[this] (auto&&... args) { this->handleReceive(std::forward<decltype(args)>(args)...); });
}
template<class T>
+16 -22
View File
@@ -24,22 +24,24 @@
*/
#include "tcp-channel.hpp"
#include "core/global-io.hpp"
#include "generic-link-service.hpp"
#include "tcp-transport.hpp"
#include "core/global-io.hpp"
namespace nfd {
namespace face {
NFD_LOG_INIT("TcpChannel");
NFD_LOG_INIT(TcpChannel);
namespace ip = boost::asio::ip;
TcpChannel::TcpChannel(const tcp::Endpoint& localEndpoint, bool wantCongestionMarking)
TcpChannel::TcpChannel(const tcp::Endpoint& localEndpoint, bool wantCongestionMarking,
DetermineFaceScopeFromAddress determineFaceScope)
: m_localEndpoint(localEndpoint)
, m_acceptor(getGlobalIoService())
, m_socket(getGlobalIoService())
, m_wantCongestionMarking(wantCongestionMarking)
, m_determineFaceScope(std::move(determineFaceScope))
{
setUri(FaceUri(m_localEndpoint));
NFD_LOG_CHAN_INFO("Creating channel");
@@ -81,15 +83,15 @@ TcpChannel::connect(const tcp::Endpoint& remoteEndpoint,
return;
}
auto clientSocket = make_shared<ip::tcp::socket>(ref(getGlobalIoService()));
auto timeoutEvent = scheduler::schedule(timeout, bind(&TcpChannel::handleConnectTimeout, this,
remoteEndpoint, clientSocket, onConnectFailed));
auto clientSocket = make_shared<ip::tcp::socket>(std::ref(getGlobalIoService()));
auto timeoutEvent = scheduler::schedule(timeout, [=] {
handleConnectTimeout(remoteEndpoint, clientSocket, onConnectFailed);
});
NFD_LOG_CHAN_TRACE("Connecting to " << remoteEndpoint);
clientSocket->async_connect(remoteEndpoint,
bind(&TcpChannel::handleConnect, this,
boost::asio::placeholders::error, remoteEndpoint, clientSocket,
params, timeoutEvent, onFaceCreated, onConnectFailed));
clientSocket->async_connect(remoteEndpoint, [=] (const auto& e) {
this->handleConnect(e, remoteEndpoint, clientSocket, params, timeoutEvent, onFaceCreated, onConnectFailed);
});
}
void
@@ -122,7 +124,9 @@ TcpChannel::createFace(ip::tcp::socket&& socket,
}
auto linkService = make_unique<GenericLinkService>(options);
auto transport = make_unique<TcpTransport>(std::move(socket), params.persistency);
auto faceScope = m_determineFaceScope(socket.local_endpoint().address(),
socket.remote_endpoint().address());
auto transport = make_unique<TcpTransport>(std::move(socket), params.persistency, faceScope);
face = make_shared<Face>(std::move(linkService), std::move(transport));
m_channelFaces[remoteEndpoint] = face;
@@ -147,9 +151,7 @@ void
TcpChannel::accept(const FaceCreatedCallback& onFaceCreated,
const FaceCreationFailedCallback& onAcceptFailed)
{
m_acceptor.async_accept(m_socket, bind(&TcpChannel::handleAccept, this,
boost::asio::placeholders::error,
onFaceCreated, onAcceptFailed));
m_acceptor.async_accept(m_socket, [=] (const auto& e) { this->handleAccept(e, onFaceCreated, onAcceptFailed); });
}
void
@@ -187,15 +189,7 @@ TcpChannel::handleConnect(const boost::system::error_code& error,
{
scheduler::cancel(connectTimeoutEvent);
#if (BOOST_VERSION == 105400)
// To handle regression in Boost 1.54
// https://svn.boost.org/trac/boost/ticket/8795
boost::system::error_code anotherErrorCode;
socket->remote_endpoint(anotherErrorCode);
if (error || anotherErrorCode) {
#else
if (error) {
#endif
if (error != boost::asio::error::operation_aborted) {
NFD_LOG_CHAN_DEBUG("Connection to " << remoteEndpoint << " failed: " << error.message());
if (onConnectFailed)
+6 -1
View File
@@ -37,6 +37,9 @@ typedef boost::asio::ip::tcp::endpoint Endpoint;
namespace 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
*
@@ -53,7 +56,8 @@ public:
* To enable creation faces upon incoming connections,
* one needs to explicitly call TcpChannel::listen method.
*/
TcpChannel(const tcp::Endpoint& localEndpoint, bool wantCongestionMarking);
TcpChannel(const tcp::Endpoint& localEndpoint, bool wantCongestionMarking,
DetermineFaceScopeFromAddress determineFaceScope);
bool
isListening() const override
@@ -126,6 +130,7 @@ private:
boost::asio::ip::tcp::socket m_socket;
std::map<tcp::Endpoint, shared_ptr<Face>> m_channelFaces;
bool m_wantCongestionMarking;
DetermineFaceScopeFromAddress m_determineFaceScope;
};
} // namespace face
+42 -5
View File
@@ -25,14 +25,12 @@
#include "tcp-factory.hpp"
#include <ndn-cxx/net/address-converter.hpp>
namespace nfd {
namespace face {
namespace ip = boost::asio::ip;
NFD_LOG_INIT("TcpFactory");
NFD_LOG_INIT(TcpFactory);
NFD_REGISTER_PROTOCOL_FACTORY(TcpFactory);
const std::string&
@@ -72,6 +70,8 @@ TcpFactory::processConfig(OptionalConfigSection configSection,
uint16_t port = 6363;
bool enableV4 = true;
bool enableV6 = true;
IpAddressPredicate local;
bool isLocalConfigured = false;
for (const auto& pair : *configSection) {
const std::string& key = pair.first;
@@ -88,10 +88,28 @@ TcpFactory::processConfig(OptionalConfigSection configSection,
else if (key == "enable_v6") {
enableV6 = ConfigFile::parseYesNo(pair, "face_system.tcp");
}
else if (key == "local") {
isLocalConfigured = true;
for (const auto& localPair : pair.second) {
const std::string& localKey = localPair.first;
if (localKey == "whitelist") {
local.parseWhitelist(localPair.second);
}
else if (localKey == "blacklist") {
local.parseBlacklist(localPair.second);
}
else {
BOOST_THROW_EXCEPTION(ConfigFile::Error("Unrecognized option face_system.tcp.local." + localKey));
}
}
}
else {
BOOST_THROW_EXCEPTION(ConfigFile::Error("Unrecognized option face_system.tcp." + key));
}
}
if (!isLocalConfigured) {
local.assign({{"subnet", "127.0.0.0/8"}, {"subnet", "::1/128"}}, {});
}
if (!enableV4 && !enableV6) {
BOOST_THROW_EXCEPTION(ConfigFile::Error(
@@ -125,6 +143,8 @@ TcpFactory::processConfig(OptionalConfigSection configSection,
else if (providedSchemes.count("tcp6") > 0) {
NFD_LOG_WARN("Cannot close tcp6 channel after its creation");
}
m_local = std::move(local);
}
}
@@ -147,7 +167,7 @@ TcpFactory::createFace(const CreateFaceRequest& req,
return;
}
tcp::Endpoint endpoint(ndn::ip::addressFromString(req.remoteUri.getHost()),
tcp::Endpoint endpoint(ip::address::from_string(req.remoteUri.getHost()),
boost::lexical_cast<uint16_t>(req.remoteUri.getPort()));
// a canonical tcp4/tcp6 FaceUri cannot have a multicast address
@@ -159,6 +179,12 @@ TcpFactory::createFace(const CreateFaceRequest& req,
return;
}
if (req.params.mtu) {
NFD_LOG_TRACE("createFace cannot create a TCP face with an overridden MTU");
onFailure(406, "TCP faces do not support MTU overrides");
return;
}
// very simple logic for now
for (const auto& i : m_channels) {
if ((i.first.address().is_v4() && endpoint.address().is_v4()) ||
@@ -179,7 +205,8 @@ TcpFactory::createChannel(const tcp::Endpoint& endpoint)
if (it != m_channels.end())
return it->second;
auto channel = make_shared<TcpChannel>(endpoint, m_wantCongestionMarking);
auto channel = make_shared<TcpChannel>(endpoint, m_wantCongestionMarking,
bind(&TcpFactory::determineFaceScopeFromAddresses, this, _1, _2));
m_channels[endpoint] = channel;
return channel;
}
@@ -190,5 +217,15 @@ TcpFactory::getChannels() const
return getChannelsFromMap(m_channels);
}
ndn::nfd::FaceScope
TcpFactory::determineFaceScopeFromAddresses(const boost::asio::ip::address& localAddress,
const boost::asio::ip::address& remoteAddress) const
{
if (m_local(localAddress) && m_local(remoteAddress)) {
return ndn::nfd::FACE_SCOPE_LOCAL;
}
return ndn::nfd::FACE_SCOPE_NON_LOCAL;
}
} // namespace face
} // namespace nfd
+8
View File
@@ -71,9 +71,17 @@ public:
std::vector<shared_ptr<const Channel>>
getChannels() const override;
private:
ndn::nfd::FaceScope
determineFaceScopeFromAddresses(const boost::asio::ip::address& local,
const boost::asio::ip::address& remote) const;
private:
bool m_wantCongestionMarking = false;
std::map<tcp::Endpoint, shared_ptr<TcpChannel>> m_channels;
PUBLIC_WITH_TESTS_ELSE_PRIVATE:
IpAddressPredicate m_local;
};
} // namespace face
+7 -15
View File
@@ -33,26 +33,20 @@
namespace nfd {
namespace face {
NFD_LOG_INCLASS_TEMPLATE_SPECIALIZATION_DEFINE(StreamTransport, TcpTransport::protocol, "TcpTransport");
NFD_LOG_MEMBER_INIT_SPECIALIZED(StreamTransport<boost::asio::ip::tcp>, TcpTransport);
time::milliseconds TcpTransport::s_initialReconnectWait = time::seconds(1);
time::milliseconds TcpTransport::s_maxReconnectWait = time::minutes(5);
time::milliseconds TcpTransport::s_initialReconnectWait = 1_s;
time::milliseconds TcpTransport::s_maxReconnectWait = 5_min;
float TcpTransport::s_reconnectWaitMultiplier = 2.0f;
TcpTransport::TcpTransport(protocol::socket&& socket, ndn::nfd::FacePersistency persistency)
TcpTransport::TcpTransport(protocol::socket&& socket, ndn::nfd::FacePersistency persistency, ndn::nfd::FaceScope faceScope)
: StreamTransport(std::move(socket))
, m_remoteEndpoint(m_socket.remote_endpoint())
, m_nextReconnectWait(s_initialReconnectWait)
{
this->setLocalUri(FaceUri(m_socket.local_endpoint()));
this->setRemoteUri(FaceUri(m_socket.remote_endpoint()));
if (m_socket.local_endpoint().address().is_loopback() &&
m_socket.remote_endpoint().address().is_loopback())
this->setScope(ndn::nfd::FACE_SCOPE_LOCAL);
else
this->setScope(ndn::nfd::FACE_SCOPE_NON_LOCAL);
this->setScope(faceScope);
this->setPersistency(persistency);
this->setLinkType(ndn::nfd::LINK_TYPE_POINT_TO_POINT);
this->setMtu(MTU_UNLIMITED);
@@ -140,10 +134,8 @@ TcpTransport::reconnect()
this->resetReceiveBuffer();
this->resetSendQueue();
m_reconnectEvent = scheduler::schedule(m_nextReconnectWait,
[this] { handleReconnectTimeout(); });
m_socket.async_connect(m_remoteEndpoint,
[this] (const boost::system::error_code& error) { handleReconnect(error); });
m_reconnectEvent = scheduler::schedule(m_nextReconnectWait, [this] { this->handleReconnectTimeout(); });
m_socket.async_connect(m_remoteEndpoint, [this] (const auto& e) { this->handleReconnect(e); });
}
void
+3 -1
View File
@@ -32,6 +32,8 @@
namespace nfd {
namespace face {
NFD_LOG_MEMBER_DECL_SPECIALIZED(StreamTransport<boost::asio::ip::tcp>);
/**
* \brief A Transport that communicates on a connected TCP socket
*
@@ -42,7 +44,7 @@ namespace face {
class TcpTransport FINAL_UNLESS_WITH_TESTS : public StreamTransport<boost::asio::ip::tcp>
{
public:
TcpTransport(protocol::socket&& socket, ndn::nfd::FacePersistency persistency);
TcpTransport(protocol::socket&& socket, ndn::nfd::FacePersistency persistency, ndn::nfd::FaceScope faceScope);
ssize_t
getSendQueueLength() final;
+3 -7
View File
@@ -29,7 +29,9 @@
namespace nfd {
namespace face {
NFD_LOG_INIT("Transport");
NFD_LOG_INIT(Transport);
const ssize_t Transport::MIN_MTU;
std::ostream&
operator<<(std::ostream& os, TransportState state)
@@ -126,12 +128,6 @@ Transport::receive(Packet&& packet)
m_service->receivePacket(std::move(packet));
}
ssize_t
Transport::getSendQueueLength()
{
return QUEUE_UNSUPPORTED;
}
bool
Transport::canChangePersistencyTo(ndn::nfd::FacePersistency newPersistency) const
{
+19 -9
View File
@@ -202,13 +202,6 @@ public: // upper interface
void
send(Packet&& packet);
protected: // upper interface to be invoked by subclass
/** \brief receive a link-layer packet
* \warning undefined behavior if packet size exceeds MTU limit
*/
void
receive(Packet&& packet);
public: // static properties
/** \return a FaceUri representing local endpoint
*/
@@ -291,7 +284,17 @@ public: // dynamic properties
* \retval QUEUE_ERROR transport was unable to retrieve the queue length
*/
virtual ssize_t
getSendQueueLength();
getSendQueueLength()
{
return QUEUE_UNSUPPORTED;
}
protected: // upper interface to be invoked by subclass
/** \brief receive a link-layer packet
* \warning undefined behavior if packet size exceeds MTU limit
*/
void
receive(Packet&& packet);
protected: // properties to be set by subclass
void
@@ -363,6 +366,13 @@ private: // to be overridden by subclass
virtual void
doSend(Packet&& packet) = 0;
public:
/** \brief minimum MTU that may be set on a transport
*
* This is done to ensure the NDNLPv2 fragmentation feature functions properly.
*/
static constexpr ssize_t MIN_MTU = 64;
private:
Face* m_face;
LinkService* m_service;
@@ -372,7 +382,7 @@ private:
ndn::nfd::FacePersistency m_persistency;
ndn::nfd::LinkType m_linkType;
ssize_t m_mtu;
size_t m_sendQueueCapacity;
ssize_t m_sendQueueCapacity;
TransportState m_state;
time::steady_clock::TimePoint m_expirationTime;
};
+10 -8
View File
@@ -31,7 +31,7 @@
namespace nfd {
namespace face {
NFD_LOG_INIT("UdpChannel");
NFD_LOG_INIT(UdpChannel);
namespace ip = boost::asio::ip;
@@ -60,7 +60,7 @@ UdpChannel::connect(const udp::Endpoint& remoteEndpoint,
catch (const boost::system::system_error& e) {
NFD_LOG_CHAN_DEBUG("Face creation for " << remoteEndpoint << " failed: " << e.what());
if (onConnectFailed)
onConnectFailed(504, std::string("Face creation failed: ") + e.what());
onConnectFailed(504, "Face creation failed: "s + e.what());
return;
}
@@ -94,10 +94,9 @@ UdpChannel::waitForNewPeer(const FaceCreatedCallback& onFaceCreated,
const FaceCreationFailedCallback& onReceiveFailed)
{
m_socket.async_receive_from(boost::asio::buffer(m_receiveBuffer), m_remoteEndpoint,
bind(&UdpChannel::handleNewPeer, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred,
onFaceCreated, onReceiveFailed));
[=] (auto&&... args) {
this->handleNewPeer(std::forward<decltype(args)>(args)..., onFaceCreated, onReceiveFailed);
});
}
void
@@ -127,7 +126,7 @@ UdpChannel::handleNewPeer(const boost::system::error_code& error,
catch (const boost::system::system_error& e) {
NFD_LOG_CHAN_DEBUG("Face creation for " << m_remoteEndpoint << " failed: " << e.what());
if (onReceiveFailed)
onReceiveFailed(504, std::string("Face creation failed: ") + e.what());
onReceiveFailed(504, "Face creation failed: "s + e.what());
return;
}
@@ -161,6 +160,8 @@ UdpChannel::createFace(const udp::Endpoint& remoteEndpoint,
socket.connect(remoteEndpoint);
GenericLinkService::Options options;
options.allowFragmentation = true;
options.allowReassembly = true;
options.reliabilityOptions.isEnabled = params.wantLpReliability;
if (boost::logic::indeterminate(params.wantCongestionMarking)) {
@@ -179,7 +180,8 @@ UdpChannel::createFace(const udp::Endpoint& remoteEndpoint,
}
auto linkService = make_unique<GenericLinkService>(options);
auto transport = make_unique<UnicastUdpTransport>(std::move(socket), params.persistency, m_idleFaceTimeout);
auto transport = make_unique<UnicastUdpTransport>(std::move(socket), params.persistency,
m_idleFaceTimeout, params.mtu);
auto face = make_shared<Face>(std::move(linkService), std::move(transport));
m_channelFaces[remoteEndpoint] = face;
+16 -8
View File
@@ -28,7 +28,6 @@
#include "multicast-udp-transport.hpp"
#include "core/global-io.hpp"
#include <ndn-cxx/net/address-converter.hpp>
#include <boost/range/adaptor/map.hpp>
#include <boost/range/algorithm/copy.hpp>
@@ -38,7 +37,7 @@ namespace face {
namespace ip = boost::asio::ip;
namespace net = ndn::net;
NFD_LOG_INIT("UdpFactory");
NFD_LOG_INIT(UdpFactory);
NFD_REGISTER_PROTOCOL_FACTORY(UdpFactory);
const std::string&
@@ -51,7 +50,9 @@ UdpFactory::getId()
UdpFactory::UdpFactory(const CtorParams& params)
: ProtocolFactory(params)
{
m_netifAddConn = netmon->onInterfaceAdded.connect(bind(&UdpFactory::applyMcastConfigToNetif, this, _1));
m_netifAddConn = netmon->onInterfaceAdded.connect([this] (const auto& netif) {
this->applyMcastConfigToNetif(netif);
});
}
void
@@ -137,7 +138,7 @@ UdpFactory::processConfig(OptionalConfigSection configSection,
else if (key == "mcast_group_v6") {
const std::string& valueStr = value.get_value<std::string>();
boost::system::error_code ec;
mcastConfig.groupV6.address(ndn::ip::addressV6FromString(valueStr, ec));
mcastConfig.groupV6.address(ip::address_v6::from_string(valueStr, ec));
if (ec) {
BOOST_THROW_EXCEPTION(ConfigFile::Error("face_system.udp.mcast_group_v6: '" +
valueStr + "' cannot be parsed as an IPv6 address"));
@@ -253,7 +254,7 @@ UdpFactory::createFace(const CreateFaceRequest& req,
return;
}
udp::Endpoint endpoint(ndn::ip::addressFromString(req.remoteUri.getHost()),
udp::Endpoint endpoint(ip::address::from_string(req.remoteUri.getHost()),
boost::lexical_cast<uint16_t>(req.remoteUri.getPort()));
if (endpoint.address().is_multicast()) {
@@ -269,6 +270,13 @@ UdpFactory::createFace(const CreateFaceRequest& req,
return;
}
if (req.params.mtu && *req.params.mtu < Transport::MIN_MTU) {
// The specified MTU must be greater than the minimum possible
NFD_LOG_TRACE("createFace cannot create a face with MTU less than " << Transport::MIN_MTU);
onFailure(406, "MTU cannot be less than " + to_string(Transport::MIN_MTU));
return;
}
// very simple logic for now
for (const auto& i : m_channels) {
if ((i.first.address().is_v4() && endpoint.address().is_v4()) ||
@@ -363,7 +371,7 @@ UdpFactory::createMulticastFace(const shared_ptr<const net::NetworkInterface>& n
return face;
}
static ndn::optional<ip::address>
static optional<ip::address>
pickAddress(const net::NetworkInterface& netif, net::AddressFamily af)
{
for (const auto& na : netif.getNetworkAddresses()) {
@@ -372,7 +380,7 @@ pickAddress(const net::NetworkInterface& netif, net::AddressFamily af)
return na.getIp();
}
}
return ndn::nullopt;
return nullopt;
}
std::vector<shared_ptr<Face>>
@@ -415,7 +423,7 @@ UdpFactory::applyMcastConfigToNetif(const shared_ptr<const net::NetworkInterface
NFD_LOG_DEBUG("Not creating multicast faces on " << netif->getName() << ": no viable IP address");
// keep an eye on new addresses
m_netifConns[netif->getIndex()].addrAddConn =
netif->onAddressAdded.connect(bind(&UdpFactory::applyMcastConfigToNetif, this, netif));
netif->onAddressAdded.connect([=] (auto...) { this->applyMcastConfigToNetif(netif); });
return {};
}
+11 -4
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-2018, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -30,12 +30,13 @@
namespace nfd {
namespace face {
NFD_LOG_INIT("UnicastEthernetTransport");
NFD_LOG_INIT(UnicastEthernetTransport);
UnicastEthernetTransport::UnicastEthernetTransport(const ndn::net::NetworkInterface& localEndpoint,
const ethernet::Address& remoteEndpoint,
ndn::nfd::FacePersistency persistency,
time::nanoseconds idleTimeout)
time::nanoseconds idleTimeout,
optional<ssize_t> overrideMtu)
: EthernetTransport(localEndpoint, remoteEndpoint)
, m_idleTimeout(idleTimeout)
{
@@ -44,7 +45,13 @@ UnicastEthernetTransport::UnicastEthernetTransport(const ndn::net::NetworkInterf
this->setScope(ndn::nfd::FACE_SCOPE_NON_LOCAL);
this->setPersistency(persistency);
this->setLinkType(ndn::nfd::LINK_TYPE_POINT_TO_POINT);
this->setMtu(localEndpoint.getMtu());
if (overrideMtu) {
this->setMtu(std::min<ssize_t>(localEndpoint.getMtu(), *overrideMtu));
}
else {
this->setMtu(localEndpoint.getMtu());
}
NFD_LOG_FACE_INFO("Creating transport");
+3 -2
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-2018, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -44,7 +44,8 @@ public:
UnicastEthernetTransport(const ndn::net::NetworkInterface& localEndpoint,
const ethernet::Address& remoteEndpoint,
ndn::nfd::FacePersistency persistency,
time::nanoseconds idleTimeout);
time::nanoseconds idleTimeout,
optional<ssize_t> overrideMtu = {});
protected:
bool
+13 -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-2018, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -36,12 +36,12 @@
namespace nfd {
namespace face {
NFD_LOG_INCLASS_TEMPLATE_SPECIALIZATION_DEFINE(DatagramTransport, UnicastUdpTransport::protocol,
"UnicastUdpTransport");
NFD_LOG_MEMBER_INIT_SPECIALIZED((DatagramTransport<boost::asio::ip::udp, Unicast>), UnicastUdpTransport);
UnicastUdpTransport::UnicastUdpTransport(protocol::socket&& socket,
ndn::nfd::FacePersistency persistency,
time::nanoseconds idleTimeout)
time::nanoseconds idleTimeout,
optional<ssize_t> overrideMtu)
: DatagramTransport(std::move(socket))
, m_idleTimeout(idleTimeout)
{
@@ -50,7 +50,14 @@ UnicastUdpTransport::UnicastUdpTransport(protocol::socket&& socket,
this->setScope(ndn::nfd::FACE_SCOPE_NON_LOCAL);
this->setPersistency(persistency);
this->setLinkType(ndn::nfd::LINK_TYPE_POINT_TO_POINT);
this->setMtu(udp::computeMtu(m_socket.local_endpoint()));
if (overrideMtu) {
this->setMtu(std::min(udp::computeMtu(m_socket.local_endpoint()), *overrideMtu));
}
else {
this->setMtu(udp::computeMtu(m_socket.local_endpoint()));
}
BOOST_ASSERT(this->getMtu() >= MIN_MTU);
NFD_LOG_FACE_INFO("Creating transport");
+6 -3
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-2018, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -32,6 +32,8 @@
namespace nfd {
namespace face {
NFD_LOG_MEMBER_DECL_SPECIALIZED((DatagramTransport<boost::asio::ip::udp, Unicast>));
/**
* \brief A Transport that communicates on a unicast UDP socket
*/
@@ -40,7 +42,8 @@ class UnicastUdpTransport final : public DatagramTransport<boost::asio::ip::udp,
public:
UnicastUdpTransport(protocol::socket&& socket,
ndn::nfd::FacePersistency persistency,
time::nanoseconds idleTimeout);
time::nanoseconds idleTimeout,
optional<ssize_t> overrideMtu = {});
protected:
bool
+3 -5
View File
@@ -34,7 +34,7 @@
namespace nfd {
namespace face {
NFD_LOG_INIT("UnixStreamChannel");
NFD_LOG_INIT(UnixStreamChannel);
UnixStreamChannel::UnixStreamChannel(const unix_stream::Endpoint& endpoint,
bool wantCongestionMarking)
@@ -101,7 +101,7 @@ UnixStreamChannel::listen(const FaceCreatedCallback& onFaceCreated,
m_acceptor.bind(m_endpoint);
m_acceptor.listen(backlog);
if (::chmod(m_endpoint.path().c_str(), 0666) < 0) {
if (::chmod(m_endpoint.path().data(), 0666) < 0) {
BOOST_THROW_EXCEPTION(Error("chmod(" + m_endpoint.path() + ") failed: " + std::strerror(errno)));
}
@@ -113,9 +113,7 @@ void
UnixStreamChannel::accept(const FaceCreatedCallback& onFaceCreated,
const FaceCreationFailedCallback& onAcceptFailed)
{
m_acceptor.async_accept(m_socket, bind(&UnixStreamChannel::handleAccept, this,
boost::asio::placeholders::error,
onFaceCreated, onAcceptFailed));
m_acceptor.async_accept(m_socket, [=] (const auto& e) { this->handleAccept(e, onFaceCreated, onAcceptFailed); });
}
void
+1 -1
View File
@@ -30,7 +30,7 @@
namespace nfd {
namespace face {
NFD_LOG_INIT("UnixStreamFactory");
NFD_LOG_INIT(UnixStreamFactory);
NFD_REGISTER_PROTOCOL_FACTORY(UnixStreamFactory);
const std::string&
+3 -4
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-2018, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -28,8 +28,7 @@
namespace nfd {
namespace face {
NFD_LOG_INCLASS_TEMPLATE_SPECIALIZATION_DEFINE(StreamTransport, UnixStreamTransport::protocol,
"UnixStreamTransport");
NFD_LOG_MEMBER_INIT_SPECIALIZED(StreamTransport<boost::asio::local::stream_protocol>, UnixStreamTransport);
UnixStreamTransport::UnixStreamTransport(protocol::socket&& socket)
: StreamTransport(std::move(socket))
+4 -2
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-2018, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -35,6 +35,8 @@
namespace nfd {
namespace face {
NFD_LOG_MEMBER_DECL_SPECIALIZED(StreamTransport<boost::asio::local::stream_protocol>);
/**
* \brief A Transport that communicates on a stream-oriented Unix domain socket
*/
+2 -2
View File
@@ -31,7 +31,7 @@
namespace nfd {
namespace face {
NFD_LOG_INIT("WebSocketChannel");
NFD_LOG_INIT(WebSocketChannel);
WebSocketChannel::WebSocketChannel(const websocket::Endpoint& localEndpoint)
: m_localEndpoint(localEndpoint)
@@ -117,7 +117,7 @@ WebSocketChannel::handleOpen(websocketpp::connection_hdl hdl)
NFD_LOG_CHAN_TRACE("Incoming connection from " << m_server.get_con_from_hdl(hdl)->get_remote_endpoint());
auto linkService = make_unique<GenericLinkService>();
auto transport = make_unique<WebSocketTransport>(hdl, ref(m_server), m_pingInterval);
auto transport = make_unique<WebSocketTransport>(hdl, std::ref(m_server), m_pingInterval);
auto face = make_shared<Face>(std::move(linkService), std::move(transport));
BOOST_ASSERT(m_channelFaces.count(hdl) == 0);
+1 -1
View File
@@ -30,7 +30,7 @@ namespace face {
namespace ip = boost::asio::ip;
NFD_LOG_INIT("WebSocketFactory");
NFD_LOG_INIT(WebSocketFactory);
NFD_REGISTER_PROTOCOL_FACTORY(WebSocketFactory);
const std::string&
+5 -5
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-2018, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -28,7 +28,7 @@
namespace nfd {
namespace face {
NFD_LOG_INIT("WebSocketTransport");
NFD_LOG_INIT(WebSocketTransport);
static bool
isLoopback(const boost::asio::ip::address& addr)
@@ -97,7 +97,7 @@ WebSocketTransport::receiveMessage(const std::string& msg)
bool isOk = false;
Block element;
std::tie(isOk, element) = Block::fromBuffer(reinterpret_cast<const uint8_t*>(msg.c_str()), msg.size());
std::tie(isOk, element) = Block::fromBuffer(reinterpret_cast<const uint8_t*>(msg.data()), msg.size());
if (!isOk) {
NFD_LOG_FACE_WARN("Failed to parse message payload");
return;
@@ -109,7 +109,7 @@ WebSocketTransport::receiveMessage(const std::string& msg)
void
WebSocketTransport::schedulePing()
{
m_pingEventId = scheduler::schedule(m_pingInterval, bind(&WebSocketTransport::sendPing, this));
m_pingEventId = scheduler::schedule(m_pingInterval, [this] { sendPing(); });
}
void
+9 -12
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-2018, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -30,13 +30,12 @@
namespace nfd {
namespace fw {
NFD_LOG_INIT("AccessStrategy");
NFD_LOG_INIT(AccessStrategy);
NFD_REGISTER_STRATEGY(AccessStrategy);
AccessStrategy::AccessStrategy(Forwarder& forwarder, const Name& name)
: Strategy(forwarder)
, m_removeFaceInfoConn(this->beforeRemoveFace.connect(
bind(&AccessStrategy::removeFaceInfo, this, _1)))
, m_removeFaceInfoConn(beforeRemoveFace.connect([this] (const Face& face) { removeFaceInfo(face); }))
{
ParsedInstanceName parsed = parseInstanceName(name);
if (!parsed.parameters.empty()) {
@@ -177,14 +176,13 @@ AccessStrategy::afterRtoTimeout(weak_ptr<pit::Entry> pitWeak, FaceId inFaceId, F
return;
}
pit::InRecordCollection::iterator inRecord = pitEntry->getInRecord(*inFace);
auto inRecord = pitEntry->getInRecord(*inFace);
BOOST_ASSERT(inRecord != pitEntry->in_end());
// in-record is erased only if Interest is satisfied, and RTO timer should have been cancelled
// note: if this strategy is extended to send Nacks, that would also erase in-record,
// and RTO timer should be cancelled in that case as well
const Interest& interest = inRecord->getInterest();
const fib::Entry& fibEntry = this->lookupFib(*pitEntry);
NFD_LOG_DEBUG(pitEntry->getInterest() << " timeoutFrom " << firstOutFaceId <<
@@ -227,14 +225,14 @@ AccessStrategy::beforeSatisfyInterest(const shared_ptr<pit::Entry>& pitEntry,
return;
}
pit::OutRecordCollection::iterator outRecord = pitEntry->getOutRecord(inFace);
auto outRecord = pitEntry->getOutRecord(inFace);
if (outRecord == pitEntry->out_end()) { // no out-record
NFD_LOG_DEBUG(pitEntry->getInterest() << " dataFrom " << inFace.getId() <<
" no-out-record");
return;
}
time::steady_clock::Duration rtt = time::steady_clock::now() - outRecord->getLastRenewed();
auto rtt = time::steady_clock::now() - outRecord->getLastRenewed();
NFD_LOG_DEBUG(pitEntry->getInterest() << " dataFrom " << inFace.getId() <<
" rtt=" << time::duration_cast<time::microseconds>(rtt).count());
this->updateMeasurements(inFace, data, time::duration_cast<RttEstimator::Duration>(rtt));
@@ -260,7 +258,7 @@ AccessStrategy::updateMeasurements(const Face& inFace, const Data& data,
AccessStrategy::MtInfo::MtInfo()
: lastNexthop(face::INVALID_FACEID)
, rtt(1, time::milliseconds(1), 0.1)
, rtt(1, 1_ms, 0.1)
{
}
@@ -292,14 +290,13 @@ AccessStrategy::addPrefixMeasurements(const Data& data)
BOOST_ASSERT(me != nullptr);
}
static const time::nanoseconds ME_LIFETIME = time::seconds(8);
this->getMeasurements().extendLifetime(*me, ME_LIFETIME);
this->getMeasurements().extendLifetime(*me, 8_s);
return me->insertStrategyInfo<MtInfo>().first;
}
AccessStrategy::FaceInfo::FaceInfo()
: rtt(1, time::milliseconds(1), 0.1)
: rtt(1, 1_ms, 0.1)
{
}
+3 -5
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-2018, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -27,10 +27,8 @@
#define NFD_DAEMON_FW_ACCESS_STRATEGY_HPP
#include "strategy.hpp"
#include "core/rtt-estimator.hpp"
#include "retx-suppression-fixed.hpp"
#include <unordered_set>
#include <unordered_map>
#include "core/rtt-estimator.hpp"
namespace nfd {
namespace fw {
+3 -5
View File
@@ -29,7 +29,7 @@ namespace nfd {
namespace fw {
namespace asf {
NFD_LOG_INIT("AsfMeasurements");
NFD_LOG_INIT(AsfMeasurements);
const RttStats::Rtt RttStats::RTT_TIMEOUT(-1.0);
const RttStats::Rtt RttStats::RTT_NO_MEASUREMENT(0.0);
@@ -168,7 +168,7 @@ NamespaceInfo::getOrCreateFaceInfo(const fib::Entry& fibEntry, FaceId faceId)
FaceInfo* info = nullptr;
if (it == m_fit.end()) {
const auto& pair = m_fit.insert(std::make_pair(faceId, FaceInfo()));
const auto& pair = m_fit.emplace(faceId, FaceInfo());
info = &pair.first->second;
extendFaceInfoLifetime(*info, faceId);
@@ -193,9 +193,7 @@ NamespaceInfo::extendFaceInfoLifetime(FaceInfo& info, FaceId faceId)
scheduler::cancel(info.getMeasurementExpirationEventId());
// Refresh measurement
scheduler::EventId id = scheduler::schedule(AsfMeasurements::MEASUREMENTS_LIFETIME,
bind(&NamespaceInfo::expireFaceInfo, this, faceId));
auto id = scheduler::schedule(AsfMeasurements::MEASUREMENTS_LIFETIME, [=] { expireFaceInfo(faceId); });
info.setMeasurementExpirationEventId(id);
}
+2 -3
View File
@@ -254,8 +254,7 @@ public:
const FaceInfoTable::iterator
insert(FaceId faceId)
{
const auto& pair = m_fit.insert(std::make_pair(faceId, FaceInfo()));
return pair.first;
return m_fit.emplace(faceId, FaceInfo()).first;
}
bool
@@ -317,7 +316,7 @@ private:
extendLifetime(measurements::Entry& me);
public:
static constexpr time::microseconds MEASUREMENTS_LIFETIME = time::seconds(300);
static constexpr time::microseconds MEASUREMENTS_LIFETIME = 300_s;
private:
MeasurementsAccessor& m_measurements;
+3 -4
View File
@@ -70,7 +70,7 @@ ProbingModule::getFaceToProbe(const Face& inFace,
const Face& faceUsed)
{
FaceInfoFacePairSet rankedFaces(
[] (FaceInfoFacePair pairLhs, FaceInfoFacePair pairRhs) -> bool {
[] (const auto& pairLhs, const auto& pairRhs) -> bool {
// Sort by RTT
// If a face has timed-out, rank it behind non-timed-out faces
FaceInfo& lhs = *pairLhs.first;
@@ -93,14 +93,13 @@ ProbingModule::getFaceToProbe(const Face& inFace,
}
FaceInfo* info = m_measurements.getFaceInfo(fibEntry, interest, hopFace.getId());
// If no RTT has been recorded, probe this face
if (info == nullptr || !info->hasSrttMeasurement()) {
return &hopFace;
}
// Add FaceInfo to container sorted by RTT
rankedFaces.insert(std::make_pair(info, &hopFace));
rankedFaces.insert({info, &hopFace});
}
if (rankedFaces.empty()) {
@@ -149,7 +148,7 @@ ProbingModule::getFaceBasedOnProbability(const FaceInfoFacePairSet& rankedFaces)
uint64_t rank = 1;
double offset = 0.0;
for (const FaceInfoFacePair pair : rankedFaces) {
for (const auto& pair : rankedFaces) {
double probability = getProbingProbability(rank++, rankSum, rankedFaces.size());
// Is the random number within the bounds of this face's probability + the previous faces'
+2 -2
View File
@@ -80,8 +80,8 @@ private:
getRandomNumber(double start, double end);
public:
static constexpr time::milliseconds DEFAULT_PROBING_INTERVAL = time::milliseconds(60000);
static constexpr time::milliseconds MIN_PROBING_INTERVAL = time::milliseconds(1000);
static constexpr time::milliseconds DEFAULT_PROBING_INTERVAL = 1_min;
static constexpr time::milliseconds MIN_PROBING_INTERVAL = 1_s;
private:
time::milliseconds m_probingInterval;
+1 -2
View File
@@ -25,14 +25,13 @@
#include "asf-strategy.hpp"
#include "algorithm.hpp"
#include "core/logger.hpp"
namespace nfd {
namespace fw {
namespace asf {
NFD_LOG_INIT("AsfStrategy");
NFD_LOG_INIT(AsfStrategy);
NFD_REGISTER_STRATEGY(AsfStrategy);
const time::milliseconds AsfStrategy::RETX_SUPPRESSION_INITIAL(10);
+3 -5
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-2018, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -44,10 +44,8 @@ BestRouteStrategyBase::afterReceiveInterest(const Face& inFace, const Interest&
}
const fib::Entry& fibEntry = this->lookupFib(*pitEntry);
const fib::NextHopList& nexthops = fibEntry.getNextHops();
for (fib::NextHopList::const_iterator it = nexthops.begin(); it != nexthops.end(); ++it) {
Face& outFace = it->getFace();
for (const auto& nexthop : fibEntry.getNextHops()) {
Face& outFace = nexthop.getFace();
if (!wouldViolateScope(inFace, interest, outFace) &&
canForwardToLegacy(*pitEntry, outFace)) {
this->sendInterest(pitEntry, outFace, interest);
+20 -16
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-2018, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -30,7 +30,7 @@
namespace nfd {
namespace fw {
NFD_LOG_INIT("BestRouteStrategy2");
NFD_LOG_INIT(BestRouteStrategy2);
NFD_REGISTER_STRATEGY(BestRouteStrategy2);
const time::milliseconds BestRouteStrategy2::RETX_SUPPRESSION_INITIAL(10);
@@ -69,7 +69,7 @@ BestRouteStrategy2::getStrategyName()
* \param wantUnused if true, NextHop must not have unexpired out-record
* \param now time::steady_clock::now(), ignored if !wantUnused
*/
static inline bool
static bool
isNextHopEligible(const Face& inFace, const Interest& interest,
const fib::NextHop& nexthop,
const shared_ptr<pit::Entry>& pitEntry,
@@ -88,7 +88,7 @@ isNextHopEligible(const Face& inFace, const Interest& interest,
if (wantUnused) {
// nexthop must not have unexpired out-record
pit::OutRecordCollection::iterator outRecord = pitEntry->getOutRecord(outFace);
auto outRecord = pitEntry->getOutRecord(outFace);
if (outRecord != pitEntry->out_end() && outRecord->getExpiry() > now) {
return false;
}
@@ -100,23 +100,26 @@ isNextHopEligible(const Face& inFace, const Interest& interest,
/** \brief pick an eligible NextHop with earliest out-record
* \note It is assumed that every nexthop has an out-record.
*/
static inline fib::NextHopList::const_iterator
static fib::NextHopList::const_iterator
findEligibleNextHopWithEarliestOutRecord(const Face& inFace, const Interest& interest,
const fib::NextHopList& nexthops,
const shared_ptr<pit::Entry>& pitEntry)
{
fib::NextHopList::const_iterator found = nexthops.end();
time::steady_clock::TimePoint earliestRenewed = time::steady_clock::TimePoint::max();
for (fib::NextHopList::const_iterator it = nexthops.begin(); it != nexthops.end(); ++it) {
auto found = nexthops.end();
auto earliestRenewed = time::steady_clock::TimePoint::max();
for (auto it = nexthops.begin(); it != nexthops.end(); ++it) {
if (!isNextHopEligible(inFace, interest, *it, pitEntry))
continue;
pit::OutRecordCollection::iterator outRecord = pitEntry->getOutRecord(it->getFace());
auto outRecord = pitEntry->getOutRecord(it->getFace());
BOOST_ASSERT(outRecord != pitEntry->out_end());
if (outRecord->getLastRenewed() < earliestRenewed) {
found = it;
earliestRenewed = outRecord->getLastRenewed();
}
}
return found;
}
@@ -133,13 +136,13 @@ BestRouteStrategy2::afterReceiveInterest(const Face& inFace, const Interest& int
const fib::Entry& fibEntry = this->lookupFib(*pitEntry);
const fib::NextHopList& nexthops = fibEntry.getNextHops();
fib::NextHopList::const_iterator it = nexthops.end();
auto it = nexthops.end();
if (suppression == RetxSuppressionResult::NEW) {
// forward to nexthop with lowest cost except downstream
it = std::find_if(nexthops.begin(), nexthops.end(),
bind(&isNextHopEligible, cref(inFace), interest, _1, pitEntry,
false, time::steady_clock::TimePoint::min()));
it = std::find_if(nexthops.begin(), nexthops.end(), [&] (const auto& nexthop) {
return isNextHopEligible(inFace, interest, nexthop, pitEntry);
});
if (it == nexthops.end()) {
NFD_LOG_DEBUG(interest << " from=" << inFace.getId() << " noNextHop");
@@ -160,9 +163,10 @@ BestRouteStrategy2::afterReceiveInterest(const Face& inFace, const Interest& int
}
// find an unused upstream with lowest cost except downstream
it = std::find_if(nexthops.begin(), nexthops.end(),
bind(&isNextHopEligible, cref(inFace), interest, _1, pitEntry,
true, time::steady_clock::now()));
it = std::find_if(nexthops.begin(), nexthops.end(), [&] (const auto& nexthop) {
return isNextHopEligible(inFace, interest, nexthop, pitEntry, true, time::steady_clock::now());
});
if (it != nexthops.end()) {
Face& outFace = it->getFace();
this->sendInterest(pitEntry, outFace, interest);
+2 -2
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-2018, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -29,7 +29,7 @@
namespace nfd {
namespace fw {
NFD_LOG_INIT("ClientControlStrategy");
NFD_LOG_INIT(ClientControlStrategy);
NFD_REGISTER_STRATEGY(ClientControlStrategy);
ClientControlStrategy::ClientControlStrategy(Forwarder& forwarder, const Name& name)
+7 -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-2018, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -24,16 +24,17 @@
*/
#include "face-table.hpp"
#include "core/asserts.hpp"
#include "core/global-io.hpp"
#include "core/logger.hpp"
#include "face/channel.hpp"
#include <ndn-cxx/util/concepts.hpp>
namespace nfd {
NFD_ASSERT_FORWARD_ITERATOR(FaceTable::const_iterator);
NDN_CXX_ASSERT_FORWARD_ITERATOR(FaceTable::const_iterator);
NFD_LOG_INIT("FaceTable");
NFD_LOG_INIT(FaceTable);
FaceTable::FaceTable()
: m_lastFaceId(face::FACEID_RESERVED_MAX)
@@ -85,7 +86,7 @@ FaceTable::addImpl(shared_ptr<Face> face, FaceId faceId)
" remote=" << face->getRemoteUri() <<
" local=" << face->getLocalUri());
connectFaceClosedSignal(*face, bind(&FaceTable::remove, this, faceId));
connectFaceClosedSignal(*face, [=] { remove(faceId); });
this->afterAdd(*face);
}
+107 -133
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-2018, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -24,16 +24,18 @@
*/
#include "forwarder.hpp"
#include "algorithm.hpp"
#include "best-route-strategy2.hpp"
#include "strategy.hpp"
#include "core/logger.hpp"
#include "table/cleanup.hpp"
#include <ndn-cxx/lp/tags.hpp>
namespace nfd {
NFD_LOG_INIT("Forwarder");
NFD_LOG_INIT(Forwarder);
static Name
getDefaultStrategyName()
@@ -127,14 +129,11 @@ Forwarder::onIncomingInterest(Face& inFace, const Interest& interest)
return;
}
// cancel unsatisfy & straggler timer
this->cancelUnsatisfyAndStragglerTimer(*pitEntry);
// is pending?
if (!pitEntry->hasInRecords()) {
m_cs.find(interest,
bind(&Forwarder::onContentStoreHit, this, ref(inFace), pitEntry, _1, _2),
bind(&Forwarder::onContentStoreMiss, this, ref(inFace), pitEntry, _1));
bind(&Forwarder::onContentStoreHit, this, std::ref(inFace), pitEntry, _1, _2),
bind(&Forwarder::onContentStoreMiss, this, std::ref(inFace), pitEntry, _1));
}
else {
this->onContentStoreMiss(inFace, pitEntry, interest);
@@ -163,6 +162,12 @@ Forwarder::onInterestLoop(Face& inFace, const Interest& interest)
inFace.sendNack(nack);
}
static inline bool
compare_InRecord_expiry(const pit::InRecord& a, const pit::InRecord& b)
{
return a.getExpiry() < b.getExpiry();
}
void
Forwarder::onContentStoreMiss(const Face& inFace, const shared_ptr<pit::Entry>& pitEntry,
const Interest& interest)
@@ -173,8 +178,10 @@ Forwarder::onContentStoreMiss(const Face& inFace, const shared_ptr<pit::Entry>&
// insert in-record
pitEntry->insertOrUpdateInRecord(const_cast<Face&>(inFace), interest);
// set PIT unsatisfy timer
this->setUnsatisfyTimer(pitEntry);
// set PIT expiry timer to the time that the last PIT in-record expires
auto lastExpiring = std::max_element(pitEntry->in_begin(), pitEntry->in_end(), &compare_InRecord_expiry);
auto lastExpiryFromNow = lastExpiring->getExpiry() - time::steady_clock::now();
this->setExpiryTimer(pitEntry, time::duration_cast<time::milliseconds>(lastExpiryFromNow));
// has NextHopFaceId?
shared_ptr<lp::NextHopFaceIdTag> nextHopTag = interest.getTag<lp::NextHopFaceIdTag>();
@@ -205,11 +212,15 @@ Forwarder::onContentStoreHit(const Face& inFace, const shared_ptr<pit::Entry>& p
data.setTag(make_shared<lp::IncomingFaceIdTag>(face::FACEID_CONTENT_STORE));
// XXX should we lookup PIT for other Interests that also match csMatch?
// set PIT straggler timer
this->setStragglerTimer(pitEntry, true, data.getFreshnessPeriod());
pitEntry->isSatisfied = true;
pitEntry->dataFreshnessPeriod = data.getFreshnessPeriod();
// goto outgoing Data pipeline
this->onOutgoingData(data, *const_pointer_cast<Face>(inFace.shared_from_this()));
// set PIT expiry timer to now
this->setExpiryTimer(pitEntry, 0_ms);
// dispatch to strategy: after Content Store hit
this->dispatchToStrategy(*pitEntry,
[&] (fw::Strategy& strategy) { strategy.afterContentStoreHit(pitEntry, inFace, data); });
}
void
@@ -227,47 +238,16 @@ Forwarder::onOutgoingInterest(const shared_ptr<pit::Entry>& pitEntry, Face& outF
}
void
Forwarder::onInterestReject(const shared_ptr<pit::Entry>& pitEntry)
{
if (fw::hasPendingOutRecords(*pitEntry)) {
NFD_LOG_ERROR("onInterestReject interest=" << pitEntry->getName() <<
" cannot reject forwarded Interest");
return;
}
NFD_LOG_DEBUG("onInterestReject interest=" << pitEntry->getName());
// cancel unsatisfy & straggler timer
this->cancelUnsatisfyAndStragglerTimer(*pitEntry);
// set PIT straggler timer
this->setStragglerTimer(pitEntry, false);
}
void
Forwarder::onInterestUnsatisfied(const shared_ptr<pit::Entry>& pitEntry)
{
NFD_LOG_DEBUG("onInterestUnsatisfied interest=" << pitEntry->getName());
// invoke PIT unsatisfied callback
this->dispatchToStrategy(*pitEntry,
[&] (fw::Strategy& strategy) { strategy.beforeExpirePendingInterest(pitEntry); });
// goto Interest Finalize pipeline
this->onInterestFinalize(pitEntry, false);
}
void
Forwarder::onInterestFinalize(const shared_ptr<pit::Entry>& pitEntry, bool isSatisfied,
ndn::optional<time::milliseconds> dataFreshnessPeriod)
Forwarder::onInterestFinalize(const shared_ptr<pit::Entry>& pitEntry)
{
NFD_LOG_DEBUG("onInterestFinalize interest=" << pitEntry->getName() <<
(isSatisfied ? " satisfied" : " unsatisfied"));
(pitEntry->isSatisfied ? " satisfied" : " unsatisfied"));
// Dead Nonce List insert if necessary
this->insertDeadNonceList(*pitEntry, isSatisfied, dataFreshnessPeriod, 0);
this->insertDeadNonceList(*pitEntry, 0);
// PIT delete
this->cancelUnsatisfyAndStragglerTimer(*pitEntry);
scheduler::cancel(pitEntry->expiryTimer);
m_pit.erase(pitEntry.get());
}
@@ -291,7 +271,7 @@ Forwarder::onIncomingData(Face& inFace, const Data& data)
// PIT match
pit::DataMatchResult pitMatches = m_pit.findAllDataMatches(data);
if (pitMatches.begin() == pitMatches.end()) {
if (pitMatches.size() == 0) {
// goto Data unsolicited pipeline
this->onDataUnsolicited(inFace, data);
return;
@@ -300,45 +280,73 @@ Forwarder::onIncomingData(Face& inFace, const Data& data)
// CS insert
m_cs.insert(data);
std::set<Face*> pendingDownstreams;
// foreach PitEntry
auto now = time::steady_clock::now();
for (const shared_ptr<pit::Entry>& pitEntry : pitMatches) {
// when only one PIT entry is matched, trigger strategy: after receive Data
if (pitMatches.size() == 1) {
auto& pitEntry = pitMatches.front();
NFD_LOG_DEBUG("onIncomingData matching=" << pitEntry->getName());
// cancel unsatisfy & straggler timer
this->cancelUnsatisfyAndStragglerTimer(*pitEntry);
// set PIT expiry timer to now
this->setExpiryTimer(pitEntry, 0_ms);
// remember pending downstreams
for (const pit::InRecord& inRecord : pitEntry->getInRecords()) {
if (inRecord.getExpiry() > now) {
pendingDownstreams.insert(&inRecord.getFace());
}
}
// invoke PIT satisfy callback
// trigger strategy: after receive Data
this->dispatchToStrategy(*pitEntry,
[&] (fw::Strategy& strategy) { strategy.beforeSatisfyInterest(pitEntry, inFace, data); });
// Dead Nonce List insert if necessary (for out-record of inFace)
this->insertDeadNonceList(*pitEntry, true, data.getFreshnessPeriod(), &inFace);
[&] (fw::Strategy& strategy) { strategy.afterReceiveData(pitEntry, inFace, data); });
// mark PIT satisfied
pitEntry->clearInRecords();
pitEntry->isSatisfied = true;
pitEntry->dataFreshnessPeriod = data.getFreshnessPeriod();
// Dead Nonce List insert if necessary (for out-record of inFace)
this->insertDeadNonceList(*pitEntry, &inFace);
// delete PIT entry's out-record
pitEntry->deleteOutRecord(inFace);
// set PIT straggler timer
this->setStragglerTimer(pitEntry, true, data.getFreshnessPeriod());
}
// when more than one PIT entry is matched, trigger strategy: before satisfy Interest,
// and send Data to all matched out faces
else {
std::set<Face*> pendingDownstreams;
auto now = time::steady_clock::now();
// foreach pending downstream
for (Face* pendingDownstream : pendingDownstreams) {
if (pendingDownstream->getId() == inFace.getId() &&
pendingDownstream->getLinkType() != ndn::nfd::LINK_TYPE_AD_HOC) {
continue;
for (const shared_ptr<pit::Entry>& pitEntry : pitMatches) {
NFD_LOG_DEBUG("onIncomingData matching=" << pitEntry->getName());
// remember pending downstreams
for (const pit::InRecord& inRecord : pitEntry->getInRecords()) {
if (inRecord.getExpiry() > now) {
pendingDownstreams.insert(&inRecord.getFace());
}
}
// set PIT expiry timer to now
this->setExpiryTimer(pitEntry, 0_ms);
// invoke PIT satisfy callback
this->dispatchToStrategy(*pitEntry,
[&] (fw::Strategy& strategy) { strategy.beforeSatisfyInterest(pitEntry, inFace, data); });
// mark PIT satisfied
pitEntry->isSatisfied = true;
pitEntry->dataFreshnessPeriod = data.getFreshnessPeriod();
// Dead Nonce List insert if necessary (for out-record of inFace)
this->insertDeadNonceList(*pitEntry, &inFace);
// clear PIT entry's in and out records
pitEntry->clearInRecords();
pitEntry->deleteOutRecord(inFace);
}
// foreach pending downstream
for (Face* pendingDownstream : pendingDownstreams) {
if (pendingDownstream->getId() == inFace.getId() &&
pendingDownstream->getLinkType() != ndn::nfd::LINK_TYPE_AD_HOC) {
continue;
}
// goto outgoing Data pipeline
this->onOutgoingData(data, *pendingDownstream);
}
// goto outgoing Data pipeline
this->onOutgoingData(data, *pendingDownstream);
}
}
@@ -434,6 +442,11 @@ Forwarder::onIncomingNack(Face& inFace, const lp::Nack& nack)
// record Nack on out-record
outRecord->setIncomingNack(nack);
// set PIT expiry timer to now when all out-record receive Nack
if (!fw::hasPendingOutRecords(*pitEntry)) {
this->setExpiryTimer(pitEntry, 0_ms);
}
// trigger strategy: after receive NACK
this->dispatchToStrategy(*pitEntry,
[&] (fw::Strategy& strategy) { strategy.afterReceiveNack(inFace, nack, pitEntry); });
@@ -491,65 +504,25 @@ Forwarder::onDroppedInterest(Face& outFace, const Interest& interest)
m_strategyChoice.findEffectiveStrategy(interest.getName()).onDroppedInterest(outFace, interest);
}
static inline bool
compare_InRecord_expiry(const pit::InRecord& a, const pit::InRecord& b)
void
Forwarder::setExpiryTimer(const shared_ptr<pit::Entry>& pitEntry, time::milliseconds duration)
{
return a.getExpiry() < b.getExpiry();
BOOST_ASSERT(duration >= 0_ms);
scheduler::cancel(pitEntry->expiryTimer);
pitEntry->expiryTimer = scheduler::schedule(duration, [=] { onInterestFinalize(pitEntry); });
}
void
Forwarder::setUnsatisfyTimer(const shared_ptr<pit::Entry>& pitEntry)
{
pit::InRecordCollection::iterator lastExpiring =
std::max_element(pitEntry->in_begin(), pitEntry->in_end(), &compare_InRecord_expiry);
time::steady_clock::TimePoint lastExpiry = lastExpiring->getExpiry();
time::nanoseconds lastExpiryFromNow = lastExpiry - time::steady_clock::now();
if (lastExpiryFromNow <= time::seconds::zero()) {
// TODO all in-records are already expired; will this happen?
}
scheduler::cancel(pitEntry->m_unsatisfyTimer);
pitEntry->m_unsatisfyTimer = scheduler::schedule(lastExpiryFromNow,
bind(&Forwarder::onInterestUnsatisfied, this, pitEntry));
}
void
Forwarder::setStragglerTimer(const shared_ptr<pit::Entry>& pitEntry, bool isSatisfied,
ndn::optional<time::milliseconds> dataFreshnessPeriod)
{
time::nanoseconds stragglerTime = time::milliseconds(100);
scheduler::cancel(pitEntry->m_stragglerTimer);
pitEntry->m_stragglerTimer = scheduler::schedule(stragglerTime,
bind(&Forwarder::onInterestFinalize, this, pitEntry, isSatisfied, dataFreshnessPeriod));
}
void
Forwarder::cancelUnsatisfyAndStragglerTimer(pit::Entry& pitEntry)
{
scheduler::cancel(pitEntry.m_unsatisfyTimer);
scheduler::cancel(pitEntry.m_stragglerTimer);
}
static inline void
insertNonceToDnl(DeadNonceList& dnl, const pit::Entry& pitEntry,
const pit::OutRecord& outRecord)
{
dnl.add(pitEntry.getName(), outRecord.getLastNonce());
}
void
Forwarder::insertDeadNonceList(pit::Entry& pitEntry, bool isSatisfied,
ndn::optional<time::milliseconds> dataFreshnessPeriod, Face* upstream)
Forwarder::insertDeadNonceList(pit::Entry& pitEntry, Face* upstream)
{
// need Dead Nonce List insert?
bool needDnl = true;
if (isSatisfied) {
BOOST_ASSERT(dataFreshnessPeriod);
BOOST_ASSERT(*dataFreshnessPeriod >= time::milliseconds::zero());
if (pitEntry.isSatisfied) {
BOOST_ASSERT(pitEntry.dataFreshnessPeriod >= 0_ms);
needDnl = static_cast<bool>(pitEntry.getInterest().getMustBeFresh()) &&
*dataFreshnessPeriod < m_deadNonceList.getLifetime();
pitEntry.dataFreshnessPeriod < m_deadNonceList.getLifetime();
}
if (!needDnl) {
@@ -559,13 +532,14 @@ Forwarder::insertDeadNonceList(pit::Entry& pitEntry, bool isSatisfied,
// Dead Nonce List insert
if (upstream == nullptr) {
// insert all outgoing Nonces
const pit::OutRecordCollection& outRecords = pitEntry.getOutRecords();
std::for_each(outRecords.begin(), outRecords.end(),
bind(&insertNonceToDnl, ref(m_deadNonceList), cref(pitEntry), _1));
const auto& outRecords = pitEntry.getOutRecords();
std::for_each(outRecords.begin(), outRecords.end(), [&] (const auto& outRecord) {
m_deadNonceList.add(pitEntry.getName(), outRecord.getLastNonce());
});
}
else {
// insert outgoing Nonce of a specific face
pit::OutRecordCollection::iterator outRecord = pitEntry.getOutRecord(*upstream);
auto outRecord = pitEntry.getOutRecord(*upstream);
if (outRecord != pitEntry.getOutRecords().end()) {
m_deadNonceList.add(pitEntry.getName(), outRecord->getLastNonce());
}
+8 -27
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-2018, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -209,23 +209,10 @@ PUBLIC_WITH_TESTS_ELSE_PRIVATE: // pipelines
VIRTUAL_WITH_TESTS void
onOutgoingInterest(const shared_ptr<pit::Entry>& pitEntry, Face& outFace, const Interest& interest);
/** \brief Interest reject pipeline
*/
VIRTUAL_WITH_TESTS void
onInterestReject(const shared_ptr<pit::Entry>& pitEntry);
/** \brief Interest unsatisfied pipeline
*/
VIRTUAL_WITH_TESTS void
onInterestUnsatisfied(const shared_ptr<pit::Entry>& pitEntry);
/** \brief Interest finalize pipeline
* \param isSatisfied whether the Interest has been satisfied
* \param dataFreshnessPeriod FreshnessPeriod of satisfying Data
*/
VIRTUAL_WITH_TESTS void
onInterestFinalize(const shared_ptr<pit::Entry>& pitEntry, bool isSatisfied,
ndn::optional<time::milliseconds> dataFreshnessPeriod = ndn::nullopt);
onInterestFinalize(const shared_ptr<pit::Entry>& pitEntry);
/** \brief incoming Data pipeline
*/
@@ -256,29 +243,23 @@ PUBLIC_WITH_TESTS_ELSE_PRIVATE: // pipelines
onDroppedInterest(Face& outFace, const Interest& interest);
PROTECTED_WITH_TESTS_ELSE_PRIVATE:
VIRTUAL_WITH_TESTS void
setUnsatisfyTimer(const shared_ptr<pit::Entry>& pitEntry);
VIRTUAL_WITH_TESTS void
setStragglerTimer(const shared_ptr<pit::Entry>& pitEntry, bool isSatisfied,
ndn::optional<time::milliseconds> dataFreshnessPeriod = ndn::nullopt);
VIRTUAL_WITH_TESTS void
cancelUnsatisfyAndStragglerTimer(pit::Entry& pitEntry);
/** \brief set a new expiry timer (now + \p duration) on a PIT entry
*/
void
setExpiryTimer(const shared_ptr<pit::Entry>& pitEntry, time::milliseconds duration);
/** \brief insert Nonce to Dead Nonce List if necessary
* \param upstream if null, insert Nonces from all out-records;
* if not null, insert Nonce only on the out-records of this face
*/
VIRTUAL_WITH_TESTS void
insertDeadNonceList(pit::Entry& pitEntry, bool isSatisfied,
ndn::optional<time::milliseconds> dataFreshnessPeriod, Face* upstream);
insertDeadNonceList(pit::Entry& pitEntry, Face* upstream);
/** \brief call trigger (method) on the effective strategy of pitEntry
*/
#ifdef WITH_TESTS
virtual void
dispatchToStrategy(pit::Entry& pitEntry, function<void(fw::Strategy&)> trigger)
dispatchToStrategy(pit::Entry& pitEntry, std::function<void(fw::Strategy&)> trigger)
#else
template<class Function>
void
+2 -2
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-2018, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -32,7 +32,7 @@ namespace fw {
NFD_REGISTER_STRATEGY(MulticastStrategy);
NFD_LOG_INIT("MulticastStrategy");
NFD_LOG_INIT(MulticastStrategy);
const time::milliseconds MulticastStrategy::RETX_SUPPRESSION_INITIAL(10);
const time::milliseconds MulticastStrategy::RETX_SUPPRESSION_MAX(250);
Loaded 100 of 293 files, more files were not shown because too many files have changed in this diff. Show more