Compare commits

...
198 Commits
Author SHA1 Message Date
root 1a792daaa3 feat(qsccp): Add QSCCP strategy 2023-12-18 12:49:43 +08:00
SunnyQjm 34e13e9802 fix: Do calculateRate by trigger not by scheduler 2023-12-15 14:55:20 +00:00
SunnyQjm 3813f1c9ee feat: Add qsccp sched 2023-12-03 21:08:06 +08:00
Eric Newberry 3dc9fd0b82 Prepare release 0.7.1
refs #5129

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

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

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

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

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

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

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

refs: #4843, #4973

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

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

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

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

refs #4744

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Change-Id: Iefa1c730cd83e2965bf92ef6598eb092c4de48f7
2020-01-30 17:13:10 -08:00
Davide Pesavento e89118e8be build: upgrade waf to version 2.0.19
Change-Id: I513db4ba8a12a269deca378e0ab77c7946b3dd63
2020-01-13 21:52:03 -05:00
Alexander Afanasyev fb034219ef Prepare release 0.7.0
Change-Id: I86281204533ea893dd03f35fc0d9403be14f7da4
Refs: #5045
2020-01-13 13:23:45 -05:00
Davide Pesavento cf9e1c7789 tests: avoid deprecated boost headers
Change-Id: I1b79c9422109d2ce8832fd386b524bd9ffffa231
2019-12-22 17:56:07 -05:00
Davide Pesavento 5a897699cf Use NDN_CXX_UNREACHABLE where appropriate
Change-Id: Idb3d8eade91c9e4d6e09f45a54af170f9c74ff12
2019-11-24 13:48:47 -05:00
Teng Liang 18c2b29e41 mgmt: use a separate validator for prefix announcements
This commit also configures the default prefix_announcement_validation
section in nfd.conf.sample to accept any prefix announcement.

refs: #5031
Change-Id: I82e34ce783dfe77c170dd02e78a4bc86faa0147a
2019-11-14 14:00:41 -05:00
Davide Pesavento f7d2050f70 build: pass pkg_config_path to check_cfg() when looking for libndn-cxx
Instead of modifying os.environ

Refs: #5042
Change-Id: Iaf1b87e99d2df6541bc44b1a2f49651c3d5f8c0e
2019-11-07 10:48:44 -05:00
Teng Liang 8e53127d0a fw: SelfLearningStrategy: check if PIT out-record exists
Refs: #5022
Change-Id: Ib4c5288b2b48a65350fbbd6b38892c72aba00f86
2019-11-06 16:43:57 -08:00
Ju Pan 2feb4596a9 fw: add processing for afterNewNextHop signal
Refs: #4931
Change-Id: I08bddc0ae3ceca0ddb777392ea656876ad6fe701
2019-11-06 13:10:57 -08:00
Wenkai Zheng 6598fb0881 rib: error out if both localhop_security and auto_prefix_propagate are enabled
Refs: #4989
Change-Id: Ib742880736a8f5c25e2531d2669a8b993f9f1cd6
2019-10-31 23:13:51 -04:00
Zhiyi Zhang a499aa230f mgmt: Enable use of direct fetch in RibManager
Refs: #2237
Change-Id: I4920af46f03ee5b1471f53f53e2394cca3a2a755
2019-10-13 03:17:58 -07:00
Davide Pesavento 4bd4f71f60 ci: upgrade Travis config to Ubuntu 18.04
Also in this commit:

 * Drop clang 3.8 (no easy way to install it on 18.04)
 * Add clang 10 (trunk)
 * Drop Xcode 8.3
 * Upgrade Xcode 10.2 to 10.3
 * Output folding markers to improve readability of CI logs

Change-Id: I234fcb06527eb60cc1fe4cf5b16eafaa972e07f6
2019-10-09 01:02:45 -04:00
Davide Pesavento a4abfb010f fw: pull FaceTable construction out of Forwarder class
Refs: #4922, #4973
Change-Id: Ibbd4a8840cb0d01ebbd4cabf9c34fa78a1d23db1
2019-10-06 16:08:01 -04:00
Klaus Schneider 380668b6e2 face: Make congestion marking less aggressive
Implement something closer to the CoDel Algorithm (RFC 8289)

Refs: #5003
Change-Id: I909975e7ae1c50d08561a001b67cd9c2c2f150b1
2019-10-05 19:14:39 -07:00
Junxiao Shi 606d5ddc9e face+fw: store and return PitToken from downstream
refs #4532

Change-Id: I97b95232a242186601459622f17983d1bef806d6
2019-09-23 12:47:44 -06:00
Junxiao Shi 24be073413 face: increase pcap buffer size
refs #2441

Change-Id: I927687401fae2d4a9d337d6827f9a735a38ea1bc
2019-09-23 12:38:30 -06:00
Davide Pesavento 759db61b84 daemon: add missing include
Change-Id: I169e1c9e911bf298cd415746b58fda4c4290c931
2019-09-22 19:17:57 -07:00
Ju Pan 6c8c2a0b9c face: add a per face counter for Interests kept by the forwarder
Refs: #4931
Change-Id: Ica1bcec02309eff4d28a55983f089355eb3096fb
2019-09-13 13:03:34 -07:00
Md Ashiqur Rahman c88d2d4a61 Revert "pit: add EndpointId field in in-record and out-record"
This reverts commit d3ae85dbad.

refs: #4973

Change-Id: I0aedfca8ae75137c8c9073a51642bfacf9d8f212
2019-09-11 17:44:17 +00:00
Klaus Schneider cf1d0c0286 fw: Add Random Forwarding Strategy
Implement a forwarding strategy that chooses a random outgoing face,
excluding the incoming face of an Interest packet.

Refs: #4992
Change-Id: I056cd0f05463f5f0742c6adcb32ec1df8ef7529b
2019-09-09 07:04:36 -07:00
Davide Pesavento f689c7944b mgmt: avoid deprecated KeyLocator::Type enum
Change-Id: I8e1528dfee9636096dc10892a37b6d39414e2f4a
2019-08-31 19:42:11 -04:00
Davide Pesavento a6f637a166 fw: various code simplifications in AsfStrategy
Change-Id: Ie006680b2469fa7dc5d9b19665320b2686564f2c
2019-08-31 15:50:35 -04:00
Junxiao Shi df1dc6590c rib: change FIB update mocking method
Previously, FIB update mocking occurs in Rib class. Test coverage
for FibUpdater class is limited to update computation only.
Now, mocking is moved to a subclass of FibUpdater. Test coverage
for FibUpdater class extends to include FIB update queuing.

Previously, mocked FIB update succeeds synchronously.
Now, mocked FIB update completes via io.post, which better
reflects reality that FIB commands are asynchronous.

refs #4731

Change-Id: I563edda5d398eb915f22fecd4b987f32c610d323
2019-08-30 19:03:19 +00:00
wenkaizheng 55d83d449d docs: remove "Installing from Binaries" section from INSTALL doc
Refs: #4984

Change-Id: I56e3be670e0981c4f9e30a7bcec73d8533bde847
2019-08-28 07:42:02 -07:00
Ju Pan d8315bf75b table: add Fib::afterNewNextHop signal
Refs: #4931
Change-Id: I68915b5f5688ad2f62147069fea86956a22672b6
2019-08-27 10:41:59 -07:00
Davide Pesavento 7890a9f26d tests: avoid comparing Interests with operator==
Refs: #4569
Change-Id: Ia75169c147976d3980dd113054ba560caf0f33c8
2019-08-25 23:11:18 -04:00
Davide Pesavento eb7b7abbee fw: use ndn-cxx's RttEstimator in AccessStrategy
Refs: #4887
Change-Id: I7e404df953f99374e676c7eb29897c45d0868eef
2019-08-22 22:15:53 -04:00
Ernest McCracken 1402fa153d fw: Use ndn-cxx's RttEstimator in AsfStrategy
Refs: #4887
Change-Id: Ice718be99f2b96f183bb35c5df84930be54a9f8e
2019-08-13 13:15:50 -04:00
Md Ashiqur Rahman 6be9387a4f Revert "fib: add EndpointId field in NextHop record"
This reverts commit 3ad49db6ea.

refs: #4973

Change-Id: I3216a55a8c4ed52cd9181f790f8ab72e44330a38
2019-08-12 12:00:30 -07:00
Ju Pan 9aafc2a086 Revert "mgmt: add EndpointId for fib dataset"
This reverts commit 602c3aaa56.

Refs: #4973
Change-Id: I02553dc7385d430cf719db3b0f576dc48f6ec059
2019-08-12 08:46:08 -07:00
Ju Pan 57113d1369 Revert "tools: display EndpointId in 'nfdc fib list'"
This reverts commit 13839ac94a.

Refs: #4973
Change-Id: If03e8f22ff4c8c65b20b486302fda0ffc8192662
2019-08-07 21:21:47 +00:00
Junxiao Shi 07f2e2f516 table: rename cs::iterator to cs::Table::const_iterator
refs #4914

Change-Id: I0d81a0983c6bbf8ad2bdf78eec4f37ac73ec3d2d
2019-07-22 09:10:06 -06:00
Davide Pesavento f190cfa470 face: use ndn-cxx's RttEstimator in LpReliability
Refs: #4887
Change-Id: Iaf8b04e33de363bae2c99f10f3866773c900f30d
2019-07-20 02:25:14 -04:00
Junxiao Shi 5153338a18 rib: make several Rib methods private
refs #4731

Change-Id: Id0e7aa70bb21c2a5f08679a2d82e5dc91d618ef4
2019-07-19 13:50:26 +00:00
Davide Pesavento cb425e83e4 face: move common declarations to face-common.hpp
Change-Id: I0e3e7a93f0693b0e24ca67493a4229987e792ef4
2019-07-18 11:07:40 -04:00
Davide Pesavento d214881326 ci: add Xcode 11 to Travis CI build matrix
Also reenable ASan on Linux with clang 9, it seems to be working now.

Change-Id: If1beb0d9437954a229d9dbf248c6a231f6e11ace
2019-07-18 11:03:29 -04:00
Junxiao Shi 5e4a02fe9e cs: avoid Entry construction during query
Using C++14's transparent comparators, CS lookup logic can
compare stored Entry objects with the queried Name without
constructing an Entry object. This in turn eliminates the need
for a special "query entry", so EntryImpl class is deleted.

refs #4914

Change-Id: I5b05a1ab9ad696e79f7ebd6045be8de11cd58ee6
2019-07-15 11:59:18 +00:00
Davide Pesavento 859a69e349 daemon: globally disable automatic verification of Interest parameters digest
Refs: #4658
Change-Id: I07cc6811fc42ee216e0b84cdcb3165170e5d3f89
2019-07-13 17:10:46 -04:00
Md Ashiqur Rahman 115ea63ecf fw: on CS miss, pass ingress with EndpointId=0 to strategy
refs: #4849

Change-Id: Idebbd60c185497bde5c4372e512a5f937b42f0a7
2019-07-05 22:32:19 -07:00
Junxiao Shi 17a7001ae9 rib: consolidate RibManager::FaceIdSet into Rib
refs #4731

Change-Id: Ic78f44e8a504ebf1490dfc1ee4f0fe6cbc7135d0
2019-06-25 10:50:32 +00:00
Davide Pesavento 9d491024ac ci: add gcc-9 to Travis CI build matrix
Change-Id: Id4165765e2099ba9ff242dcef6b4a6fe08eaba97
2019-06-23 19:15:05 -04:00
Ju Pan 13839ac94a tools: display EndpointId in 'nfdc fib list'
Refs: #4816
Change-Id: Id656939d9595adbd8c96a78e9aedfdd8dda2a555
2019-06-19 12:08:43 -07:00
Ju Pan 602c3aaa56 mgmt: add EndpointId for fib dataset
Refs: #4816
Change-Id: Ic463ac34fca8d9c415e66347dfe642ad01c1ce59
2019-06-04 21:45:49 +00:00
Junxiao Shi 47c343b9f2 tools: set CanBePrefix in autoconfig
Also, rewrite RoutablePrefixesDataset test suite to use
SegmentFetcher.

refs #4581

Change-Id: I68e0ffcd59dcbae0856bfa2977545f06482f3515
2019-05-25 07:53:01 +00:00
Junxiao Shi 73b4980eb6 tests: add FreshnessPeriod where MustBeFresh is used
Also, set MustBeFresh in autoconfig-server HubData test,
to reflect the behavior of autoconfig client.

refs #4913

Change-Id: I0af29378630a2208e98ef0913d83668a603e9a88
2019-05-25 07:52:26 +00:00
Junxiao Shi 25d9728d2f table: drop Selectors processing from PIT
refs #4805

Change-Id: Ic15aec7f30d40485031e48e83377a621279e82f1
2019-05-14 13:44:46 -06:00
Junxiao Shi 9d727857dc tests: set CanBePrefix in daemon tests
This commit also updates makeInterest and makeNack functions
so that their APIs are compatible with ndn-cxx test suite.

refs #4581

Change-Id: I0c81740416c26a03450dc3a12c89944b72ce5901
2019-05-14 13:44:22 -06:00
Davide Pesavento 5f59607a8a pit-fib-benchmark: remove gap4 and simplify
Refs: #4929
Change-Id: Iebe064ace48a78aa88449c17f08a9522935448f0
2019-05-11 16:52:05 -04:00
Davide Pesavento b3a23ca711 face: eliminate Transport::Packet wrapper type
Refs: #4843
Change-Id: I5977be55e8bdac33c989e3b8523fea764f304c37
2019-05-07 00:32:57 -04:00
ashiqopu 075bb7dac4 face: add EndpointId in Face and LinkService
refs: #4843

Change-Id: If1249015392ef904a56a0d0d97946e2b3024d7d4
2019-05-02 06:04:43 +00:00
Junxiao Shi 14b391842b table: drop ChildSelector processing in CS
refs #4805

Change-Id: I994d1955091421e6a4ab682f40898999875736fe
2019-04-29 19:19:18 +00:00
Alexander Afanasyev 65c494acf0 Prepare release 0.6.6
Refs: #4916
Change-Id: I1134244b58f14afa32c21dd8270103693cea4e84
2019-04-29 11:05:38 -04:00
Alexander Afanasyev a6bd7da559 build: Remove unnecessary std::ref, causing compilation issues with Boost 1.70.0
Refs: #4923
Change-Id: Idba1abe89161b11b1ec80fdceac51e2b00ed507b
2019-04-26 10:49:02 -04:00
Davide Pesavento b31206e87e fw: always create PIT in-records with EndpointId=0 for now
Also improve test coverage

Refs: #4849
Change-Id: I0f3aba98ec7460f0dbf58b6dc00414e1f722c036
2019-04-23 13:30:56 -04:00
Davide Pesavento 2cae8cacf0 core: move nfd-specific files to daemon/
Refs: #4922
Change-Id: I2243dbb87c63f9cbaf7d7051d7a0d4bca2f9fdb5
2019-04-21 22:15:03 -04:00
Davide Pesavento 2840dbc868 tests: remove support for unit-tests.conf
Logging can be configured, as usual, via the
NDN_LOG environment variable.

Change-Id: I488d4c85961cb013b9e3421d049a9baa8ef45357
2019-04-21 16:27:39 -04:00
Davide Pesavento 0dc3cb1788 ci: adapt to new repo layout for CentOS boost RPMs
Change-Id: I8f8c804d0499fecaac744a08111709d2fd49e7b7
2019-04-20 16:38:06 -04:00
Junxiao Shi 9222f3665b table: eliminate Selectors from CS tests
refs #4805

Change-Id: I6ae48fc40e62aeeb41cde7530d6bfa6b6d5ef000
2019-04-16 15:15:23 +00:00
Davide Pesavento 08b91c8d4e docs: sync sphinx build config with ndn-cxx, improve README.md
Replace custom redmine_issue extension with sphinx.ext.extlinks

Change-Id: Ie6995fd418e4e355cc193b68423899fc029d93ce
2019-04-14 16:01:15 -04:00
Saurab Dulal a6dec22caa fw: properly handle consumer retransmission in AsfStrategy
Do not reject an existing PIT entry if there are no
next hops during consumer retransmission

refs: #4874

Change-Id: Iea8602897e99fdf2f6fd0226b5eb74bd7a4bced1
2019-04-12 20:05:53 -04:00
Davide Pesavento 03f45d2bb6 core: move NFD_VERSION{,_BUILD}_STRING to version.cpp
Change-Id: I97c23de24d8a176bb83a8f481f4880ff49ea710d
2019-04-04 12:35:17 -04:00
Davide Pesavento a809858c53 tests: merge DummyFace::LinkService with DummyReceiveLinkService
Change-Id: I0b45d80055085278bbe028ef95898d68c6e3f824
2019-04-01 22:23:13 -04:00
Davide Pesavento 284bd626fd face: simplify and optimize Internal{Forwarder,Client}Transport
Refs: #4528
Change-Id: Ie3246382965640e0d2cb71116b6526e68925887c
2019-03-31 02:10:02 -04:00
Davide Pesavento 16916ae20a face: introduce NullTransport and use it in several places
Refs: #4528
Change-Id: Icc7a77232bca1a700ce1319493c15a85d05d7488
2019-03-30 15:30:09 -04:00
Davide Pesavento a681a24c22 face: downgrade "Creating transport" log message to DEBUG
FaceTable already logs at INFO level whenever a new face is added.

Change-Id: Id2905c8b6d42df8bfc4c43cc12d432d9ce180aae
2019-03-29 23:51:04 -04:00
Davide Pesavento 14e71f0fe8 tests+tools: minor code cleanup
Change-Id: Ic3356d4a18a8e5eeb45fc076fc0563c3d1549c8a
2019-03-28 18:46:47 -04:00
Davide Pesavento c6a65ad55e nfd-status-http-server: fix display of satisfied/unsatisfied Interests
Amends commit 7570e778e4

Refs: #4720
Change-Id: I61bd78076b0b8d14b106e056a0ea9e000d70369b
2019-03-27 18:30:25 -04:00
Davide Pesavento 17c172ba6b fw: AccessStrategy: fix PIT in-record lookup with EndpointId
Refs: #4849
Change-Id: Ia3e2d033be507cb782b8d6c234a0e53c18590528
2019-03-26 22:53:08 -04:00
Davide Pesavento cf7db2fd83 tests: unit-tests-{core,tools} no longer require a global io_service
BaseFixture is moved to tests/daemon and renamed to GlobalIoFixture

Refs: #4528
Change-Id: If9184e9f7f1d6072b0103d3ea3ca6c31a9e505c8
2019-03-26 22:52:16 -04:00
Davide Pesavento b7703adb88 tests: introduce ClockFixture
Identical to UnitTestTimeFixture, except that it does not derive
from BaseFixture, and thus does not depend on a global io_service.

Refs: #4528
Change-Id: Ia2e6c4835a1e461c73281e103109d5cc85be355e
2019-03-26 22:51:04 -04:00
Davide Pesavento 1d12d2fe4e tests: IdentityManagementFixture no longer derives from BaseFixture
Also rename it to KeyChainFixture

Refs: #4528
Change-Id: Id86f4affc9c4c9ae159912430cc3e78557bf1ac2
2019-03-26 22:50:07 -04:00
Davide Pesavento 3626b59818 ci: update .travis.yml
Change-Id: Iffa90852e74b6ea40bbb52239a91f4fd98de27c4
2019-03-23 13:10:06 -04:00
Davide Pesavento fa2aa50d8d face+tools: fix compilation with Boost 1.69.0
Refs: #4890
Change-Id: I64c2e6ac99767fbd0b8afa9669eb6097148f8628
2019-03-22 21:44:29 -04:00
Davide Pesavento 0a71dd3a00 mgmt+rib: use getScheduler() in RibManager and Readvertise
Refs: #4528
Change-Id: Ie6dd2b0fbe5d57cd7878d86b0185ae5d9bd92cf0
2019-03-19 16:05:24 -04:00
Davide Pesavento 3dade00499 core+daemon: eliminate scheduler::{schedule,cancel} wrappers
Also move core/global-io.hpp to daemon/global.hpp

Refs: #4528, #4883
Change-Id: I0b99029f1a19d7451aab57099cd3303b7eb42ff3
2019-03-19 11:29:56 -06:00
Davide Pesavento 2d83a86255 face: introduce NullLinkService and use it in makeNullFace()
Change-Id: Ia983c62fecdf94aa4f8cbb034735a229bd58d742
2019-03-16 19:27:48 -04:00
ashiqopu c707948105 fw: add FaceEndpoint parameter in Forwarding and Strategy API
refs: #4849

Change-Id: Ibe22557488fa83a555fd13d6eb8e03f8d81d0b2b
2019-03-06 02:27:50 +00:00
Davide Pesavento 78ddcabcd0 mgmt: merge ManagerBase with NfdManagerBase
Refs: #4528
Change-Id: I2ecb4af68927157a9eafc269399855cff192bb54
2019-02-28 23:37:02 -05:00
Davide Pesavento 8a05c7fd2a rib: move RibManager to mgmt
Refs: #4528
Change-Id: Idff4ce8fe28b48163794cd12f0d185f8ca4233e3
2019-02-28 12:32:31 -05:00
Davide Pesavento 1b077f6028 rib: move entire subdir to daemon/rib
Refs: #4528
Change-Id: I7de03631ddef0f014f12f979373aa449f42486d1
2019-02-21 12:37:03 -05:00
Davide Pesavento 50a6af341d table: code modernization
Change-Id: I9ca9a1905aea316726d0323f4537a2420890735f
2019-02-21 00:42:49 -05:00
ashiqopu 77d0bfdaf0 face+table: move EndpointId typedef out of Transport and use it in table
refs: #4843

Change-Id: I2b200518a57b21d66eae4360166afda31c3bf11b
2019-02-20 21:18:08 -05:00
Davide Pesavento 2bdf60c4e8 core+main: switch to std::thread and thread_local
Change-Id: I892eb7d87639c2b0d24a8ed457b9d32635269216
2019-02-19 18:23:45 -05:00
Davide Pesavento 6ecc3f8141 build: respect --without-systemd
Change-Id: I5c5b5f43c5e3ae3ca2812b1f167179d4b6624319
2019-02-19 16:26:33 -05:00
ashiqopu d3ae85dbad pit: add EndpointId field in in-record and out-record
refs: #4842

Change-Id: Id4bca4ad9c2d7c8a2fd975c0b052fb9271b6e47d
2019-02-18 00:07:10 +00:00
Davide Pesavento 97e33024f2 Replace nfd::getExtendedErrorMessage with boost::diagnostic_information
Refs: #4834
Change-Id: I7fc00960d7e5a97748b2277c525a19775810377f
2019-02-15 18:48:22 -05:00
Davide Pesavento 19779d861e Replace all uses of BOOST_THROW_EXCEPTION with NDN_THROW
Refs: #4834
Change-Id: If2455e1830f310beea434ffb455d960e11c4c2ed
2019-02-14 20:48:34 -05:00
Alexander Afanasyev 99a7ce1363 core: Fix compilation error when privilege drop is not supported
Refs: #4833
Change-Id: I2ccc80b31eb5642d66b28e205143243e006f18ca
2019-02-05 14:38:19 -05:00
Davide Pesavento b8bd5ee965 core: use ndn-cxx's getRandomNumberEngine()
Change-Id: I3b5b3ac5238d47ac14481b21d0303c63d0c93b56
2019-02-04 18:52:05 -05:00
Alexander Afanasyev 77cddbc978 Prepare release 0.6.5
Change-Id: I2cc63230fd6b949cfae763a7a1cbeb03ea1d6400
Refs: #4821
2019-02-04 13:31:06 -05:00
Alexander Afanasyev c38219e208 build: Upgrade waf build system to version 2.0.14
Version 2.0.6 had some strange issues with Python 3.7.2 on macOS with
Homebrew.

Change-Id: I1f61c343cbef37db0dbf3fe8b4b291afd84bc0f0
2019-01-30 05:32:53 -08:00
Davide Pesavento 48b4587eee systemd: allow nfd-status-http-server to bind to any port
Change-Id: Ie6e2af3b2e194fbe0c4952b90fc39844b20722f0
Refs: #4533
2019-01-28 22:22:18 -05:00
ashiqopu 3ad49db6ea fib: add EndpointId field in NextHop record
refs: #4284

Change-Id: If0cfc21cfa81d6fa3c1590ecdce8fbbc1ea95e13
2019-01-24 18:07:07 +00:00
Junxiao Shi feddc3c054 core: use ndn-cxx scheduler::ScopedEventId
refs #4698

Change-Id: I5ab56855fb22824e129fd7e3ccfb53174cf34f82
2019-01-17 19:06:00 +00:00
Davide Pesavento 9120cee21d systemd: allow AF_NETLINK in ndn-autoconfig-client.service
It uses NetworkMonitor

Change-Id: I244f61578614307b13ed5b67981e1409e3d9e677
2019-01-16 15:40:36 -05:00
Davide Pesavento 97ab201be7 systemd: add WantedBy=nfd.service to units that bind to nfd
Change-Id: I09c0f05a22985b9182e75feaae0d97791827675e
Refs: #4594
2019-01-16 02:50:56 -05:00
Teng Liang 39465c218d fw: implement self-learning forwarding strategy
refs #4279

Change-Id: I3c80820f9e3382d204a75ea3248234581b4d97d2
2019-01-16 02:25:53 -05:00
Junxiao Shi 00e32fede9 fw: delete deprecated ClientControlStrategy
refs #3783

Change-Id: Ib26ac493a4481dfd26bf01e73d11521f8bb5fde9
2019-01-14 23:34:32 +00:00
Davide Pesavento f392b8ff44 systemd: improve nfd.service, add unit files for tools
Change-Id: I0012278b1898a48ea5594ce648dea1ebc2152113
2019-01-11 14:14:08 -05:00
Davide Pesavento 90290c5664 Add git .mailmap
Change-Id: Ifda2482b1ed27c12efd757f7b2b5b72b28af95a6
2019-01-09 16:54:46 -05:00
Davide Pesavento 2849fd45f0 contrib: remove obsolete upstart files
Move the remaining launchd and systemd files to top-level directories

Change-Id: Ic459b9b7302a7fc574b4e93f1c9d1fe05350761c
2019-01-03 18:43:48 -05:00
Davide Pesavento e271260c49 core: seed the global PRNG with more entropy
Change-Id: I874b742e0d7cccfc71eb4ea21c60e6e1042d7d6f
2019-01-03 15:50:54 -05:00
Davide Pesavento edb69c4375 tests: don't throw if NetworkMonitor lacks CAP_ENUM
Gracefully handle this case by returning an empty list of interfaces

Change-Id: I481e35bd0632db56beca410c4c41dd03a4e04ea8
Refs: #4796
2019-01-02 16:51:21 -05:00
Davide Pesavento dfbeda2f10 build: ensure /usr/local/include is treated as system include path on FreeBSD
Also use the LLD linker by default on FreeBSD.

Change-Id: I45fd307417768e6f79fefdb6ebc6b4dbcafd2b92
Refs: #4790
2018-12-19 01:15:48 -05:00
Junxiao Shi fbdd5cec13 face: set EthernetTransport UP/DOWN based on netif state
refs #3352

Change-Id: I24476ee293d229cd9222996f91f31cfb15728c47
2018-11-26 15:10:51 +00:00
Davide Pesavento 8b663a9528 tools: replace boost::any usage with ndn::any
Change-Id: I7048a64b7c17353037ea9a64a11366d2fae6fd49
2018-11-25 02:49:27 -05:00
ashiqopu d29a5dab89 ci: install gcovr via apt
Change-Id: I83a16e080145e206a08cc5255a906e41605ceca8
refs: #4771
2018-11-25 01:09:15 +00:00
Davide Pesavento 16cbadb47a Use the official markdown version of the GPLv3
Also mention CityHash license

Change-Id: I67b7081cedacc7847c928a6bf8c6450e6849513d
2018-11-23 22:30:20 -05:00
Davide Pesavento 774071c8d5 daemon: basic systemd integration
Notify systemd when NFD is ready/reloading/terminating

Change-Id: I833b48fbcaf6ecc2c4bb8a1da67d4eb9a050c116
Refs: #2815
2018-11-21 00:19:22 -05:00
Davide Pesavento d27841b7d5 face: consistently use the template method pattern in ProtocolFactory
Change-Id: Ied0bf02cfcdffc7e9b2c28c5452441c01f98ccbc
2018-11-21 00:19:01 -05:00
Ju Pan bc59dd0075 face: don't set SO_BINDTODEVICE on Android
refs: #4761

Change-Id: Ife5c61fbc0d6e1af8148c32de5d89d8a3e7fbfee
2018-11-19 20:30:43 -07:00
Davide Pesavento 096f86a311 face: support IPv6-only WebSocket channels
Change-Id: Ib9ba27d04611c13882e50995d701fc1b707cea5f
Refs: #4710
2018-11-11 19:02:18 -05:00
Davide Pesavento 9be9980011 Update WebSocket++ to 0.8.1
Change-Id: I185c26a78aaf8ba6edeec935b0b0e3aa6c6c5f4c
2018-11-11 16:44:31 -05:00
Junxiao Shi eef49a922e face: parse face_system.netdev_bound config section
refs #3521

Change-Id: I803a1651d5b44e021ec7bedb8001e216c849b9ab
2018-11-10 12:19:36 +00:00
Davide Pesavento 28181320e8 mgmt: report face MTU in faces/list and faces/query datasets
This commit also contains an overall cleanup of FaceManager
and extends the FaceDataset test case.

Change-Id: I8c8290b0dc04b25582e66a5c6dad3cca4dd226eb
Refs: #4763, #3325
2018-11-08 18:38:16 -05:00
Teng Liang a4e6ec3155 rib: do the longest-prefix match in self-learning route renew helper
Change-Id: I7f6f349fda6925dc3847716fed123d745f11b02a
refs: #4683
2018-11-08 13:39:37 -07:00
Davide Pesavento 5e1124ccac ci: fix several issues with preinstalled homebrew packages on Travis
Change-Id: I7fa52e6ed80d8c46398243412967226b40882796
2018-11-06 14:40:50 -05:00
Ju Pan 7570e778e4 tools: display satisfied and unsatisfied interests counters
refs: #4720

Change-Id: I69c2400a558997ff48f2b66883cc680dc497360a
2018-11-02 19:49:00 +00:00
Ju Pan 6eb1ac9b49 mgmt: add satisfied and unsatisfied counters for forwarder status management
refs: #4720

Change-Id: I69545e0fbf4ebba75a292644631c2cf9fdaa301a
2018-10-27 21:57:33 +00:00
Yanbiao Li f48d0809f0 rib: reimplement auto prefix propagation based on readvertise
Change-Id: I6c4d81b829cf78084d26121c81d977d0a86c9a0c
Refs: #3819
2018-10-20 10:31:50 +00:00
Davide Pesavento e1bdc08302 rib: stop using the global scheduler
Change-Id: I0e205e2f1adf85be49b132b47791b27e4530697a
Refs: #4528
2018-10-19 14:41:30 -04:00
Alexander Afanasyev 407d569821 Prepare release 0.6.4
Change-Id: I5f72c2fbf2a2ec86c108a47b4c854b069267276b
2018-10-19 10:25:29 -04:00
Alexander Afanasyev 3c0c035609 rib: Avoid use of orphaned ValidationPolicyConfig
Change-Id: Id1fa969a2e4b3c88a21cacdbbeda32d17834fe6f
Refs: #4759
2018-10-17 12:00:17 -04:00
Junxiao Shi 5ba7dfc10f rib: provide self-learning helpers
refs #4683

Change-Id: Ib1e586a505d07a5e1f7a4b6d78306ea08b4dcda8
2018-09-26 14:24:05 +00:00
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
554 changed files with 19948 additions and 18720 deletions

No files matched your search

+1 -2
View File
@@ -26,5 +26,4 @@ __pycache__/
*.py[cod]
# Other
/unit-tests.conf
/VERSION
/VERSION.info
+1 -1
View File
@@ -1,3 +1,3 @@
[submodule "websocketpp"]
path = websocketpp
url = https://github.com/zaphoyd/websocketpp.git
url = https://github.com/cawka/websocketpp.git
+25 -3
View File
@@ -1,10 +1,32 @@
#!/usr/bin/env bash
set -e
source .jenkins.d/util.sh
DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
export CACHE_DIR=${CACHE_DIR:-/tmp}
export WAF_JOBS=${WAF_JOBS:-1}
[[ $JOB_NAME == *"code-coverage" ]] && export DISABLE_ASAN=yes
for file in "$DIR"/.jenkins.d/*; do
nanos() {
# Cannot use date(1) because macOS does not support %N format specifier
python3 -c 'import time; print(int(time.time() * 1e9))'
}
for file in .jenkins.d/*; do
[[ -f $file && -x $file ]] || continue
echo "Run: $file"
if [[ -n $TRAVIS ]]; then
label=$(basename "$file" | sed -E 's/[[:digit:]]+-(.*)\..*/\1/')
echo -ne "travis_fold:start:${label}\r"
echo -ne "travis_time:start:${label}\r"
start=$(nanos)
fi
echo "\$ $file"
"$file"
if [[ -n $TRAVIS ]]; then
finish=$(nanos)
echo -ne "travis_time:end:${label}:start=${start},finish=${finish},duration=$((finish-start)),event=${label}\r"
echo -ne "travis_fold:end:${label}\r"
fi
done
+30 -23
View File
@@ -1,34 +1,41 @@
#!/usr/bin/env bash
set -e
JDIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
source "$JDIR"/util.sh
set -x
set -ex
if has OSX $NODE_LABELS; then
FORMULAE=(boost openssl pkg-config)
brew update
if [[ -n $TRAVIS ]]; then
# travis images come with a large number of brew packages
# pre-installed, don't waste time upgrading all of them
for FORMULA in "${FORMULAE[@]}"; do
brew outdated $FORMULA || brew upgrade $FORMULA
done
else
brew upgrade
if has OSX-10.13 $NODE_LABELS || has OSX-10.14 $NODE_LABELS; then
FORMULAE+=(python)
fi
brew install "${FORMULAE[@]}"
brew cleanup
fi
if has Ubuntu $NODE_LABELS; then
if [[ -n $TRAVIS ]]; then
# Travis images come with a large number of pre-installed
# brew packages, don't waste time upgrading all of them
brew list --versions "${FORMULAE[@]}" || brew update
for FORMULA in "${FORMULAE[@]}"; do
brew list --versions "$FORMULA" || brew install "$FORMULA"
done
# Ensure /usr/local/opt/openssl exists
brew reinstall openssl
else
brew update
brew upgrade
brew install "${FORMULAE[@]}"
brew cleanup
fi
elif has Ubuntu $NODE_LABELS; then
sudo apt-get -qq update
sudo apt-get -qy install build-essential pkg-config libboost-all-dev \
libsqlite3-dev libssl-dev libpcap-dev
sudo apt-get -qy install build-essential pkg-config python3-minimal \
libboost-all-dev libssl-dev libsqlite3-dev \
libpcap-dev libsystemd-dev
if [[ $JOB_NAME == *"code-coverage" ]]; then
sudo apt-get -qy install lcov libgd-perl python-setuptools
sudo easy_install --upgrade gcovr
sudo apt-get -qy install gcovr lcov
fi
elif has CentOS-8 $NODE_LABELS; then
sudo dnf config-manager --enable PowerTools
sudo dnf -y install gcc-c++ libasan pkgconf-pkg-config python3 \
boost-devel openssl-devel sqlite-devel \
libpcap-devel systemd-devel
fi
+19 -20
View File
@@ -1,12 +1,7 @@
#!/usr/bin/env bash
set -e
set -ex
JDIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
source "$JDIR"/util.sh
set -x
pushd "${CACHE_DIR:-/tmp}" >/dev/null
pushd "$CACHE_DIR" >/dev/null
INSTALLED_VERSION=
if has OSX $NODE_LABELS; then
@@ -22,35 +17,39 @@ if [[ -z $INSTALLED_VERSION ]]; then
INSTALLED_VERSION=$(git -C ndn-cxx rev-parse HEAD 2>/dev/null || echo NONE)
fi
sudo rm -Rf ndn-cxx-latest
git clone --depth 1 git://github.com/named-data/ndn-cxx ndn-cxx-latest
sudo rm -rf ndn-cxx-latest
git clone --depth 1 https://github.com/named-data/ndn-cxx.git ndn-cxx-latest
LATEST_VERSION=$(git -C ndn-cxx-latest rev-parse HEAD 2>/dev/null || echo UNKNOWN)
if [[ $INSTALLED_VERSION != $LATEST_VERSION ]]; then
sudo rm -Rf ndn-cxx
sudo rm -rf ndn-cxx
mv ndn-cxx-latest ndn-cxx
else
sudo rm -Rf ndn-cxx-latest
sudo rm -rf ndn-cxx-latest
fi
sudo rm -f /usr/local/bin/ndnsec*
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
if has CentOS-8 $NODE_LABELS; then
# https://bugzilla.redhat.com/show_bug.cgi?id=1721553
PCH="--without-pch"
fi
./waf --color=yes configure --disable-static --enable-shared --without-osx-keychain $PCH
./waf --color=yes build -j$WAF_JOBS
sudo_preserve_env PATH -- ./waf --color=yes install
popd >/dev/null
popd >/dev/null
if has CentOS-8 $NODE_LABELS; then
sudo tee /etc/ld.so.conf.d/ndn.conf >/dev/null <<< /usr/local/lib64
fi
if has Linux $NODE_LABELS; then
sudo ldconfig
elif has FreeBSD10 $NODE_LABELS; then
sudo ldconfig -m
fi
+30 -34
View File
@@ -1,45 +1,41 @@
#!/usr/bin/env bash
set -e
set -ex
JDIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
source "$JDIR"/util.sh
set -x
git submodule init
git submodule sync
git submodule update
git submodule update --init
if [[ $JOB_NAME == *"code-coverage" ]]; then
COVERAGE="--with-coverage"
elif [[ -z $DISABLE_ASAN ]]; then
if [[ -z $DISABLE_ASAN ]]; then
ASAN="--with-sanitizer=address"
fi
# Cleanup
sudo env "PATH=$PATH" ./waf --color=yes distclean
if [[ $JOB_NAME != *"code-coverage" && $JOB_NAME != *"limited-build" ]]; then
# Configure/build in optimized mode with tests
./waf --color=yes configure --with-tests
./waf --color=yes build -j${WAF_JOBS:-1}
# Cleanup
sudo env "PATH=$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
if [[ $JOB_NAME == *"code-coverage" ]]; then
COVERAGE="--with-coverage"
fi
if has CentOS-8 $NODE_LABELS; then
# https://bugzilla.redhat.com/show_bug.cgi?id=1721553
PCH="--without-pch"
fi
# Configure/build in debug mode with tests and without precompiled headers
./waf --color=yes configure --debug --with-tests --without-pch $ASAN $COVERAGE
./waf --color=yes build -j${WAF_JOBS:-1}
if [[ $JOB_NAME != *"code-coverage" && $JOB_NAME != *"limited-build" ]]; then
# Build in release mode with tests and without precompiled headers
./waf --color=yes configure --with-tests --without-pch
./waf --color=yes build -j$WAF_JOBS
# (tests will be run against debug version)
# Cleanup
./waf --color=yes distclean
# Build in release mode without tests, but with "other tests"
./waf --color=yes configure --with-other-tests $PCH
./waf --color=yes build -j$WAF_JOBS
# Cleanup
./waf --color=yes distclean
fi
# Build in debug mode with tests
./waf --color=yes configure --debug --with-tests $ASAN $COVERAGE $PCH
./waf --color=yes build -j$WAF_JOBS
# (tests will be run against the debug version)
# Install
sudo env "PATH=$PATH" ./waf --color=yes install
sudo_preserve_env PATH -- ./waf --color=yes install
+24 -33
View File
@@ -1,13 +1,8 @@
#!/usr/bin/env bash
set -e
JDIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
source "$JDIR"/util.sh
set -x
set -ex
# Prepare environment
rm -Rf ~/.ndn
rm -rf ~/.ndn
if has OSX $NODE_LABELS; then
security unlock-keychain -p named-data
@@ -15,32 +10,26 @@ fi
ndnsec-keygen "/tmp/jenkins/$NODE_NAME" | ndnsec-install-cert -
BOOST_VERSION=$(python -c "import sys; sys.path.append('build/c4che'); import _cache; print(_cache.BOOST_VERSION_NUMBER);")
ut_log_args() {
if (( BOOST_VERSION >= 106200 )); then
echo --logger=HRF,test_suite,stdout:XML,all,build/xunit-${1:-report}.xml
else
if [[ -n $XUNIT ]]; then
echo --log_level=all $( (( BOOST_VERSION >= 106000 )) && echo -- ) \
--log_format2=XML --log_sink2=build/xunit-${1:-report}.xml
else
echo --log_level=test_suite
fi
fi
}
# https://github.com/google/sanitizers/wiki/AddressSanitizerFlags
ASAN_OPTIONS="color=always"
ASAN_OPTIONS+=":detect_leaks=false"
ASAN_OPTIONS+=":detect_stack_use_after_return=true"
ASAN_OPTIONS+=":check_initialization_order=true"
ASAN_OPTIONS+=":strict_init_order=true"
ASAN_OPTIONS+=":detect_invalid_pointer_pairs=1"
ASAN_OPTIONS+=":detect_container_overflow=false"
ASAN_OPTIONS+=":strict_string_checks=true"
ASAN_OPTIONS+=":check_initialization_order=1"
ASAN_OPTIONS+=":detect_stack_use_after_return=1"
ASAN_OPTIONS+=":strict_init_order=1"
ASAN_OPTIONS+=":strict_string_checks=1"
ASAN_OPTIONS+=":detect_invalid_pointer_pairs=2"
ASAN_OPTIONS+=":detect_container_overflow=0"
ASAN_OPTIONS+=":detect_leaks=0"
ASAN_OPTIONS+=":strip_path_prefix=${PWD}/"
export ASAN_OPTIONS
export BOOST_TEST_BUILD_INFO=1
export BOOST_TEST_COLOR_OUTPUT=1
export BOOST_TEST_DETECT_MEMORY_LEAK=0
ut_log_args() {
echo --logger=HRF,test_suite,stdout:XML,all,build/xunit-log${1:+-$1}.xml
}
# First run all tests as unprivileged user
./build/unit-tests-core $(ut_log_args core)
./build/unit-tests-daemon $(ut_log_args daemon)
@@ -48,7 +37,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-daemon -t TestPrivilegeHelper $(ut_log_args daemon-privilege-helper)
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)
+1 -7
View File
@@ -1,10 +1,5 @@
#!/usr/bin/env bash
set -e
JDIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
source "$JDIR"/util.sh
set -x
set -ex
if [[ $JOB_NAME == *"code-coverage" ]]; then
gcovr --object-directory=build \
@@ -33,7 +28,6 @@ if [[ $JOB_NAME == *"code-coverage" ]]; then
genhtml --branch-coverage \
--demangle-cpp \
--frames \
--legend \
--output-directory build/coverage \
--title "NFD unit tests" \
+16 -24
View File
@@ -1,36 +1,28 @@
CONTINUOUS INTEGRATION SCRIPTS
==============================
# CONTINUOUS INTEGRATION SCRIPTS
Environment Variables Used in Build Scripts
-------------------------------------------
## Environment Variables Used in Build Scripts
- `NODE_LABELS`: the variable defines a list of OS properties. The set values are used by the
build scripts to select proper behavior for different OS.
- `NODE_LABELS`: space-separated list of platform properties. The included values are used by
the build scripts to select the proper behavior for different operating systems and versions.
The list should include at least `[OS_TYPE]`, `[DISTRO_TYPE]`, and `[DISTRO_VERSION]`.
The list should normally contain `[OS_TYPE]`, `[DISTRO_TYPE]`, and `[DISTRO_VERSION]`.
Possible values for Linux:
Example values:
* `[OS_TYPE]`: `Linux`
* `[DISTRO_TYPE]`: `Ubuntu`
* `[DISTRO_VERSION]`: `Ubuntu-14.04`, `Ubuntu-16.04`
- `[OS_TYPE]`: `Linux`, `OSX`
- `[DISTRO_TYPE]`: `Ubuntu`, `CentOS`
- `[DISTRO_VERSION]`: `Ubuntu-16.04`, `Ubuntu-18.04`, `CentOS-8`, `OSX-10.14`, `OSX-10.15`
Possible values for OS X / macOS:
* `[OS_TYPE]`: `OSX`
* `[DISTRO_TYPE]`: `OSX` (can be absent)
* `[DISTRO_VERSION]`: `OSX-10.10`, `OSX-10.11`, `OSX-10.12`
- `JOB_NAME`: optional variable to define type of the job. Depending on the defined job type,
- `JOB_NAME`: optional variable that defines the type of build job. Depending on the job type,
the build scripts can perform different tasks.
Possible values:
* empty: default build process
* `code-coverage` (Linux OS is assumed): debug build with tests and code coverage analysis
* `limited-build`: only a single debug build with tests
- empty: default build task
- `code-coverage`: debug build with tests and code coverage analysis (Ubuntu Linux is assumed)
- `limited-build`: only a single debug build with tests
- `CACHE_DIR`: the variable defines a path to folder containing cached files from previous builds,
e.g., a compiled version of ndn-cxx library. If not set, `/tmp` is used.
- `CACHE_DIR`: directory containing cached files from previous builds, e.g., a compiled version
of ndn-cxx. If not set, `/tmp` is used.
- `WAF_JOBS`: number of parallel build jobs used by waf, defaults to 1.
- `WAF_JOBS`: number of parallel build threads used by waf, defaults to 1.
+21
View File
@@ -16,3 +16,24 @@ has() {
set ${saved_xtrace}
return ${ret}
}
export -f has
sudo_preserve_env() {
local saved_xtrace
[[ $- == *x* ]] && saved_xtrace=-x || saved_xtrace=+x
set +x
local vars=()
while [[ $# -gt 0 ]]; do
local arg=$1
shift
case ${arg} in
--) break ;;
*) vars+=("${arg}=${!arg}") ;;
esac
done
set ${saved_xtrace}
sudo env "${vars[@]}" "$@"
}
export -f sudo_preserve_env
+14
View File
@@ -0,0 +1,14 @@
<aa@cs.fiu.edu> <alexander.afanasyev@ucla.edu>
<davidepesa@gmail.com> <davide.pesavento@lip6.fr>
<enewberry@email.arizona.edu> <enewberry@cs.arizona.edu>
Vince Lehman <vslehman@memphis.edu> <vlehman1@gmail.com>
<lybmath2009@gmail.com> <lybmath@ucla.edu>
Hila Ben Abraham <hilata@gmail.com>
<tuyukai1994@gmail.com> <tyk@bupt.edu.cn>
Haowei Yuan <hyuan@wustl.edu>
Minsheng Zhang <jimmyzms5@gmail.com>
Spyridon Mastorakis <spiros.mastorakis@gmail.com>
Md Ashiqur Rahman <marahman@email.arizona.edu>
Yumin Xia <me@yumin-xia.com>
<chghasemi@cs.arizona.edu> <chavoosh.ghasemi@gmail.com>
Tai-Lin Chu <tailinchu@gmail.com>
+97 -108
View File
@@ -1,126 +1,115 @@
version: ~> 1.0
language: cpp
dist: trusty
sudo: required
os: linux
dist: bionic
arch:
- amd64
#- arm64 # Too slow, exceeds time limit
#- ppc64le # Fails transport tests
#- s390x # Fails transport tests
env:
global:
- JOB_NAME=limited-build
- WAF_JOBS=2
- COMPILER=g++-7
- COMPILER=g++-9
- COMPILER=clang++-6.0
- COMPILER=clang++-9
matrix:
jobs:
include:
# Linux/gcc
# https://launchpad.net/~ubuntu-toolchain-r/+archive/ubuntu/test/+packages
- os: linux
env: COMPILER=g++-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
addons:
apt:
sources: ubuntu-toolchain-r-test
packages: g++-8
# Linux
- env: COMPILER=g++-5
- env: COMPILER=g++-6
- env: COMPILER=g++-8
- env: COMPILER=clang++-4.0
- env: COMPILER=clang++-5.0
- env: COMPILER=clang++-7
- env: COMPILER=clang++-8
- env: COMPILER=clang++-10
- env: COMPILER=clang++-11
- env: COMPILER=clang++-12
# Linux/clang
# https://apt.llvm.org/
- os: linux
env: COMPILER=clang++-3.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
- 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-6.0", "ubuntu-toolchain-r-test"]
packages: clang-6.0
- os: linux
env: COMPILER=clang++-7
addons:
apt:
sources: ["llvm-toolchain-trusty", "ubuntu-toolchain-r-test"]
packages: clang-7
# macOS/clang
# https://docs.travis-ci.com/user/reference/osx/#OS-X-Version
# macOS
- os: osx
osx_image: xcode7.3
env: OSX_VERSION=10.11
osx_image: xcode9.4
env: # default compiler
- os: osx
osx_image: xcode8.3
env: OSX_VERSION=10.12
osx_image: xcode10.1
env: # default compiler
- os: osx
osx_image: xcode9.3
env: OSX_VERSION=10.13
osx_image: xcode10.3
env: # default compiler
- os: osx
osx_image: xcode11.3
env: # default compiler
- os: osx
osx_image: xcode11.6
env: # default compiler
- os: osx
osx_image: xcode12
env: # default compiler
allow_failures:
- env: COMPILER=clang++-7
- env: COMPILER=g++-5
- env: COMPILER=g++-6
- env: COMPILER=clang++-4.0
- env: COMPILER=clang++-12
fast_finish: true
before_install:
- |
: Adding apt repositories
case ${COMPILER} in
g++-9)
# https://launchpad.net/~ubuntu-toolchain-r/+archive/ubuntu/test/+packages
travis_retry sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
travis_retry sudo apt-get -qq update
;;
clang++-1?)
# https://apt.llvm.org/
LLVM_REPO=${COMPILER/clang++/llvm-toolchain-${TRAVIS_DIST}}
travis_retry wget -nv -O - "https://apt.llvm.org/llvm-snapshot.gpg.key" | sudo apt-key add -
travis_retry sudo add-apt-repository -y "deb http://apt.llvm.org/${TRAVIS_DIST}/ ${LLVM_REPO%-12} main"
travis_retry sudo apt-get -qq update
;;
esac
install:
- |
: Installing C++ compiler
if [[ -n ${COMPILER} ]]; then
travis_retry sudo apt-get -qy install ${COMPILER/clang++/clang}
fi
before_script:
- if [[ ${TRAVIS_OS_NAME} == linux ]]; then export NODE_LABELS="Linux Ubuntu Ubuntu-14.04"; fi
- if [[ ${TRAVIS_OS_NAME} == osx ]]; then export NODE_LABELS="OSX OSX-${OSX_VERSION}"; fi
- if [[ -n ${COMPILER} ]]; then export CXX=${COMPILER}; fi
- |
: Setting environment variables
if [[ -n ${COMPILER} ]]; then
export CXX=${COMPILER}
fi
case ${TRAVIS_OS_NAME} in
linux) export NODE_LABELS="Linux Ubuntu Ubuntu-18.04" ;;
osx) export NODE_LABELS="OSX OSX-$(sw_vers -productVersion | cut -d . -f -2)" ;;
esac
export JOB_NAME=limited-build
export WAF_JOBS=2
- |
: Enabling workarounds
case "${TRAVIS_CPU_ARCH},${COMPILER}" in
ppc64le,g++-7)
# AddressSanitizer does not seem to be working
export DISABLE_ASAN=yes
;;
*,clang++-8)
# https://bugs.llvm.org/show_bug.cgi?id=40808
export DISABLE_ASAN=yes
;;
esac
if [[ ${TRAVIS_OS_NAME} == linux ]]; then
sudo sysctl -e -w net.ipv6.conf.all.disable_ipv6=0
fi
- ${CXX:-c++} --version
- python --version
script:
- ./.jenkins
-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
+51 -40
View File
@@ -56,6 +56,7 @@ from waflib.TaskGen import feature, after_method
BOOST_LIBS = ['/usr/lib', '/usr/local/lib', '/opt/local/lib', '/sw/lib', '/lib']
BOOST_INCLUDES = ['/usr/include', '/usr/local/include', '/opt/local/include', '/sw/include']
BOOST_VERSION_FILE = 'boost/version.hpp'
BOOST_VERSION_CODE = '''
#include <iostream>
@@ -90,13 +91,18 @@ int main() { boost::thread t; }
BOOST_LOG_CODE = '''
#include <boost/log/trivial.hpp>
int main() { BOOST_LOG_TRIVIAL(info) << "boost_log is working"; }
'''
BOOST_LOG_SETUP_CODE = '''
#include <boost/log/trivial.hpp>
#include <boost/log/utility/setup/console.hpp>
#include <boost/log/utility/setup/common_attributes.hpp>
int main() {
using namespace boost::log;
add_common_attributes();
add_console_log(std::clog, keywords::format = "%Message%");
BOOST_LOG_TRIVIAL(debug) << "log is working" << std::endl;
BOOST_LOG_TRIVIAL(info) << "boost_log_setup is working";
}
'''
@@ -145,7 +151,7 @@ def options(opt):
opt.add_option('--boost-abi', type='string', default='', dest='boost_abi',
help='''select libraries with tags (gd for debug, static is automatically added),
see doc Boost, Getting Started, chapter 6.1''')
opt.add_option('--boost-linkage_autodetect', action="store_true", dest='boost_linkage_autodetect',
opt.add_option('--boost-linkage_autodetect', action='store_true', dest='boost_linkage_autodetect',
help="auto-detect boost linkage options (don't get used to it / might break other stuff)")
opt.add_option('--boost-toolset', type='string',
default='', dest='boost_toolset',
@@ -175,7 +181,7 @@ def boost_get_version(self, d):
try:
txt = node.read()
except EnvironmentError:
Logs.error("Could not read the file %r" % node.abspath())
Logs.error('Could not read the file %r' % node.abspath())
else:
re_but1 = re.compile('^#define\\s+BOOST_LIB_VERSION\\s+"(.+)"', re.M)
m1 = re_but1.search(txt)
@@ -183,7 +189,7 @@ def boost_get_version(self, d):
m2 = re_but2.search(txt)
if m1 and m2:
return (m1.group(1), m2.group(1))
return self.check_cxx(fragment=BOOST_VERSION_CODE, includes=[d], execute=True, define_ret=True).split(":")
return self.check_cxx(fragment=BOOST_VERSION_CODE, includes=[d], execute=True, define_ret=True).split(':')
@conf
def boost_get_includes(self, *k, **kw):
@@ -194,10 +200,10 @@ def boost_get_includes(self, *k, **kw):
if self.__boost_get_version_file(d):
return d
if includes:
self.end_msg('headers not found in %s' % includes)
self.end_msg('headers not found in %s' % includes, 'YELLOW')
self.fatal('The configuration failed')
else:
self.end_msg('headers not found, please provide a --boost-includes argument (see help)')
self.end_msg('headers not found, please provide a --boost-includes argument (see help)', 'YELLOW')
self.fatal('The configuration failed')
@@ -240,10 +246,10 @@ def __boost_get_libs_path(self, *k, **kw):
break
if not path:
if libs:
self.end_msg('libs not found in %s' % libs)
self.end_msg('libs not found in %s' % libs, 'YELLOW')
self.fatal('The configuration failed')
else:
self.end_msg('libs not found, please provide a --boost-libs argument (see help)')
self.end_msg('libs not found, please provide a --boost-libs argument (see help)', 'YELLOW')
self.fatal('The configuration failed')
self.to_log('Found the boost path in %r with the libraries:' % path)
@@ -313,7 +319,7 @@ def boost_get_libs(self, *k, **kw):
libs.append(format_lib_name(file.name))
break
else:
self.end_msg('lib %s not found in %s' % (lib, path.abspath()))
self.end_msg('lib %s not found in %s' % (lib, path.abspath()), 'YELLOW')
self.fatal('The configuration failed')
return libs
@@ -354,7 +360,7 @@ def _check_pthread_flag(self, *k, **kw):
# ... -mt is also the pthreads flag for HP/aCC
# -lpthread: GNU Linux, etc.
# --thread-safe: KAI C++
if Utils.unversioned_sys_platform() == "sunos":
if Utils.unversioned_sys_platform() == 'sunos':
# On Solaris (at least, for some versions), libc contains stubbed
# (non-functional) versions of the pthreads routines, so link-based
# tests will erroneously succeed. (We need to link with -pthreads/-mt/
@@ -362,23 +368,22 @@ def _check_pthread_flag(self, *k, **kw):
# a function called by this macro, so we could check for that, but
# who knows whether they'll stub that too in a future libc.) So,
# we'll just look for -pthreads and -lpthread first:
boost_pthread_flags = ["-pthreads", "-lpthread", "-mt", "-pthread"]
boost_pthread_flags = ['-pthreads', '-lpthread', '-mt', '-pthread']
else:
boost_pthread_flags = ["", "-lpthreads", "-Kthread", "-kthread", "-llthread", "-pthread",
"-pthreads", "-mthreads", "-lpthread", "--thread-safe", "-mt"]
boost_pthread_flags = ['', '-lpthreads', '-Kthread', '-kthread', '-llthread', '-pthread',
'-pthreads', '-mthreads', '-lpthread', '--thread-safe', '-mt']
for boost_pthread_flag in boost_pthread_flags:
try:
self.env.stash()
self.env['CXXFLAGS_%s' % var] += [boost_pthread_flag]
self.env['LINKFLAGS_%s' % var] += [boost_pthread_flag]
self.check_cxx(code=PTHREAD_CODE, msg=None, use=var, execute=False)
self.check_cxx(code=PTHREAD_CODE, msg=None, use=var, execute=False, quiet=True)
self.end_msg(boost_pthread_flag)
return
except self.errors.ConfigurationError:
self.env.revert()
self.end_msg('None')
self.end_msg('none')
@conf
def check_boost(self, *k, **kw):
@@ -403,21 +408,24 @@ 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())
if not self.env.DONE_FIND_BOOST_COMMON:
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)
self.env.BOOST_VERSION = versions[0]
self.env.BOOST_VERSION_NUMBER = int(versions[1])
self.end_msg("%d.%d.%d" % (int(versions[1]) / 100000,
int(versions[1]) / 100 % 1000,
int(versions[1]) % 100))
if Logs.verbose:
Logs.pprint('CYAN', ' path : %s' % self.env['INCLUDES_%s' % var])
self.start_msg('Checking boost includes')
self.env['INCLUDES_%s' % var] = inc = self.boost_get_includes(**params)
versions = self.boost_get_version(inc)
self.env.BOOST_VERSION = versions[0]
self.env.BOOST_VERSION_NUMBER = int(versions[1])
self.end_msg('%d.%d.%d' % (int(versions[1]) / 100000,
int(versions[1]) / 100 % 1000,
int(versions[1]) % 100))
if Logs.verbose:
Logs.pprint('CYAN', ' path : %s' % self.env['INCLUDES_%s' % var])
self.env.DONE_FIND_BOOST_COMMON = True
if not params['lib'] and not params['stlib']:
return
@@ -429,7 +437,7 @@ def check_boost(self, *k, **kw):
self.env['STLIBPATH_%s' % var] = [path]
self.env['LIB_%s' % var] = libs
self.env['STLIB_%s' % var] = stlibs
self.end_msg('ok')
self.end_msg(' '.join(libs + stlibs))
if Logs.verbose:
Logs.pprint('CYAN', ' path : %s' % path)
Logs.pprint('CYAN', ' shared libs : %s' % libs)
@@ -450,15 +458,18 @@ def check_boost(self, *k, **kw):
self.check_cxx(fragment=BOOST_ERROR_CODE, use=var, execute=False)
if has_lib('thread'):
self.check_cxx(fragment=BOOST_THREAD_CODE, use=var, execute=False)
if has_lib('log'):
if has_lib('log') or has_lib('log_setup'):
if not has_lib('thread'):
self.env['DEFINES_%s' % var] += ['BOOST_LOG_NO_THREADS']
if has_shlib('log'):
if has_shlib('log') or has_shlib('log_setup'):
self.env['DEFINES_%s' % var] += ['BOOST_LOG_DYN_LINK']
self.check_cxx(fragment=BOOST_LOG_CODE, use=var, execute=False)
if has_lib('log_setup'):
self.check_cxx(fragment=BOOST_LOG_SETUP_CODE, use=var, execute=False)
else:
self.check_cxx(fragment=BOOST_LOG_CODE, use=var, execute=False)
if params.get('linkage_autodetect', False):
self.start_msg("Attempting to detect boost linkage flags")
self.start_msg('Attempting to detect boost linkage flags')
toolset = self.boost_get_toolset(kw.get('toolset', ''))
if toolset in ('vc',):
# disable auto-linking feature, causing error LNK1181
@@ -480,10 +491,10 @@ def check_boost(self, *k, **kw):
# we attempt to play with some known-to-work CXXFLAGS combinations
for cxxflags in (['/MD', '/EHsc'], []):
self.env.stash()
self.env["CXXFLAGS_%s" % var] += cxxflags
self.env['CXXFLAGS_%s' % var] += cxxflags
try:
try_link()
self.end_msg("ok: winning cxxflags combination: %s" % (self.env["CXXFLAGS_%s" % var]))
self.end_msg('ok: winning cxxflags combination: %s' % (self.env['CXXFLAGS_%s' % var]))
exc = None
break
except Errors.ConfigurationError as e:
@@ -491,17 +502,17 @@ def check_boost(self, *k, **kw):
exc = e
if exc is not None:
self.end_msg("Could not auto-detect boost linking flags combination, you may report it to boost.py author", ex=exc)
self.end_msg('Could not auto-detect boost linking flags combination, you may report it to boost.py author', ex=exc)
self.fatal('The configuration failed')
else:
self.end_msg("Boost linkage flags auto-detection not implemented (needed ?) for this toolchain")
self.end_msg('Boost linkage flags auto-detection not implemented (needed ?) for this toolchain')
self.fatal('The configuration failed')
else:
self.start_msg('Checking for boost linkage')
try:
try_link()
except Errors.ConfigurationError as e:
self.end_msg("Could not link against boost libraries using supplied options")
self.end_msg('Could not link against boost libraries using supplied options', 'YELLOW')
self.fatal('The configuration failed')
self.end_msg('ok')
-30
View File
@@ -1,30 +0,0 @@
# -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
"""
Copyright (c) 2014-2016, Regents of the University of California,
Arizona Board of Regents,
Colorado State University,
University Pierre & Marie Curie, Sorbonne University,
Washington University in St. Louis,
Beijing Institute of Technology,
The University of Memphis.
This file is part of NFD (Named Data Networking Forwarding Daemon).
See AUTHORS.md for complete list of NFD authors and contributors.
NFD is free software: you can redistribute it and/or modify it under the terms
of the GNU General Public License as published by the Free Software Foundation,
either version 3 of the License, or (at your option) any later version.
NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
"""
from waflib.Configure import conf
def configure(conf):
pass
+45 -32
View File
@@ -1,10 +1,11 @@
# -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
import platform
from waflib import Configure, Logs, Utils
def options(opt):
opt.add_option('--debug', '--with-debug', action='store_true', default=False,
help='Compile in debugging mode with minimal optimizations (-O0 or -Og)')
help='Compile in debugging mode with minimal optimizations (-Og)')
def configure(conf):
conf.start_msg('Checking C++ compiler version')
@@ -15,17 +16,23 @@ def configure(conf):
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 7.4.0.')
elif ccver < (7, 4, 0):
warnmsg = ('Using a version of gcc older than 7.4.0 is not '
'officially supported and may result in build failures.')
conf.flags = GccFlags()
elif cxx == 'clang':
if ccver < (3, 4, 0):
if Utils.unversioned_sys_platform() == 'darwin' and ccver < (9, 0, 0):
errmsg = ('The version of Xcode you are using is too old.\n'
'The minimum supported Xcode version is 9.0.')
elif ccver < (4, 0, 0):
errmsg = ('The version of clang you are using is too old.\n'
'The minimum supported clang version is 3.4.0.')
'The minimum supported clang version is 4.0.')
conf.flags = ClangFlags()
else:
warnmsg = 'Note: %s compiler is unsupported' % cxx
warnmsg = '%s compiler is unsupported' % cxx
conf.flags = CompilerFlags()
if errmsg:
@@ -33,13 +40,13 @@ def configure(conf):
conf.fatal(errmsg)
elif warnmsg:
conf.end_msg(ccverstr, color='YELLOW')
Logs.warn(warnmsg)
Logs.warn('WARNING: ' + warnmsg)
else:
conf.end_msg(ccverstr)
conf.areCustomCxxflagsPresent = (len(conf.env.CXXFLAGS) > 0)
# 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'])
@@ -128,24 +135,29 @@ class GccBasicFlags(CompilerFlags):
"""
def getGeneralFlags(self, conf):
flags = super(GccBasicFlags, self).getGeneralFlags(conf)
flags['CXXFLAGS'] += ['-std=c++11']
flags['CXXFLAGS'] += ['-std=c++14']
if Utils.unversioned_sys_platform() == 'linux':
flags['LINKFLAGS'] += ['-fuse-ld=gold']
elif Utils.unversioned_sys_platform() == 'freebsd':
flags['LINKFLAGS'] += ['-fuse-ld=lld']
return flags
def getDebugFlags(self, conf):
flags = super(GccBasicFlags, self).getDebugFlags(conf)
flags['CXXFLAGS'] += ['-O0',
'-Og', # gcc >= 4.8, clang >= 4.0
flags['CXXFLAGS'] += ['-Og',
'-g3',
'-pedantic',
'-Wall',
'-Wextra',
'-Werror',
'-Wcatch-value=2',
'-Wextra-semi',
'-Wnon-virtual-dtor',
'-Wno-error=deprecated-declarations', # Bug #3795
'-Wno-error=maybe-uninitialized', # Bug #1615
'-Wno-unused-parameter',
]
flags['LINKFLAGS'] += ['-fuse-ld=gold', '-Wl,-O1']
flags['LINKFLAGS'] += ['-Wl,-O1']
return flags
def getOptimizedFlags(self, conf):
@@ -155,60 +167,61 @@ class GccBasicFlags(CompilerFlags):
'-pedantic',
'-Wall',
'-Wextra',
'-Wcatch-value=2',
'-Wextra-semi',
'-Wnon-virtual-dtor',
'-Wno-unused-parameter',
]
flags['LINKFLAGS'] += ['-fuse-ld=gold', '-Wl,-O1']
flags['LINKFLAGS'] += ['-Wl,-O1']
return flags
class GccFlags(GccBasicFlags):
def getDebugFlags(self, conf):
flags = super(GccFlags, self).getDebugFlags(conf)
if self.getCompilerVersion(conf) < (5, 1, 0):
flags['CXXFLAGS'] += ['-Wno-missing-field-initializers']
flags['CXXFLAGS'] += ['-fdiagnostics-color'] # gcc >= 4.9
flags['CXXFLAGS'] += ['-fdiagnostics-color',
'-Wredundant-tags',
]
if platform.machine() == 'armv7l' and self.getCompilerVersion(conf) >= (7, 1, 0):
flags['CXXFLAGS'] += ['-Wno-psabi'] # Bug #5106
return flags
def getOptimizedFlags(self, conf):
flags = super(GccFlags, self).getOptimizedFlags(conf)
if self.getCompilerVersion(conf) < (5, 1, 0):
flags['CXXFLAGS'] += ['-Wno-missing-field-initializers']
flags['CXXFLAGS'] += ['-fdiagnostics-color'] # gcc >= 4.9
flags['CXXFLAGS'] += ['-fdiagnostics-color',
'-Wredundant-tags',
]
if platform.machine() == 'armv7l' and self.getCompilerVersion(conf) >= (7, 1, 0):
flags['CXXFLAGS'] += ['-Wno-psabi'] # Bug #5106
return flags
class ClangFlags(GccBasicFlags):
def getGeneralFlags(self, conf):
flags = super(ClangFlags, self).getGeneralFlags(conf)
if Utils.unversioned_sys_platform() == 'darwin' and self.getCompilerVersion(conf) >= (9, 0, 0):
if Utils.unversioned_sys_platform() == 'darwin':
# Bug #4296
flags['CXXFLAGS'] += [['-isystem', '/usr/local/include'], # for Homebrew
['-isystem', '/opt/local/include']] # for MacPorts
elif Utils.unversioned_sys_platform() == 'freebsd':
# Bug #4790
flags['CXXFLAGS'] += [['-isystem', '/usr/local/include']]
return flags
def getDebugFlags(self, conf):
flags = super(ClangFlags, self).getDebugFlags(conf)
flags['CXXFLAGS'] += ['-fcolor-diagnostics',
'-Wextra-semi',
'-Wundefined-func-template',
'-Wno-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 = 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 self.getCompilerVersion(conf) < (6, 0, 0):
flags['CXXFLAGS'] += ['-Wno-missing-braces'] # Bug #4721
return flags
def getOptimizedFlags(self, conf):
flags = super(ClangFlags, self).getOptimizedFlags(conf)
flags['CXXFLAGS'] += ['-fcolor-diagnostics',
'-Wextra-semi',
'-Wundefined-func-template',
'-Wno-unused-local-typedef', # Bugs #2657 and #3209
]
version = self.getCompilerVersion(conf)
if version < (3, 9, 0) or (Utils.unversioned_sys_platform() == 'darwin' and version < (8, 1, 0)):
flags['CXXFLAGS'] += ['-Wno-unknown-pragmas']
if self.getCompilerVersion(conf) < (6, 0, 0):
flags['CXXFLAGS'] += ['-Wno-missing-braces'] # Bug #4721
return flags
+8 -8
View File
@@ -44,28 +44,28 @@ def apply_sphinx(self):
task.inputs.append(conf)
confdir = conf.parent.abspath()
buildername = getattr(self, "builder", "html")
srcdir = getattr(self, "srcdir", confdir)
outdir = self.path.find_or_declare(getattr(self, "outdir", buildername)).get_bld()
doctreedir = getattr(self, "doctreedir", os.path.join(outdir.abspath(), ".doctrees"))
buildername = getattr(self, 'builder', 'html')
srcdir = getattr(self, 'srcdir', confdir)
outdir = self.path.find_or_declare(getattr(self, 'outdir', buildername)).get_bld()
doctreedir = getattr(self, 'doctreedir', os.path.join(outdir.abspath(), '.doctrees'))
task.env['BUILDERNAME'] = buildername
task.env['SRCDIR'] = srcdir
task.env['DOCTREEDIR'] = doctreedir
task.env['OUTDIR'] = outdir.abspath()
task.env['VERSION'] = "version=%s" % self.VERSION
task.env['RELEASE'] = "release=%s" % self.VERSION
task.env['VERSION'] = 'version=%s' % self.version
task.env['RELEASE'] = 'release=%s' % getattr(self, 'release', self.version)
import imp
confData = imp.load_source('sphinx_conf', conf.abspath())
if buildername == "man":
if buildername == 'man':
for i in confData.man_pages:
target = outdir.find_or_declare('%s.%d' % (i[1], i[4]))
task.outputs.append(target)
if self.install_path:
self.bld.install_files("%s/man%d/" % (self.install_path, i[4]), target)
self.bld.install_files('%s/man%d/' % (self.install_path, i[4]), target)
else:
task.outputs.append(outdir)
-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
+4 -5
View File
@@ -1,13 +1,13 @@
# -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
#
# Copyright (c) 2014-2018, Regents of the University of California
# Copyright (c) 2014-2019, Regents of the University of California
#
# GPL 3.0 license, see the COPYING.md file for more information
from waflib import Options
BOOST_ASIO_HAS_LOCAL_SOCKETS_CHECK = '''
#include <boost/asio.hpp>
#include <boost/asio/local/basic_endpoint.hpp>
#ifndef BOOST_ASIO_HAS_LOCAL_SOCKETS
#error "Unix sockets are not available on this platform"
#endif
@@ -25,6 +25,5 @@ def configure(conf):
fragment=BOOST_ASIO_HAS_LOCAL_SOCKETS_CHECK,
features='cxx', use='BOOST', mandatory=False)
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 = conf.options.force_unix_socket or boost_asio_has_local_sockets()
conf.define_cond('HAVE_UNIX_SOCKETS', conf.env.HAVE_UNIX_SOCKETS)
+7 -7
View File
@@ -61,13 +61,13 @@ def checkWebsocket(self, **kw):
except Errors.WafError as error:
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('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('If you are using NFD from the git repository, checkout the websocketpp submodule: ')
Logs.warn(' git submodule update --init')
Logs.warn('Otherwise, manually download and extract the websocketpp library:')
Logs.warn(' mkdir -p websocketpp')
Logs.warn(' curl -L https://github.com/cawka/websocketpp/archive/0.8.1-hotfix.tar.gz > websocketpp.tar.gz')
Logs.warn(' tar xf websocketpp.tar.gz -C websocketpp/ --strip 1')
Logs.warn('Alternatively, WebSocket support can be disabled with --without-websocket')
self.fatal('The configuration failed')
self.fatal('WebSocket++ not found')
else:
self.end_msg(str(error))
+58 -78
View File
@@ -1,82 +1,62 @@
NFD Authors
===========
# NFD Authors
NFD is an open source project started in late 2013, includes contributions
from many people around the world, and open for new contributions from new
volunteers.
The following lists maintainers, primary developers, and all much-appreciated contributors to NFD in alphabetic order.
The specific contributions of individual authors can be obtained from the git history of the [official NFD repository](https://github.com/named-data/NFD).
If you would like to become a contributor to the official repository, please follow the recommendations in https://github.com/named-data/.github/blob/master/CONTRIBUTING.md.
* Jerald Paul Abraham <https://cs.arizona.edu/~jeraldabraham>
* ***(Maintainer)*** Alexander Afanasyev <https://users.cs.fiu.edu/~afanasyev>
* Syed Obai Amin <http://obaidamin.weebly.com>
* Hila Ben Abraham <https://sites.wustl.edu/hbabraham>
* Muktadir R Chowdhury <https://github.com/alvyC>
* Tai-Lin Chu <https://www.linkedin.com/pub/tai-lin-chu/55/5b2/669>
* Stephanie DiBenedetto
* Saurab Dulal <https://dulalsaurab.github.io>
* Chengyu Fan <https://github.com/chengyu>
* Ashlesh Gawande <https://www.linkedin.com/in/agawande>
* Chavoosh Ghasemi <https://chavoosh.github.io>
* Mathias Gibbens <https://calenhad.com>
* Nick Gordon <https://github.com/gorgonical>
* Giulio Grassi <https://www.lip6.fr/actualite/personnes-fiche.php?ident=D1461>
* Yi Huang <https://www.linkedin.com/in/yihuang1991>
* Jongseok Lee <https://github.com/imwhiz>
* Spencer Lee <https://www.linkedin.com/in/spenlee>
* Vince Lehman <http://vslehman.com>
* Yanbiao Li <https://www.linkedin.com/pub/yanbiao-li/24/7a1/4ba>
* Teng Liang <https://cs.arizona.edu/~philoliang>
* Weiwei Liu <https://www.linkedin.com/in/weiweiliu10>
* Spyridon Mastorakis <https://sites.google.com/site/spyridonmastorakis>
* Ernest McCracken <https://github.com/emccrckn>
* Ilya Moiseenko <https://www.linkedin.com/in/ilya-moiseenko-52884317>
* Eric Newberry <https://ericnewberry.com>
* Ju Pan <https://cs-jupan.com>
* João Pereira <http://website.jpereira.co.uk>
* Davide Pesavento <https://github.com/Pesa>
* Felix Rabe <https://twitter.com/felixrabe>
* Md Ashiqur Rahman <https://ashiqrahman.com>
* Matteo Sammarco <https://www.linkedin.com/in/matteo-sammarco-9b544530>
* Niv Sardi <http://core.evilgiggle.com>
* Klaus Schneider <https://cs.arizona.edu/~klaus>
* Wentao Shang <https://irl.cs.ucla.edu/~wentao>
* Susmit Shannigrahi <https://susm.it>
* ***(Former Maintainer)*** Junxiao Shi <https://cs.arizona.edu/~shijunxiao>
* Yukai Tu <https://irl.cs.ucla.edu/~yukai>
* Sebastian Wölke <https://inet.haw-hamburg.de/members/alumni-1/sebastian-woelke>
* Yumin Xia <https://github.com/Stumble>
* Yingdi Yu <https://irl.cs.ucla.edu/~yingdi>
* Haowei Yuan <http://www.cse.wustl.edu/~yuanh>
* Hang Zhang <http://netlab.bit.edu.cn/z_hang>
* Minsheng Zhang <https://github.com/mzhang4>
* Zhiyi Zhang <https://zhiyi-zhang.com>
* Qi Zhao <https://web.cs.ucla.edu/~qi.zhao>
* Wenkai Zheng <https://github.com/wenkaizheng>
## Project technical leads:
## Technical Advisors
* Alexander Afanasyev <http://lasr.cs.ucla.edu/afanasyev/index.html>
* Junxiao Shi <http://www.cs.arizona.edu/people/shijunxiao/>
## Technical advisors:
* Beichuan Zhang <http://www.cs.arizona.edu/~bzhang/>
* Lixia Zhang <http://www.cs.ucla.edu/~lixia/>
## Main project authors and their affiliations:
* University of California, Los Angeles
* Alexander Afanasyev <http://lasr.cs.ucla.edu/afanasyev/index.html>
* Ilya Moiseenko <http://ilyamoiseenko.com/>
* Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/web/index.html>
* Wentao Shang <http://irl.cs.ucla.edu/~wentao/>
* Lixia Zhang <http://www.cs.ucla.edu/~lixia/>
* The University of Arizona
* Junxiao Shi <http://www.cs.arizona.edu/people/shijunxiao/>
* Yi Huang <ethanhuang1991@gmail.com>
* Jerald Paul Abraham <http://www.cs.arizona.edu/people/jeraldabraham/>
* Beichuan Zhang <http://www.cs.arizona.edu/~bzhang/>
* Colorado State University
* Steve DiBenedetto <http://www.cs.colostate.edu/~dibenede/>
* Chengyu Fan <chengyu@cs.colostate.edu>
* Christos Papadopoulos <http://www.cs.colostate.edu/~christos/>
* University Pierre & Marie Curie, Sorbonne University
* Davide Pesavento <https://www.linkedin.com/in/davidepesavento>
* Giulio Grassi <http://www.lip6.fr/actualite/personnes-fiche.php?ident=D1461>
* Giovanni Pau <http://www.cs.ucla.edu/~gpau/Giovanni_Paus_Home_Page/Home.html>
* Beijing Institute of Technology
* Hang Zhang <http://netlab.bit.edu.cn/z_hang>
* Tian Song <http://cs.bit.edu.cn/songtian>
* Washington University in St. Louis
* Haowei Yuan <http://www.cse.wustl.edu/~yuanh/>
* Hila Ben Abraham <http://research.engineering.wustl.edu/~abrahamh/>
* Patrick Crowley <http://www.arl.wustl.edu/~pcrowley/>
* The University of Memphis
* Syed Obaid Amin <http://obaidamin.weebly.com/>
* Vince Lehman <vslehman@memphis.edu>
* Minsheng Zhang <mzhang4@memphis.edu>
* Lan Wang <http://www.cs.memphis.edu/~lanwang/>
## Project contributors
The following is an inevitably incomplete list of MUCH-APPRECIATED CONTRIBUTORS,
people who have reported bugs, submitted patches, and implemented new features
in the library:
* Tai-Lin Chu <https://www.linkedin.com/pub/tai-lin-chu/55/5b2/669>
* Spyridon Mastorakis <http://cs.ucla.edu/~mastorakis/>
* Eric Newberry <http://cs.arizona.edu/~enewberry/>
* Yukai Tu <tuyukai1994@gmail.com>
* João Pereira <http://website.jpereira.co.uk>
* Mathias Gibbens <gibmat@cs.arizona.edu>
* Yanbiao Li <https://www.linkedin.com/pub/yanbiao-li/24/7a1/4ba>
* Weiwei Liu <https://www.linkedin.com/in/weiweiliu10>
* Spencer Lee <https://www.linkedin.com/in/spenlee>
* Patrick Crowley <https://www.arl.wustl.edu/~pcrowley>
* Christos Papadopoulos <https://www.cs.colostate.edu/~christos>
* Giovanni Pau <http://www.cs.ucla.edu/~gpau/Giovanni_Paus_Home_Page/Home.html>
* Tian Song <http://www.bit-netlab.org/songtian>
* Lan Wang <http://www.cs.memphis.edu/~lanwang>
* Beichuan Zhang <https://cs.arizona.edu/~bzhang>
* Lixia Zhang <https://cs.ucla.edu/~lixia>
+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
+370 -370
View File
File diff suppressed because it is too large. Load diff
-5
View File
@@ -1,5 +0,0 @@
NFD Installation Instructions
=============================
See [`docs/INSTALL.rst`](https://github.com/named-data/NFD/blob/master/docs/INSTALL.rst)
for detailed NFD installation instructions.
+26 -26
View File
@@ -1,21 +1,23 @@
Notes for NFD developers
========================
# Notes for NFD developers
If you are new to the NDN software community, please read the
[Contributor's Guide](https://github.com/named-data/NFD/blob/master/CONTRIBUTING.md)
[Contributor's Guide](https://github.com/named-data/.github/blob/master/CONTRIBUTING.md).
Requirements
------------
## Code style
Contributions to NFD must be licensed under GPL 3.0 or compatible license. If you are
choosing GPL 3.0, please use the following license boilerplate in all `.hpp` and `.cpp`
files:
NFD code is subject to [NFD code style](https://redmine.named-data.net/projects/nfd/wiki/CodeStyle).
## Licensing
Contributions to NFD must be licensed under the GPL 3.0 or compatible license. If you
are choosing GPL 3.0, please use the following license boilerplate in all `.hpp` and
`.cpp` files:
Include the following license boilerplate into all `.hpp` and `.cpp` files:
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) [Year(s)], [Copyright Holder(s)].
* Copyright (c) [Year(s)], [Copyright Holder(s)].
*
* This file is part of NFD (Named Data Networking Forwarding Daemon).
* See AUTHORS.md for complete list of NFD authors and contributors.
@@ -35,37 +37,36 @@ Include the following license boilerplate into all `.hpp` and `.cpp` files:
If you are affiliated to an NSF-supported NDN project institution, please use the [NDN Team License
Boilerplate](https://redmine.named-data.net/projects/nfd/wiki/NDN_Team_License_Boilerplate_(NFD)).
Recommendations
---------------
## Logging
NFD code is subject to NFD [code style](https://redmine.named-data.net/projects/nfd/wiki/CodeStyle).
Fine-grained per-module logging can be configured via the `NDN_LOG` environment variable.
This is especially useful when running unit tests or tools such as `nfdc` that do not
have a configuration file. See `ndn-log(7)` manual page for syntax and examples.
Running unit-tests
------------------
## Unit tests
To run unit tests, NFD needs to be configured and build with unit test support:
./waf configure --with-tests
./waf configure --with-tests # --debug is also strongly recommended while developing
./waf
The simplest way to run tests, is just to run the compiled binary without any parameters:
The simplest way to run the tests is to launch the compiled binary without any parameters:
# Run core tests
./build/unit-tests-core
# Run NFD daemon tests
# Run NFD daemon tests
./build/unit-tests-daemon
# 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)
The [Boost.Test framework](https://www.boost.org/doc/libs/1_65_1/libs/test/doc/html/index.html)
is very flexible and allows a number of run-time customization of what tests should be run.
For example, it is possible to choose to run only a specific test suite, only a specific
test case within a suite, or specific test cases within specific test suites:
# Run only TCP Face test suite of NFD daemon tests (see tests/daemon/face/tcp.cpp)
# Run only the TCP Face test suite of NFD daemon tests
./build/unit-tests-daemon -t FaceTcp
# Run only test case EndToEnd4 from the same test suite
@@ -76,8 +77,8 @@ test case within a suite, or specific test cases within specific test suites:
By default, Boost.Test framework will produce verbose output only when a test case fails.
If it is desired to see verbose output (result of each test assertion), add `-l all`
option to `./build/unit-tests` command. To see test progress, you can use `-l test_suite`
or `-p` to show progress bar:
option to `./build/unit-tests` command. To see test progress, you can use `-l test_suite`,
or `-p` to show a progress bar:
# Show report all log messages including the passed test notification
./build/unit-tests-daemon -l all
@@ -91,7 +92,6 @@ or `-p` to show progress bar:
# Show progress bar
./build/unit-tests-core -p
There are many more command line options available, information about
which can be obtained either from the command line using `--help`
switch, or online on [Boost.Test library](http://www.boost.org/doc/libs/1_54_0/libs/test/doc/html/index.html)
website.
There are many more command line options available, information about which can be obtained
either from the command line using the `--help` switch, or online on the
[Boost.Test website](https://www.boost.org/doc/libs/1_65_1/libs/test/doc/html/index.html).
+37 -29
View File
@@ -1,38 +1,15 @@
NFD - Named Data Networking Forwarding Daemon
=============================================
# NFD - Named Data Networking Forwarding Daemon
![Language](https://img.shields.io/badge/C%2B%2B-14-blue.svg)
[![Build Status](https://travis-ci.org/named-data/NFD.svg?branch=master)](https://travis-ci.org/named-data/NFD)
For complete documentation, including step-by-step installation instructions and
tutorials, please visit the [NFD homepage](https://named-data.net/doc/NFD/).
If you are new to the NDN software community, please read README-dev.md and the
[Contributor's Guide](https://github.com/named-data/NFD/blob/master/CONTRIBUTING.md).
![Latest Version](https://img.shields.io/github/tag/named-data/NFD.svg?color=darkkhaki&label=latest%20version)
## Overview
NFD is a network forwarder that implements and evolves together with the Named Data
Networking (NDN) [protocol](https://named-data.net/doc/ndn-tlv/). After the initial
release, NFD will become a core component of the
[NDN Platform](https://named-data.net/codebase/platform/) and will follow the same release
cycle.
NFD is an open and free software package licensed under GPL 3.0 license and is the
centerpiece of our committement to making NDN's core technology open and free to all
Internet users and developers. For more information about the licensing details and
limitation, refer to
[`COPYING.md`](https://github.com/named-data/NFD/blob/master/COPYING.md).
NFD is developed by a community effort. Although the first release was mostly done by the
members of [NSF-sponsored NDN project team](https://named-data.net/project/participants/),
it already contains significant contributions from people outside the project team (for
more details, refer to
[`AUTHORS.md`](https://github.com/named-data/NFD/blob/master/AUTHORS.md)). We strongly
encourage participation from all interested parties, since broader community support is
key for NDN to succeed as a new Internet architecture. Bug reports and feedback are
highly appreciated and can be made through
[Redmine site](https://redmine.named-data.net/projects/nfd) and the
[ndn-interest mailing list](http://www.lists.cs.ucla.edu/mailman/listinfo/ndn-interest).
Networking (NDN) [protocol](https://named-data.net/doc/NDN-packet-spec/current/).
Since the initial public release in 2014, NFD has been a core component of the
[NDN Platform](https://named-data.net/codebase/platform/).
The main design goal of NFD is to support diverse experimentation of NDN technology. The
design emphasizes *modularity* and *extensibility* to allow easy experiments with new
@@ -45,3 +22,34 @@ NFD will keep evolving in three aspects: improvement of the modularity framework
up with the NDN protocol spec, and addition of other new features. We hope to keep the
modular framework stable and lean, allowing researchers to implement and experiment with
various features, some of which may eventually work into the protocol spec.
## Documentation
See [`docs/INSTALL.rst`](docs/INSTALL.rst) for compilation and installation instructions.
Extensive documentation is available on NFD's [homepage](https://named-data.net/doc/NFD/).
## Reporting bugs
Bug reports and feedback are highly appreciated and can be submitted through the
[NFD issue tracker](https://redmine.named-data.net/projects/nfd/issues) or the
[ndn-interest mailing list](http://www.lists.cs.ucla.edu/mailman/listinfo/ndn-interest).
## Contributing
NFD is developed by a community effort. Although the first release was mostly done by the
members of [NSF-sponsored NDN project team](https://named-data.net/project/participants/),
it already contains significant contributions from people outside the project team (see
[`AUTHORS.md`](AUTHORS.md)). We strongly encourage participation from all interested parties,
since broader community support is key for NDN to succeed as a new Internet architecture.
If you are new to the NDN software community, please read [`README-dev.md`](README-dev.md)
and the [Contributor's Guide](https://github.com/named-data/.github/blob/master/CONTRIBUTING.md)
to get started.
## License
NFD is a free and open-source software package licensed under the GPL version 3 and
is the centerpiece of our committement to making NDN's core technology free and open
to all Internet users and developers. For more information about licensing, refer to
[`COPYING.md`](COPYING.md).
-130
View File
@@ -1,130 +0,0 @@
Starting NFD on Linux with systemd
==================================
Newer versions of Ubuntu (starting with 15.04) and some other Linux distributions, including Debian
use systemd to start system daemons, monitor their health, and restart them when they die.
Initial setup
-------------
* Edit `nfd.service`, correcting the paths to the `nfd` executable, configuration, and
``HOME`` directories.
* Copy the systemd config file for NFD to the proper directory
sudo cp nfd.service /etc/systemd/system
* Reload the systemd manager configuration
sudo systemctl daemon-reload
### Assumptions in the default scripts
* `nfd` is installed into `/usr/local/bin`
* Configuraton file is `/usr/local/etc/ndn/nfd.conf`
* `nfd` will be run as root
* Log files will be written to `/usr/local/var/log/ndn` folder, which is owned by user `ndn`
### Creating users
If the `ndn` user and group do not exist, they need to be manually created.
# Create group `ndn`
sudo addgroup --system ndn
# Create user `ndn`
sudo adduser --system \
--disabled-login \
--ingroup ndn \
--home /nonexistent \
--gecos "NDN User" \
--shell /bin/false \
ndn
### Creating folders
Folder `/usr/local/var/log/ndn` should be created and assigned proper user and group:
sudo mkdir -p /usr/local/var/log/ndn
sudo chown -R ndn:ndn /usr/local/var/log/ndn
`HOME` directory for `nfd` should be created prior to starting. This is necessary to manage
unique security credentials for the daemon.
# Create HOME and generate self-signed NDN certificate for nfd
sudo sh -c ' \
mkdir -p /usr/local/var/lib/ndn/nfd/.ndn; \
export HOME=/usr/local/var/lib/ndn/nfd; \
ndnsec-keygen /localhost/daemons/nfd | ndnsec-install-cert -; \
'
### Configuring NFD's security
NFD sample configuration allows anybody to create faces, add nexthops to FIB, and set
strategy choice for namespaces. While such settings could be a good start, it is
generally not a good idea to run NFD in this mode.
While thorough discussion about the security configuration of NFD is outside the scope of
this document, at least the following change should be done in ``nfd.conf`` in the
authorize section:
authorizations
{
authorize
{
certfile certs/localhost_daemons_nfd.ndncert
privileges
{
faces
fib
strategy-choice
}
}
authorize
{
certfile any
privileges
{
faces
strategy-choice
}
}
}
While this configuration still allows the management of faces and updating strategy choice by
anyone, only NFD's RIB Manager (i.e., NFD itself) is allowed to manage FIB.
As the final step to make this configuration work, nfd's self-signed certificate needs to
be exported into the `localhost_daemons_nfd.ndncert` file:
sudo sh -c '\
mkdir -p /usr/local/etc/ndn/certs || true; \
export HOME=/usr/local/var/lib/ndn/nfd; \
ndnsec-dump-certificate -i /localhost/daemons/nfd > \
/usr/local/etc/ndn/certs/localhost_daemons_nfd.ndncert; \
'
Enable auto-start
-----------------
After copying the provided upstart script, auto-start of the `nfd` daemon can be enabled with:
sudo systemctl enable nfd
To manually start it, use the following command:
sudo systemctl start nfd
Disable auto-start
------------------
To stop the `nfd` daemon, use the following command:
sudo systemctl stop nfd
To permanently stop the `nfd` daemon and disable it from being automatically started on reboot,
disable the service:
sudo systemctl disable nfd
-125
View File
@@ -1,125 +0,0 @@
Starting NFD on Linux with upstart
==================================
Some Linux distributions, such as Ubuntu, use [upstart](http://upstart.ubuntu.com/) as a
standard mechanism to start system daemons, monitor their health, and restart
when they die.
Initial setup
-------------
* Edit `nfd.conf` correcting paths for `nfd` binary, configuration and log files.
* Copy upstart config file for NFD
sudo cp nfd.conf /etc/init/
### Assumptions in the default scripts
* `nfd` is installed into `/usr/local/bin`
* Configuration file is `/usr/local/etc/ndn/nfd.conf`
* `nfd` will be run as root
* Log files will be written to `/usr/local/var/log/ndn` folder, which is owned by user `ndn`
### Creating users
If `ndn` user and group does not exists, they need to be manually created.
# Create group `ndn`
addgroup --system ndn
# Create user `ndn`
sudo adduser --system \
--disabled-login \
--ingroup ndn \
--home /nonexistent \
--gecos "NDN User" \
--shell /bin/false \
ndn
### Creating folders
Folder `/usr/local/var/log/ndn` should be created and assigned proper user and group:
sudo mkdir -p /usr/local/var/log/ndn
sudo chown -R ndn:ndn /usr/local/var/log/ndn
`HOME` directory for `nfd` should be created prior to starting. This is necessary to manage
unique security credentials for the deamon.
# Create HOME and generate self-signed NDN certificate for nfd
sudo -s -- ' \
mkdir -p /usr/local/var/lib/ndn/nfd/.ndn; \
export HOME=/usr/local/var/lib/ndn/nfd; \
ndnsec-keygen /localhost/daemons/nfd | ndnsec-install-cert -; \
'
### Configuring NFD's security
NFD sample configuration allows anybody to create faces, add nexthops to FIB, and set
strategy choice for namespaces. While such settings could be a good start, it is
generally not a good idea to run NFD in this mode.
While thorough discussion about security configuration of NFD is outside the scope of this
document, at least the following change should be done to ``nfd.conf`` in authorize
section:
authorizations
{
authorize
{
certfile certs/localhost_daemons_nfd.ndncert
privileges
{
faces
fib
strategy-choice
}
}
authorize
{
certfile any
privileges
{
faces
strategy-choice
}
}
}
While this configuration still allows management of faces and updating strategy choice by
anybody, only NFD's RIB Manager (i.e., NFD itself) is allowed to manage FIB.
As the final step to make this configuration work, nfd's self-signed certificate needs to
be exported into `localhost_daemons_nfd.ndncert` file:
sudo -s -- '\
mkdir -p /usr/local/etc/ndn/certs || true; \
export HOME=/usr/local/var/lib/ndn/nfd; \
ndnsec-dump-certificate -i /localhost/daemons/nfd > \
/usr/local/etc/ndn/certs/localhost_daemons_nfd.ndncert; \
'
Enable auto-start
-----------------
After copying the provided upstart script, `nfd` daemon will automatically run after the reboot.
To manually start them, use the following commands:
sudo start nfd
Disable auto-start
------------------
To stop `nfd` daemon, use the following commands:
sudo stop nfd
Note that as long as upstart files are present in `/etc/init/`, the daemon will
automatically start after the reboot. To permanently stop `nfd` daemon, delete
the upstart files:
sudo rm /etc/init/nfd.conf
-26
View File
@@ -1,26 +0,0 @@
# nfd.conf
#
# NDN Forwarding Daemon
description "NDN forwarding daemon"
start on (local-filesystems and net-device-up IFACE!=lo)
stop on runlevel [!2345]
respawn
respawn limit unlimited
env HOME=/usr/local/var/lib/ndn/nfd
export HOME
exec /usr/local/bin/nfd --config /usr/local/etc/ndn/nfd.conf 2>> /usr/local/var/log/ndn/nfd.log
post-start script
if [ -f /usr/local/etc/ndn/nfd-init.sh ]; then
sleep 2 # post-start is executed just after nfd process starts, but there is no guarantee
# that all initialization has been finished
. /usr/local/etc/ndn/nfd-init.sh
fi
end script
post-stop exec sleep 2
+14 -8
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2018, Regents of the University of California,
* Copyright (c) 2014-2020, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -33,12 +33,14 @@
#define PUBLIC_WITH_TESTS_ELSE_PROTECTED public
#define PUBLIC_WITH_TESTS_ELSE_PRIVATE public
#define PROTECTED_WITH_TESTS_ELSE_PRIVATE protected
#define OVERRIDE_WITH_TESTS_ELSE_FINAL override
#define FINAL_UNLESS_WITH_TESTS
#else
#define VIRTUAL_WITH_TESTS
#define PUBLIC_WITH_TESTS_ELSE_PROTECTED protected
#define PUBLIC_WITH_TESTS_ELSE_PRIVATE private
#define PROTECTED_WITH_TESTS_ELSE_PRIVATE private
#define OVERRIDE_WITH_TESTS_ELSE_FINAL final
#define FINAL_UNLESS_WITH_TESTS final
#endif
@@ -46,10 +48,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>
@@ -65,14 +67,16 @@
#include <ndn-cxx/lp/nack.hpp>
#include <ndn-cxx/net/face-uri.hpp>
#include <ndn-cxx/util/backports.hpp>
#include <ndn-cxx/util/exception.hpp>
#include <ndn-cxx/util/scheduler.hpp>
#include <ndn-cxx/util/signal.hpp>
#include <ndn-cxx/util/time.hpp>
#include <boost/asio.hpp>
#include <boost/assert.hpp>
#include <boost/core/noncopyable.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/noncopyable.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/throw_exception.hpp>
namespace nfd {
@@ -84,16 +88,15 @@ 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::bind;
using std::cref;
using std::ref;
using namespace std::string_literals;
using ndn::optional;
using ndn::nullopt;
@@ -107,6 +110,7 @@ using ndn::FaceUri;
using ndn::Interest;
using ndn::Name;
using ndn::PartialName;
using ndn::Scheduler;
// Not using a namespace alias (namespace tlv = ndn::tlv), because
// it doesn't allow NFD to add other members to the namespace
@@ -116,9 +120,11 @@ using namespace ndn::tlv;
namespace lp = ndn::lp;
namespace name = ndn::name;
namespace scheduler = ndn::scheduler;
namespace signal = ndn::util::signal;
namespace time = ndn::time;
using namespace ndn::time_literals;
using ndn::operator""_block;
} // namespace nfd
-57
View File
@@ -1,57 +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_EXTENDED_ERROR_MESSAGE_HPP
#define NFD_CORE_EXTENDED_ERROR_MESSAGE_HPP
#include <boost/exception/get_error_info.hpp>
#include <sstream>
namespace nfd {
template<typename E>
std::string
getExtendedErrorMessage(const E& exception)
{
std::ostringstream errorMessage;
errorMessage << exception.what();
const char* const* file = boost::get_error_info<boost::throw_file>(exception);
const int* line = boost::get_error_info<boost::throw_line>(exception);
const char* const* func = boost::get_error_info<boost::throw_function>(exception);
if (file && line) {
errorMessage << " [from " << *file << ":" << *line;
if (func) {
errorMessage << " in " << *func;
}
errorMessage << "]";
}
return errorMessage.str();
}
} // namespace nfd
#endif // NFD_CORE_EXTENDED_ERROR_MESSAGE_HPP
-48
View File
@@ -1,48 +0,0 @@
/* -*- 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
*
* 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_GLOBAL_IO_HPP
#define NFD_CORE_GLOBAL_IO_HPP
#include "common.hpp"
namespace nfd {
/** \return the global io_service instance
*/
boost::asio::io_service&
getGlobalIoService();
#ifdef WITH_TESTS
/** \brief delete the global io_service instance
*
* It will be recreated at the next invocation of getGlobalIoService.
*/
void
resetGlobalIoService();
#endif
} // namespace nfd
#endif // NFD_CORE_GLOBAL_IO_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
-71
View File
@@ -1,71 +0,0 @@
/* -*- 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 "logger.hpp"
#ifdef HAVE_CUSTOM_LOGGER
#error "This file should not be compiled when custom logger is used"
#endif
#include <cinttypes>
#include <cstdlib>
#include <stdio.h>
#include <type_traits>
#include <ndn-cxx/util/time.hpp>
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;
const auto sinceEpoch = system_clock::now().time_since_epoch();
BOOST_ASSERT(sinceEpoch.count() >= 0);
// use abs() to silence truncation warning in snprintf(), see #4365
const auto usecs = std::abs(duration_cast<microseconds>(sinceEpoch).count());
const auto usecsPerSec = microseconds::period::den;
// 10 (whole seconds) + '.' + 6 (fraction) + '\0'
char buffer[10 + 1 + 6 + 1];
BOOST_ASSERT_MSG(usecs / usecsPerSec <= 9999999999, "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 unavailable on some platforms, see #2299
::snprintf(buffer, sizeof(buffer), "%" PRIdLEAST64 ".%06" PRIdLEAST64,
usecs / usecsPerSec, usecs % usecsPerSec);
return os << buffer;
}
} // namespace nfd
-171
View File
@@ -1,171 +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_HPP
#define NFD_CORE_LOGGER_HPP
#include "common.hpp"
#ifdef HAVE_CUSTOM_LOGGER
#include "custom-logger.hpp"
#else
#include <boost/log/common.hpp>
#include <boost/log/sources/logger.hpp>
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
#endif // NFD_CORE_LOGGER_HPP
+3 -4
View File
@@ -25,7 +25,6 @@
#include "network.hpp"
#include <ndn-cxx/net/address-converter.hpp>
#include <boost/utility/value_init.hpp>
#include <algorithm>
#include <cctype>
@@ -93,8 +92,8 @@ operator>>(std::istream& is, Network& network)
size_t position = networkStr.find('/');
if (position == std::string::npos) {
try {
network.m_minAddress = ndn::ip::addressFromString(networkStr);
network.m_maxAddress = ndn::ip::addressFromString(networkStr);
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);
@@ -103,7 +102,7 @@ operator>>(std::istream& is, Network& network)
}
else {
boost::system::error_code ec;
ip::address address = ndn::ip::addressFromString(networkStr.substr(0, position), ec);
auto address = ip::address::from_string(networkStr.substr(0, position), ec);
if (ec) {
is.setstate(std::ios::failbit);
return is;
-42
View File
@@ -1,42 +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 "random.hpp"
#include <boost/thread/tss.hpp>
namespace nfd {
std::mt19937&
getGlobalRng()
{
static boost::thread_specific_ptr<std::mt19937> rng;
if (rng.get() == nullptr) {
std::random_device rd;
rng.reset(new std::mt19937(rd()));
}
return *rng;
}
} // namespace nfd
-80
View File
@@ -1,80 +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 "rtt-estimator.hpp"
namespace nfd {
RttEstimator::RttEstimator(uint16_t maxMultiplier, Duration minRto, double gain)
: m_maxMultiplier(maxMultiplier)
, m_minRto(minRto.count())
, m_rtt(RttEstimator::getInitialRtt().count())
, m_gain(gain)
, m_variance(0)
, m_multiplier(1)
, m_nSamples(0)
{
}
void
RttEstimator::addMeasurement(Duration measure)
{
double m = static_cast<double>(measure.count());
if (m_nSamples > 0) {
double err = m - m_rtt;
double gErr = err * m_gain;
m_rtt += gErr;
double difference = std::abs(err) - m_variance;
m_variance += difference * m_gain;
}
else {
m_rtt = m;
m_variance = m;
}
++m_nSamples;
m_multiplier = 1;
}
void
RttEstimator::incrementMultiplier()
{
m_multiplier = std::min(static_cast<uint16_t>(m_multiplier + 1), m_maxMultiplier);
}
void
RttEstimator::doubleMultiplier()
{
m_multiplier = std::min(static_cast<uint16_t>(m_multiplier * 2), m_maxMultiplier);
}
RttEstimator::Duration
RttEstimator::computeRto() const
{
double rto = std::max(m_minRto, m_rtt + 4 * m_variance);
rto *= m_multiplier;
return Duration(static_cast<Duration::rep>(rto));
}
} // namespace nfd
-100
View File
@@ -1,100 +0,0 @@
/* -*- 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_SCHEDULER_HPP
#define NFD_CORE_SCHEDULER_HPP
#include "common.hpp"
#include <ndn-cxx/util/scheduler.hpp>
namespace nfd {
namespace scheduler {
using ndn::Scheduler;
/** \class nfd::scheduler::EventId
* \brief Opaque handle for a scheduled event.
*/
using ndn::EventId;
using ndn::util::scheduler::EventCallback;
/** \brief Schedule an event.
*/
EventId
schedule(time::nanoseconds after, const EventCallback& event);
/** \brief Cancel a scheduled event.
*/
void
cancel(const EventId& eventId);
/** \brief Cancels an event automatically upon destruction.
*/
class ScopedEventId : noncopyable
{
public:
ScopedEventId();
/** \brief Implicit constructor from EventId.
* \param event the event to be cancelled upon destruction
*/
ScopedEventId(const EventId& event);
/** \brief Move constructor.
*/
ScopedEventId(ScopedEventId&& other);
/** \brief Assigns an event.
*
* If a different event has been assigned to this instance previously,
* that event will be cancelled immediately.
*/
ScopedEventId&
operator=(const EventId& event);
/** \brief Cancels the event.
*/
~ScopedEventId();
/** \brief Cancels the event manually.
*/
void
cancel();
/** \brief Releases the event so that it won't be cancelled when this ScopedEventId is destructed.
*/
void
release();
private:
EventId m_event;
};
} // namespace scheduler
} // namespace nfd
#endif // NFD_CORE_SCHEDULER_HPP
@@ -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-2019, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -23,17 +23,7 @@
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*/
#include "readvertised-route.hpp"
#include "core/random.hpp"
#include "core/version.hpp"
namespace nfd {
namespace rib {
ReadvertisedRoute::ReadvertisedRoute(const Name& prefix)
: prefix(prefix)
, nRibRoutes(0)
{
}
} // namespace rib
} // namespace nfd
const char NFD_VERSION_STRING[] = "@VERSION_STRING@";
const char NFD_VERSION_BUILD_STRING[] = "@VERSION_BUILD@";
+35 -36
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-2019, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -26,49 +26,48 @@
#ifndef NFD_CORE_VERSION_HPP
#define NFD_CORE_VERSION_HPP
namespace nfd {
/** NFD version follows Semantic Versioning 2.0.0 specification
* http://semver.org/
*/
// NFD version follows Semantic Versioning 2.0.0
// https://semver.org/spec/v2.0.0.html
//
// To change version number, modify VERSION variable in top-level wscript.
/** \brief NFD version represented as an integer
/** \brief NFD version represented as an integer.
*
* MAJOR*1000000 + MINOR*1000 + PATCH
* Equivalent to: `#NFD_VERSION_MAJOR*1000000 + #NFD_VERSION_MINOR*1000 + #NFD_VERSION_PATCH`
*/
#define NFD_VERSION @VERSION@
/** \brief NFD version represented as a string
*
* MAJOR.MINOR.PATCH
*/
#define NFD_VERSION_STRING "@VERSION_STRING@"
/** \brief NFD version string, including git commit information, if NFD is build from
* specific git commit
*
* NFD_VERSION_BUILD_STRING is obtained using the following command (`NFD-` prefix is
* afterwards removed):
*
* `git describe --match 'NFD-*'`
*
* When NFD is built not from git, NFD_VERSION_BUILD_STRING equals NFD_VERSION_STRING
*
* MAJOR.MINOR.PATCH(-release-candidate-tag)(-(number-of-commits-since-tag)-COMMIT-HASH)
*
* Example, 0.1.0-rc1-1-g5c86570
*/
#define NFD_VERSION_BUILD_STRING "@VERSION_BUILD@"
/// MAJOR version
/// The major version of NFD
#define NFD_VERSION_MAJOR @VERSION_MAJOR@
/// MINOR version
/// The minor version of NFD
#define NFD_VERSION_MINOR @VERSION_MINOR@
/// PATCH version
/// The patch version of NFD
#define NFD_VERSION_PATCH @VERSION_PATCH@
} // namespace nfd
/** \brief NFD version represented as a string.
*
* Format:
* @code
* MAJOR.MINOR.PATCH
* @endcode
*/
extern const char NFD_VERSION_STRING[];
/** \brief NFD version string, including git commit information, if NFD is build from
* specific git commit.
*
* #NFD_VERSION_BUILD_STRING is obtained using the following command (`NFD-` prefix is
* afterwards removed): `git describe --match 'NFD-*'`
*
* When NFD is not built from git, #NFD_VERSION_BUILD_STRING equals #NFD_VERSION_STRING.
*
* Format:
* @code
* MAJOR.MINOR.PATCH(-release-candidate-tag)(-(number-of-commits-since-tag)-COMMIT-HASH)
* @endcode
*
* Example: 0.1.0-rc1-1-g5c86570
*/
extern const char NFD_VERSION_BUILD_STRING[];
#endif // NFD_CORE_VERSION_HPP
File renamed without changes.
File renamed without changes.
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2018, Regents of the University of California,
* Copyright (c) 2014-2019, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -23,9 +23,10 @@
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config-file.hpp"
#include "common/config-file.hpp"
#include <boost/property_tree/info_parser.hpp>
#include <fstream>
#include <sstream>
@@ -42,8 +43,8 @@ ConfigFile::throwErrorOnUnknownSection(const std::string& filename,
const ConfigSection& section,
bool isDryRun)
{
BOOST_THROW_EXCEPTION(Error("Error processing configuration file " + filename +
": no module subscribed for section \"" + sectionName + "\""));
NDN_THROW(Error("Error processing configuration file " + filename +
": no module subscribed for section '" + sectionName + "'"));
}
void
@@ -68,8 +69,8 @@ ConfigFile::parseYesNo(const ConfigSection& node, const std::string& key,
return false;
}
BOOST_THROW_EXCEPTION(Error("Invalid value \"" + value + "\" for option \"" +
key + "\" in \"" + sectionName + "\" section"));
NDN_THROW(Error("Invalid value '" + value + "' for option '" +
key + "' in section '" + sectionName + "'"));
}
void
@@ -84,7 +85,7 @@ ConfigFile::parse(const std::string& filename, bool isDryRun)
{
std::ifstream inputFile(filename);
if (!inputFile.good() || !inputFile.is_open()) {
BOOST_THROW_EXCEPTION(Error("Failed to read configuration file " + filename));
NDN_THROW(Error("Failed to read configuration file " + filename));
}
parse(inputFile, isDryRun, filename);
inputFile.close();
@@ -104,8 +105,8 @@ ConfigFile::parse(std::istream& input, bool isDryRun, const std::string& filenam
boost::property_tree::read_info(input, m_global);
}
catch (const boost::property_tree::info_parser_error& error) {
BOOST_THROW_EXCEPTION(Error("Failed to parse configuration file " + filename +
": " + error.message() + " on line " + to_string(error.line())));
NDN_THROW(Error("Failed to parse configuration file " + filename +
": " + error.message() + " on line " + to_string(error.line())));
}
process(isDryRun, filename);
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2018, Regents of the University of California,
* Copyright (c) 2014-2020, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -23,10 +23,10 @@
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef NFD_CORE_CONFIG_FILE_HPP
#define NFD_CORE_CONFIG_FILE_HPP
#ifndef NFD_DAEMON_COMMON_CONFIG_FILE_HPP
#define NFD_DAEMON_COMMON_CONFIG_FILE_HPP
#include "common.hpp"
#include "core/common.hpp"
#include <boost/property_tree/ptree.hpp>
@@ -60,11 +60,7 @@ public:
class Error : public std::runtime_error
{
public:
explicit
Error(const std::string& what)
: std::runtime_error(what)
{
}
using std::runtime_error::runtime_error;
};
explicit
@@ -112,11 +108,13 @@ public: // parse helpers
static_assert(std::is_arithmetic<T>::value, "T must be an arithmetic type");
boost::optional<T> value = node.get_value_optional<T>();
if (value) {
// Unsigned logic is workaround for https://redmine.named-data.net/issues/4489
if (value &&
(std::is_signed<T>() || node.get_value<std::string>().find("-") == std::string::npos)) {
return *value;
}
BOOST_THROW_EXCEPTION(Error("Invalid value \"" + node.get_value<std::string>() +
"\" for option \"" + key + "\" in \"" + sectionName + "\" section"));
NDN_THROW(Error("Invalid value '" + node.get_value<std::string>() +
"' for option '" + key + "' in section '" + sectionName + "'"));
}
template <typename T>
@@ -181,4 +179,4 @@ private:
} // namespace nfd
#endif // NFD_CORE_CONFIG_FILE_HPP
#endif // NFD_DAEMON_COMMON_CONFIG_FILE_HPP
+15 -31
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-2019, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -23,10 +23,10 @@
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef NFD_CORE_COUNTER_HPP
#define NFD_CORE_COUNTER_HPP
#ifndef NFD_DAEMON_COMMON_COUNTER_HPP
#define NFD_DAEMON_COMMON_COUNTER_HPP
#include "common.hpp"
#include "core/common.hpp"
namespace nfd {
@@ -35,25 +35,14 @@ namespace nfd {
* SimpleCounter is noncopyable, because increment should be called on the counter,
* not a copy of it; it's implicitly convertible to an integral type to be observed
*/
class SimpleCounter
class SimpleCounter : noncopyable
{
public:
typedef uint64_t rep;
constexpr
SimpleCounter()
: m_value(0)
{
}
SimpleCounter(const SimpleCounter&) = delete;
SimpleCounter&
operator=(const SimpleCounter&) = delete;
/** \brief observe the counter
*/
operator rep() const
operator rep() const noexcept
{
return m_value;
}
@@ -61,13 +50,13 @@ public:
/** \brief replace the counter value
*/
void
set(rep value)
set(rep value) noexcept
{
m_value = value;
}
protected:
rep m_value;
rep m_value = 0;
};
/** \brief represents a counter of number of packets
@@ -80,7 +69,7 @@ public:
/** \brief increment the counter by one
*/
PacketCounter&
operator++()
operator++() noexcept
{
++m_value;
return *this;
@@ -98,7 +87,7 @@ public:
/** \brief increase the counter
*/
ByteCounter&
operator+=(rep n)
operator+=(rep n) noexcept
{
m_value += n;
return *this;
@@ -111,24 +100,19 @@ public:
* if table not specified in constructor, it can be added later by invoking observe()
*/
template<typename T>
class SizeCounter
class SizeCounter : noncopyable
{
public:
typedef size_t Rep;
explicit constexpr
SizeCounter(const T* table = nullptr)
SizeCounter(const T* table = nullptr) noexcept
: m_table(table)
{
}
SizeCounter(const SizeCounter&) = delete;
SizeCounter&
operator=(const SizeCounter&) = delete;
void
observe(const T* table)
observe(const T* table) noexcept
{
m_table = table;
}
@@ -147,4 +131,4 @@ private:
} // namespace nfd
#endif // NFD_CORE_COUNTER_HPP
#endif // NFD_DAEMON_COMMON_COUNTER_HPP
+50 -57
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-2019, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -23,85 +23,78 @@
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*/
#include "scheduler.hpp"
#include "global-io.hpp"
#include <boost/thread/tss.hpp>
#include "common/global.hpp"
namespace nfd {
namespace scheduler {
static boost::thread_specific_ptr<Scheduler> g_scheduler;
static thread_local unique_ptr<boost::asio::io_service> g_ioService;
static thread_local unique_ptr<Scheduler> g_scheduler;
static boost::asio::io_service* g_mainIoService = nullptr;
static boost::asio::io_service* g_ribIoService = nullptr;
boost::asio::io_service&
getGlobalIoService()
{
if (g_ioService == nullptr) {
g_ioService = make_unique<boost::asio::io_service>();
}
return *g_ioService;
}
Scheduler&
getGlobalScheduler()
getScheduler()
{
if (g_scheduler.get() == nullptr) {
g_scheduler.reset(new Scheduler(getGlobalIoService()));
if (g_scheduler == nullptr) {
g_scheduler = make_unique<Scheduler>(getGlobalIoService());
}
return *g_scheduler;
}
EventId
schedule(time::nanoseconds after, const EventCallback& event)
{
return getGlobalScheduler().scheduleEvent(after, event);
}
#ifdef WITH_TESTS
void
cancel(const EventId& eventId)
{
getGlobalScheduler().cancelEvent(eventId);
}
void
resetGlobalScheduler()
resetGlobalIoService()
{
g_scheduler.reset();
g_ioService.reset();
}
#endif
boost::asio::io_service&
getMainIoService()
{
BOOST_ASSERT(g_mainIoService != nullptr);
return *g_mainIoService;
}
ScopedEventId::ScopedEventId()
boost::asio::io_service&
getRibIoService()
{
}
ScopedEventId::ScopedEventId(const EventId& event)
: m_event(event)
{
}
ScopedEventId::ScopedEventId(ScopedEventId&& other)
: m_event(other.m_event)
{
other.release();
}
ScopedEventId&
ScopedEventId::operator=(const EventId& event)
{
if (m_event != event) {
scheduler::cancel(m_event);
m_event = event;
}
return *this;
}
ScopedEventId::~ScopedEventId()
{
scheduler::cancel(m_event);
BOOST_ASSERT(g_ribIoService != nullptr);
return *g_ribIoService;
}
void
ScopedEventId::cancel()
setMainIoService(boost::asio::io_service* mainIo)
{
scheduler::cancel(m_event);
g_mainIoService = mainIo;
}
void
ScopedEventId::release()
setRibIoService(boost::asio::io_service* ribIo)
{
m_event.reset();
g_ribIoService = ribIo;
}
void
runOnMainIoService(const std::function<void()>& f)
{
getMainIoService().post(f);
}
void
runOnRibIoService(const std::function<void()>& f)
{
getRibIoService().post(f);
}
} // namespace scheduler
} // namespace nfd
+75
View File
@@ -0,0 +1,75 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2019 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.
*
* 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_DAEMON_COMMON_GLOBAL_HPP
#define NFD_DAEMON_COMMON_GLOBAL_HPP
#include "core/common.hpp"
namespace nfd {
/** \brief Returns the global io_service instance for the calling thread.
*/
boost::asio::io_service&
getGlobalIoService();
/** \brief Returns the global Scheduler instance for the calling thread.
*/
Scheduler&
getScheduler();
boost::asio::io_service&
getMainIoService();
boost::asio::io_service&
getRibIoService();
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);
#ifdef WITH_TESTS
/** \brief Destroy the global io_service instance.
*
* It will be recreated at the next invocation of getGlobalIoService().
*/
void
resetGlobalIoService();
#endif
} // namespace nfd
#endif // NFD_DAEMON_COMMON_GLOBAL_HPP
+16 -24
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-2019, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -23,30 +23,22 @@
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* \file
* \brief Declares the global pseudorandom number generator (PRNG) for NFD
*
* All random numbers generated by NFD should use this global generator,
* so that it can be properly seeded when necessary.
*
* \warning This PRNG is not suitable for security purposes; security-critical
* code must use a cryptographically secure PRNG, such as that provided
* by OpenSSL.
*/
#ifndef NFD_DAEMON_COMMON_LOGGER_HPP
#define NFD_DAEMON_COMMON_LOGGER_HPP
#ifndef NFD_CORE_RANDOM_HPP
#define NFD_CORE_RANDOM_HPP
#include <ndn-cxx/util/logger.hpp>
#include <random>
#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 {
#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
/** \return the global random number generator instance
*/
std::mt19937&
getGlobalRng();
} // namespace nfd
#endif // NFD_CORE_RANDOM_HPP
#endif // NFD_DAEMON_COMMON_LOGGER_HPP
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2018, Regents of the University of California,
* Copyright (c) 2014-2020, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -23,15 +23,15 @@
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*/
#include "privilege-helper.hpp"
#include "core/logger.hpp"
#include "common/privilege-helper.hpp"
#include "common/logger.hpp"
#include <pwd.h>
#include <grp.h>
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,27 +62,24 @@ PrivilegeHelper::initialize(const std::string& userName, const std::string& grou
if (groupSize == -1)
groupSize = FALLBACK_GROUP_BUFFER_SIZE;
std::vector<char> groupBuffer(groupSize);
struct group group;
struct group* groupResult = nullptr;
std::vector<char> groupBuffer(static_cast<size_t>(groupSize));
group gr;
group* grResult = nullptr;
int errorCode = getgrnam_r(groupName.data(), &group,
&groupBuffer[0], groupBuffer.size(), &groupResult);
int errorCode = getgrnam_r(groupName.data(), &gr, groupBuffer.data(), groupBuffer.size(), &grResult);
while (errorCode == ERANGE) {
if (groupBuffer.size() * 2 > MAX_GROUP_BUFFER_SIZE)
throw Error("Cannot allocate large enough buffer for struct group");
groupBuffer.resize(groupBuffer.size() * 2);
errorCode = getgrnam_r(groupName.data(), &group,
&groupBuffer[0], groupBuffer.size(), &groupResult);
errorCode = getgrnam_r(groupName.data(), &gr, groupBuffer.data(), groupBuffer.size(), &grResult);
}
if (errorCode != 0 || !groupResult)
if (errorCode != 0 || !grResult)
throw Error("Failed to get gid for \"" + groupName + "\"");
s_normalGid = group.gr_gid;
s_normalGid = gr.gr_gid;
}
if (!userName.empty()) {
@@ -91,27 +88,24 @@ PrivilegeHelper::initialize(const std::string& userName, const std::string& grou
if (passwdSize == -1)
passwdSize = FALLBACK_PASSWD_BUFFER_SIZE;
std::vector<char> passwdBuffer(passwdSize);
struct passwd passwd;
struct passwd* passwdResult = nullptr;
std::vector<char> passwdBuffer(static_cast<size_t>(passwdSize));
passwd pw;
passwd* pwResult = nullptr;
int errorCode = getpwnam_r(userName.data(), &passwd,
&passwdBuffer[0], passwdBuffer.size(), &passwdResult);
int errorCode = getpwnam_r(userName.data(), &pw, passwdBuffer.data(), passwdBuffer.size(), &pwResult);
while (errorCode == ERANGE) {
if (passwdBuffer.size() * 2 > MAX_PASSWD_BUFFER_SIZE)
throw Error("Cannot allocate large enough buffer for struct passwd");
passwdBuffer.resize(passwdBuffer.size() * 2);
errorCode = getpwnam_r(userName.data(), &passwd,
&passwdBuffer[0], passwdBuffer.size(), &passwdResult);
errorCode = getpwnam_r(userName.data(), &pw, passwdBuffer.data(), passwdBuffer.size(), &pwResult);
}
if (errorCode != 0 || !passwdResult)
if (errorCode != 0 || !pwResult)
throw Error("Failed to get uid for \"" + userName + "\"");
s_normalUid = passwd.pw_uid;
s_normalUid = pw.pw_uid;
}
#else
if (!userName.empty() || !groupName.empty()) {
@@ -124,6 +118,9 @@ void
PrivilegeHelper::drop()
{
#ifdef HAVE_PRIVILEGE_DROP_AND_ELEVATE
if (::geteuid() == s_normalUid && ::getegid() == s_normalGid)
return;
NFD_LOG_TRACE("dropping to effective gid=" << s_normalGid);
if (::setegid(s_normalGid) != 0)
throw Error("Failed to drop to effective gid=" + to_string(s_normalGid));
@@ -142,6 +139,9 @@ void
PrivilegeHelper::raise()
{
#ifdef HAVE_PRIVILEGE_DROP_AND_ELEVATE
if (::geteuid() == s_privilegedUid && ::getegid() == s_privilegedGid)
return;
NFD_LOG_TRACE("elevating to effective uid=" << s_privilegedUid);
if (::seteuid(s_privilegedUid) != 0)
throw Error("Failed to elevate to effective uid=" + to_string(s_privilegedUid));
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2018, Regents of the University of California,
* Copyright (c) 2014-2019, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -23,10 +23,10 @@
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef NFD_CORE_PRIVILEGE_HELPER_HPP
#define NFD_CORE_PRIVILEGE_HELPER_HPP
#ifndef NFD_DAEMON_COMMON_PRIVILEGE_HELPER_HPP
#define NFD_DAEMON_COMMON_PRIVILEGE_HELPER_HPP
#include "common.hpp"
#include "core/common.hpp"
#include <unistd.h>
@@ -38,7 +38,7 @@ public:
/** \brief represents a serious seteuid/gid failure
*
* This should only be caught by main as part of a graceful program termination.
* \note This is not an std::exception and BOOST_THROW_EXCEPTION should not be used.
* \note This is not an std::exception and NDN_THROW should not be used.
*/
class Error
{
@@ -96,4 +96,4 @@ PUBLIC_WITH_TESTS_ELSE_PRIVATE:
} // namespace nfd
#endif // NFD_CORE_PRIVILEGE_HELPER_HPP
#endif // NFD_DAEMON_COMMON_PRIVILEGE_HELPER_HPP
+62
View File
@@ -0,0 +1,62 @@
#include "TokenBucket.hpp"
#include "common/global.hpp"
#include "common/logger.hpp"
#include <iostream>
#include <functional>
namespace nfd {
namespace face {
NFD_LOG_INIT(QSCCPTokenBucket);
TokenBucket::TokenBucket(uint64_t rateLimit, uint64_t bucketSize, const std::string& name): rateLimit(rateLimit), bucketSize(bucketSize), name(name) {
this->eachStep = this->rateLimit / 250.0;
this->currentTokenSize = 0;
this->isStart = false;
// NFD_LOG_DEBUG("Create tokenBucket: " << name << ", eachStep: " << this->eachStep << ", rateLimit: " << this->rateLimit);
}
void TokenBucket::start() {
if (this->isStart) {
return;
}
// 每 4ms 增加一次令牌
getScheduler().schedule(time::milliseconds(4), std::bind(&TokenBucket::generateToken, this));
}
void TokenBucket::generateToken() {
// NFD_LOG_DEBUG(this->name << "=> do generateToken => " << this->currentTokenSize);
if (this->currentTokenSize + this->eachStep > this->bucketSize) {
this->currentTokenSize = this->bucketSize;
} else {
this->currentTokenSize += this->eachStep;
}
getScheduler().schedule(time::milliseconds(4), std::bind(&TokenBucket::generateToken, this));
}
void TokenBucket::generateTokenByCurrentTime(long currentTime) {
if (this->lastGenerateTokenTime == -1) {
this->lastGenerateTokenTime = currentTime;
return;
}
if (currentTime - this->lastGenerateTokenTime < 1) {
return;
}
long currentStep = (currentTime - this->lastGenerateTokenTime) * this->rateLimit / 1000.0;
// std::cout << "currentStep: " << currentStep << "currentTime: " << currentTime << "lastGenerateTokenTime: " << this->lastGenerateTokenTime << std::endl;
// NFD_LOG_DEBUG(this->name << "=> do generateToken => " << this->currentTokenSize);
this->lastGenerateTokenTime = currentTime;
if (this->currentTokenSize + currentStep > this->bucketSize) {
this->currentTokenSize = this->bucketSize;
} else {
this->currentTokenSize += currentStep;
}
}
bool TokenBucket::use(uint64_t tokenNum) {
if(this->currentTokenSize > tokenNum) {
this->currentTokenSize -= tokenNum;
// NFD_LOG_DEBUG(this->name << "=> use success => " << this->currentTokenSize);
return true;
} else {
// NFD_LOG_DEBUG(this->name << "=> use failed => " << this->currentTokenSize);
return false;
}
}
}
}
+41
View File
@@ -0,0 +1,41 @@
//
// Created by gdcni21 on 3/25/22.
//
#ifndef NS_TOKENBUCKET_H
#define NS_TOKENBUCKET_H
#include <memory>
#include <string>
namespace nfd {
namespace face {
class TokenBucket {
public:
explicit TokenBucket(uint64_t rateLimit, uint64_t bucketSize, const std::string& name);
void start();
/**
* 周期性增加token
**/
void generateToken();
/**
* 根据当前时间生成token
*/
void generateTokenByCurrentTime(long currentTime);
/**
* 尝试消费n个token
* @param tokenNum
* @return
*/
bool use(uint64_t tokenNum);
public:
double eachStep; // 每个周期增加的令牌
double currentTokenSize; // 当前令牌数
uint64_t rateLimit; // 令牌生成速率
uint64_t bucketSize; // 令牌桶容量
std::string name;
bool isStart; // 标识是否启动
long lastGenerateTokenTime = -1;
};
}
}
#endif //NS_TOKENBUCKET_H
+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-2019, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -26,7 +26,7 @@
#ifndef NFD_DAEMON_FACE_CHANNEL_LOG_HPP
#define NFD_DAEMON_FACE_CHANNEL_LOG_HPP
#include "core/logger.hpp"
#include "common/logger.hpp"
/** \defgroup ChannelLogging Channel logging macros
*
+9 -9
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-2019, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -24,6 +24,7 @@
*/
#include "channel.hpp"
#include "face.hpp"
namespace nfd {
namespace face {
@@ -37,14 +38,13 @@ Channel::setUri(const FaceUri& uri)
}
void
connectFaceClosedSignal(Face& face, const std::function<void()>& f)
connectFaceClosedSignal(Face& face, std::function<void()> f)
{
face.afterStateChange.connect(
[f] (FaceState oldState, FaceState newState) {
if (newState == FaceState::CLOSED) {
f();
}
});
face.afterStateChange.connect([f = std::move(f)] (auto, FaceState newState) {
if (newState == FaceState::CLOSED) {
f();
}
});
}
} // namespace face
+13 -41
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2018, Regents of the University of California,
* Copyright (c) 2014-2020, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -27,29 +27,18 @@
#define NFD_DAEMON_FACE_CHANNEL_HPP
#include "channel-log.hpp"
#include "face.hpp"
#include <boost/logic/tribool.hpp>
#include "face-common.hpp"
namespace nfd {
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 = 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 = std::function<void(uint32_t status, const std::string& reason)>;
/** \brief represent a channel that communicates on a local endpoint
/** \brief Represents a channel that listens on a local endpoint.
* \sa FaceSystem
*
* A channel can listen on a local endpoint and initiate outgoing connection from a local endpoint.
* A channel creates Face objects and retains shared ownership of them.
*/
class Channel : noncopyable
class Channel : public std::enable_shared_from_this<Channel>, noncopyable
{
public:
virtual
@@ -79,41 +68,24 @@ private:
FaceUri m_uri;
};
/** \brief Parameters used to set Transport properties or LinkService options on a newly created face
*
* 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.
/** \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).
*/
class 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)
{
}
using FaceCreatedCallback = std::function<void(const shared_ptr<Face>&)>;
public:
ndn::nfd::FacePersistency persistency;
optional<time::nanoseconds> baseCongestionMarkingInterval;
optional<uint64_t> defaultCongestionThreshold;
bool wantLocalFields;
bool wantLpReliability;
boost::logic::tribool wantCongestionMarking;
};
/** \brief Prototype for the callback that is invoked when a face fails to be created.
*/
using FaceCreationFailedCallback = std::function<void(uint32_t status, const std::string& reason)>;
/** \brief invokes a callback when the face is closed
/** \brief Invokes a callback when a face is closed.
* \param face the face
* \param f the callback to be invoked when the face enters CLOSED state
*
* This function connects a callback to the afterStateChange signal on the \p face,
* This function connects a callback to the afterStateChange signal of \p face,
* and invokes \p f when the state becomes CLOSED.
*/
void
connectFaceClosedSignal(Face& face, const std::function<void()>& f);
connectFaceClosedSignal(Face& face, std::function<void()> f);
} // namespace face
} // namespace nfd
+23 -30
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2018, Regents of the University of California,
* Copyright (c) 2014-2020, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -28,7 +28,7 @@
#include "transport.hpp"
#include "socket-utils.hpp"
#include "core/global-io.hpp"
#include "common/global.hpp"
#include <array>
@@ -69,15 +69,13 @@ protected:
doClose() override;
void
doSend(Transport::Packet&& packet) override;
doSend(const Block& 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>
@@ -159,15 +157,15 @@ DatagramTransport<T, U>::doClose()
template<class T, class U>
void
DatagramTransport<T, U>::doSend(Transport::Packet&& packet)
DatagramTransport<T, U>::doSend(const Block& 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));
m_socket.async_send(boost::asio::buffer(packet),
// 'packet' is copied into the lambda to retain the underlying Buffer
[this, packet] (auto&&... args) {
this->handleSend(std::forward<decltype(args)>(args)...);
});
}
template<class T, class U>
@@ -195,30 +193,25 @@ DatagramTransport<T, U>::receiveDatagram(const uint8_t* buffer, size_t nBytesRec
}
m_hasRecentlyReceived = true;
Transport::Packet tp(std::move(element));
tp.remoteEndpoint = makeEndpointId(m_sender);
this->receive(std::move(tp));
this->receive(element, makeEndpointId(m_sender));
}
template<class T, class U>
void
DatagramTransport<T, U>::handleReceive(const boost::system::error_code& error,
size_t nBytesReceived)
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);
@@ -265,8 +258,8 @@ DatagramTransport<T, U>::resetRecentlyReceived()
}
template<class T, class U>
Transport::EndpointId
DatagramTransport<T, U>::makeEndpointId(const typename protocol::endpoint& ep)
EndpointId
DatagramTransport<T, U>::makeEndpointId(const typename protocol::endpoint&)
{
return 0;
}
+15 -9
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2018, Regents of the University of California,
* Copyright (c) 2014-2020, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -25,9 +25,10 @@
#include "ethernet-channel.hpp"
#include "ethernet-protocol.hpp"
#include "face.hpp"
#include "generic-link-service.hpp"
#include "unicast-ethernet-transport.hpp"
#include "core/global-io.hpp"
#include "common/global.hpp"
#include <boost/range/adaptor/map.hpp>
#include <pcap/pcap.h>
@@ -35,7 +36,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 +66,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;
}
@@ -89,7 +90,7 @@ EthernetChannel::listen(const FaceCreatedCallback& onFaceCreated,
m_socket.assign(m_pcap.getFd());
}
catch (const PcapHelper::Error& e) {
BOOST_THROW_EXCEPTION(Error(e.what()));
NDN_THROW_NESTED(Error(e.what()));
}
updateFilter();
@@ -102,9 +103,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 +171,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;
}
@@ -202,11 +201,18 @@ EthernetChannel::createFace(const ethernet::Address& remoteEndpoint,
options.allowFragmentation = true;
options.allowReassembly = true;
options.reliabilityOptions.isEnabled = params.wantLpReliability;
if (params.mtu) {
options.overrideMtu = *params.mtu;
}
if (params.bandwidth) {
options.C = *params.bandwidth;
}
auto linkService = make_unique<GenericLinkService>(options);
auto transport = make_unique<UnicastEthernetTransport>(*m_localEndpoint, remoteEndpoint,
params.persistency, m_idleFaceTimeout);
auto face = make_shared<Face>(std::move(linkService), std::move(transport));
face->setChannel(shared_from_this()); // use weak_from_this() in C++17
m_channelFaces[remoteEndpoint] = face;
connectFaceClosedSignal(*face, [this, remoteEndpoint] {
+29 -24
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2018, Regents of the University of California,
* Copyright (c) 2014-2020, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -33,11 +33,11 @@
namespace nfd {
namespace face {
NFD_LOG_INIT("EthernetFactory");
NFD_LOG_INIT(EthernetFactory);
NFD_REGISTER_PROTOCOL_FACTORY(EthernetFactory);
const std::string&
EthernetFactory::getId()
EthernetFactory::getId() noexcept
{
static std::string id("ether");
return id;
@@ -46,16 +46,15 @@ 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
EthernetFactory::processConfig(OptionalConfigSection configSection,
FaceSystem::ConfigContext& context)
EthernetFactory::doProcessConfig(OptionalConfigSection configSection,
FaceSystem::ConfigContext& context)
{
// ether
// {
@@ -97,12 +96,12 @@ EthernetFactory::processConfig(OptionalConfigSection configSection,
const std::string& valueStr = value.get_value<std::string>();
mcastConfig.group = ethernet::Address::fromString(valueStr);
if (mcastConfig.group.isNull()) {
BOOST_THROW_EXCEPTION(ConfigFile::Error("face_system.ether.mcast_group: '" +
valueStr + "' cannot be parsed as an Ethernet address"));
NDN_THROW(ConfigFile::Error("face_system.ether.mcast_group: '" +
valueStr + "' cannot be parsed as an Ethernet address"));
}
else if (!mcastConfig.group.isMulticast()) {
BOOST_THROW_EXCEPTION(ConfigFile::Error("face_system.ether.mcast_group: '" +
valueStr + "' is not a multicast address"));
NDN_THROW(ConfigFile::Error("face_system.ether.mcast_group: '" +
valueStr + "' is not a multicast address"));
}
}
else if (key == "mcast_ad_hoc") {
@@ -116,7 +115,7 @@ EthernetFactory::processConfig(OptionalConfigSection configSection,
mcastConfig.netifPredicate.parseBlacklist(value);
}
else {
BOOST_THROW_EXCEPTION(ConfigFile::Error("Unrecognized option face_system.ether." + key));
NDN_THROW(ConfigFile::Error("Unrecognized option face_system.ether." + key));
}
}
}
@@ -166,18 +165,15 @@ EthernetFactory::processConfig(OptionalConfigSection configSection,
}
void
EthernetFactory::createFace(const CreateFaceRequest& req,
const FaceCreatedCallback& onCreated,
const FaceCreationFailedCallback& onFailure)
EthernetFactory::doCreateFace(const CreateFaceRequest& req,
const FaceCreatedCallback& onCreated,
const FaceCreationFailedCallback& onFailure)
{
BOOST_ASSERT(req.remoteUri.isCanonical());
if (!req.localUri || req.localUri->getScheme() != "dev") {
NFD_LOG_TRACE("Cannot create unicast Ethernet face without dev:// LocalUri");
onFailure(406, "Creation of unicast Ethernet faces requires a LocalUri with dev:// scheme");
return;
}
BOOST_ASSERT(req.localUri->isCanonical());
if (req.params.persistency == ndn::nfd::FACE_PERSISTENCY_ON_DEMAND) {
NFD_LOG_TRACE("createFace does not support FACE_PERSISTENCY_ON_DEMAND");
@@ -201,6 +197,13 @@ EthernetFactory::createFace(const CreateFaceRequest& req,
return;
}
if (req.params.mtu && *req.params.mtu < MIN_MTU) {
// The specified MTU must be greater than the minimum possible
NFD_LOG_TRACE("createFace: override MTU cannot be less than " << MIN_MTU);
onFailure(406, "Override MTU cannot be less than " + to_string(MIN_MTU));
return;
}
for (const auto& i : m_channels) {
if (i.first == localEndpoint) {
i.second->connect(remoteEndpoint, req.params, onCreated, onFailure);
@@ -222,12 +225,11 @@ EthernetFactory::createChannel(const shared_ptr<const ndn::net::NetworkInterface
auto channel = std::make_shared<EthernetChannel>(localEndpoint, idleTimeout);
m_channels[localEndpoint->getName()] = channel;
return channel;
}
std::vector<shared_ptr<const Channel>>
EthernetFactory::getChannels() const
EthernetFactory::doGetChannels() const
{
return getChannelsFromMap(m_channels);
}
@@ -255,6 +257,9 @@ EthernetFactory::createMulticastFace(const ndn::net::NetworkInterface& netif,
m_mcastFaces[key] = face;
connectFaceClosedSignal(*face, [this, key] { m_mcastFaces.erase(key); });
auto channelIt = m_channels.find(netif.getName());
face->setChannel(channelIt != m_channels.end() ? channelIt->second : nullptr);
return face;
}
@@ -342,7 +347,7 @@ EthernetFactory::applyMcastConfigToNetif(const ndn::net::NetworkInterface& netif
}
void
EthernetFactory::applyConfig(const FaceSystem::ConfigContext& context)
EthernetFactory::applyConfig(const FaceSystem::ConfigContext&)
{
if (m_unicastConfig.isEnabled) {
providedSchemes.insert("ether");
+16 -16
View File
@@ -32,28 +32,17 @@
namespace nfd {
namespace face {
/** \brief protocol factory for Ethernet
/** \brief Protocol factory for Ethernet
*/
class EthernetFactory : public ProtocolFactory
{
public:
static const std::string&
getId();
getId() noexcept;
explicit
EthernetFactory(const CtorParams& params);
/** \brief process face_system.ether config section
*/
void
processConfig(OptionalConfigSection configSection,
FaceSystem::ConfigContext& context) override;
void
createFace(const CreateFaceRequest& req,
const FaceCreatedCallback& onCreated,
const FaceCreationFailedCallback& onFailure) override;
/**
* \brief Create Ethernet-based channel on the specified network interface
*
@@ -68,9 +57,6 @@ public:
createChannel(const shared_ptr<const ndn::net::NetworkInterface>& localEndpoint,
time::nanoseconds idleTimeout);
std::vector<shared_ptr<const Channel>>
getChannels() const override;
/**
* \brief Create a face to communicate on the given Ethernet multicast group
*
@@ -87,6 +73,20 @@ public:
const ethernet::Address& group);
private:
/** \brief process face_system.ether config section
*/
void
doProcessConfig(OptionalConfigSection configSection,
FaceSystem::ConfigContext& context) override;
void
doCreateFace(const CreateFaceRequest& req,
const FaceCreatedCallback& onCreated,
const FaceCreationFailedCallback& onFailure) override;
std::vector<shared_ptr<const Channel>>
doGetChannels() const override;
/** \brief Create EthernetChannel on \p netif if requested by \p m_unicastConfig.
* \return new or existing channel, or nullptr if no channel should be created
*/
+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);
+43 -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-2020, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -25,17 +25,18 @@
#include "ethernet-transport.hpp"
#include "ethernet-protocol.hpp"
#include "core/global-io.hpp"
#include "common/global.hpp"
#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)
@@ -54,9 +55,22 @@ EthernetTransport::EthernetTransport(const ndn::net::NetworkInterface& localEndp
m_socket.assign(m_pcap.getFd());
}
catch (const PcapHelper::Error& e) {
BOOST_THROW_EXCEPTION(Error(e.what()));
NDN_THROW_NESTED(Error(e.what()));
}
// Set initial transport state based upon the state of the underlying NetworkInterface
handleNetifStateChange(localEndpoint.getState());
m_netifStateChangedConn = localEndpoint.onStateChanged.connect(
[this] (ndn::net::InterfaceState, ndn::net::InterfaceState newState) {
handleNetifStateChange(newState);
});
m_netifMtuChangedConn = localEndpoint.onMtuChanged.connect(
[this] (uint32_t, uint32_t mtu) {
setMtu(mtu);
});
asyncRead();
}
@@ -82,11 +96,25 @@ EthernetTransport::doClose()
}
void
EthernetTransport::doSend(Transport::Packet&& packet)
EthernetTransport::handleNetifStateChange(ndn::net::InterfaceState netifState)
{
NFD_LOG_FACE_TRACE("netif is " << netifState);
if (netifState == ndn::net::InterfaceState::RUNNING) {
if (getState() == TransportState::DOWN) {
this->setState(TransportState::UP);
}
}
else if (getState() == TransportState::UP) {
this->setState(TransportState::DOWN);
}
}
void
EthernetTransport::doSend(const Block& packet)
{
NFD_LOG_FACE_TRACE(__func__);
sendPacket(packet.packet);
sendPacket(packet);
}
void
@@ -101,7 +129,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 +150,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
@@ -190,13 +217,13 @@ EthernetTransport::receivePayload(const uint8_t* payload, size_t length,
}
m_hasRecentlyReceived = true;
Transport::Packet tp(std::move(element));
static_assert(sizeof(tp.remoteEndpoint) >= ethernet::ADDR_LEN,
"Transport::Packet::remoteEndpoint is too small");
static_assert(sizeof(EndpointId) >= ethernet::ADDR_LEN, "EndpointId is too small");
EndpointId endpoint = 0;
if (m_destAddress.isMulticast()) {
std::memcpy(&tp.remoteEndpoint, sender.data(), sender.size());
std::memcpy(&endpoint, sender.data(), sender.size());
}
this->receive(std::move(tp));
this->receive(element, endpoint);
}
void
+9 -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-2020, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -29,6 +29,7 @@
#include "ethernet-protocol.hpp"
#include "pcap-helper.hpp"
#include "transport.hpp"
#include <ndn-cxx/net/network-interface.hpp>
namespace nfd {
@@ -43,11 +44,7 @@ public:
class Error : public std::runtime_error
{
public:
explicit
Error(const std::string& what)
: std::runtime_error(what)
{
}
using std::runtime_error::runtime_error;
};
/**
@@ -81,7 +78,10 @@ protected:
private:
void
doSend(Transport::Packet&& packet) final;
handleNetifStateChange(ndn::net::InterfaceState netifState);
void
doSend(const Block& packet) final;
/**
* @brief Sends the specified TLV block on the network wrapped in an Ethernet frame
@@ -106,6 +106,8 @@ protected:
std::string m_interfaceName;
private:
signal::ScopedConnection m_netifStateChangedConn;
signal::ScopedConnection m_netifMtuChangedConn;
bool m_hasRecentlyReceived;
#ifdef _DEBUG
/// number of frames dropped by the kernel, as reported by libpcap
@@ -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-2020, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -23,28 +23,84 @@
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef NFD_DAEMON_FACE_FACE_LOG_HPP
#define NFD_DAEMON_FACE_FACE_LOG_HPP
#ifndef NFD_DAEMON_FACE_FACE_COMMON_HPP
#define NFD_DAEMON_FACE_FACE_COMMON_HPP
#include "core/logger.hpp"
#include "core/common.hpp"
#include "common/logger.hpp"
#include <ndn-cxx/encoding/nfd-constants.hpp>
#include <boost/logic/tribool.hpp>
namespace nfd {
namespace face {
/** \brief for internal use by FaceLogging macros
class Face;
class LinkService;
/** \brief Identifies a face.
*/
using FaceId = uint64_t;
/// indicates an invalid FaceId
const FaceId INVALID_FACEID = ndn::nfd::INVALID_FACE_ID;
/// identifies the InternalFace used in management
const FaceId FACEID_INTERNAL_FACE = 1;
/// identifies a packet comes from the ContentStore
const FaceId FACEID_CONTENT_STORE = 254;
/// identifies the NullFace that drops every packet
const FaceId FACEID_NULL = 255;
/// upper bound of reserved FaceIds
const FaceId FACEID_RESERVED_MAX = 255;
/** \brief Minimum MTU that may be set
*
* FaceLogHelper wraps a Face, LinkService, or Transport object.
* This is done to ensure the NDNLPv2 fragmentation feature functions properly.
*/
const ssize_t MIN_MTU = 64;
/** \brief Identifies a remote endpoint on the link.
*
* std::ostream& operator<<(std::ostream& os, const FaceLogHelper<T>& flh)
* This ID is only meaningful in the context of the same Transport.
* Incoming packets from the same remote endpoint have the same EndpointId,
* and incoming packets from different remote endpoints have different EndpointIds.
*
* Typically, a point-to-point Transport has only one meaningful EndpointId (usually 0).
*/
using EndpointId = uint64_t;
/** \brief Parameters used to set Transport properties or LinkService options on a newly created face.
*
* 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.
*/
struct FaceParams
{
ndn::nfd::FacePersistency persistency = ndn::nfd::FACE_PERSISTENCY_PERSISTENT;
optional<time::nanoseconds> baseCongestionMarkingInterval;
optional<uint64_t> defaultCongestionThreshold;
optional<ssize_t> mtu;
optional<uint64_t> bandwidth;
bool wantLocalFields = false;
bool wantLpReliability = false;
boost::logic::tribool wantCongestionMarking = boost::logic::indeterminate;
};
/** \brief For internal use by FaceLogging macros.
*
* FaceLogHelper wraps a reference to Face, LinkService, or Transport object.
*
* `std::ostream& operator<<(std::ostream& os, const FaceLogHelper<T>& flh)`
* should be specialized to print "[id=888,local=scheme://local/uri,remote=scheme://remote/uri] "
* which appears as part of the log message.
* which will appear as part of the log message.
*/
template<typename T>
class FaceLogHelper
{
public:
explicit
FaceLogHelper(const T& obj1)
FaceLogHelper(const T& obj1) noexcept
: obj(obj1)
{
}
@@ -54,6 +110,10 @@ public:
};
} // namespace face
using face::EndpointId;
using face::FaceId;
} // namespace nfd
/** \defgroup FaceLogging Face logging macros
@@ -66,6 +126,7 @@ public:
*/
/** \cond */
// implementation detail
#define NFD_LOG_FACE(level, msg) NFD_LOG_##level( \
::nfd::face::FaceLogHelper< \
typename std::remove_cv< \
@@ -92,4 +153,4 @@ public:
/** @} */
#endif // NFD_DAEMON_FACE_FACE_LOG_HPP
#endif // NFD_DAEMON_FACE_FACE_COMMON_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-2020, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -32,7 +32,7 @@ FaceCounters::FaceCounters(const LinkService::Counters& linkServiceCounters,
const Transport::Counters& transportCounters)
: nInInterests(linkServiceCounters.nInInterests)
, nOutInterests(linkServiceCounters.nOutInterests)
, nDroppedInterests(linkServiceCounters.nDroppedInterests)
, nInterestsExceededRetx(linkServiceCounters.nInterestsExceededRetx)
, nInData(linkServiceCounters.nInData)
, nOutData(linkServiceCounters.nOutData)
, nInNacks(linkServiceCounters.nInNacks)
+10 -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-2020, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -70,7 +70,7 @@ public:
public:
const PacketCounter& nInInterests;
const PacketCounter& nOutInterests;
const PacketCounter& nDroppedInterests;
const PacketCounter& nInterestsExceededRetx;
const PacketCounter& nInData;
const PacketCounter& nOutData;
const PacketCounter& nInNacks;
@@ -81,6 +81,14 @@ public:
const ByteCounter& nInBytes;
const ByteCounter& nOutBytes;
/** \brief count of incoming Interests dropped due to HopLimit == 0
*/
PacketCounter nInHopLimitZero;
/** \brief count of outgoing Interests dropped due to HopLimit == 0 on non-local faces
*/
PacketCounter nOutHopLimitZero;
private:
const LinkService::Counters& m_linkServiceCounters;
const Transport::Counters& m_transportCounters;
@@ -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-2019, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -23,28 +23,36 @@
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef NFD_DAEMON_FW_CLIENT_CONTROL_STRATEGY_HPP
#define NFD_DAEMON_FW_CLIENT_CONTROL_STRATEGY_HPP
#ifndef NFD_DAEMON_FACE_FACE_ENDPOINT_HPP
#define NFD_DAEMON_FACE_FACE_ENDPOINT_HPP
#include "best-route-strategy.hpp"
#include "face.hpp"
namespace nfd {
namespace fw {
/** \brief identical to BestRouteStrategy v1, for backwards compatibility
* \deprecated NextHopFaceId field is honored universally and it's unnecessary to set this strategy
/** \brief Represents a face-endpoint pair in the forwarder.
* \sa face::Face, face::EndpointId
*/
class ClientControlStrategy : public BestRouteStrategyBase
class FaceEndpoint
{
public:
explicit
ClientControlStrategy(Forwarder& forwarder, const Name& name = getStrategyName());
FaceEndpoint(const Face& face, EndpointId endpoint)
: face(const_cast<Face&>(face))
, endpoint(endpoint)
{
}
static const Name&
getStrategyName();
public:
Face& face;
const EndpointId endpoint;
};
} // namespace fw
inline std::ostream&
operator<<(std::ostream& os, const FaceEndpoint& fe)
{
return os << '(' << fe.face.getId() << ',' << fe.endpoint << ')';
}
} // namespace nfd
#endif // NFD_DAEMON_FW_CLIENT_CONTROL_STRATEGY_HPP
#endif // NFD_DAEMON_FACE_FACE_ENDPOINT_HPP
+35 -18
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2018, Regents of the University of California,
* Copyright (c) 2014-2019, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -25,29 +25,37 @@
#include "face-system.hpp"
#include "protocol-factory.hpp"
#include "core/global-io.hpp"
#include "netdev-bound.hpp"
#include "common/global.hpp"
#include "fw/face-table.hpp"
namespace nfd {
namespace face {
NFD_LOG_INIT("FaceSystem");
NFD_LOG_INIT(FaceSystem);
const std::string CFGSEC_FACESYSTEM = "face_system";
const std::string CFGSEC_GENERAL = "general";
const std::string CFGSEC_GENERAL_FQ = CFGSEC_FACESYSTEM + ".general";
const std::string CFGSEC_NETDEVBOUND = "netdev_bound";
FaceSystem::FaceSystem(FaceTable& faceTable, shared_ptr<ndn::net::NetworkMonitor> netmon)
: m_faceTable(faceTable)
, m_netmon(std::move(netmon))
{
auto pfCtorParams = this->makePFCtorParams();
for (const std::string& id : ProtocolFactory::listRegistered()) {
for (const auto& id : ProtocolFactory::listRegistered()) {
NFD_LOG_TRACE("creating factory " << id);
m_factories[id] = ProtocolFactory::create(id, pfCtorParams);
}
m_netdevBound = make_unique<NetdevBound>(pfCtorParams, *this);
}
ProtocolFactoryCtorParams
FaceSystem::makePFCtorParams()
{
auto addFace = bind(&FaceTable::add, &m_faceTable, _1);
auto addFace = [this] (auto face) { m_faceTable.add(std::move(face)); };
return {addFace, m_netmon};
}
@@ -77,33 +85,39 @@ FaceSystem::getFactoryByScheme(const std::string& scheme)
return found == m_factoryByScheme.end() ? nullptr : found->second;
}
void
FaceSystem::setConfigFile(ConfigFile& configFile)
bool
FaceSystem::hasFactoryForScheme(const std::string& scheme) const
{
configFile.addSectionHandler("face_system", bind(&FaceSystem::processConfig, this, _1, _2, _3));
return m_factoryByScheme.count(scheme) > 0;
}
void
FaceSystem::processConfig(const ConfigSection& configSection, bool isDryRun, const std::string& filename)
FaceSystem::setConfigFile(ConfigFile& configFile)
{
configFile.addSectionHandler(CFGSEC_FACESYSTEM, bind(&FaceSystem::processConfig, this, _1, _2, _3));
}
void
FaceSystem::processConfig(const ConfigSection& configSection, bool isDryRun, const std::string&)
{
ConfigContext context;
context.isDryRun = isDryRun;
// process general protocol factory config section
auto generalSection = configSection.get_child_optional("general");
auto generalSection = configSection.get_child_optional(CFGSEC_GENERAL);
if (generalSection) {
for (const auto& pair : *generalSection) {
const std::string& key = pair.first;
if (key == "enable_congestion_marking") {
context.generalConfig.wantCongestionMarking = ConfigFile::parseYesNo(pair, "face_system.general");
context.generalConfig.wantCongestionMarking = ConfigFile::parseYesNo(pair, CFGSEC_GENERAL_FQ);
}
else {
BOOST_THROW_EXCEPTION(ConfigFile::Error("Unrecognized option face_system.general." + key));
NDN_THROW(ConfigFile::Error("Unrecognized option " + CFGSEC_GENERAL_FQ + "." + key));
}
}
}
// process sections in protocol factories
// process in protocol factories
for (const auto& pair : m_factories) {
const std::string& sectionName = pair.first;
ProtocolFactory* factory = pair.second.get();
@@ -127,6 +141,10 @@ FaceSystem::processConfig(const ConfigSection& configSection, bool isDryRun, con
}
}
// process netdev_bound section, after factories start providing *+dev schemes
auto netdevBoundSection = configSection.get_child_optional(CFGSEC_NETDEVBOUND);
m_netdevBound->processConfig(netdevBoundSection, context);
// process other sections
std::set<std::string> seenSections;
for (const auto& pair : configSection) {
@@ -134,16 +152,15 @@ FaceSystem::processConfig(const ConfigSection& configSection, bool isDryRun, con
// const ConfigSection& subSection = pair.second;
if (!seenSections.insert(sectionName).second) {
BOOST_THROW_EXCEPTION(ConfigFile::Error("Duplicate section face_system." + sectionName));
NDN_THROW(ConfigFile::Error("Duplicate section " + CFGSEC_FACESYSTEM + "." + sectionName));
}
if (sectionName == "general" || m_factories.count(sectionName) > 0) {
if (sectionName == CFGSEC_GENERAL || sectionName == CFGSEC_NETDEVBOUND ||
m_factories.count(sectionName) > 0) {
continue;
}
///\todo #3521 nicfaces
BOOST_THROW_EXCEPTION(ConfigFile::Error("Unrecognized option face_system." + sectionName));
NDN_THROW(ConfigFile::Error("Unrecognized option " + CFGSEC_FACESYSTEM + "." + sectionName));
}
}
+9 -5
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2018, Regents of the University of California,
* Copyright (c) 2014-2019, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -26,9 +26,9 @@
#ifndef NFD_DAEMON_FACE_FACE_SYSTEM_HPP
#define NFD_DAEMON_FACE_FACE_SYSTEM_HPP
#include "channel.hpp"
#include "core/config-file.hpp"
#include "core/network-predicate.hpp"
#include "network-predicate.hpp"
#include "common/config-file.hpp"
#include <ndn-cxx/net/network-address.hpp>
#include <ndn-cxx/net/network-interface.hpp>
#include <ndn-cxx/net/network-monitor.hpp>
@@ -39,6 +39,7 @@ class FaceTable;
namespace face {
class NetdevBound;
class ProtocolFactory;
struct ProtocolFactoryCtorParams;
@@ -69,6 +70,9 @@ public:
ProtocolFactory*
getFactoryByScheme(const std::string& scheme);
bool
hasFactoryForScheme(const std::string& scheme) const;
FaceTable&
getFaceTable()
{
@@ -109,6 +113,7 @@ PUBLIC_WITH_TESTS_ELSE_PRIVATE:
/** \brief config section name => protocol factory
*/
std::map<std::string, unique_ptr<ProtocolFactory>> m_factories;
unique_ptr<NetdevBound> m_netdevBound;
private:
/** \brief scheme => protocol factory
@@ -118,7 +123,6 @@ private:
std::map<std::string, ProtocolFactory*> m_factoryByScheme;
FaceTable& m_faceTable;
shared_ptr<ndn::net::NetworkMonitor> m_netmon;
};
+61 -49
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-2020, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -26,28 +26,15 @@
#ifndef NFD_DAEMON_FACE_FACE_HPP
#define NFD_DAEMON_FACE_FACE_HPP
#include "face-common.hpp"
#include "face-counters.hpp"
#include "face-log.hpp"
#include "link-service.hpp"
#include "transport.hpp"
namespace nfd {
namespace face {
/** \brief identifies a face
*/
typedef uint64_t FaceId;
/// indicates an invalid FaceId
const FaceId INVALID_FACEID = 0;
/// identifies the InternalFace used in management
const FaceId FACEID_INTERNAL_FACE = 1;
/// identifies a packet comes from the ContentStore
const FaceId FACEID_CONTENT_STORE = 254;
/// identifies the NullFace that drops every packet
const FaceId FACEID_NULL = 255;
/// upper bound of reserved FaceIds
const FaceId FACEID_RESERVED_MAX = 255;
class Channel;
/** \brief indicates the state of a face
*/
@@ -64,11 +51,7 @@ typedef TransportState FaceState;
* LinkService is the upper part, which translates between network-layer packets
* and TLV blocks, and may provide additional services such as fragmentation and reassembly.
*/
class Face
#ifndef WITH_TESTS
final
#endif
: public enable_shared_from_this<Face>, noncopyable
class Face FINAL_UNLESS_WITH_TESTS : public std::enable_shared_from_this<Face>, noncopyable
{
public:
Face(unique_ptr<LinkService> service, unique_ptr<Transport> transport);
@@ -79,39 +62,51 @@ public:
Transport*
getTransport() const;
/** \brief Request that the face be closed
*
* This operation is effective only if face is in the UP or DOWN state; otherwise, it has no effect.
* The face will change state to CLOSING, and then perform a cleanup procedure.
* When the cleanup is complete, the state will be changed to CLOSED, which may happen
* synchronously or asynchronously.
*
* \warning The face must not be deallocated until its state changes to CLOSED.
*/
void
close();
public: // upper interface connected to forwarding
/** \brief sends Interest on Face
/** \brief send Interest
*/
void
sendInterest(const Interest& interest);
/** \brief sends Data on Face
/** \brief send Data
*/
void
sendData(const Data& data);
/** \brief sends Nack on Face
/** \brief send Nack
*/
void
sendNack(const lp::Nack& nack);
/** \brief signals on Interest received
*/
signal::Signal<LinkService, Interest>& afterReceiveInterest;
signal::Signal<LinkService, Interest, EndpointId>& afterReceiveInterest;
/** \brief signals on Data received
*/
signal::Signal<LinkService, Data>& afterReceiveData;
signal::Signal<LinkService, Data, EndpointId>& afterReceiveData;
/** \brief signals on Nack received
*/
signal::Signal<LinkService, lp::Nack>& afterReceiveNack;
signal::Signal<LinkService, lp::Nack, EndpointId>& afterReceiveNack;
/** \brief signals on Interest dropped by reliability system for exceeding allowed number of retx
*/
signal::Signal<LinkService, Interest>& onDroppedInterest;
public: // static properties
public: // properties
/** \return face ID
*/
FaceId
@@ -153,7 +148,13 @@ public: // static properties
ndn::nfd::LinkType
getLinkType() const;
public: // dynamic properties
/** \brief Returns face effective MTU
*
* This function is a wrapper. The effective MTU of a face is determined by the link service.
*/
ssize_t
getMtu() const;
/** \return face state
*/
FaceState
@@ -169,27 +170,33 @@ public: // dynamic properties
time::steady_clock::TimePoint
getExpirationTime() const;
/** \brief request the face to be closed
*
* This operation is effective only if face is in UP or DOWN state,
* otherwise it has no effect.
* The face changes state to CLOSING, and performs cleanup procedure.
* The state will be changed to CLOSED when cleanup is complete, which may
* happen synchronously or asynchronously.
*
* \warning the face must not be deallocated until its state changes to CLOSED
*/
void
close();
const FaceCounters&
getCounters() const;
/**
* \brief Get channel on which face was created (unicast) or the associated channel (multicast)
*/
weak_ptr<Channel>
getChannel() const
{
return m_channel;
}
/**
* \brief Set channel on which face was created (unicast) or the associated channel (multicast)
*/
void
setChannel(weak_ptr<Channel> channel)
{
m_channel = std::move(channel);
}
private:
FaceId m_id;
unique_ptr<LinkService> m_service;
unique_ptr<Transport> m_transport;
FaceCounters m_counters;
weak_ptr<Channel> m_channel;
};
inline LinkService*
@@ -204,6 +211,12 @@ Face::getTransport() const
return m_transport.get();
}
inline void
Face::close()
{
m_transport->close();
}
inline void
Face::sendInterest(const Interest& interest)
{
@@ -270,6 +283,12 @@ Face::getLinkType() const
return m_transport->getLinkType();
}
inline ssize_t
Face::getMtu() const
{
return m_service->getEffectiveMtu();
}
inline FaceState
Face::getState() const
{
@@ -282,12 +301,6 @@ Face::getExpirationTime() const
return m_transport->getExpirationTime();
}
inline void
Face::close()
{
m_transport->close();
}
inline const FaceCounters&
Face::getCounters() const
{
@@ -299,7 +312,6 @@ operator<<(std::ostream& os, const FaceLogHelper<Face>& flh);
} // namespace face
using face::FaceId;
using face::Face;
} // namespace nfd
+167 -85
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2018, Regents of the University of California,
* Copyright (c) 2014-2020, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -24,7 +24,8 @@
*/
#include "generic-link-service.hpp"
#include <iostream>
#include <ndn-cxx/lp/pit-token.hpp>
#include <ndn-cxx/lp/tags.hpp>
#include <cmath>
@@ -32,20 +33,11 @@
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)
{
}
constexpr size_t CONGESTION_MARK_SIZE = tlv::sizeOfVarNumber(lp::tlv::CongestionMark) + // type
tlv::sizeOfVarNumber(sizeof(uint64_t)) + // length
tlv::sizeOfNonNegativeInteger(UINT64_MAX); // value
GenericLinkService::GenericLinkService(const GenericLinkService::Options& options)
: m_options(options)
@@ -54,12 +46,45 @@ GenericLinkService::GenericLinkService(const GenericLinkService::Options& option
, m_reliability(m_options.reliabilityOptions, this)
, m_lastSeqNo(-2)
, m_nextMarkTime(time::steady_clock::TimePoint::max())
, m_lastMarkTime(time::steady_clock::TimePoint::min())
, m_nMarkedSinceInMarkingState(0)
, globalSp(options.C * 0.99, options.vqSize)
{
m_reassembler.beforeTimeout.connect(bind([this] { ++this->nReassemblyTimeouts; }));
m_reliability.onDroppedInterest.connect([this] (const Interest& i) { this->notifyDroppedInterest(i); });
std::cout << "C: " << options.C << std::endl;
m_reassembler.beforeTimeout.connect([this] (auto...) { ++this->nReassemblyTimeouts; });
m_reliability.onDroppedInterest.connect([this] (const auto& i) { this->notifyDroppedInterest(i); });
nReassembling.observe(&m_reassembler);
this->sendPacketCallback = [this](std::shared_ptr<VirtualQueueItem> taskPtr) {
this->globalSp.triggerCalObjectRate();
if (taskPtr != nullptr) {
const Block &block = taskPtr->item->wireEncode();
// std::cout << "interest wireEncode size: " << block.size() << std::endl;
lp::Packet lpPacket(block);
// std::cout << "Interest lppacket size before encode lp fields: " << lpPacket.wireEncode().size() << std::endl;
encodeLpFields(*(taskPtr->item), lpPacket);
// std::cout << "Interest lppacket size after encode lp fields: " << lpPacket.wireEncode().size() << std::endl;
this->sendNetPacket(std::move(lpPacket), true);
// lp::Packet lpPacket(taskPtr->item->wireEncode());
// encodeLpFields(*(taskPtr->item), lpPacket);
// this->sendNetPacket(std::move(lpPacket), taskPtr->endpointId, true);
}
// 得到下一个需要调度的包
auto newTaskPtr = this->globalSp.scheduleNext();
if (newTaskPtr == nullptr) {
//NFD_LOG_ERROR("FUCK");
// std::cout << "FUCK" << std::endl;
// 如果没有可调度的包,则 1 ms 之后再调度
this->canScheduler = true;
// getScheduler().schedule(time::milliseconds(1), std::bind(this->sendPacketCallback, nullptr));
} else {
// 等待足够的 token 再发送
this->canScheduler = false;
// std::cout << "Route waitTime: " << newTaskPtr->waitNsTime << std::endl;
// NFD_LOG_DEBUG("Route waitTime: " << newTaskPtr->waitNsTime);
getScheduler().schedule(time::nanoseconds((uint32_t)(newTaskPtr->waitNsTime)),
std::bind(this->sendPacketCallback, newTaskPtr));
}
};
// getScheduler().schedule(time::nanoseconds(0), std::bind(this->sendPacketCallback, nullptr));
}
void
@@ -71,18 +96,38 @@ GenericLinkService::setOptions(const GenericLinkService::Options& options)
m_reliability.setOptions(m_options.reliabilityOptions);
}
ssize_t
GenericLinkService::getEffectiveMtu() const
{
// Since MTU_UNLIMITED is negative, it will implicitly override any finite override MTU
return std::min(m_options.overrideMtu, getTransport()->getMtu());
}
bool
GenericLinkService::canOverrideMtuTo(ssize_t mtu) const
{
// Not allowed to override unlimited transport MTU
if (getTransport()->getMtu() == MTU_UNLIMITED) {
return false;
}
// Override MTU must be at least MIN_MTU (also implicitly forbids MTU_UNLIMITED and MTU_INVALID)
return mtu >= MIN_MTU;
}
void
GenericLinkService::requestIdlePacket()
{
// No need to request Acks to attach to this packet from LpReliability, as they are already
// attached in sendLpPacket
NFD_LOG_FACE_TRACE("IDLE packet requested");
this->sendLpPacket({});
}
void
GenericLinkService::sendLpPacket(lp::Packet&& pkt)
{
const ssize_t mtu = this->getTransport()->getMtu();
const ssize_t mtu = getEffectiveMtu();
if (m_options.reliabilityOptions.isEnabled) {
m_reliability.piggyback(pkt, mtu);
@@ -92,23 +137,46 @@ GenericLinkService::sendLpPacket(lp::Packet&& pkt)
checkCongestionLevel(pkt);
}
Transport::Packet tp(pkt.wireEncode());
if (mtu != MTU_UNLIMITED && tp.packet.size() > static_cast<size_t>(mtu)) {
auto block = pkt.wireEncode();
if (mtu != MTU_UNLIMITED && block.size() > static_cast<size_t>(mtu)) {
++this->nOutOverMtu;
NFD_LOG_FACE_WARN("attempted to send packet over MTU limit");
return;
}
this->sendPacket(std::move(tp));
this->sendPacket(block);
}
void
GenericLinkService::doSendInterest(const Interest& interest)
{
lp::Packet lpPacket(interest.wireEncode());
if (interest.getName().getPrefix(1).toUri() == "/localhost") {
const Block &block = interest.wireEncode();
// // std::cout << "interest wireEncode size: " << block.size() << std::endl;
lp::Packet lpPacket(block);
// // std::cout << "lppacket size before encode lp fields: " << lpPacket.wireEncode().size() << std::endl;
encodeLpFields(interest, lpPacket);
// // std::cout << "lppacket size after encode lp fields: " << lpPacket.wireEncode().size() << std::endl;
this->sendNetPacket(std::move(lpPacket), true);
} else {
this->globalSp.appendInterest(interest);
if (this->canScheduler) {
this->sendPacketCallback(nullptr);
}
//if (!success) {
// // send Nack
// lp::Nack nack(interest);
// nack.setReason(lp::NackReason::CONGESTION);
// if (this->nwfq.canMark(nack)) {
// // 拥塞标记
// nack.getInterest().setTag(make_shared<lp::CongestionMarkTag>(1));
// }
// this->receiveNack(nack, endpointId);
//}
}
encodeLpFields(interest, lpPacket);
// encodeLpFields(interest, lpPacket);
this->sendNetPacket(std::move(lpPacket), true);
// this->sendNetPacket(std::move(lpPacket), true);
}
void
@@ -132,39 +200,52 @@ GenericLinkService::doSendNack(const lp::Nack& nack)
this->sendNetPacket(std::move(lpPacket), false);
}
void
GenericLinkService::assignSequences(std::vector<lp::Packet>& pkts)
{
std::for_each(pkts.begin(), pkts.end(), [this] (lp::Packet& pkt) {
pkt.set<lp::SequenceField>(++m_lastSeqNo);
});
}
void
GenericLinkService::encodeLpFields(const ndn::PacketBase& netPkt, lp::Packet& lpPacket)
{
if (m_options.allowLocalFields) {
shared_ptr<lp::IncomingFaceIdTag> incomingFaceIdTag = netPkt.getTag<lp::IncomingFaceIdTag>();
auto incomingFaceIdTag = netPkt.getTag<lp::IncomingFaceIdTag>();
if (incomingFaceIdTag != nullptr) {
lpPacket.add<lp::IncomingFaceIdField>(*incomingFaceIdTag);
}
}
shared_ptr<lp::CongestionMarkTag> congestionMarkTag = netPkt.getTag<lp::CongestionMarkTag>();
auto congestionMarkTag = netPkt.getTag<lp::CongestionMarkTag>();
if (congestionMarkTag != nullptr) {
lpPacket.add<lp::CongestionMarkField>(*congestionMarkTag);
}
if (m_options.allowSelfLearning) {
shared_ptr<lp::NonDiscoveryTag> nonDiscoveryTag = netPkt.getTag<lp::NonDiscoveryTag>();
auto nonDiscoveryTag = netPkt.getTag<lp::NonDiscoveryTag>();
if (nonDiscoveryTag != nullptr) {
lpPacket.add<lp::NonDiscoveryField>(*nonDiscoveryTag);
}
shared_ptr<lp::PrefixAnnouncementTag> prefixAnnouncementTag = netPkt.getTag<lp::PrefixAnnouncementTag>();
auto prefixAnnouncementTag = netPkt.getTag<lp::PrefixAnnouncementTag>();
if (prefixAnnouncementTag != nullptr) {
lpPacket.add<lp::PrefixAnnouncementField>(*prefixAnnouncementTag);
}
}
auto pitToken = netPkt.getTag<lp::PitToken>();
if (pitToken != nullptr) {
lpPacket.add<lp::PitTokenField>(*pitToken);
}
}
void
GenericLinkService::sendNetPacket(lp::Packet&& pkt, bool isInterest)
{
std::vector<lp::Packet> frags;
ssize_t mtu = this->getTransport()->getMtu();
ssize_t mtu = getEffectiveMtu();
// Make space for feature fields in fragments
if (m_options.reliabilityOptions.isEnabled && mtu != MTU_UNLIMITED) {
@@ -175,7 +256,8 @@ GenericLinkService::sendNetPacket(lp::Packet&& pkt, bool isInterest)
mtu -= CONGESTION_MARK_SIZE;
}
BOOST_ASSERT(mtu == MTU_UNLIMITED || mtu > 0);
// An MTU of 0 is allowed but will cause all packets to be dropped before transmission
BOOST_ASSERT(mtu == MTU_UNLIMITED || mtu >= 0);
if (m_options.allowFragmentation && mtu != MTU_UNLIMITED) {
bool isOk = false;
@@ -202,8 +284,8 @@ GenericLinkService::sendNetPacket(lp::Packet&& pkt, bool isInterest)
BOOST_ASSERT(!frags.front().has<lp::FragCountField>());
}
// Only assign sequences to fragments if packet contains more than 1 fragment
if (frags.size() > 1) {
// Only assign sequences to fragments if reliability enabled or if packet contains >1 fragment
if (m_options.reliabilityOptions.isEnabled || frags.size() > 1) {
// Assign sequences to all fragments
this->assignSequences(frags);
}
@@ -217,50 +299,30 @@ GenericLinkService::sendNetPacket(lp::Packet&& pkt, bool isInterest)
}
}
void
GenericLinkService::assignSequence(lp::Packet& pkt)
{
pkt.set<lp::SequenceField>(++m_lastSeqNo);
}
void
GenericLinkService::assignSequences(std::vector<lp::Packet>& pkts)
{
std::for_each(pkts.begin(), pkts.end(), bind(&GenericLinkService::assignSequence, this, _1));
}
void
GenericLinkService::checkCongestionLevel(lp::Packet& pkt)
{
ssize_t sendQueueLength = getTransport()->getSendQueueLength();
// This operation requires that the transport supports retrieving current send queue length
// The transport must support retrieving the current send queue length
if (sendQueueLength < 0) {
return;
}
// To avoid overflowing the queue, set the congestion threshold to at least half of the send
// queue capacity.
size_t congestionThreshold = m_options.defaultCongestionThreshold;
if (getTransport()->getSendQueueCapacity() >= 0) {
congestionThreshold = std::min(congestionThreshold,
static_cast<size_t>(getTransport()->getSendQueueCapacity()) /
DEFAULT_CONGESTION_THRESHOLD_DIVISOR);
}
if (sendQueueLength > 0) {
NFD_LOG_FACE_TRACE("txqlen=" << sendQueueLength << " threshold=" << congestionThreshold <<
" capacity=" << getTransport()->getSendQueueCapacity());
NFD_LOG_FACE_TRACE("txqlen=" << sendQueueLength << " threshold=" <<
m_options.defaultCongestionThreshold << " capacity=" <<
getTransport()->getSendQueueCapacity());
}
if (static_cast<size_t>(sendQueueLength) > congestionThreshold) { // Send queue is congested
// sendQueue is above target
if (static_cast<size_t>(sendQueueLength) > m_options.defaultCongestionThreshold) {
const auto now = time::steady_clock::now();
if (now >= m_nextMarkTime || now >= m_lastMarkTime + m_options.baseCongestionMarkingInterval) {
// Mark at most one initial packet per baseCongestionMarkingInterval
if (m_nMarkedSinceInMarkingState == 0) {
m_nextMarkTime = now;
}
// Time to mark packet
if (m_nextMarkTime == time::steady_clock::TimePoint::max()) {
m_nextMarkTime = now + m_options.baseCongestionMarkingInterval;
}
// Mark packet if sendQueue stays above target for one interval
else if (now >= m_nextMarkTime) {
pkt.set<lp::CongestionMarkField>(1);
++nCongestionMarked;
NFD_LOG_FACE_DEBUG("LpPacket was marked as congested");
@@ -268,10 +330,10 @@ GenericLinkService::checkCongestionLevel(lp::Packet& pkt)
++m_nMarkedSinceInMarkingState;
// Decrease the marking interval by the inverse of the square root of the number of packets
// marked in this incident of congestion
m_nextMarkTime += time::nanoseconds(static_cast<time::nanoseconds::rep>(
m_options.baseCongestionMarkingInterval.count() /
std::sqrt(m_nMarkedSinceInMarkingState)));
m_lastMarkTime = now;
time::nanoseconds interval(static_cast<time::nanoseconds::rep>(
m_options.baseCongestionMarkingInterval.count() /
std::sqrt(m_nMarkedSinceInMarkingState + 1)));
m_nextMarkTime += interval;
}
}
else if (m_nextMarkTime != time::steady_clock::TimePoint::max()) {
@@ -283,13 +345,17 @@ GenericLinkService::checkCongestionLevel(lp::Packet& pkt)
}
void
GenericLinkService::doReceivePacket(Transport::Packet&& packet)
GenericLinkService::doReceivePacket(const Block& packet, const EndpointId& endpoint)
{
try {
lp::Packet pkt(packet.packet);
lp::Packet pkt(packet);
if (m_options.reliabilityOptions.isEnabled) {
m_reliability.processIncomingPacket(pkt);
if (!m_reliability.processIncomingPacket(pkt)) {
NFD_LOG_FACE_TRACE("received duplicate fragment: DROP");
++this->nDuplicateSequence;
return;
}
}
if (!pkt.has<lp::FragmentField>()) {
@@ -306,10 +372,9 @@ GenericLinkService::doReceivePacket(Transport::Packet&& packet)
bool isReassembled = false;
Block netPkt;
lp::Packet firstPkt;
std::tie(isReassembled, netPkt, firstPkt) = m_reassembler.receiveFragment(packet.remoteEndpoint,
pkt);
std::tie(isReassembled, netPkt, firstPkt) = m_reassembler.receiveFragment(endpoint, pkt);
if (isReassembled) {
this->decodeNetPacket(netPkt, firstPkt);
this->decodeNetPacket(netPkt, firstPkt, endpoint);
}
}
catch (const tlv::Error& e) {
@@ -319,20 +384,21 @@ GenericLinkService::doReceivePacket(Transport::Packet&& packet)
}
void
GenericLinkService::decodeNetPacket(const Block& netPkt, const lp::Packet& firstPkt)
GenericLinkService::decodeNetPacket(const Block& netPkt, const lp::Packet& firstPkt,
const EndpointId& endpointId)
{
try {
switch (netPkt.type()) {
case tlv::Interest:
if (firstPkt.has<lp::NackField>()) {
this->decodeNack(netPkt, firstPkt);
this->decodeNack(netPkt, firstPkt, endpointId);
}
else {
this->decodeInterest(netPkt, firstPkt);
this->decodeInterest(netPkt, firstPkt, endpointId);
}
break;
case tlv::Data:
this->decodeData(netPkt, firstPkt);
this->decodeData(netPkt, firstPkt, endpointId);
break;
default:
++this->nInNetInvalid;
@@ -342,12 +408,13 @@ GenericLinkService::decodeNetPacket(const Block& netPkt, const lp::Packet& first
}
catch (const tlv::Error& e) {
++this->nInNetInvalid;
NFD_LOG_FACE_WARN("packet parse error (" << e.what() << "): DROP");
NFD_LOG_FACE_WARN("packet parse error (" << e.what() << "): DROP" << netPkt.type());
}
}
void
GenericLinkService::decodeInterest(const Block& netPkt, const lp::Packet& firstPkt)
GenericLinkService::decodeInterest(const Block& netPkt, const lp::Packet& firstPkt,
const EndpointId& endpointId)
{
BOOST_ASSERT(netPkt.type() == tlv::Interest);
BOOST_ASSERT(!firstPkt.has<lp::NackField>());
@@ -394,11 +461,18 @@ GenericLinkService::decodeInterest(const Block& netPkt, const lp::Packet& firstP
return;
}
this->receiveInterest(*interest);
if (firstPkt.has<lp::PitTokenField>()) {
interest->setTag(make_shared<lp::PitToken>(firstPkt.get<lp::PitTokenField>()));
}
this->globalSp.receiveInterest(*interest);
this->globalSp.triggerCalObjectRate();
this->receiveInterest(*interest, endpointId);
}
void
GenericLinkService::decodeData(const Block& netPkt, const lp::Packet& firstPkt)
GenericLinkService::decodeData(const Block& netPkt, const lp::Packet& firstPkt,
const EndpointId& endpointId)
{
BOOST_ASSERT(netPkt.type() == tlv::Data);
@@ -447,11 +521,19 @@ GenericLinkService::decodeData(const Block& netPkt, const lp::Packet& firstPkt)
}
}
this->receiveData(*data);
// 不处理本地命令通信
if (data->getName().getPrefix(1).toUri() != "/localhost") {
// TR = min(TR, OR)
this->globalSp.assignObjectRate(*data);
}
this->globalSp.triggerCalObjectRate();
this->receiveData(*data, endpointId);
}
void
GenericLinkService::decodeNack(const Block& netPkt, const lp::Packet& firstPkt)
GenericLinkService::decodeNack(const Block& netPkt, const lp::Packet& firstPkt,
const EndpointId& endpointId)
{
BOOST_ASSERT(netPkt.type() == tlv::Interest);
BOOST_ASSERT(firstPkt.has<lp::NackField>());
@@ -491,7 +573,7 @@ GenericLinkService::decodeNack(const Block& netPkt, const lp::Packet& firstPkt)
return;
}
this->receiveNack(nack);
this->receiveNack(nack, endpointId);
}
} // namespace face
+71 -44
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2018, Regents of the University of California,
* Copyright (c) 2014-2020, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -30,6 +30,7 @@
#include "lp-fragmenter.hpp"
#include "lp-reassembler.hpp"
#include "lp-reliability.hpp"
#include "queues.hpp"
namespace nfd {
namespace face {
@@ -81,6 +82,10 @@ public:
*/
PacketCounter nRetxExhausted;
/** \brief count of LpPackets dropped due to duplicate Sequence numbers
*/
PacketCounter nDuplicateSequence;
/** \brief count of outgoing LpPackets that were marked with congestion marks
*/
PacketCounter nCongestionMarked;
@@ -89,8 +94,8 @@ public:
/** \brief GenericLinkService is a LinkService that implements the NDNLPv2 protocol
* \sa https://redmine.named-data.net/projects/nfd/wiki/NDNLPv2
*/
class GenericLinkService : public LinkService
, protected virtual GenericLinkServiceCounters
class GenericLinkService FINAL_UNLESS_WITH_TESTS : public LinkService
, protected virtual GenericLinkServiceCounters
{
public:
/** \brief Options that control the behavior of GenericLinkService
@@ -98,16 +103,18 @@ public:
class Options
{
public:
Options();
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 +122,7 @@ public:
/** \brief enables reassembly
*/
bool allowReassembly;
bool allowReassembly = false;
/** \brief options for reassembly
*/
@@ -127,19 +134,40 @@ public:
/** \brief enables send queue congestion detection and marking
*/
bool allowCongestionMarking;
bool allowCongestionMarking = false;
/** \brief starting value for congestion marking interval
*
* Packets are marked if the queue size stays above THRESHOLD for at least one 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
*
* Packets are marked if the queue size stays above THRESHOLD for at least one INTERVAL.
*
* 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 = true;
/** \brief overrides MTU provided by Transport
*
* This MTU value will be used instead of the MTU provided by the transport if it is less than
* the transport MTU. However, it will not be utilized when the transport MTU is unlimited.
*
* Acceptable values for the override MTU are values >= MIN_MTU, which can be validated before
* being set with canOverrideMtuTo().
*/
ssize_t overrideMtu = std::numeric_limits<ssize_t>::max();
uint64_t C = 100000000; // 100Mbps
size_t vqSize = 20;
};
/** \brief counters provided by GenericLinkService
@@ -147,7 +175,7 @@ public:
using Counters = GenericLinkServiceCounters;
explicit
GenericLinkService(const Options& options = Options());
GenericLinkService(const Options& options = {});
/** \brief get Options used by GenericLinkService
*/
@@ -160,7 +188,17 @@ public:
setOptions(const Options& options);
const Counters&
getCounters() const override;
getCounters() const OVERRIDE_WITH_TESTS_ELSE_FINAL;
ssize_t
getEffectiveMtu() const OVERRIDE_WITH_TESTS_ELSE_FINAL;
/** \brief Whether MTU can be overridden to the specified value
*
* If the transport MTU is unlimited, then this will always return false.
*/
bool
canOverrideMtuTo(ssize_t mtu) const;
PROTECTED_WITH_TESTS_ELSE_PRIVATE: // send path
/** \brief request an IDLE packet to transmit pending service fields
@@ -168,26 +206,24 @@ PROTECTED_WITH_TESTS_ELSE_PRIVATE: // send path
void
requestIdlePacket();
/** \brief send an LpPacket fragment
* \param pkt LpPacket to send
/** \brief send an LpPacket
*/
void
sendLpPacket(lp::Packet&& pkt);
/** \brief send Interest
*/
void
doSendInterest(const Interest& interest) override;
doSendInterest(const Interest& interest) OVERRIDE_WITH_TESTS_ELSE_FINAL;
/** \brief send Data
*/
void
doSendData(const Data& data) override;
doSendData(const Data& data) OVERRIDE_WITH_TESTS_ELSE_FINAL;
/** \brief send Nack
void
doSendNack(const ndn::lp::Nack& nack) OVERRIDE_WITH_TESTS_ELSE_FINAL;
/** \brief assign consecutive sequence numbers to LpPackets
*/
void
doSendNack(const ndn::lp::Nack& nack) override;
assignSequences(std::vector<lp::Packet>& pkts);
private: // send path
/** \brief encode link protocol fields from tags onto an outgoing LpPacket
@@ -204,16 +240,6 @@ private: // send path
void
sendNetPacket(lp::Packet&& pkt, bool isInterest);
/** \brief assign a sequence number to an LpPacket
*/
void
assignSequence(lp::Packet& pkt);
/** \brief assign consecutive sequence numbers to LpPackets
*/
void
assignSequences(std::vector<lp::Packet>& pkts);
/** \brief if the send queue is found to be congested, add a congestion mark to the packet
* according to CoDel
* \sa https://tools.ietf.org/html/rfc8289
@@ -222,24 +248,24 @@ private: // send path
checkCongestionLevel(lp::Packet& pkt);
private: // receive path
/** \brief receive Packet from Transport
*/
void
doReceivePacket(Transport::Packet&& packet) override;
doReceivePacket(const Block& packet, const EndpointId& endpoint) OVERRIDE_WITH_TESTS_ELSE_FINAL;
/** \brief decode incoming network-layer packet
* \param netPkt reassembled network-layer packet
* \param firstPkt LpPacket of first fragment
* \param endpointId endpoint of peer who sent the packet
*
* If decoding is successful, a receive signal is emitted;
* otherwise, a warning is logged.
*/
void
decodeNetPacket(const Block& netPkt, const lp::Packet& firstPkt);
decodeNetPacket(const Block& netPkt, const lp::Packet& firstPkt, const EndpointId& endpointId);
/** \brief decode incoming Interest
* \param netPkt reassembled network-layer packet; TLV-TYPE must be Interest
* \param firstPkt LpPacket of first fragment; must not have Nack field
* \param endpointId endpoint of peer who sent the Interest
*
* If decoding is successful, receiveInterest signal is emitted;
* otherwise, a warning is logged.
@@ -247,11 +273,12 @@ private: // receive path
* \throw tlv::Error parse error in an LpHeader field
*/
void
decodeInterest(const Block& netPkt, const lp::Packet& firstPkt);
decodeInterest(const Block& netPkt, const lp::Packet& firstPkt, const EndpointId& endpointId);
/** \brief decode incoming Interest
* \param netPkt reassembled network-layer packet; TLV-TYPE must be Data
* \param firstPkt LpPacket of first fragment
* \param endpointId endpoint of peer who sent the Data
*
* If decoding is successful, receiveData signal is emitted;
* otherwise, a warning is logged.
@@ -259,11 +286,12 @@ private: // receive path
* \throw tlv::Error parse error in an LpHeader field
*/
void
decodeData(const Block& netPkt, const lp::Packet& firstPkt);
decodeData(const Block& netPkt, const lp::Packet& firstPkt, const EndpointId& endpointId);
/** \brief decode incoming Interest
* \param netPkt reassembled network-layer packet; TLV-TYPE must be Interest
* \param firstPkt LpPacket of first fragment; must have Nack field
* \param endpointId endpoint of peer who sent the Nack
*
* If decoding is successful, receiveNack signal is emitted;
* otherwise, a warning is logged.
@@ -271,7 +299,7 @@ private: // receive path
* \throw tlv::Error parse error in an LpHeader field
*/
void
decodeNack(const Block& netPkt, const lp::Packet& firstPkt);
decodeNack(const Block& netPkt, const lp::Packet& firstPkt, const EndpointId& endpointId);
PROTECTED_WITH_TESTS_ELSE_PRIVATE:
Options m_options;
@@ -281,15 +309,14 @@ PROTECTED_WITH_TESTS_ELSE_PRIVATE:
lp::Sequence m_lastSeqNo;
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
time::steady_clock::TimePoint m_lastMarkTime;
/// number of marked packets in the current incident of congestion
size_t m_nMarkedSinceInMarkingState;
GlobalSP globalSp;
bool canScheduler = true;
std::function<void(std::shared_ptr<VirtualQueueItem>)> sendPacketCallback;
friend class LpReliability;
};
+3 -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-2019, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -26,7 +26,7 @@
#include "internal-face.hpp"
#include "generic-link-service.hpp"
#include "internal-transport.hpp"
#include "core/global-io.hpp"
#include "common/global.hpp"
namespace nfd {
namespace face {
+48 -41
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-2020, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -24,16 +24,16 @@
*/
#include "internal-transport.hpp"
#include "core/global-io.hpp"
#include "common/global.hpp"
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);
@@ -42,25 +42,25 @@ InternalForwarderTransport::InternalForwarderTransport(
this->setLinkType(linkType);
this->setMtu(MTU_UNLIMITED);
NFD_LOG_FACE_INFO("Creating transport");
NFD_LOG_FACE_DEBUG("Creating transport");
}
void
InternalForwarderTransport::receiveFromLink(const Block& packet)
InternalForwarderTransport::receivePacket(const Block& packet)
{
NFD_LOG_FACE_TRACE(__func__);
Packet p;
p.packet = packet;
this->receive(std::move(p));
getGlobalIoService().post([this, packet] {
NFD_LOG_FACE_TRACE("Received: " << packet.size() << " bytes");
receive(packet);
});
}
void
InternalForwarderTransport::doSend(Packet&& packet)
InternalForwarderTransport::doSend(const Block& packet)
{
NFD_LOG_FACE_TRACE(__func__);
NFD_LOG_FACE_TRACE("Sending to " << m_peer);
this->emitSignal(afterSend, packet.packet);
if (m_peer)
m_peer->receivePacket(packet);
}
void
@@ -68,52 +68,59 @@ InternalForwarderTransport::doClose()
{
NFD_LOG_FACE_TRACE(__func__);
this->setState(TransportState::CLOSED);
setState(TransportState::CLOSED);
}
NFD_LOG_INCLASS_DEFINE(InternalClientTransport, "InternalClientTransport");
static void
asyncReceive(InternalTransportBase* recipient, const Block& packet)
InternalClientTransport::~InternalClientTransport()
{
getGlobalIoService().post([packet, recipient] {
recipient->receiveFromLink(packet);
});
if (m_forwarder != nullptr) {
m_forwarder->setPeer(nullptr);
}
}
void
InternalClientTransport::connectToForwarder(InternalForwarderTransport* forwarderTransport)
InternalClientTransport::connectToForwarder(InternalForwarderTransport* forwarder)
{
NFD_LOG_DEBUG(__func__ << " " << forwarderTransport);
NFD_LOG_DEBUG(__func__ << " " << forwarder);
m_fwToClientTransmitConn.disconnect();
m_clientToFwTransmitConn.disconnect();
m_fwTransportStateConn.disconnect();
if (m_forwarder != nullptr) {
// disconnect from the old forwarder transport
m_forwarder->setPeer(nullptr);
m_fwTransportStateConn.disconnect();
}
if (forwarderTransport != nullptr) {
m_fwToClientTransmitConn = forwarderTransport->afterSend.connect(bind(&asyncReceive, this, _1));
m_clientToFwTransmitConn = this->afterSend.connect(bind(&asyncReceive, forwarderTransport, _1));
m_fwTransportStateConn = forwarderTransport->afterStateChange.connect(
m_forwarder = forwarder;
if (m_forwarder != nullptr) {
// connect to the new forwarder transport
m_forwarder->setPeer(this);
m_fwTransportStateConn = m_forwarder->afterStateChange.connect(
[this] (TransportState oldState, TransportState newState) {
if (newState == TransportState::CLOSED) {
this->connectToForwarder(nullptr);
connectToForwarder(nullptr);
}
});
}
}
void
InternalClientTransport::receiveFromLink(const Block& packet)
InternalClientTransport::receivePacket(const Block& packet)
{
if (m_receiveCallback) {
m_receiveCallback(packet);
}
getGlobalIoService().post([this, packet] {
NFD_LOG_TRACE("Received: " << packet.size() << " bytes");
if (m_receiveCallback) {
m_receiveCallback(packet);
}
});
}
void
InternalClientTransport::send(const Block& wire)
{
this->emitSignal(afterSend, wire);
NFD_LOG_TRACE("Sending to " << m_forwarder);
if (m_forwarder)
m_forwarder->receivePacket(wire);
}
void
@@ -123,7 +130,7 @@ InternalClientTransport::send(const Block& header, const Block& payload)
encoder.appendByteArray(header.wire(), header.size());
encoder.appendByteArray(payload.wire(), payload.size());
this->send(encoder.block());
send(encoder.block());
}
} // namespace face
+38 -34
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-2020, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -27,12 +27,13 @@
#define NFD_DAEMON_FACE_INTERNAL_TRANSPORT_HPP
#include "transport.hpp"
#include <ndn-cxx/transport/transport.hpp>
namespace nfd {
namespace face {
/** \brief abstracts a transport that can be paired with another
/** \brief Abstracts a transport that can be paired with another.
*/
class InternalTransportBase
{
@@ -40,49 +41,53 @@ public:
virtual
~InternalTransportBase() = default;
/** \brief causes the transport to receive a link-layer packet
*/
virtual void
receiveFromLink(const Block& packet) = 0;
signal::Signal<InternalTransportBase, Block> afterSend;
protected:
DECLARE_SIGNAL_EMIT(afterSend)
receivePacket(const Block& packet) = 0;
};
/** \brief implements a forwarder-side transport that can be paired with another
/** \brief Implements a forwarder-side transport that can be paired with another transport.
*/
class InternalForwarderTransport : public Transport, public InternalTransportBase
class InternalForwarderTransport final : public Transport, public InternalTransportBase
{
public:
explicit
InternalForwarderTransport(const FaceUri& localUri = FaceUri("internal://"),
const FaceUri& remoteUri = FaceUri("internal://"),
ndn::nfd::FaceScope scope = ndn::nfd::FACE_SCOPE_LOCAL,
ndn::nfd::LinkType linkType = ndn::nfd::LINK_TYPE_POINT_TO_POINT);
void
receiveFromLink(const Block& packet) override;
setPeer(InternalTransportBase* peer)
{
m_peer = peer;
}
void
receivePacket(const Block& packet) final;
protected:
void
doClose() override;
doClose() final;
private:
void
doSend(Packet&& packet) override;
doSend(const Block& packet) final;
private:
NFD_LOG_INCLASS_DECLARE();
NFD_LOG_MEMBER_DECL();
InternalTransportBase* m_peer = nullptr;
};
/** \brief implements a client-side transport that can be paired with another
/** \brief Implements a client-side transport that can be paired with an InternalForwarderTransport.
*/
class InternalClientTransport : public ndn::Transport, public InternalTransportBase
class InternalClientTransport final : public ndn::Transport, public InternalTransportBase
{
public:
/** \brief connect to a forwarder-side transport
* \param forwarderTransport the forwarder-side transport to connect to; may be nullptr
~InternalClientTransport() final;
/** \brief Connect to a forwarder-side transport.
* \param forwarder the forwarder-side transport to connect to; may be nullptr
*
* The connected forwarder-side transport will be disconnected automatically if this method
* is called again, or if that transport is closed.
@@ -90,37 +95,36 @@ public:
* all sent packets would be lost, and nothing would be received.
*/
void
connectToForwarder(InternalForwarderTransport* forwarderTransport);
connectToForwarder(InternalForwarderTransport* forwarder);
void
receiveFromLink(const Block& packet) override;
receivePacket(const Block& packet) final;
void
close() override
send(const Block& wire) final;
void
send(const Block& header, const Block& payload) final;
void
close() final
{
}
void
pause() override
pause() final
{
}
void
resume() override
resume() final
{
}
void
send(const Block& wire) override;
void
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;
InternalForwarderTransport* m_forwarder = nullptr;
signal::ScopedConnection m_fwTransportStateConn;
};
+9 -9
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-2020, 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)
@@ -85,39 +85,39 @@ LinkService::sendNack(const ndn::lp::Nack& nack)
}
void
LinkService::receiveInterest(const Interest& interest)
LinkService::receiveInterest(const Interest& interest, const EndpointId& endpoint)
{
NFD_LOG_FACE_TRACE(__func__);
++this->nInInterests;
afterReceiveInterest(interest);
afterReceiveInterest(interest, endpoint);
}
void
LinkService::receiveData(const Data& data)
LinkService::receiveData(const Data& data, const EndpointId& endpoint)
{
NFD_LOG_FACE_TRACE(__func__);
++this->nInData;
afterReceiveData(data);
afterReceiveData(data, endpoint);
}
void
LinkService::receiveNack(const ndn::lp::Nack& nack)
LinkService::receiveNack(const ndn::lp::Nack& nack, const EndpointId& endpoint)
{
NFD_LOG_FACE_TRACE(__func__);
++this->nInNacks;
afterReceiveNack(nack);
afterReceiveNack(nack, endpoint);
}
void
LinkService::notifyDroppedInterest(const Interest& interest)
{
++this->nDroppedInterests;
++this->nInterestsExceededRetx;
onDroppedInterest(interest);
}
+31 -24
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-2020, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -26,15 +26,13 @@
#ifndef NFD_DAEMON_FACE_LINK_SERVICE_HPP
#define NFD_DAEMON_FACE_LINK_SERVICE_HPP
#include "core/counter.hpp"
#include "face-log.hpp"
#include "face-common.hpp"
#include "transport.hpp"
#include "common/counter.hpp"
namespace nfd {
namespace face {
class Face;
/** \brief counters provided by LinkService
* \note The type name 'LinkServiceCounters' is implementation detail.
* Use 'LinkService::Counters' in public API.
@@ -52,7 +50,7 @@ public:
/** \brief count of Interests dropped by reliability system for exceeding allowed number of retx
*/
PacketCounter nDroppedInterests;
PacketCounter nInterestsExceededRetx;
/** \brief count of incoming Data packets
*/
@@ -111,20 +109,23 @@ public:
virtual const Counters&
getCounters() const;
virtual ssize_t
getEffectiveMtu() const;
public: // upper interface to be used by forwarding
/** \brief send Interest
/** \brief Send Interest
* \pre setTransport has been called
*/
void
sendInterest(const Interest& interest);
/** \brief send Data
/** \brief Send Data
* \pre setTransport has been called
*/
void
sendData(const Data& data);
/** \brief send Nack
/** \brief Send Nack
* \pre setTransport has been called
*/
void
@@ -132,15 +133,15 @@ public: // upper interface to be used by forwarding
/** \brief signals on Interest received
*/
signal::Signal<LinkService, Interest> afterReceiveInterest;
signal::Signal<LinkService, Interest, EndpointId> afterReceiveInterest;
/** \brief signals on Data received
*/
signal::Signal<LinkService, Data> afterReceiveData;
signal::Signal<LinkService, Data, EndpointId> afterReceiveData;
/** \brief signals on Nack received
*/
signal::Signal<LinkService, lp::Nack> afterReceiveNack;
signal::Signal<LinkService, lp::Nack, EndpointId> afterReceiveNack;
/** \brief signals on Interest dropped by reliability system for exceeding allowed number of retx
*/
@@ -150,29 +151,29 @@ public: // lower interface to be invoked by Transport
/** \brief performs LinkService specific operations to receive a lower-layer packet
*/
void
receivePacket(Transport::Packet&& packet);
receivePacket(const Block& packet, const EndpointId& endpoint);
protected: // upper interface to be invoked in subclass (receive path termination)
/** \brief delivers received Interest to forwarding
*/
void
receiveInterest(const Interest& interest);
receiveInterest(const Interest& interest, const EndpointId& endpoint);
/** \brief delivers received Data to forwarding
*/
void
receiveData(const Data& data);
receiveData(const Data& data, const EndpointId& endpoint);
/** \brief delivers received Nack to forwarding
*/
void
receiveNack(const lp::Nack& nack);
receiveNack(const lp::Nack& nack, const EndpointId& endpoint);
protected: // lower interface to be invoked in subclass (send path termination)
/** \brief sends a lower-layer packet via Transport
/** \brief send a lower-layer packet via Transport
*/
void
sendPacket(Transport::Packet&& packet);
sendPacket(const Block& packet);
protected:
void
@@ -196,7 +197,7 @@ private: // upper interface to be overridden in subclass (send path entrypoint)
private: // lower interface to be overridden in subclass
virtual void
doReceivePacket(Transport::Packet&& packet) = 0;
doReceivePacket(const Block& packet, const EndpointId& endpoint) = 0;
private:
Face* m_face;
@@ -227,16 +228,22 @@ LinkService::getCounters() const
return *this;
}
inline void
LinkService::receivePacket(Transport::Packet&& packet)
inline ssize_t
LinkService::getEffectiveMtu() const
{
doReceivePacket(std::move(packet));
return m_transport->getMtu();
}
inline void
LinkService::sendPacket(Transport::Packet&& packet)
LinkService::receivePacket(const Block& packet, const EndpointId& endpoint)
{
m_transport->send(std::move(packet));
doReceivePacket(packet, endpoint);
}
inline void
LinkService::sendPacket(const Block& packet)
{
m_transport->send(packet);
}
std::ostream&
+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 -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-2019, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -26,36 +26,30 @@
#ifndef NFD_DAEMON_FACE_LP_FRAGMENTER_HPP
#define NFD_DAEMON_FACE_LP_FRAGMENTER_HPP
#include "face-log.hpp"
#include "face-common.hpp"
#include <ndn-cxx/lp/packet.hpp>
namespace nfd {
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
*/
+9 -14
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-2019, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -25,18 +25,14 @@
#include "lp-reassembler.hpp"
#include "link-service.hpp"
#include "common/global.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)
@@ -45,7 +41,7 @@ LpReassembler::LpReassembler(const LpReassembler::Options& options, const LinkSe
}
std::tuple<bool, Block, lp::Packet>
LpReassembler::receiveFragment(Transport::EndpointId remoteEndpoint, const lp::Packet& packet)
LpReassembler::receiveFragment(EndpointId remoteEndpoint, const lp::Packet& packet)
{
BOOST_ASSERT(packet.has<lp::FragmentField>());
@@ -118,8 +114,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 = getScheduler().schedule(m_options.reassemblyTimeout, [=] { timeoutPartialPacket(key); });
return FALSE_RETURN;
}
@@ -129,7 +124,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 +132,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;
+18 -26
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-2019, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -26,44 +26,36 @@
#ifndef NFD_DAEMON_FACE_LP_REASSEMBLER_HPP
#define NFD_DAEMON_FACE_LP_REASSEMBLER_HPP
#include "core/scheduler.hpp"
#include "face-log.hpp"
#include "transport.hpp"
#include "face-common.hpp"
#include <ndn-cxx/lp/packet.hpp>
namespace nfd {
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
*/
@@ -77,17 +69,17 @@ public:
const LinkService*
getLinkService() const;
/** \brief adds received fragment to buffer
* \param remoteEndpoint endpoint whose sends the packet
* \param packet received fragment;
* must have Fragment field
* \return whether network-layer packet has been completely received,
/** \brief adds received fragment to the buffer
* \param remoteEndpoint endpoint that sent the packet
* \param packet received fragment; must have Fragment field
* \return a tuple containing:
* whether a network-layer packet has been completely received,
* the reassembled network-layer packet,
* and the first fragment for inspecting other NDNLPv2 headers
* the first fragment for inspecting other NDNLPv2 headers
* \throw tlv::Error packet is malformed
*/
std::tuple<bool, Block, lp::Packet>
receiveFragment(Transport::EndpointId remoteEndpoint, const lp::Packet& packet);
receiveFragment(EndpointId remoteEndpoint, const lp::Packet& packet);
/** \brief count of partial packets
*/
@@ -101,7 +93,7 @@ public:
* Before it's erased, this signal is emitted with the remote endpoint,
* and the number of fragments being dropped.
*/
signal::Signal<LpReassembler, Transport::EndpointId, size_t> beforeTimeout;
signal::Signal<LpReassembler, EndpointId, size_t> beforeTimeout;
private:
/** \brief holds all fragments of packet until reassembled
@@ -117,7 +109,7 @@ private:
/** \brief index key for PartialPackets
*/
typedef std::tuple<
Transport::EndpointId, // remoteEndpoint
EndpointId, // remoteEndpoint
lp::Sequence // message identifier (sequence of the first fragment)
> Key;
@@ -129,8 +121,8 @@ private:
private:
Options m_options;
std::map<Key, PartialPacket> m_partialPackets;
const LinkService* m_linkService;
std::map<Key, PartialPacket> m_partialPackets;
};
std::ostream&
+100 -38
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2018, Regents of the University of California,
* Copyright (c) 2014-2020, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -26,29 +26,30 @@
#include "lp-reliability.hpp"
#include "generic-link-service.hpp"
#include "transport.hpp"
#include "common/global.hpp"
namespace nfd {
namespace face {
NFD_LOG_INIT(LpReliability);
LpReliability::LpReliability(const LpReliability::Options& options, GenericLinkService* linkService)
: m_options(options)
, m_linkService(linkService)
, m_firstUnackedFrag(m_unackedFrags.begin())
, m_lastTxSeqNo(-1) // set to "-1" to start TxSequence numbers at 0
, m_isIdleAckTimerRunning(false)
{
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();
m_idleAckTimer.cancel();
}
m_options = options;
@@ -72,6 +73,9 @@ LpReliability::handleOutgoing(std::vector<lp::Packet>& frags, lp::Packet&& pkt,
netPkt->unackedFrags.reserve(frags.size());
for (lp::Packet& frag : frags) {
// Non-IDLE packets are required to have assigned Sequence numbers with LpReliability enabled
BOOST_ASSERT(frag.has<lp::SequenceField>());
// Assign TxSequence number
lp::Sequence txSeq = assignTxSequence(frag);
@@ -81,8 +85,13 @@ LpReliability::handleOutgoing(std::vector<lp::Packet>& frags, lp::Packet&& pkt,
std::forward_as_tuple(txSeq),
std::forward_as_tuple(frag));
unackedFragsIt->second.sendTime = sendTime;
unackedFragsIt->second.rtoTimer =
scheduler::schedule(m_rto.computeRto(), bind(&LpReliability::onLpPacketLost, this, txSeq));
auto rto = m_rttEst.getEstimatedRto();
lp::Sequence seq = frag.get<lp::SequenceField>();
NFD_LOG_FACE_TRACE("transmitting seq=" << seq << ", txseq=" << txSeq << ", rto=" <<
time::duration_cast<time::milliseconds>(rto).count() << "ms");
unackedFragsIt->second.rtoTimer = getScheduler().schedule(rto, [=] {
onLpPacketLost(txSeq, true);
});
unackedFragsIt->second.netPkt = netPkt;
if (m_unackedFrags.size() == 1) {
@@ -94,18 +103,20 @@ LpReliability::handleOutgoing(std::vector<lp::Packet>& frags, lp::Packet&& pkt,
}
}
void
bool
LpReliability::processIncomingPacket(const lp::Packet& pkt)
{
BOOST_ASSERT(m_options.isEnabled);
bool isDuplicate = false;
auto now = time::steady_clock::now();
// Extract and parse Acks
for (lp::Sequence ackSeq : pkt.list<lp::AckField>()) {
auto fragIt = m_unackedFrags.find(ackSeq);
for (lp::Sequence ackTxSeq : pkt.list<lp::AckField>()) {
auto fragIt = m_unackedFrags.find(ackTxSeq);
if (fragIt == m_unackedFrags.end()) {
// Ignore an Ack for an unknown TxSequence number
NFD_LOG_FACE_DEBUG("received ack for unknown txseq=" << ackTxSeq);
continue;
}
auto& frag = fragIt->second;
@@ -114,12 +125,19 @@ LpReliability::processIncomingPacket(const lp::Packet& pkt)
frag.rtoTimer.cancel();
if (frag.retxCount == 0) {
// This sequence had no retransmissions, so use it to calculate the RTO
m_rto.addMeasurement(time::duration_cast<RttEstimator::Duration>(now - frag.sendTime));
NFD_LOG_FACE_TRACE("received ack for seq=" << frag.pkt.get<lp::SequenceField>() << ", txseq=" <<
ackTxSeq << ", retx=0, rtt=" <<
time::duration_cast<time::milliseconds>(now - frag.sendTime).count() << "ms");
// This sequence had no retransmissions, so use it to estimate the RTO
m_rttEst.addMeasurement(now - frag.sendTime);
}
else {
NFD_LOG_FACE_TRACE("received ack for seq=" << frag.pkt.get<lp::SequenceField>() << ", txseq=" <<
ackTxSeq << ", retx=" << frag.retxCount);
}
// Look for frags with TxSequence numbers < ackSeq (allowing for wraparound) and consider them
// lost if a configurable number of Acks containing greater TxSequence numbers have been
// Look for frags with TxSequence numbers < ackTxSeq (allowing for wraparound) and consider
// them lost if a configurable number of Acks containing greater TxSequence numbers have been
// received.
auto lostLpPackets = findLostLpPackets(fragIt);
@@ -136,8 +154,8 @@ LpReliability::processIncomingPacket(const lp::Packet& pkt)
// Resend or fail fragments considered lost. Potentially increment the start of the window.
for (lp::Sequence txSeq : lostLpPackets) {
if (removedLpPackets.find(txSeq) == removedLpPackets.end()) {
auto removedThisTxSeq = this->onLpPacketLost(txSeq);
for (auto removedTxSeq : removedThisTxSeq) {
auto removedTxSeqs = onLpPacketLost(txSeq, false);
for (auto removedTxSeq : removedTxSeqs) {
removedLpPackets.insert(removedTxSeq);
}
}
@@ -146,11 +164,29 @@ LpReliability::processIncomingPacket(const lp::Packet& pkt)
// If packet has Fragment and TxSequence fields, extract TxSequence and add to AckQueue
if (pkt.has<lp::FragmentField>() && pkt.has<lp::TxSequenceField>()) {
NFD_LOG_FACE_TRACE("queueing ack for remote txseq=" << pkt.get<lp::TxSequenceField>());
m_ackQueue.push(pkt.get<lp::TxSequenceField>());
if (!m_isIdleAckTimerRunning) {
this->startIdleAckTimer();
// Check for received frames with duplicate Sequences
if (pkt.has<lp::SequenceField>()) {
lp::Sequence pktSequence = pkt.get<lp::SequenceField>();
isDuplicate = m_recentRecvSeqs.count(pktSequence) > 0;
// Check for recent received Sequences to remove
auto now = time::steady_clock::now();
auto rto = m_rttEst.getEstimatedRto();
while (m_recentRecvSeqsQueue.size() > 0 &&
now > m_recentRecvSeqs[m_recentRecvSeqsQueue.front()] + rto) {
m_recentRecvSeqs.erase(m_recentRecvSeqsQueue.front());
m_recentRecvSeqsQueue.pop();
}
m_recentRecvSeqs.emplace(pktSequence, now);
m_recentRecvSeqsQueue.push(pktSequence);
}
startIdleAckTimer();
}
return !isDuplicate;
}
void
@@ -167,8 +203,8 @@ LpReliability::piggyback(lp::Packet& pkt, ssize_t mtu)
remainingSpace -= pktSize;
while (!m_ackQueue.empty()) {
lp::Sequence ackSeq = m_ackQueue.front();
// Ack size = Ack TLV-TYPE (3 octets) + TLV-LENGTH (1 octet) + uint64_t (8 octets)
lp::Sequence ackTxSeq = m_ackQueue.front();
// Ack size = Ack TLV-TYPE (3 octets) + TLV-LENGTH (1 octet) + lp::Sequence (8 octets)
const ssize_t ackSize = tlv::sizeOfVarNumber(lp::tlv::Ack) +
tlv::sizeOfVarNumber(sizeof(lp::Sequence)) +
sizeof(lp::Sequence);
@@ -177,7 +213,9 @@ LpReliability::piggyback(lp::Packet& pkt, ssize_t mtu)
break;
}
pkt.add<lp::AckField>(ackSeq);
NFD_LOG_FACE_TRACE("piggybacking ack for remote txseq=" << ackTxSeq);
pkt.add<lp::AckField>(ackTxSeq);
m_ackQueue.pop();
remainingSpace -= ackSize;
}
@@ -189,7 +227,7 @@ LpReliability::assignTxSequence(lp::Packet& frag)
lp::Sequence txSeq = ++m_lastTxSeqNo;
frag.set<lp::TxSequenceField>(txSeq);
if (m_unackedFrags.size() > 0 && m_lastTxSeqNo == m_firstUnackedFrag->first) {
BOOST_THROW_EXCEPTION(std::length_error("TxSequence range exceeded"));
NDN_THROW(std::length_error("TxSequence range exceeded"));
}
return m_lastTxSeqNo;
}
@@ -197,25 +235,18 @@ LpReliability::assignTxSequence(lp::Packet& frag)
void
LpReliability::startIdleAckTimer()
{
BOOST_ASSERT(!m_isIdleAckTimerRunning);
m_isIdleAckTimerRunning = true;
if (m_idleAckTimer) {
// timer is already running, do nothing
return;
}
m_idleAckTimer = scheduler::schedule(m_options.idleAckTimerPeriod, [this] {
m_idleAckTimer = getScheduler().schedule(m_options.idleAckTimerPeriod, [this] {
while (!m_ackQueue.empty()) {
m_linkService->requestIdlePacket();
}
m_isIdleAckTimerRunning = false;
});
}
void
LpReliability::stopIdleAckTimer()
{
m_idleAckTimer.cancel();
m_isIdleAckTimerRunning = false;
}
std::vector<lp::Sequence>
LpReliability::findLostLpPackets(LpReliability::UnackedFrags::iterator ackIt)
{
@@ -232,6 +263,8 @@ LpReliability::findLostLpPackets(LpReliability::UnackedFrags::iterator ackIt)
auto& unackedFrag = it->second;
unackedFrag.nGreaterSeqAcks++;
NFD_LOG_FACE_TRACE("received ack=" << ackIt->first << " before=" << it->first <<
", before count=" << unackedFrag.nGreaterSeqAcks);
if (unackedFrag.nGreaterSeqAcks >= m_options.seqNumLossThreshold) {
lostLpPackets.push_back(it->first);
@@ -242,7 +275,7 @@ LpReliability::findLostLpPackets(LpReliability::UnackedFrags::iterator ackIt)
}
std::vector<lp::Sequence>
LpReliability::onLpPacketLost(lp::Sequence txSeq)
LpReliability::onLpPacketLost(lp::Sequence txSeq, bool isTimeout)
{
BOOST_ASSERT(m_unackedFrags.count(txSeq) > 0);
auto txSeqIt = m_unackedFrags.find(txSeq);
@@ -251,9 +284,19 @@ LpReliability::onLpPacketLost(lp::Sequence txSeq)
txFrag.rtoTimer.cancel();
auto netPkt = txFrag.netPkt;
std::vector<lp::Sequence> removedThisTxSeq;
lp::Sequence seq = txFrag.pkt.get<lp::SequenceField>();
if (isTimeout) {
NFD_LOG_FACE_TRACE("rto timer expired for seq=" << seq << ", txseq=" << txSeq);
}
else { // lost due to out-of-order TxSeqs
NFD_LOG_FACE_TRACE("seq=" << seq << ", txseq=" << txSeq <<
" considered lost from acks for more recent txseqs");
}
// Check if maximum number of retransmissions exceeded
if (txFrag.retxCount >= m_options.maxRetx) {
NFD_LOG_FACE_DEBUG("seq=" << seq << " exceeded allowed retransmissions: DROP");
// Delete all LpPackets of NetPkt from m_unackedFrags (except this one)
for (size_t i = 0; i < netPkt->unackedFrags.size(); i++) {
if (netPkt->unackedFrags[i] != txSeqIt) {
@@ -273,6 +316,7 @@ LpReliability::onLpPacketLost(lp::Sequence txSeq)
onDroppedInterest(Interest(frag));
}
// Delete this LpPacket from m_unackedFrags
removedThisTxSeq.push_back(txSeqIt->first);
deleteUnackedFrag(txSeqIt);
}
@@ -304,9 +348,15 @@ LpReliability::onLpPacketLost(lp::Sequence txSeq)
// Retransmit fragment
m_linkService->sendLpPacket(lp::Packet(newTxFrag.pkt));
auto rto = m_rttEst.getEstimatedRto();
NFD_LOG_FACE_TRACE("retransmitting seq=" << seq << ", txseq=" << newTxSeq << ", retx=" <<
txFrag.retxCount << ", rto=" <<
time::duration_cast<time::milliseconds>(rto).count() << "ms");
// Start RTO timer for this sequence
newTxFrag.rtoTimer = scheduler::schedule(m_rto.computeRto(),
bind(&LpReliability::onLpPacketLost, this, newTxSeq));
newTxFrag.rtoTimer = getScheduler().schedule(rto, [=] {
onLpPacketLost(newTxSeq, true);
});
}
return removedThisTxSeq;
@@ -372,5 +422,17 @@ LpReliability::NetPkt::NetPkt(lp::Packet&& pkt, bool isInterest)
{
}
std::ostream&
operator<<(std::ostream& os, const FaceLogHelper<LpReliability>& flh)
{
if (flh.obj.getLinkService() == nullptr) {
os << "[id=0,local=unknown,remote=unknown] ";
}
else {
os << FaceLogHelper<LinkService>(*flh.obj.getLinkService());
}
return os;
}
} // namespace face
} // namespace nfd
+17 -15
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2018, Regents of the University of California,
* Copyright (c) 2014-2020, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -26,11 +26,11 @@
#ifndef NFD_DAEMON_FACE_LP_RELIABILITY_HPP
#define NFD_DAEMON_FACE_LP_RELIABILITY_HPP
#include "core/rtt-estimator.hpp"
#include "core/scheduler.hpp"
#include "face-common.hpp"
#include <ndn-cxx/lp/packet.hpp>
#include <ndn-cxx/lp/sequence.hpp>
#include <ndn-cxx/util/rtt-estimator.hpp>
#include <queue>
@@ -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
@@ -93,8 +93,9 @@ public:
/** \brief extract and parse all Acks and add Ack for contained Fragment (if any) to AckQueue
* \param pkt incoming LpPacket
* \return whether incoming LpPacket is new and not a duplicate
*/
void
bool
processIncomingPacket(const lp::Packet& pkt);
/** \brief called by GenericLinkService to attach Acks onto an outgoing LpPacket
@@ -127,11 +128,6 @@ PUBLIC_WITH_TESTS_ELSE_PRIVATE:
void
startIdleAckTimer();
/** \brief cancel the idle Ack timer
*/
void
stopIdleAckTimer();
/** \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
@@ -144,7 +140,7 @@ PUBLIC_WITH_TESTS_ELSE_PRIVATE:
* \return vector of the TxSequences of fragments removed due to a network packet being removed
*/
std::vector<lp::Sequence>
onLpPacketLost(lp::Sequence txSeq);
onLpPacketLost(lp::Sequence txSeq, bool isTimeout);
/** \brief remove the fragment with the given sequence number from the map of unacknowledged
* fragments, as well as its associated network packet (if any)
@@ -199,8 +195,10 @@ PUBLIC_WITH_TESTS_ELSE_PRIVATE:
};
public:
/// TxSequence TLV-TYPE (3 octets) + TxSequence TLV-LENGTH (1 octet) + sizeof(lp::Sequence)
static constexpr size_t RESERVED_HEADER_SPACE = 3 + 1 + sizeof(lp::Sequence);
/// TxSequence TLV-TYPE (3 octets) + TLV-LENGTH (1 octet) + lp::Sequence (8 octets)
static constexpr size_t RESERVED_HEADER_SPACE = tlv::sizeOfVarNumber(lp::tlv::TxSequence) +
tlv::sizeOfVarNumber(sizeof(lp::Sequence)) +
sizeof(lp::Sequence);
PUBLIC_WITH_TESTS_ELSE_PRIVATE:
Options m_options;
@@ -213,12 +211,16 @@ PUBLIC_WITH_TESTS_ELSE_PRIVATE:
*/
UnackedFrags::iterator m_firstUnackedFrag;
std::queue<lp::Sequence> m_ackQueue;
std::map<lp::Sequence, time::steady_clock::TimePoint> m_recentRecvSeqs;
std::queue<lp::Sequence> m_recentRecvSeqsQueue;
lp::Sequence m_lastTxSeqNo;
scheduler::ScopedEventId m_idleAckTimer;
bool m_isIdleAckTimerRunning;
RttEstimator m_rto;
ndn::util::RttEstimator m_rttEst;
};
std::ostream&
operator<<(std::ostream& os, const FaceLogHelper<LpReliability>& flh);
} // namespace face
} // namespace nfd
+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-2019, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -24,7 +24,7 @@
*/
#include "multicast-ethernet-transport.hpp"
#include "core/global-io.hpp"
#include "common/global.hpp"
#include <cerrno> // for errno
#include <cstring> // for memcpy(), strerror(), strncpy()
@@ -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,
@@ -63,7 +63,7 @@ MulticastEthernetTransport::MulticastEthernetTransport(const ndn::net::NetworkIn
this->setLinkType(linkType);
this->setMtu(localEndpoint.getMtu());
NFD_LOG_FACE_INFO("Creating transport");
NFD_LOG_FACE_DEBUG("Creating transport");
char filter[110];
// note #1: we cannot use std::snprintf because it's not available
@@ -144,7 +144,7 @@ MulticastEthernetTransport::joinMulticastGroup()
NFD_LOG_FACE_WARN("ioctl(SIOCADDMULTI) failed: " << std::strerror(errno));
#endif
BOOST_THROW_EXCEPTION(Error("Failed to join multicast group"));
NDN_THROW(Error("Failed to join multicast group"));
}
} // namespace face
+16 -16
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2018, Regents of the University of California,
* Copyright (c) 2014-2020, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -27,7 +27,7 @@
#include "socket-utils.hpp"
#include "udp-protocol.hpp"
#include "core/privilege-helper.hpp"
#include "common/privilege-helper.hpp"
#include <boost/functional/hash.hpp>
@@ -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,
@@ -69,7 +68,7 @@ MulticastUdpTransport::MulticastUdpTransport(const protocol::endpoint& multicast
this->setSendQueueCapacity(sendBufferSizeOption.value());
}
NFD_LOG_FACE_INFO("Creating transport");
NFD_LOG_FACE_DEBUG("Creating transport");
}
ssize_t
@@ -83,15 +82,15 @@ MulticastUdpTransport::getSendQueueLength()
}
void
MulticastUdpTransport::doSend(Transport::Packet&& packet)
MulticastUdpTransport::doSend(const Block& 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));
m_sendSocket.async_send_to(boost::asio::buffer(packet), m_multicastGroup,
// 'packet' is copied into the lambda to retain the underlying Buffer
[this, packet] (auto&&... args) {
this->handleSend(std::forward<decltype(args)>(args)...);
});
}
void
@@ -119,15 +118,16 @@ bindToDevice(int fd, const std::string& ifname)
// receive all packets sent to the other interfaces as well.
// This is needed only on Linux. On macOS, the boost::asio::ip::multicast::join_group
// option is sufficient to obtain the desired behavior.
// We dont't set SO_BINDTODEVICE on Android because this operation requires root privilege
// which is not allowed on Android, it will cause "Operation not permitted" error.
#ifdef __linux__
#if defined(__linux__) && !defined(__ANDROID__)
PrivilegeHelper::runElevated([=] {
if (::setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, ifname.data(), ifname.size() + 1) < 0) {
BOOST_THROW_EXCEPTION(MulticastUdpTransport::Error("Cannot bind multicast rx socket to " +
ifname + ": " + std::strerror(errno)));
NDN_THROW_ERRNO(MulticastUdpTransport::Error("Cannot bind multicast rx socket to " + ifname));
}
});
#endif // __linux__
#endif
}
void
@@ -191,7 +191,7 @@ MulticastUdpTransport::openTxSocket(protocol::socket& sock,
}
template<>
Transport::EndpointId
EndpointId
DatagramTransport<boost::asio::ip::udp, Multicast>::makeEndpointId(const protocol::endpoint& ep)
{
if (ep.address().is_v4()) {
+6 -8
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2018, Regents of the University of California,
* Copyright (c) 2014-2020, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -33,12 +33,14 @@
namespace nfd {
namespace face {
NFD_LOG_MEMBER_DECL_SPECIALIZED((DatagramTransport<boost::asio::ip::udp, Multicast>));
// Explicit specialization of makeEndpointId for the UDP multicast case.
// Note that this "shall be declared before the first use of the specialization
// that would cause an implicit instantiation to take place, in every translation
// unit in which such a use occurs".
template<>
Transport::EndpointId
EndpointId
DatagramTransport<boost::asio::ip::udp, Multicast>::makeEndpointId(const protocol::endpoint& ep);
/**
@@ -50,11 +52,7 @@ public:
class Error : public std::runtime_error
{
public:
explicit
Error(const std::string& what)
: std::runtime_error(what)
{
}
using std::runtime_error::runtime_error;
};
/**
@@ -86,7 +84,7 @@ public:
private:
void
doSend(Transport::Packet&& packet) final;
doSend(const Block& packet) final;
void
doClose() final;
+149
View File
@@ -0,0 +1,149 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2019, 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 "netdev-bound.hpp"
#include "face-system.hpp"
#include "common/logger.hpp"
namespace nfd {
namespace face {
NFD_LOG_INIT(NetdevBound);
NetdevBound::NetdevBound(const ProtocolFactoryCtorParams& params, const FaceSystem& faceSystem)
: m_faceSystem(faceSystem)
, m_addFace(params.addFace)
, m_netmon(params.netmon)
{
}
void
NetdevBound::processConfig(OptionalConfigSection configSection,
FaceSystem::ConfigContext& context)
{
std::vector<Rule> rules;
if (configSection) {
int ruleIndex = 0;
for (const auto& pair : *configSection) {
const std::string& key = pair.first;
const ConfigSection& value = pair.second;
if (key == "rule") {
rules.push_back(parseRule(ruleIndex++, value));
}
else {
NDN_THROW(ConfigFile::Error("Unrecognized option face_system.netdev_bound." + key));
}
}
}
if (context.isDryRun) {
return;
}
///\todo #3521 this should be verified in dry-run, but PFs won't publish their *+dev schemes
/// in dry-run
for (size_t i = 0; i < rules.size(); ++i) {
const Rule& rule = rules[i];
for (const FaceUri& remote : rule.remotes) {
std::string devScheme = remote.getScheme() + "+dev";
if (!m_faceSystem.hasFactoryForScheme(devScheme)) {
NDN_THROW(RuleParseError(i, "scheme '" + devScheme + "' for " +
remote.toString() + " is unavailable"));
}
}
}
NFD_LOG_DEBUG("processConfig: processed " << rules.size() << " rules");
m_rules.swap(rules);
std::map<Key, shared_ptr<Face>> oldFaces;
oldFaces.swap(m_faces);
///\todo #3521 for each face needed under m_rules:
/// if it's in oldFaces, add to m_faces and remove from oldFaces;
/// otherwise, create via factory and add to m_faces
///\todo #3521 close faces in oldFaces
}
NetdevBound::Rule
NetdevBound::parseRule(int index, const ConfigSection& confRule) const
{
Rule rule;
bool hasWhitelist = false;
bool hasBlacklist = false;
for (const auto& pair : confRule) {
const std::string& key = pair.first;
const ConfigSection& value = pair.second;
if (key == "remote") {
try {
rule.remotes.emplace_back(value.get_value<std::string>());
}
catch (const FaceUri::Error&) {
NDN_THROW_NESTED(RuleParseError(index, "invalid remote FaceUri"));
}
if (!rule.remotes.back().isCanonical()) {
NDN_THROW(RuleParseError(index, "remote FaceUri is not canonical"));
}
}
else if (key == "whitelist") {
if (hasWhitelist) {
NDN_THROW(RuleParseError(index, "duplicate whitelist"));
}
try {
rule.netifPredicate.parseWhitelist(value);
}
catch (const ConfigFile::Error&) {
NDN_THROW_NESTED(RuleParseError(index, "invalid whitelist"));
}
hasWhitelist = true;
}
else if (key == "blacklist") {
if (hasBlacklist) {
NDN_THROW(RuleParseError(index, "duplicate blacklist"));
}
try {
rule.netifPredicate.parseBlacklist(value);
}
catch (const ConfigFile::Error&) {
NDN_THROW_NESTED(RuleParseError(index, "invalid blacklist"));
}
hasBlacklist = true;
}
else {
NDN_THROW(RuleParseError(index, "unrecognized option " + key));
}
}
if (rule.remotes.empty()) {
NDN_THROW(RuleParseError(index, "remote FaceUri is missing"));
}
///\todo #3521 for each remote, check that there is a factory providing scheme+dev scheme
return rule;
}
} // namespace face
} // namespace nfd
+88
View File
@@ -0,0 +1,88 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2019, 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_DAEMON_FACE_NETDEV_BOUND_HPP
#define NFD_DAEMON_FACE_NETDEV_BOUND_HPP
#include "protocol-factory.hpp"
namespace nfd {
namespace face {
class FaceSystem;
/** \brief manages netdev-bound faces
*/
class NetdevBound : noncopyable
{
public:
class RuleParseError : public ConfigFile::Error
{
public:
RuleParseError(int index, std::string msg)
: Error("Error parsing face_system.netdev_bound.rule[" + to_string(index) + "]: " + msg)
, index(index)
, msg(std::move(msg))
{
}
public:
int index;
std::string msg;
};
NetdevBound(const ProtocolFactoryCtorParams& params, const FaceSystem& faceSystem);
/** \brief process face_system.netdev_bound config section
*/
void
processConfig(OptionalConfigSection configSection,
FaceSystem::ConfigContext& context);
PUBLIC_WITH_TESTS_ELSE_PRIVATE:
struct Rule
{
std::vector<FaceUri> remotes;
NetworkInterfacePredicate netifPredicate;
};
Rule
parseRule(int index, const ConfigSection& confRule) const;
PUBLIC_WITH_TESTS_ELSE_PRIVATE:
const FaceSystem& m_faceSystem;
FaceCreatedCallback m_addFace;
shared_ptr<ndn::net::NetworkMonitor> m_netmon;
std::vector<Rule> m_rules;
using Key = std::pair<FaceUri, std::string>;
std::map<Key, shared_ptr<Face>> m_faces;
};
} // namespace face
} // namespace nfd
#endif // NFD_DAEMON_FACE_NETDEV_BOUND_HPP
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2018, Regents of the University of California,
* Copyright (c) 2014-2019, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -24,13 +24,13 @@
*/
#include "network-predicate.hpp"
#include "config-file.hpp"
#include "network.hpp"
#include "common/config-file.hpp"
#include "core/network.hpp"
#include <fnmatch.h>
namespace nfd {
namespace face {
NetworkPredicateBase::NetworkPredicateBase()
{
@@ -47,7 +47,9 @@ NetworkPredicateBase::clear()
}
void
NetworkPredicateBase::parseList(std::set<std::string>& set, const boost::property_tree::ptree& list, const std::string& section)
NetworkPredicateBase::parseList(std::set<std::string>& set,
const boost::property_tree::ptree& list,
const std::string& section)
{
set.clear();
@@ -58,12 +60,14 @@ NetworkPredicateBase::parseList(std::set<std::string>& set, const boost::propert
}
else {
if (!isRuleSupported(item.first)) {
BOOST_THROW_EXCEPTION(ConfigFile::Error("Unrecognized rule \"" + item.first + "\" in \"" + section + "\" section"));
NDN_THROW(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"));
NDN_THROW(ConfigFile::Error("Malformed " + item.first + " '" + value +
"' in section '" + section + "'"));
}
set.insert(value);
}
@@ -71,7 +75,8 @@ NetworkPredicateBase::parseList(std::set<std::string>& set, const boost::propert
}
void
NetworkPredicateBase::parseList(std::set<std::string>& set, std::initializer_list<std::pair<std::string, std::string>> list)
NetworkPredicateBase::parseList(std::set<std::string>& set,
std::initializer_list<std::pair<std::string, std::string>> list)
{
set.clear();
@@ -82,11 +87,11 @@ NetworkPredicateBase::parseList(std::set<std::string>& set, std::initializer_lis
}
else {
if (!isRuleSupported(item.first)) {
BOOST_THROW_EXCEPTION(std::runtime_error("Unrecognized rule \"" + item.first + "\""));
NDN_THROW(std::runtime_error("Unrecognized rule '" + item.first + "'"));
}
if (!isRuleValid(item.first, item.second)) {
BOOST_THROW_EXCEPTION(std::runtime_error("Malformed " + item.first + " \"" + item.second + "\""));
NDN_THROW(std::runtime_error("Malformed " + item.first + " '" + item.second + "'"));
}
set.insert(item.second);
}
@@ -135,7 +140,7 @@ NetworkInterfacePredicate::isRuleValid(const std::string& key, const std::string
return Network::isValidCidr(value);
}
else {
BOOST_THROW_EXCEPTION(std::logic_error("Only supported rules are expected"));
NDN_THROW(std::logic_error("Only supported rules are expected"));
}
}
@@ -153,7 +158,7 @@ IpAddressPredicate::isRuleValid(const std::string& key, const std::string& value
return Network::isValidCidr(value);
}
else {
BOOST_THROW_EXCEPTION(std::logic_error("Only supported rules are expected"));
NDN_THROW(std::logic_error("Only supported rules are expected"));
}
}
@@ -193,8 +198,8 @@ doesNetifMatchRule(const ndn::net::NetworkInterface& netif, const std::string& r
bool
NetworkInterfacePredicate::operator()(const ndn::net::NetworkInterface& netif) const
{
return std::any_of(m_whitelist.begin(), m_whitelist.end(), bind(&doesNetifMatchRule, cref(netif), _1)) &&
std::none_of(m_blacklist.begin(), m_blacklist.end(), bind(&doesNetifMatchRule, cref(netif), _1));
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
@@ -214,8 +219,9 @@ doesAddressMatchRule(const boost::asio::ip::address& address, const std::string&
bool
IpAddressPredicate::operator()(const boost::asio::ip::address& address) const
{
return std::any_of(m_whitelist.begin(), m_whitelist.end(), bind(&doesAddressMatchRule, cref(address), _1)) &&
std::none_of(m_blacklist.begin(), m_blacklist.end(), bind(&doesAddressMatchRule, cref(address), _1));
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 face
} // namespace nfd
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2018, Regents of the University of California,
* Copyright (c) 2014-2019, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -23,13 +23,15 @@
* 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
#ifndef NFD_DAEMON_FACE_NETWORK_PREDICATE_HPP
#define NFD_DAEMON_FACE_NETWORK_PREDICATE_HPP
#include "core/common.hpp"
#include "common.hpp"
#include <ndn-cxx/net/network-interface.hpp>
namespace nfd {
namespace face {
class NetworkPredicateBase
{
@@ -128,6 +130,7 @@ private:
isRuleValid(const std::string& key, const std::string& value) final;
};
} // namespace face
} // namespace nfd
#endif // NFD_CORE_NETWORK_PREDICATE_HPP
#endif // NFD_DAEMON_FACE_NETWORK_PREDICATE_HPP
+8 -9
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2014-2015, Regents of the University of California,
/*
* Copyright (c) 2014-2019, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -24,20 +24,19 @@
*/
#include "null-face.hpp"
#include "generic-link-service.hpp"
#include "internal-transport.hpp"
#include "null-link-service.hpp"
#include "null-transport.hpp"
namespace nfd {
namespace face {
// FIB could restrict creating a nexthop record toward non-local face in /localhost namespace.
// NullFace has scope=local to enable creating a "blackhole" FIB entry under /localhost.
shared_ptr<Face>
makeNullFace(const FaceUri& uri)
{
return make_shared<Face>(make_unique<GenericLinkService>(),
make_unique<InternalForwarderTransport>(uri, uri, ndn::nfd::FACE_SCOPE_LOCAL));
// FIB could restrict creating a nexthop record toward a non-local face in /localhost namespace.
// Therefore, NullFace has scope=local to enable creating a "blackhole" FIB entry under /localhost.
return make_shared<Face>(make_unique<NullLinkService>(),
make_unique<NullTransport>(uri, uri, ndn::nfd::FACE_SCOPE_LOCAL));
}
} // namespace face
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2017, Regents of the University of California,
* Copyright (c) 2014-2020, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -23,24 +23,41 @@
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*/
/** \file
* \brief declares ContentStore internal types
*/
#ifndef NFD_DAEMON_FACE_NULL_LINK_SERVICE_HPP
#define NFD_DAEMON_FACE_NULL_LINK_SERVICE_HPP
#ifndef NFD_DAEMON_TABLE_CS_INTERNAL_HPP
#define NFD_DAEMON_TABLE_CS_INTERNAL_HPP
#include "core/common.hpp"
#include "link-service.hpp"
namespace nfd {
namespace cs {
namespace face {
class EntryImpl;
/** \brief A LinkService that drops every packet.
*/
class NullLinkService final : public LinkService
{
private:
void
doSendInterest(const Interest&) final
{
}
typedef std::set<EntryImpl> Table;
typedef Table::const_iterator iterator;
void
doSendData(const Data&) final
{
}
} // namespace cs
void
doSendNack(const lp::Nack&) final
{
}
void
doReceivePacket(const Block&, const EndpointId&) final
{
}
};
} // namespace face
} // namespace nfd
#endif // NFD_DAEMON_TABLE_CS_INTERNAL_HPP
#endif // NFD_DAEMON_FACE_NULL_LINK_SERVICE_HPP
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2014-2015, Regents of the University of California,
/*
* Copyright (c) 2014-2019, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -23,33 +23,25 @@
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*/
#include "core/global-io.hpp"
#include "tests/test-common.hpp"
#include <boost/thread.hpp>
#include "null-transport.hpp"
namespace nfd {
namespace tests {
namespace face {
BOOST_FIXTURE_TEST_SUITE(TestGlobalIo, BaseFixture)
NFD_LOG_INIT(NullTransport);
BOOST_AUTO_TEST_CASE(ThreadLocalGlobalIoService)
NullTransport::NullTransport(const FaceUri& localUri, const FaceUri& remoteUri,
ndn::nfd::FaceScope scope, ndn::nfd::FacePersistency persistency)
{
boost::asio::io_service* s1 = &getGlobalIoService();
boost::asio::io_service* s2 = nullptr;
boost::thread t([&s2] {
s2 = &getGlobalIoService();
});
this->setLocalUri(localUri);
this->setRemoteUri(remoteUri);
this->setScope(scope);
this->setPersistency(persistency);
this->setLinkType(ndn::nfd::LINK_TYPE_POINT_TO_POINT);
this->setMtu(MTU_UNLIMITED);
t.join();
BOOST_CHECK(s1 != nullptr);
BOOST_CHECK(s2 != nullptr);
BOOST_CHECK(s1 != s2);
NFD_LOG_FACE_DEBUG("Creating transport");
}
BOOST_AUTO_TEST_SUITE_END()
} // namespace tests
} // namespace face
} // namespace nfd
@@ -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-2020, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -23,36 +23,40 @@
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef NFD_DAEMON_MGMT_NFD_MANAGER_BASE_HPP
#define NFD_DAEMON_MGMT_NFD_MANAGER_BASE_HPP
#ifndef NFD_DAEMON_FACE_NULL_TRANSPORT_HPP
#define NFD_DAEMON_FACE_NULL_TRANSPORT_HPP
#include "core/manager-base.hpp"
#include "command-authenticator.hpp"
#include "transport.hpp"
namespace nfd {
namespace face {
using ndn::mgmt::Dispatcher;
using ndn::nfd::ControlParameters;
/**
* @brief a collection of common functions shared by all NFD managers,
* such as communicating with the dispatcher and command validator.
/** \brief A Transport that drops every packet.
*/
class NfdManagerBase : public ManagerBase
class NullTransport FINAL_UNLESS_WITH_TESTS : public Transport
{
public:
NfdManagerBase(Dispatcher& dispatcher,
CommandAuthenticator& authenticator,
const std::string& module);
explicit
NullTransport(const FaceUri& localUri = FaceUri("null://"),
const FaceUri& remoteUri = FaceUri("null://"),
ndn::nfd::FaceScope scope = ndn::nfd::FACE_SCOPE_NON_LOCAL,
ndn::nfd::FacePersistency persistency = ndn::nfd::FACE_PERSISTENCY_PERMANENT);
PUBLIC_WITH_TESTS_ELSE_PRIVATE: // command validation
virtual ndn::mgmt::Authorization
makeAuthorization(const std::string& verb) override;
protected:
void
doClose() OVERRIDE_WITH_TESTS_ELSE_FINAL
{
setState(TransportState::CLOSED);
}
private:
CommandAuthenticator& m_authenticator;
void
doSend(const Block&) OVERRIDE_WITH_TESTS_ELSE_FINAL
{
}
};
} // namespace face
} // namespace nfd
#endif // NFD_DAEMON_MGMT_NFD_MANAGER_BASE_HPP
#endif // NFD_DAEMON_FACE_NULL_TRANSPORT_HPP
+15 -13
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-2019, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -24,6 +24,7 @@
*/
#include "pcap-helper.hpp"
#include "ethernet-protocol.hpp"
#include <pcap/pcap.h>
#include <unistd.h>
@@ -41,16 +42,17 @@ PcapHelper::PcapHelper(const std::string& interfaceName)
char errbuf[PCAP_ERRBUF_SIZE] = {};
m_pcap = pcap_create(interfaceName.data(), errbuf);
if (!m_pcap)
BOOST_THROW_EXCEPTION(Error("pcap_create: " + std::string(errbuf)));
NDN_THROW(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
NDN_THROW(Error("pcap_set_immediate_mode failed"));
pcap_set_snaplen(m_pcap, ethernet::HDR_LEN + ndn::MAX_NDN_PACKET_SIZE);
pcap_set_buffer_size(m_pcap, 4 * 1024 * 1024);
}
PcapHelper::~PcapHelper()
@@ -63,13 +65,13 @@ PcapHelper::activate(int dlt)
{
int ret = pcap_activate(m_pcap);
if (ret < 0)
BOOST_THROW_EXCEPTION(Error("pcap_activate: " + std::string(pcap_statustostr(ret))));
NDN_THROW(Error("pcap_activate: " + std::string(pcap_statustostr(ret))));
if (pcap_set_datalink(m_pcap, dlt) < 0)
BOOST_THROW_EXCEPTION(Error("pcap_set_datalink: " + getLastError()));
NDN_THROW(Error("pcap_set_datalink: " + getLastError()));
if (pcap_setdirection(m_pcap, PCAP_D_IN) < 0)
BOOST_THROW_EXCEPTION(Error("pcap_setdirection: " + getLastError()));
NDN_THROW(Error("pcap_setdirection: " + getLastError()));
}
void
@@ -86,7 +88,7 @@ PcapHelper::getFd() const
{
int fd = pcap_get_selectable_fd(m_pcap);
if (fd < 0)
BOOST_THROW_EXCEPTION(Error("pcap_get_selectable_fd failed"));
NDN_THROW(Error("pcap_get_selectable_fd failed"));
// we need to duplicate the fd, otherwise both pcap_close() and the
// caller may attempt to close the same fd and one of them will fail
@@ -104,7 +106,7 @@ PcapHelper::getNDropped() const
{
pcap_stat ps{};
if (pcap_stats(m_pcap, &ps) < 0)
BOOST_THROW_EXCEPTION(Error("pcap_stats: " + getLastError()));
NDN_THROW(Error("pcap_stats: " + getLastError()));
return ps.ps_drop;
}
@@ -114,12 +116,12 @@ PcapHelper::setPacketFilter(const char* filter) const
{
bpf_program prog;
if (pcap_compile(m_pcap, &prog, filter, 1, PCAP_NETMASK_UNKNOWN) < 0)
BOOST_THROW_EXCEPTION(Error("pcap_compile: " + getLastError()));
NDN_THROW(Error("pcap_compile: " + getLastError()));
int ret = pcap_setfilter(m_pcap, &prog);
pcap_freecode(&prog);
if (ret < 0)
BOOST_THROW_EXCEPTION(Error("pcap_setfilter: " + getLastError()));
NDN_THROW(Error("pcap_setfilter: " + getLastError()));
}
std::tuple<const uint8_t*, size_t, std::string>
+64 -1
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-2019, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -24,6 +24,7 @@
*/
#include "protocol-factory.hpp"
#include <boost/range/adaptor/map.hpp>
#include <boost/range/algorithm/copy.hpp>
@@ -66,5 +67,67 @@ ProtocolFactory::ProtocolFactory(const CtorParams& params)
BOOST_ASSERT(netmon != nullptr);
}
ProtocolFactory::~ProtocolFactory() = default;
void
ProtocolFactory::processConfig(OptionalConfigSection configSection,
FaceSystem::ConfigContext& context)
{
doProcessConfig(configSection, context);
}
void
ProtocolFactory::doProcessConfig(OptionalConfigSection,
FaceSystem::ConfigContext&)
{
}
void
ProtocolFactory::createFace(const CreateFaceRequest& req,
const FaceCreatedCallback& onCreated,
const FaceCreationFailedCallback& onFailure)
{
BOOST_ASSERT(!FaceUri::canCanonize(req.remoteUri.getScheme()) ||
req.remoteUri.isCanonical());
BOOST_ASSERT(!req.localUri || !FaceUri::canCanonize(req.localUri->getScheme()) ||
req.localUri->isCanonical());
doCreateFace(req, onCreated, onFailure);
}
void
ProtocolFactory::doCreateFace(const CreateFaceRequest&,
const FaceCreatedCallback&,
const FaceCreationFailedCallback& onFailure)
{
onFailure(406, "Unsupported protocol");
}
shared_ptr<Face>
ProtocolFactory::createNetdevBoundFace(const FaceUri& remote,
const shared_ptr<const ndn::net::NetworkInterface>& netif)
{
BOOST_ASSERT(remote.isCanonical());
return doCreateNetdevBoundFace(remote, netif);
}
shared_ptr<Face>
ProtocolFactory::doCreateNetdevBoundFace(const FaceUri&,
const shared_ptr<const ndn::net::NetworkInterface>&)
{
NDN_THROW(Error("This protocol factory does not support netdev-bound faces"));
}
std::vector<shared_ptr<const Channel>>
ProtocolFactory::getChannels() const
{
return doGetChannels();
}
std::vector<shared_ptr<const Channel>>
ProtocolFactory::doGetChannels() const
{
return {};
}
} // namespace face
} // namespace nfd
+101 -43
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2018, Regents of the University of California,
* Copyright (c) 2014-2019, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -27,11 +27,11 @@
#define NFD_DAEMON_FACE_PROTOCOL_FACTORY_HPP
#include "channel.hpp"
#include "face.hpp"
#include "face-system.hpp"
#include <boost/range/adaptor/map.hpp>
#include <boost/range/algorithm/copy.hpp>
#include <ndn-cxx/encoding/nfd-constants.hpp>
namespace nfd {
namespace face {
@@ -62,7 +62,7 @@ public: // registry
using CtorParams = ProtocolFactoryCtorParams;
/** \brief Register a protocol factory type
* \tparam S subclass of ProtocolFactory
* \tparam PF subclass of ProtocolFactory
* \param id factory identifier
*/
template<typename PF>
@@ -71,16 +71,16 @@ public: // registry
{
Registry& registry = getRegistry();
BOOST_ASSERT(registry.count(id) == 0);
registry[id] = &make_unique<PF, const CtorParams&>;
registry[id] = [] (const CtorParams& p) { return make_unique<PF>(p); };
}
/** \brief Create a protocol factory instance
* \retval nullptr if factory with \p id is not registered
* \retval nullptr if a factory with the given \p id is not registered
*/
static unique_ptr<ProtocolFactory>
create(const std::string& id, const CtorParams& params);
/** \brief Get registered protocol factory ids
/** \brief Get all registered protocol factory ids
*/
static std::set<std::string>
listRegistered();
@@ -91,44 +91,40 @@ public:
class Error : public std::runtime_error
{
public:
explicit
Error(const std::string& what)
: std::runtime_error(what)
{
}
using std::runtime_error::runtime_error;
};
explicit
ProtocolFactory(const CtorParams& params);
virtual
~ProtocolFactory() = default;
~ProtocolFactory() = 0;
#ifdef DOXYGEN
/** \brief Get id for this ProtocolFactory
/** \brief Get id for this protocol factory
*
* face_system.factory-id config section is processed by the protocol factory.
*/
static const std::string&
getId();
getId() noexcept;
#endif
/** \brief Process face_system subsection that corresponds to this ProtocolFactory type
* \param configSection the configuration section or boost::null to indicate it is omitted
* \param context provides access to data structures and contextual information
* \throw ConfigFile::Error invalid configuration
*
* This function updates \p providedSchemes
*/
virtual void
processConfig(OptionalConfigSection configSection,
FaceSystem::ConfigContext& context) = 0;
/** \brief Get FaceUri schemes accepted by this ProtocolFactory
/** \brief Get FaceUri schemes accepted by this protocol factory
*/
const std::set<std::string>&
getProvidedSchemes()
getProvidedSchemes() const
{
return providedSchemes;
}
/** \brief Process face_system subsection that corresponds to this protocol factory id
* \param configSection the configuration section or boost::none to indicate it is omitted
* \param context provides access to data structures and contextual information
* \throw ConfigFile::Error invalid configuration
*/
void
processConfig(OptionalConfigSection configSection, FaceSystem::ConfigContext& context);
/** \brief Encapsulates a face creation request and all its parameters
*
* Parameters are passed as a struct rather than individually, so that a future change in the list
@@ -141,25 +137,35 @@ public:
FaceParams params;
};
/** \brief Try to create a unicast face using the supplied parameters
*
* \param req request object containing the face creation parameters
* \param onCreated callback if face creation succeeds or face already exists; the settings
* of an existing face are not updated if they differ from the request
* \param onFailure callback if face creation fails
/** \brief Create a unicast face
* \param req request object containing the face creation parameters
* \param onCreated callback if face creation succeeds or face already exists; the settings
* of an existing face are not updated if they differ from the request
* \param onFailure callback if face creation fails
*/
virtual void
void
createFace(const CreateFaceRequest& req,
const FaceCreatedCallback& onCreated,
const FaceCreationFailedCallback& onFailure) = 0;
const FaceCreationFailedCallback& onFailure);
virtual std::vector<shared_ptr<const Channel>>
getChannels() const = 0;
/** \brief Create a netdev-bound face
* \param remote remote FaceUri, must be canonical
* \param netdev local network interface
* \return new face
* \throw Error cannot create a face using specified arguments
* \note The caller must ensure there is no existing netdev-bound face with same remote FaceUri
* on the same local network interface.
*/
shared_ptr<Face>
createNetdevBoundFace(const FaceUri& remote,
const shared_ptr<const ndn::net::NetworkInterface>& netdev);
/** \brief Get list of open channels (listening + non-listening)
*/
std::vector<shared_ptr<const Channel>>
getChannels() const;
protected:
explicit
ProtocolFactory(const CtorParams& params);
template<typename ChannelMap>
static std::vector<shared_ptr<const Channel>>
getChannelsFromMap(const ChannelMap& channelMap)
@@ -169,6 +175,58 @@ protected:
return channels;
}
private:
/** \brief Process face_system subsection that corresponds to this protocol factory id
* \sa processConfig
*
* A subclass should override this method if it supports configuration options in the config
* file, and do all the required processing here. The subclass should throw ConfigFile::Error
* if it encounters unrecognized options or invalid values. It should also update
* \p providedSchemes as needed.
*
* The base class implementation does nothing.
*/
virtual void
doProcessConfig(OptionalConfigSection configSection, FaceSystem::ConfigContext& context);
/** \brief Create a unicast face
* \sa createFace
*
* The base class implementation always invokes the failure callback with error code 406,
* indicating unicast face creation is not supported.
*/
virtual void
doCreateFace(const CreateFaceRequest& req,
const FaceCreatedCallback& onCreated,
const FaceCreationFailedCallback& onFailure);
/** \brief Create a netdev-bound face
* \sa createNetdevBoundFace
*
* The base class implementation always throws Error, indicating netdev-bound faces are not
* supported.
*
* A subclass that offers netdev-bound faces should override this method, and also expose
* "scheme+dev" in providedSchemes. For example, UdpFactory should provide "udp4+dev" scheme,
* in addition to "udp4" scheme.
*
* The face should be constructed immediately. Face persistency shall be reported as PERMANENT.
* Face state shall remain DOWN until underlying transport is connected. The face shall remain
* open until after .close() is invoked, and survive all socket errors; in case the network
* interface disappears, the face shall remain DOWN until .close() is invoked.
*/
virtual shared_ptr<Face>
doCreateNetdevBoundFace(const FaceUri& remote,
const shared_ptr<const ndn::net::NetworkInterface>& netif);
/** \brief Get list of open channels (listening + non-listening)
* \sa getChannels
*
* The base class implementation returns an empty list.
*/
virtual std::vector<shared_ptr<const Channel>>
doGetChannels() const;
private: // registry
using CreateFunc = std::function<unique_ptr<ProtocolFactory>(const CtorParams&)>;
using Registry = std::map<std::string, CreateFunc>; // indexed by factory id
@@ -177,7 +235,7 @@ private: // registry
getRegistry();
protected:
std::set<std::string> providedSchemes; ///< FaceUri schemes provided by this ProtocolFactory
std::set<std::string> providedSchemes; ///< FaceUri schemes provided by this protocol factory
FaceCreatedCallback addFace; ///< callback when a new face is created
/** \brief NetworkMonitor for listing available network interfaces and monitoring their changes
@@ -191,9 +249,9 @@ protected:
} // namespace face
} // namespace nfd
/** \brief registers a protocol factory
/** \brief Registers a protocol factory
*
* This macro should appear once in .cpp of each protocol factory.
* This macro should appear once in the .cpp file of each protocol factory.
*/
#define NFD_REGISTER_PROTOCOL_FACTORY(PF) \
static class NfdAuto ## PF ## ProtocolFactoryRegistrationClass \
+534
View File
@@ -0,0 +1,534 @@
#include "queues.hpp"
#include "common/global.hpp"
#include <ndn-cxx/encoding/estimator.hpp>
namespace nfd
{
namespace face
{
NFD_LOG_INIT(QSCCPQueue);
bool VirtualQueue::push(int seq, const std::shared_ptr<const Interest> &interest,
uint64_t dataSize, bool needInsert)
{
this->recvBits += dataSize;
if (!needInsert)
{
return false;
}
if (this->currentSize >= this->size)
{
return false;
}
this->lastSeq = seq;
VirtualQueueItem vqi;
vqi.seq = seq;
vqi.item = interest;
vqi.queue = shared_from_this();
vqi.dataSize = dataSize;
this->innerQueue.push_back(vqi);
this->currentSize++;
auto serviceClass = interest->getServiceClass();
if (serviceClass && *serviceClass > 7)
{
this->penaltyFactor = 0.5;
}
return true;
}
WDRRQueue::WDRRQueue(uint32_t rateLimit, uint32_t availableBandwidth, double weight, const std::string &name,
uint32_t tos, size_t vqSize) : availableBandwidth(availableBandwidth),
weight(weight), name(name), tos(tos), vqSize(vqSize)
{
if (rateLimit > 0)
{
this->needRateLimit = true;
this->tokenBucket = std::make_shared<TokenBucket>(rateLimit, 20 * 1000 * 8, name);
// this->tokenBucket->start();
}
else
{
this->needRateLimit = false;
}
}
void WDRRQueue::updateAvailableBandwidth(uint32_t C)
{
this->availableBandwidth = C;
}
bool WDRRQueue::appendInterest(const Interest &interest)
{
std::string key = interest.getName().getPrefix(1).toUri();
if (this->virtualQueues.count(key) == 0)
{
this->virtualQueues[key] = std::make_shared<VirtualQueue>(1, this->vqSize);
this->virtualQueues[key]->tos = this->tos;
this->flows.push_back(key);
this->totalWeight += 1;
for (auto &item : this->virtualQueues)
{
item.second->objectRate = this->availableBandwidth * item.second->weight / this->totalWeight;
item.second->objectRate = item.second->objectRate * item.second->penaltyFactor;
}
}
bool needInsert = true;
if (this->cdt > 0 && this->currentPacketNum >= this->cdt)
{
needInsert = false;
}
uint64_t dataSize = 9000;
auto dsz = interest.getDsz();
if (dsz)
{
dataSize = *dsz;
}
this->recvBits += dataSize;
auto success = this->virtualQueues[key]->push(0, interest.shared_from_this(), dataSize, needInsert);
if (success)
{
this->currentPacketNum++;
}
return success;
}
std::shared_ptr<VirtualQueueItem> WDRRQueue::scheduleNext()
{
if (this->nextScheduleQueue >= this->flows.size())
{
for (auto &key : this->flows)
{
if (this->virtualQueues.count(key) == 0)
{
continue;
}
auto &item = this->virtualQueues[key];
item->balance += item->weight * item->penaltyFactor * this->MTU_QUANTA;
}
this->nextScheduleQueue = 0;
}
std::shared_ptr<VirtualQueue> selectedVQ = nullptr;
for (; this->nextScheduleQueue < this->flows.size(); this->nextScheduleQueue++)
{
auto &item = this->virtualQueues[this->flows[this->nextScheduleQueue]];
if (item->empty())
{
item->balance = 0;
continue;
}
if (item->front().dataSize < item->balance)
{
selectedVQ = item;
break;
}
if (item->len() > 10)
{
}
}
if (selectedVQ == nullptr && this->currentPacketNum > 0)
{
return scheduleNext();
}
if (selectedVQ != nullptr)
{
if (needRateLimit && !this->tokenBucket->use(selectedVQ->front().dataSize))
{
return nullptr;
}
auto item = std::make_shared<VirtualQueueItem>(selectedVQ->front());
selectedVQ->balance -= item->dataSize;
selectedVQ->pop();
if (selectedVQ->penaltyFactor < 0.9)
{
item->item->setServiceClass(selectedVQ->tos + 8);
}
this->sendBits += item->dataSize;
this->currentPacketNum--;
return item;
}
return nullptr;
}
uint32_t WDRRQueue::calObjectRate(bool getCurrentRateOnly)
{
uint32_t currentRate = this->recvBits * 1000 / this->calObjectRateInterval;
uint32_t currentSendRate = this->sendBits * 1000 / this->calObjectRateInterval;
if (getCurrentRateOnly)
{
return currentRate;
}
// if (currentRate > 0) {
// std::cout << "currentRate: " << currentRate << ", " << this->recvBits << "," << this->calObjectRateInterval << ", AvaliableBandwidth: " << this->availableBandwidth << std::endl;
// }
bool hasCleanFlow = false;
for (auto it = this->virtualQueues.begin(); it != this->virtualQueues.end();)
{
// std::cout << "key: " << it->first << ", recvBits" << it->second->recvBits << std::endl;
if (it->second->recvBits == 0 && it->second->empty())
{
this->totalWeight -= it->second->weight;
this->virtualQueues.erase(it++); // here is the key
// std::cout << "do clean: " << std::endl;
hasCleanFlow = true;
}
else
{
it++;
}
}
if (hasCleanFlow)
{
this->flows.resize(this->virtualQueues.size());
int idx = 0;
for (auto it = this->virtualQueues.begin(); it != this->virtualQueues.end(); it++, idx++)
{
this->flows[idx] = it->first;
}
}
double totalHightSpeedFlowWeight = 0;
int hightSppedFlowNum = 0;
uint32_t consumeRate = 0;
double totalWeightThisTerm = 0;
for (auto &item : this->virtualQueues)
{
totalWeightThisTerm += (item.second->weight * item.second->penaltyFactor);
}
for (auto &item : this->virtualQueues)
{
item.second->objectRate = this->availableBandwidth * item.second->weight * item.second->penaltyFactor / totalWeightThisTerm;
item.second->currentFlowRate = item.second->recvBits * 1000 / this->calObjectRateInterval;
item.second->currentRatio = item.second->currentFlowRate * 1.0 / item.second->objectRate;
auto targetHighFlowRate = (item.second->objectRate - 500000) * 1.0 / item.second->objectRate;
if (item.second->currentRatio > targetHighFlowRate)
{
if (item.second->penaltyFactor > 0.99)
{
hightSppedFlowNum++;
totalHightSpeedFlowWeight += item.second->weight;
}
consumeRate += item.second->objectRate;
}
else
{
consumeRate += item.second->currentFlowRate;
}
NFD_LOG_DEBUG(this->name << " => currentRate: " << item.second->currentFlowRate << ", consumerRate: " << consumeRate << ", objectRate: " << item.second->objectRate << ", availableBandwidth" << this->availableBandwidth << ", weight: " << item.second->weight << ", totalWeight: " << this->totalWeight << ", currentSendRate: " << currentSendRate);
// std::cout << this->name << " => currentRate: " << item.second->currentFlowRate << ", consumerRate: " << consumeRate << ", objectRate: " << item.second->objectRate <<
// ", availableBandwidth" << this->availableBandwidth << ", weight: " << item.second->weight << ", totalWeight: " <<
// this->totalWeight << ", currentSendRate: " << currentSendRate << std::endl;
item.second->recvBits = 0;
}
if (consumeRate < this->availableBandwidth && hightSppedFlowNum > 0)
{
auto remainRate = this->availableBandwidth - consumeRate;
for (auto &item : this->virtualQueues)
{
if (item.second->penaltyFactor > 0.99 && item.second->currentRatio > 0.8)
{
item.second->objectRate += (remainRate * item.second->weight / totalHightSpeedFlowWeight);
}
NFD_LOG_DEBUG(this->name << " => objectRate: " << item.second->objectRate << ", remainRate: " << remainRate << ", item.weight: " << item.second->weight << ", totalWeight: " << totalHightSpeedFlowWeight);
// std::cout << this->name << " => objectRate: " << item.second->objectRate << ", remainRate: " <<
// remainRate << ", item.weight: " << item.second->weight << ", totalWeight: " << totalHightSpeedFlowWeight << std::endl;
}
}
for (auto &item : this->virtualQueues)
{
if (item.second->currentFlowRate * 1.0 / item.second->objectRate > item.second->gredyRatio)
{
if (item.second->gredyTimes < item.second->gredyThreshold)
{
item.second->gredyTimes++;
}
if (item.second->gredyTimes == item.second->gredyThreshold)
{
// std::cout << item.first << ": PenaltyFactor => " << item.second->gredyTimes << ", currentFlowRate: " << item.second->currentFlowRate << ", objectRate: " << item.second->objectRate << std::endl;
item.second->penaltyFactor = 0.5;
item.second->size = 20;
}
}
else
{
if (item.second->gredyTimes > 0)
{
item.second->gredyTimes--;
}
}
}
// if (this->virtualQueues.size() > 0)
// {
// std::cout << "\n\n=====================: " << this->availableBandwidth << std::endl;
// }
for (auto &item : this->virtualQueues)
{
if (item.second->penaltyFactor > 0.99)
{
auto rate = this->calDiscountFactor(item.second->currentSize * 1.0 / item.second->size);
item.second->objectRate *= rate;
}
// std::cout << item.first << ", currentFlowRate: " << item.second->currentFlowRate
// << ", objectRate: " << item.second->objectRate << ", size: " << item.second->currentSize
// << ", weight: " << item.second->weight << ", penaltyFactor: " << item.second->penaltyFactor
// << std::endl;
}
// if (this->virtualQueues.size() > 0)
// {
// std::cout << "\n----------------------" << std::endl;
// }
this->sendBits = 0;
this->recvBits = 0;
return currentRate;
}
uint32_t WDRRQueue::scheduleOnePacketForWFQ(uint32_t totalLastSeq)
{
if (this->cachePacketForWFQ != nullptr)
{
return this->cachePacketForWFQ->seq;
}
if (this->currentPacketNum == 0)
{
return UINT32_MAX;
}
this->cachePacketForWFQ = this->scheduleNext();
if (this->cachePacketForWFQ == nullptr)
{
return UINT32_MAX;
}
if (this->lastSeq == -1)
{
this->lastSeq = totalLastSeq;
}
this->cachePacketForWFQ->seq = this->lastSeq + 1.0 * this->cachePacketForWFQ->dataSize / this->weight;
if (this->currentPacketNum == 0)
{
this->lastSeq = -1;
}
else
{
this->lastSeq = this->cachePacketForWFQ->seq;
}
return this->cachePacketForWFQ->seq;
}
std::shared_ptr<VirtualQueueItem> DelaySensitiveServiceSP::scheduleNext()
{
auto res = this->CS7Queue->scheduleNext();
if (res == nullptr)
{
res = this->CS6Queue->scheduleNext();
}
if (res == nullptr)
{
res = this->EFQueue->scheduleNext();
}
return res;
}
uint32_t DelaySensitiveServiceSP::calObjectRate(bool getCurrentRateOnly)
{
uint32_t res = this->CS7Queue->calObjectRate(getCurrentRateOnly);
res += this->CS6Queue->calObjectRate(getCurrentRateOnly);
res += this->EFQueue->calObjectRate(getCurrentRateOnly);
return res;
}
std::shared_ptr<VirtualQueueItem> WFQQueue::scheduleNext()
{
std::shared_ptr<WDRRQueue> selectedQueue = nullptr;
uint32_t currentMinSeq = UINT32_MAX;
for (auto &queue : this->queues)
{
uint32_t seq = queue->scheduleOnePacketForWFQ(this->lastSeq);
if (seq < currentMinSeq)
{
currentMinSeq = seq;
selectedQueue = queue;
}
}
if (selectedQueue != nullptr)
{
this->lastSeq = currentMinSeq;
auto selectPacket = selectedQueue->frontForWFQ(this->lastSeq);
selectedQueue->popForWFQ();
return selectPacket;
}
return nullptr;
}
uint32_t WFQQueue::calObjectRate(uint32_t availableBandwidth)
{
int totalRate = 0;
double totalHightSpeedFlowWeight = 0;
int hightSppedFlowNum = 0;
double totalHasFlowQueueWeight = 0;
int hasFlowQueueNum = 0;
for (auto &queue : this->queues)
{
auto recvRate = queue->calObjectRate(true);
queue->originAvaliableBandwidth = (queue->getWeight() / totalWeight) * availableBandwidth;
auto remainRate = queue->getRemainBandwidthRate(queue->originAvaliableBandwidth);
if (remainRate < 0.2)
{
hightSppedFlowNum++;
totalHightSpeedFlowWeight += queue->getWeight();
totalRate += queue->originAvaliableBandwidth;
}
else if (remainRate < 0.95)
{
hasFlowQueueNum++;
totalHasFlowQueueWeight += queue->getWeight();
totalRate += recvRate;
}
else
{
totalRate += recvRate;
}
}
this->availableBandwidth = availableBandwidth;
int remain = this->availableBandwidth - totalRate;
if (hightSppedFlowNum > 0)
{
// std::cout << "high speed flow num: " << hightSppedFlowNum << ", totalHightSpeedFlowWeight: " << totalHightSpeedFlowWeight << std::endl;
for (auto &queue : this->queues)
{
if (queue->getRemainBandwidthRate(queue->originAvaliableBandwidth) < 0.2)
{
// std::cout << "!!!" << queue->getWeight() * remain * 1.0 / totalHightSpeedFlowWeight +
// queue->originAvaliableBandwidth << std::endl;
queue->updateAvailableBandwidth(
queue->getWeight() * remain * 1.0 / totalHightSpeedFlowWeight +
queue->originAvaliableBandwidth);
}
else
{
queue->updateAvailableBandwidth(queue->originAvaliableBandwidth);
}
}
}
else
{
// std::cout << "has flow queue num: " << hasFlowQueueNum << ", totalHasFlowQueueWeight: " << totalHasFlowQueueWeight << std::endl;
for (auto &queue : this->queues)
{
if (queue->getRemainBandwidthRate(queue->originAvaliableBandwidth) < 0.95)
{
queue->updateAvailableBandwidth(
queue->getWeight() * remain * 1.0 / totalHasFlowQueueWeight +
queue->originAvaliableBandwidth);
}
else
{
queue->updateAvailableBandwidth(queue->originAvaliableBandwidth);
}
}
}
uint32_t currentTotalRate = 0;
for (auto &queue : this->queues)
{
currentTotalRate += queue->calObjectRate(false);
}
return currentTotalRate;
}
std::shared_ptr<VirtualQueueItem> GlobalSP::scheduleNext()
{
std::shared_ptr<VirtualQueueItem> selectedPacket = this->delaySensitiveServiceSp.scheduleNext();
if (selectedPacket == nullptr)
{
selectedPacket = wfqQueue.scheduleNext();
}
if (selectedPacket != nullptr)
{
selectedPacket->waitNsTime = selectedPacket->dataSize * 1000000000.0 / this->availableBandwidth + 1;
// 计算 DR => DR'(/p, j) = min(OR(/p, j), RR(/p, j) / sum(RR(/p)) * sum(AR(/p)))
auto currentObjectRate = selectedPacket->queue->objectRate;
auto downstreamRate = selectedPacket->item->getDownstreamRate();
if (downstreamRate)
{
if (*downstreamRate > currentObjectRate)
{
selectedPacket->item->setDownstreamRate(currentObjectRate);
}
}
else
{
selectedPacket->item->setDownstreamRate(currentObjectRate);
}
}
return selectedPacket;
}
std::shared_ptr<WDRRQueue> GlobalSP::getQueueByTos(int tosValue)
{
switch (tosValue)
{
case 0:
return this->delaySensitiveServiceSp.getCS7Queue();
case 1:
return this->delaySensitiveServiceSp.getCS6Queue();
case 2:
return this->delaySensitiveServiceSp.getEFQueue();
case 3:
return this->wfqQueue.getAF4Queue();
case 4:
return this->wfqQueue.getAF3Queue();
case 5:
return this->wfqQueue.getAF2Queue();
case 6:
return this->wfqQueue.getAF1Queue();
case 7:
default:
return this->wfqQueue.getBEQueue();
}
}
bool GlobalSP::appendInterest(const Interest &interest)
{
int serviceClass = 7;
if (interest.getServiceClass())
{
serviceClass = (*interest.getServiceClass()) % 8;
}
// std::cout << "appendInterest => serviceClass: " << serviceClass << std::endl;
return this->getQueueByTos(serviceClass)->appendInterest(interest);
}
void GlobalSP::receiveInterest(const Interest &interest)
{
ndn::encoding::EncodingEstimator estimator;
auto size = interest.wireEncode(estimator) + 9;
this->interestBytes += size;
// std::cout << this << "receiveInterest => size: " << size << ", interestBytes: " << this->interestBytes << std::endl;
}
void GlobalSP::calObjectRate(bool getCurrentRateOnly)
{
// getScheduler().schedule(time::nanoseconds(1000000 * this->calObjectRateInterval),
// [this] { this->calObjectRate(false); });
uint32_t remain = this->availableBandwidth;
remain -= this->interestBytes * 8000 / this->calObjectRateInterval;
this->interestBytes = 0;
remain -= this->delaySensitiveServiceSp.calObjectRate(false);
// std::cout << "AvaliableBandwidth: " << this->availableBandwidth << ", remain: " << remain << ", interestBytes" << this->interestBytes << std::endl;
this->wfqQueue.calObjectRate(remain);
}
void GlobalSP::assignObjectRate(const Data &data)
{
std::string key = data.getName().getPrefix(1).toUri();
int serviceClass = 7;
if (data.getServiceClass())
{
serviceClass = (*data.getServiceClass()) % 8;
}
// std::cout << "assignObjectRate => serviceClass: " << serviceClass << std::endl;
auto objectRate = this->getQueueByTos(serviceClass)->getObjectRateByFlowKey(key);
auto targetRate = data.getTargetRate();
if (!targetRate || *targetRate > objectRate)
{
data.setTargetRate(objectRate);
}
}
}
}
+309
View File
@@ -0,0 +1,309 @@
#ifndef NS_QUEUES_HPP
#define NS_QUEUES_HPP
#include <deque>
#include <unordered_map>
#include <memory>
#include <iostream>
#include "common/global.hpp"
#include "link-service.hpp"
#include <ndn-cxx/lp/tags.hpp>
#include "TokenBucket.hpp"
namespace nfd {
namespace face {
class VirtualQueue;
struct VirtualQueueItem {
int seq;
std::shared_ptr<const Interest> item;
uint32_t dataSize;
uint32_t waitNsTime;
std::shared_ptr<VirtualQueue> queue;
};
class VirtualQueue : public std::enable_shared_from_this<VirtualQueue>{
public:
explicit VirtualQueue(double weight, int size) :
std::enable_shared_from_this<VirtualQueue>(),
penaltyFactor(1.0),
weight(weight), size(size), currentSize(0), lastSeq(0),
C(0) {
}
void enableTokenBucket(uint32_t limitRate) {
this->C = limitRate;
}
bool push(int seq, const std::shared_ptr<const Interest>& interest,
uint64_t dataSize, bool needInsert);
bool empty() {
return this->innerQueue.empty();
}
uint32_t frontSeq() {
if (this->innerQueue.empty()) {
return this->lastSeq;
}
return this->innerQueue.front().seq;
}
VirtualQueueItem front() {
return this->innerQueue.front();
}
uint32_t backSeq() {
return this->lastSeq;
}
VirtualQueueItem back() {
return this->innerQueue.back();
}
void pop() {
if (this->currentSize <= 0) {
return;
}
this->currentSize--;
this->innerQueue.pop_front();
}
void popBack() {
if (this->currentSize <= 0) {
return;
}
this->currentSize--;
this->innerQueue.pop_back();
}
int len() {
return this->innerQueue.size();
}
void setLastSeq(uint32_t seq) {
this->lastSeq = seq;
}
uint32_t getLastSeq() {
return lastSeq;
}
void setWeight(double weight) {
this->weight = weight;
}
double getWeight() {
return this->weight;
}
public:
uint32_t objectRate;
double penaltyFactor = 1.0;
uint32_t gredyTimes = 0;
double gredyRatio = 1.2;
double gredyThreshold = 10;
double weight = 1.0;
uint32_t tos = 5;
double balance = 0;
int size = 0;
int currentSize = 0;
uint32_t recvBits = 0;
uint32_t currentFlowRate = 0;
double currentRatio = 0.0;
private:
uint32_t lastSeq;
int C;
std::deque<VirtualQueueItem> innerQueue;
};
class WDRRQueue {
public:
explicit WDRRQueue(uint32_t rateLimit, uint32_t availableBandwidth, double weight, const std::string& name,
uint32_t tos = 5, size_t vqSize = 20);
void updateAvailableBandwidth(uint32_t C);
bool appendInterest(const Interest &interest);
std::shared_ptr<VirtualQueueItem> scheduleNext();
uint32_t calObjectRate(bool getCurrentRateOnly);
void setCDTLimit(int cdt) {
this->cdt = cdt;
}
uint32_t scheduleOnePacketForWFQ(uint32_t totalLastSeq);
std::shared_ptr<VirtualQueueItem> frontForWFQ(uint32_t totalLastSeq) {
if (this->cachePacketForWFQ == nullptr) {
this->scheduleOnePacketForWFQ(totalLastSeq);
}
return this->cachePacketForWFQ;
}
void popForWFQ() {
this->cachePacketForWFQ = nullptr;
}
double getRemainBandwidthRate(double curAvailableBandWidth) {
auto currentRate = this->calObjectRate(true);
if (currentRate > curAvailableBandWidth) {
return 0;
}
return (curAvailableBandWidth - currentRate) * 1.0 / curAvailableBandWidth;
}
uint32_t getRemainBandwidth() {
return this->availableBandwidth - this->calObjectRate(true);
}
double getWeight() {
return this->weight;
}
uint32_t getAvailableBandwidth() {
return this->availableBandwidth;
}
/**
* @brief
*
* \sigma=\frac{1}{3}\arccot\funcapply(8\delta-4)
* @param x
* @return double
*/
double calDiscountFactor(double x) {
return 1.0 / 3 * (M_PI / 2 - atan(8 * x - 4)) + 0.034;
}
/**
* @brief Get the Object Rate By Flow Key object
*
* @param key
* @return uint32_t
*/
uint32_t getObjectRateByFlowKey(const std::string& key) {
if (this->virtualQueues.count(key) == 0) {
std::cout << "FUCK: " << key << ", count: " << this->virtualQueues.size() <<
", flow: " << this->flows.size() << "availbleRate: " << this->availableBandwidth << std::endl;
return 0;
}
return this->virtualQueues[key]->objectRate;
}
void triggerByCurrentTime(long currentTime) {
if (this->needRateLimit) {
this->tokenBucket->generateTokenByCurrentTime(currentTime);
}
}
public:
double originAvaliableBandwidth = 0;
private:
std::unordered_map<std::string, std::shared_ptr<VirtualQueue>> virtualQueues;
std::vector<std::string> flows;
size_t nextScheduleQueue = 0;
std::shared_ptr<TokenBucket> tokenBucket;
uint32_t availableBandwidth;
// uint32_t extraBandwidth;
double weight;
std::string name;
uint32_t tos = 5;
bool needRateLimit;
double totalWeight;
uint32_t sendBits = 0;
uint32_t recvBits = 0;
int vqSize = 20;
int cdt = -1;
int currentPacketNum = 0;
int MTU_QUANTA = 2 * 1000 * 8;
int calObjectRateInterval = 100;
int64_t lastSeq = -1;
std::shared_ptr<VirtualQueueItem> cachePacketForWFQ = nullptr;
};
class DelaySensitiveServiceSP {
public:
explicit DelaySensitiveServiceSP(uint32_t availableBandwidth, size_t vqSize = 20) {
this->CS7Queue = std::make_shared<WDRRQueue>((uint32_t) (0.2 * availableBandwidth), (uint32_t) (0.2 * availableBandwidth), 2, "CS7", 2, vqSize);
this->CS6Queue = std::make_shared<WDRRQueue>((uint32_t) (0.2 * availableBandwidth), (uint32_t) (0.2 * availableBandwidth), 2, "CS6", 1, vqSize);
this->EFQueue = std::make_shared<WDRRQueue>((uint32_t) (0.3 * availableBandwidth), (uint32_t) (0.3 * availableBandwidth), 3, "EF", 0, vqSize);
}
std::shared_ptr<VirtualQueueItem> scheduleNext();
uint32_t calObjectRate(bool getCurrentRateOnly);
std::shared_ptr<WDRRQueue> getCS7Queue() {
return this->CS7Queue;
}
std::shared_ptr<WDRRQueue> getCS6Queue() {
return this->CS6Queue;
}
std::shared_ptr<WDRRQueue> getEFQueue() {
return this->EFQueue;
}
void triggerByCurrentTime(long currentTime) {
this->CS7Queue->triggerByCurrentTime(currentTime);
this->CS6Queue->triggerByCurrentTime(currentTime);
this->EFQueue->triggerByCurrentTime(currentTime);
}
private:
std::shared_ptr<WDRRQueue> CS7Queue;
std::shared_ptr<WDRRQueue> CS6Queue;
std::shared_ptr<WDRRQueue> EFQueue;
};
class WFQQueue {
public:
explicit WFQQueue(uint32_t availableBandwidth, size_t vqSize) :
AF4Weight(5),
AF3Weight(4),
AF2Weight(3),
AF1Weight(2),
BEWeight(1),
totalWeight(AF4Weight + AF3Weight + AF2Weight + AF1Weight + BEWeight),
queues(5),
lastSeq(0),
availableBandwidth(availableBandwidth) {
this->queues[0] = std::make_shared<WDRRQueue>(0, availableBandwidth * AF4Weight / totalWeight, 5, "AF4", 3, vqSize);
this->queues[1] = std::make_shared<WDRRQueue>(0, availableBandwidth * AF3Weight / totalWeight, 4, "AF3", 4, vqSize);
this->queues[2] = std::make_shared<WDRRQueue>(0, availableBandwidth * AF2Weight / totalWeight, 3, "AF2", 5, vqSize);
this->queues[3] = std::make_shared<WDRRQueue>(0, availableBandwidth * AF1Weight / totalWeight, 2, "AF1", 6, vqSize);
this->queues[4] = std::make_shared<WDRRQueue>(0, availableBandwidth * BEWeight / totalWeight, 1, "BE", 7, vqSize);
for (auto &queue: this->queues) {
queue->setCDTLimit(this->cdt);
}
}
std::shared_ptr<VirtualQueueItem> scheduleNext();
uint32_t calObjectRate(uint32_t availableBandwidth);
std::shared_ptr<WDRRQueue> getAF4Queue() {
return this->queues[0];
}
std::shared_ptr<WDRRQueue> getAF3Queue() {
return this->queues[1];
}
std::shared_ptr<WDRRQueue> getAF2Queue() {
return this->queues[2];
}
std::shared_ptr<WDRRQueue> getAF1Queue() {
return this->queues[3];
}
std::shared_ptr<WDRRQueue> getBEQueue() {
return this->queues[4];
}
private:
double AF4Weight = 5;
double AF3Weight = 4;
double AF2Weight = 3;
double AF1Weight = 2;
double BEWeight = 1;
double totalWeight = 15;
std::vector<std::shared_ptr<WDRRQueue>> queues;
uint32_t lastSeq;
u_int32_t availableBandwidth;
int cdt = 200;
int hql;
};
class GlobalSP {
public:
explicit GlobalSP(uint32_t availableBandwidth, size_t vqSize = 20) :
delaySensitiveServiceSp(availableBandwidth, vqSize),
wfqQueue(availableBandwidth, vqSize),
availableBandwidth(availableBandwidth) {
lastTriggerTime = getCurrentTime();
// getScheduler().schedule(time::nanoseconds(1000000 * this->calObjectRateInterval),
// [this] { this->calObjectRate(false); });
}
std::shared_ptr<VirtualQueueItem> scheduleNext();
bool appendInterest(const Interest &interest);
void receiveInterest(const Interest &interest);
void calObjectRate(bool getCurrentRateOnly);
std::shared_ptr<WDRRQueue> getQueueByTos(int tosValue);
long getCurrentTime() {
return std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch()).count();
}
void triggerCalObjectRate() {
auto currentTime = getCurrentTime();
this->delaySensitiveServiceSp.triggerByCurrentTime(currentTime);
if (currentTime - lastTriggerTime > calObjectRateInterval) {
this->calObjectRate(false);
lastTriggerTime = currentTime;
}
}
void assignObjectRate(const Data &data);
private:
DelaySensitiveServiceSP delaySensitiveServiceSp;
WFQQueue wfqQueue;
int calObjectRateInterval = 100;
uint32_t availableBandwidth;
size_t interestBytes = 0;
long lastTriggerTime = 0;
};
}
}
#endif //NS_QUEUES_HPP
Loaded 100 of 554 files, more files were not shown because too many files have changed in this diff. Show more