tools: add congestion marking parameters to nfdc face create
refs #4465
Change-Id: I5df5d6136f4729ad836a72f55531208d868da5f7
diff --git a/daemon/mgmt/face-manager.cpp b/daemon/mgmt/face-manager.cpp
index 04e80a9..2be2e0b 100644
--- a/daemon/mgmt/face-manager.cpp
+++ b/daemon/mgmt/face-manager.cpp
@@ -459,6 +459,8 @@
traits.setFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED, linkServiceOptions.allowLocalFields);
traits.setFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED,
linkServiceOptions.reliabilityOptions.isEnabled);
+ traits.setFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED,
+ linkServiceOptions.allowCongestionMarking);
}
}
diff --git a/docs/_static/nfd-status.xsd b/docs/_static/nfd-status.xsd
index a34b2f2..2ad1eeb 100644
--- a/docs/_static/nfd-status.xsd
+++ b/docs/_static/nfd-status.xsd
@@ -4,6 +4,12 @@
targetNamespace="ndn:/localhost/nfd/status/1" xmlns:nfd="ndn:/localhost/nfd/status/1"
elementFormDefault="qualified">
+<xs:simpleType name="emptyType">
+ <xs:restriction base="xs:string">
+ <xs:maxLength value="0"/>
+ </xs:restriction>
+</xs:simpleType>
+
<xs:complexType name="unidirectionalPacketCountersType">
<xs:sequence>
<xs:element type="xs:nonNegativeInteger" name="nInterests"/>
@@ -53,6 +59,21 @@
</xs:sequence>
</xs:complexType>
+<xs:complexType name="congestionParamsType">
+ <xs:sequence>
+ <xs:element type="xs:duration" name="baseMarkingInterval" minOccurs="0"/>
+ <xs:element type="xs:nonNegativeInteger" name="defaultThreshold" minOccurs="0"/>
+ </xs:sequence>
+</xs:complexType>
+
+<xs:complexType name="faceFlagsType">
+ <xs:sequence>
+ <xs:element type="nfd:emptyType" name="localFieldsEnabled" minOccurs="0"/>
+ <xs:element type="nfd:emptyType" name="lpReliabilityEnabled" minOccurs="0"/>
+ <xs:element type="nfd:emptyType" name="congestionMarkingEnabled" minOccurs="0"/>
+ </xs:sequence>
+</xs:complexType>
+
<xs:complexType name="faceType">
<xs:sequence>
<xs:element type="xs:nonNegativeInteger" name="faceId"/>
@@ -62,6 +83,8 @@
<xs:element type="xs:string" name="faceScope"/>
<xs:element type="xs:string" name="facePersistency"/>
<xs:element type="xs:string" name="linkType"/>
+ <xs:element type="nfd:congestionParamsType" name="congestion"/>
+ <xs:element type="nfd:faceFlagsType" name="flags"/>
<xs:element type="nfd:bidirectionalPacketCountersType" name="packetCounters"/>
<xs:element type="nfd:bidirectionalByteCountersType" name="byteCounters"/>
</xs:sequence>
diff --git a/docs/manpages/nfdc-face.rst b/docs/manpages/nfdc-face.rst
index 6fd8779..f31a24f 100644
--- a/docs/manpages/nfdc-face.rst
+++ b/docs/manpages/nfdc-face.rst
@@ -5,7 +5,7 @@
--------
| nfdc face [list [[remote] <FACEURI>] [local <FACEURI>] [scheme <SCHEME>]]
| nfdc face show [id] <FACEID>
-| nfdc face create [remote] <FACEURI> [[persistency] <PERSISTENCY>] [local <FACEURI>] [reliability on|off]
+| nfdc face create [remote] <FACEURI> [[persistency] <PERSISTENCY>] [local <FACEURI>] [reliability on|off] [congestion-marking on|off] [congestion-marking-interval <MARKING-INTERVAL>] [default-congestion-threshold <CONGESTION-THRESHOLD>]
| nfdc face destroy [face] <FACEID|FACEURI>
| nfdc channel [list]
@@ -27,6 +27,12 @@
The NDNLPv2 unicast reliability feature may be explicitly enabled by specifying **reliability on**
or explicitly disabled by specifying **reliability off**.
If enabled, this feature must also be enabled on the other endpoint to function properly.
+Reliability is disabled by default.
+The send queue congestion detection and signaling feature may be explicitly enabled by specifying
+**congestion-marking on** or explicitly disabled by specifying **congestion-marking off**.
+Congestion marking is disabled by default.
+Parameters for this feature can set with the **congestion-marking-interval** option (specified in
+milliseconds) and the **default-congestion-threshold** option (specified in bytes).
The **nfdc face destroy** command destroys an existing face.
@@ -69,6 +75,14 @@
A "persistent" face (the default) is closed when a socket error occurs.
A "permanent" face survives socket errors, and is closed only with a **nfdc destroy** command.
+<MARKING-INTERVAL>
+ The initial marking interval (in milliseconds) during an incident of congestion.
+
+<CONGESTION-THRESHOLD>
+ This value serves two purposes:
+ It is the maximum bound of the congestion threshold for the face, as well as the default
+ threshold used if the face does not support retrieving the capacity of the send queue.
+
EXIT CODES
----------
0: Success
@@ -103,6 +117,10 @@
nfdc face create remote udp://router.example.net reliability on
Create a face with the specified remote FaceUri and enable NDNLP reliability.
+nfdc face create remote udp://router.example.net congestion-marking on congestion-marking-interval 100 default-congestion-threshold 65536
+ Create a face with the specified remote FaceUri and enable congestion marking. Set the base
+ congestion marking interval to 100 ms and the default congestion threshold to 65536 bytes.
+
nfdc face destroy 300
Destroy the face whose FaceId is 300.
diff --git a/tests/tools/nfdc/face-module.t.cpp b/tests/tools/nfdc/face-module.t.cpp
index 33e022c..22de100 100644
--- a/tests/tools/nfdc/face-module.t.cpp
+++ b/tests/tools/nfdc/face-module.t.cpp
@@ -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,
@@ -42,11 +42,13 @@
const std::string NONQUERY_OUTPUT =
"faceid=134 remote=udp4://233.252.0.4:6363 local=udp4://192.0.2.1:6363"
+ " congestion={base-marking-interval=12345ms default-threshold=54321B}"
" counters={in={22562i 22031d 63n 2522915B} out={30121i 20940d 1218n 1353592B}}"
" flags={non-local permanent multi-access}\n"
"faceid=745 remote=fd://75 local=unix:///var/run/nfd.sock"
+ " congestion={base-marking-interval=100ms default-threshold=65536B}"
" counters={in={18998i 26701d 147n 4672308B} out={34779i 17028d 1176n 8957187B}}"
- " flags={local on-demand point-to-point local-fields lp-reliability}\n";
+ " flags={local on-demand point-to-point local-fields lp-reliability congestion-marking}\n";
BOOST_AUTO_TEST_CASE(NormalNonQuery)
{
@@ -58,6 +60,8 @@
.setFaceScope(ndn::nfd::FACE_SCOPE_NON_LOCAL)
.setFacePersistency(ndn::nfd::FACE_PERSISTENCY_PERMANENT)
.setLinkType(ndn::nfd::LINK_TYPE_MULTI_ACCESS)
+ .setBaseCongestionMarkingInterval(12345_ms)
+ .setDefaultCongestionThreshold(54321)
.setNInInterests(22562)
.setNInData(22031)
.setNInNacks(63)
@@ -73,8 +77,11 @@
.setFaceScope(ndn::nfd::FACE_SCOPE_LOCAL)
.setFacePersistency(ndn::nfd::FACE_PERSISTENCY_ON_DEMAND)
.setLinkType(ndn::nfd::LINK_TYPE_POINT_TO_POINT)
+ .setBaseCongestionMarkingInterval(100_ms)
+ .setDefaultCongestionThreshold(65536)
.setFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED, true)
.setFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED, true)
+ .setFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED, true)
.setNInInterests(18998)
.setNInData(26701)
.setNInNacks(147)
@@ -94,6 +101,7 @@
const std::string QUERY_OUTPUT =
"faceid=177 remote=tcp4://53.239.9.114:6363 local=tcp4://164.0.31.106:20396"
+ " congestion={base-marking-interval=555ms default-threshold=10000B}"
" counters={in={2325i 1110d 79n 4716834B} out={2278i 485d 841n 308108B}}"
" flags={non-local persistent point-to-point}\n";
@@ -116,6 +124,8 @@
.setFaceScope(ndn::nfd::FACE_SCOPE_NON_LOCAL)
.setFacePersistency(ndn::nfd::FACE_PERSISTENCY_PERSISTENT)
.setLinkType(ndn::nfd::LINK_TYPE_POINT_TO_POINT)
+ .setBaseCongestionMarkingInterval(555_ms)
+ .setDefaultCongestionThreshold(10000)
.setNInInterests(2325)
.setNInData(1110)
.setNInNacks(79)
@@ -159,15 +169,145 @@
BOOST_FIXTURE_TEST_SUITE(ShowCommand, ExecuteCommandFixture)
-const std::string NORMAL_OUTPUT = std::string(R"TEXT(
- faceid=256
- remote=udp4://84.67.35.111:6363
- local=udp4://79.91.49.215:6363
-counters={in={28975i 28232d 212n 13307258B} out={19525i 30993d 1038n 6231946B}}
- flags={non-local on-demand point-to-point}
+const std::string NORMAL_ALL_CONGESTION_OUTPUT = std::string(R"TEXT(
+ faceid=256
+ remote=udp4://84.67.35.111:6363
+ local=udp4://79.91.49.215:6363
+congestion={base-marking-interval=123ms default-threshold=10000B}
+ counters={in={28975i 28232d 212n 13307258B} out={19525i 30993d 1038n 6231946B}}
+ flags={non-local on-demand point-to-point}
)TEXT").substr(1);
-BOOST_AUTO_TEST_CASE(Normal)
+BOOST_AUTO_TEST_CASE(NormalAllCongestionParams)
+{
+ this->processInterest = [this] (const Interest& interest) {
+ BOOST_CHECK(Name("/localhost/nfd/faces/query").isPrefixOf(interest.getName()));
+ BOOST_CHECK_EQUAL(interest.getName().size(), 5);
+ FaceQueryFilter filter(interest.getName().at(4).blockFromValue());
+ BOOST_CHECK_EQUAL(filter, FaceQueryFilter().setFaceId(256));
+
+ FaceStatus payload;
+ payload.setFaceId(256)
+ .setRemoteUri("udp4://84.67.35.111:6363")
+ .setLocalUri("udp4://79.91.49.215:6363")
+ .setFaceScope(ndn::nfd::FACE_SCOPE_NON_LOCAL)
+ .setFacePersistency(ndn::nfd::FACE_PERSISTENCY_ON_DEMAND)
+ .setLinkType(ndn::nfd::LINK_TYPE_POINT_TO_POINT)
+ .setBaseCongestionMarkingInterval(123_ms)
+ .setDefaultCongestionThreshold(10000)
+ .setNInInterests(28975)
+ .setNInData(28232)
+ .setNInNacks(212)
+ .setNOutInterests(19525)
+ .setNOutData(30993)
+ .setNOutNacks(1038)
+ .setNInBytes(13307258)
+ .setNOutBytes(6231946);
+
+ this->sendDataset(interest.getName(), payload);
+ };
+
+ this->execute("face show 256");
+ BOOST_CHECK_EQUAL(exitCode, 0);
+ BOOST_CHECK(out.is_equal(NORMAL_ALL_CONGESTION_OUTPUT));
+ BOOST_CHECK(err.is_empty());
+}
+
+const std::string NORMAL_INTERVAL_CONGESTION_OUTPUT = std::string(R"TEXT(
+ faceid=256
+ remote=udp4://84.67.35.111:6363
+ local=udp4://79.91.49.215:6363
+congestion={base-marking-interval=123ms}
+ counters={in={28975i 28232d 212n 13307258B} out={19525i 30993d 1038n 6231946B}}
+ flags={non-local on-demand point-to-point}
+)TEXT").substr(1);
+
+BOOST_AUTO_TEST_CASE(NormalIntervalCongestionParams)
+{
+ this->processInterest = [this] (const Interest& interest) {
+ BOOST_CHECK(Name("/localhost/nfd/faces/query").isPrefixOf(interest.getName()));
+ BOOST_CHECK_EQUAL(interest.getName().size(), 5);
+ FaceQueryFilter filter(interest.getName().at(4).blockFromValue());
+ BOOST_CHECK_EQUAL(filter, FaceQueryFilter().setFaceId(256));
+
+ FaceStatus payload;
+ payload.setFaceId(256)
+ .setRemoteUri("udp4://84.67.35.111:6363")
+ .setLocalUri("udp4://79.91.49.215:6363")
+ .setFaceScope(ndn::nfd::FACE_SCOPE_NON_LOCAL)
+ .setFacePersistency(ndn::nfd::FACE_PERSISTENCY_ON_DEMAND)
+ .setLinkType(ndn::nfd::LINK_TYPE_POINT_TO_POINT)
+ .setBaseCongestionMarkingInterval(123_ms)
+ .setNInInterests(28975)
+ .setNInData(28232)
+ .setNInNacks(212)
+ .setNOutInterests(19525)
+ .setNOutData(30993)
+ .setNOutNacks(1038)
+ .setNInBytes(13307258)
+ .setNOutBytes(6231946);
+
+ this->sendDataset(interest.getName(), payload);
+ };
+
+ this->execute("face show 256");
+ BOOST_CHECK_EQUAL(exitCode, 0);
+ BOOST_CHECK(out.is_equal(NORMAL_INTERVAL_CONGESTION_OUTPUT));
+ BOOST_CHECK(err.is_empty());
+}
+
+const std::string NORMAL_THRESHOLD_CONGESTION_OUTPUT = std::string(R"TEXT(
+ faceid=256
+ remote=udp4://84.67.35.111:6363
+ local=udp4://79.91.49.215:6363
+congestion={default-threshold=10000B}
+ counters={in={28975i 28232d 212n 13307258B} out={19525i 30993d 1038n 6231946B}}
+ flags={non-local on-demand point-to-point}
+)TEXT").substr(1);
+
+BOOST_AUTO_TEST_CASE(NormalThresholdCongestionParams)
+{
+ this->processInterest = [this] (const Interest& interest) {
+ BOOST_CHECK(Name("/localhost/nfd/faces/query").isPrefixOf(interest.getName()));
+ BOOST_CHECK_EQUAL(interest.getName().size(), 5);
+ FaceQueryFilter filter(interest.getName().at(4).blockFromValue());
+ BOOST_CHECK_EQUAL(filter, FaceQueryFilter().setFaceId(256));
+
+ FaceStatus payload;
+ payload.setFaceId(256)
+ .setRemoteUri("udp4://84.67.35.111:6363")
+ .setLocalUri("udp4://79.91.49.215:6363")
+ .setFaceScope(ndn::nfd::FACE_SCOPE_NON_LOCAL)
+ .setFacePersistency(ndn::nfd::FACE_PERSISTENCY_ON_DEMAND)
+ .setLinkType(ndn::nfd::LINK_TYPE_POINT_TO_POINT)
+ .setDefaultCongestionThreshold(10000)
+ .setNInInterests(28975)
+ .setNInData(28232)
+ .setNInNacks(212)
+ .setNOutInterests(19525)
+ .setNOutData(30993)
+ .setNOutNacks(1038)
+ .setNInBytes(13307258)
+ .setNOutBytes(6231946);
+
+ this->sendDataset(interest.getName(), payload);
+ };
+
+ this->execute("face show 256");
+ BOOST_CHECK_EQUAL(exitCode, 0);
+ BOOST_CHECK(out.is_equal(NORMAL_THRESHOLD_CONGESTION_OUTPUT));
+ BOOST_CHECK(err.is_empty());
+}
+
+const std::string NORMAL_NO_CONGESTION_OUTPUT = std::string(R"TEXT(
+ faceid=256
+ remote=udp4://84.67.35.111:6363
+ local=udp4://79.91.49.215:6363
+ counters={in={28975i 28232d 212n 13307258B} out={19525i 30993d 1038n 6231946B}}
+ flags={non-local on-demand point-to-point}
+)TEXT").substr(1);
+
+BOOST_AUTO_TEST_CASE(NormalNoCongestionParams)
{
this->processInterest = [this] (const Interest& interest) {
BOOST_CHECK(Name("/localhost/nfd/faces/query").isPrefixOf(interest.getName()));
@@ -196,7 +336,7 @@
this->execute("face show 256");
BOOST_CHECK_EQUAL(exitCode, 0);
- BOOST_CHECK(out.is_equal(NORMAL_OUTPUT));
+ BOOST_CHECK(out.is_equal(NORMAL_NO_CONGESTION_OUTPUT));
BOOST_CHECK(err.is_empty());
}
@@ -228,7 +368,9 @@
{
protected:
void
- respond409(const Interest& interest, FacePersistency persistency, bool enableLpReliability = false)
+ respond409(const Interest& interest, FacePersistency persistency,
+ bool enableLpReliability = false,
+ bool enableCongestionMarking = false)
{
MOCK_NFD_MGMT_REQUIRE_COMMAND_IS("/localhost/nfd/faces/create");
ControlParameters body;
@@ -240,6 +382,9 @@
if (enableLpReliability) {
body.setFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED, true, false);
}
+ if (enableCongestionMarking) {
+ body.setFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED, true, false);
+ }
this->failCommand(interest, 409, "conflict-409", body);
}
};
@@ -269,7 +414,7 @@
BOOST_CHECK_EQUAL(exitCode, 0);
BOOST_CHECK(out.is_equal("face-created id=2130 local=udp4://179.63.153.45:28835 "
"remote=udp4://159.242.33.78:6363 persistency=persistent "
- "reliability=off\n"));
+ "reliability=off congestion-marking=off\n"));
BOOST_CHECK(err.is_empty());
}
@@ -291,15 +436,21 @@
.setUri("udp4://22.91.89.51:19903")
.setLocalUri("udp4://98.68.23.71:6363")
.setFacePersistency(FacePersistency::FACE_PERSISTENCY_PERMANENT)
- .setFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED, true, false);
+ .setBaseCongestionMarkingInterval(100_ms)
+ .setDefaultCongestionThreshold(65536)
+ .setFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED, true, false)
+ .setFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED, true, false);
this->succeedCommand(interest, resp);
};
- this->execute("face create udp://22.91.89.51:19903 permanent local udp://98.68.23.71 reliability on");
+ this->execute("face create udp://22.91.89.51:19903 permanent local udp://98.68.23.71 reliability on "
+ "congestion-marking on congestion-marking-interval 100 "
+ "default-congestion-threshold 65536");
BOOST_CHECK_EQUAL(exitCode, 0);
BOOST_CHECK(out.is_equal("face-created id=301 local=udp4://98.68.23.71:6363 "
"remote=udp4://22.91.89.51:19903 persistency=permanent "
- "reliability=on\n"));
+ "reliability=on congestion-marking=on "
+ "congestion-marking-interval=100ms default-congestion-threshold=65536B\n"));
BOOST_CHECK(err.is_empty());
}
@@ -332,7 +483,7 @@
BOOST_CHECK_EQUAL(exitCode, 0);
BOOST_CHECK(out.is_equal("face-updated id=1172 local=udp4://68.62.26.57:24087 "
"remote=udp4://100.77.30.65:6363 persistency=persistent "
- "reliability=off\n"));
+ "reliability=off congestion-marking=off\n"));
BOOST_CHECK(err.is_empty());
}
@@ -347,7 +498,7 @@
BOOST_CHECK_EQUAL(exitCode, 0);
BOOST_CHECK(out.is_equal("face-exists id=1172 local=udp4://68.62.26.57:24087 "
"remote=udp4://100.77.30.65:6363 persistency=permanent "
- "reliability=off\n"));
+ "reliability=off congestion-marking=off\n"));
BOOST_CHECK(err.is_empty());
}
@@ -362,7 +513,7 @@
BOOST_CHECK_EQUAL(exitCode, 0);
BOOST_CHECK(out.is_equal("face-exists id=1172 local=udp4://68.62.26.57:24087 "
"remote=udp4://100.77.30.65:6363 persistency=persistent "
- "reliability=off\n"));
+ "reliability=off congestion-marking=off\n"));
BOOST_CHECK(err.is_empty());
}
@@ -393,7 +544,7 @@
BOOST_CHECK_EQUAL(exitCode, 0);
BOOST_CHECK(out.is_equal("face-updated id=1172 local=udp4://68.62.26.57:24087 "
"remote=udp4://100.77.30.65:6363 persistency=persistent "
- "reliability=on\n"));
+ "reliability=on congestion-marking=off\n"));
BOOST_CHECK(err.is_empty());
}
@@ -424,7 +575,79 @@
BOOST_CHECK_EQUAL(exitCode, 0);
BOOST_CHECK(out.is_equal("face-updated id=1172 local=udp4://68.62.26.57:24087 "
"remote=udp4://100.77.30.65:6363 persistency=persistent "
- "reliability=off\n"));
+ "reliability=off congestion-marking=off\n"));
+ BOOST_CHECK(err.is_empty());
+}
+
+BOOST_AUTO_TEST_CASE(EnablingCongestionMarking)
+{
+ bool hasUpdateCommand = false;
+ this->processInterest = [this, &hasUpdateCommand] (const Interest& interest) {
+ if (parseCommand(interest, "/localhost/nfd/faces/create")) {
+ this->respond409(interest, FacePersistency::FACE_PERSISTENCY_PERSISTENT);
+ return;
+ }
+
+ ControlParameters req = MOCK_NFD_MGMT_REQUIRE_COMMAND_IS("/localhost/nfd/faces/update");
+ hasUpdateCommand = true;
+ BOOST_REQUIRE(req.hasFaceId());
+ BOOST_CHECK_EQUAL(req.getFaceId(), 1172);
+ BOOST_CHECK(req.hasFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED));
+ BOOST_CHECK(req.getFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED));
+ BOOST_CHECK(!req.hasBaseCongestionMarkingInterval());
+ BOOST_CHECK(!req.hasDefaultCongestionThreshold());
+
+ ControlParameters resp;
+ resp.setFaceId(1172)
+ .setFacePersistency(FacePersistency::FACE_PERSISTENCY_PERSISTENT)
+ .setBaseCongestionMarkingInterval(100_ms)
+ .setDefaultCongestionThreshold(65536)
+ .setFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED, true, false);
+ this->succeedCommand(interest, resp);
+ };
+
+ this->execute("face create udp://100.77.30.65 congestion-marking on");
+ BOOST_CHECK_EQUAL(exitCode, 0);
+ BOOST_CHECK(out.is_equal("face-updated id=1172 local=udp4://68.62.26.57:24087 "
+ "remote=udp4://100.77.30.65:6363 persistency=persistent "
+ "reliability=off congestion-marking=on "
+ "congestion-marking-interval=100ms default-congestion-threshold=65536B\n"));
+ BOOST_CHECK(err.is_empty());
+}
+
+BOOST_AUTO_TEST_CASE(DisablingCongestionMarking)
+{
+ bool hasUpdateCommand = false;
+ this->processInterest = [this, &hasUpdateCommand] (const Interest& interest) {
+ if (parseCommand(interest, "/localhost/nfd/faces/create")) {
+ this->respond409(interest, FacePersistency::FACE_PERSISTENCY_PERSISTENT, false, true);
+ return;
+ }
+
+ ControlParameters req = MOCK_NFD_MGMT_REQUIRE_COMMAND_IS("/localhost/nfd/faces/update");
+ hasUpdateCommand = true;
+ BOOST_REQUIRE(req.hasFaceId());
+ BOOST_CHECK_EQUAL(req.getFaceId(), 1172);
+ BOOST_CHECK(req.hasFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED));
+ BOOST_CHECK(!req.getFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED));
+ BOOST_CHECK(!req.hasBaseCongestionMarkingInterval());
+ BOOST_CHECK(!req.hasDefaultCongestionThreshold());
+
+ ControlParameters resp;
+ resp.setFaceId(1172)
+ .setFacePersistency(FacePersistency::FACE_PERSISTENCY_PERSISTENT)
+ .setBaseCongestionMarkingInterval(100_ms)
+ .setDefaultCongestionThreshold(65536)
+ .setFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED, false, false);
+ this->succeedCommand(interest, resp);
+ };
+
+ this->execute("face create udp://100.77.30.65 congestion-marking off");
+ BOOST_CHECK_EQUAL(exitCode, 0);
+ BOOST_CHECK(out.is_equal("face-updated id=1172 local=udp4://68.62.26.57:24087 "
+ "remote=udp4://100.77.30.65:6363 persistency=persistent "
+ "reliability=off congestion-marking=off "
+ "congestion-marking-interval=100ms default-congestion-threshold=65536B\n"));
BOOST_CHECK(err.is_empty());
}
@@ -512,7 +735,7 @@
BOOST_CHECK_EQUAL(exitCode, 0);
BOOST_CHECK(out.is_equal("face-destroyed id=10156 local=tcp4://151.26.163.27:22967 "
"remote=tcp4://198.57.27.40:6363 persistency=persistent "
- "reliability=off\n"));
+ "reliability=off congestion-marking=off\n"));
BOOST_CHECK(err.is_empty());
}
@@ -536,7 +759,7 @@
BOOST_CHECK_EQUAL(exitCode, 0);
BOOST_CHECK(out.is_equal("face-destroyed id=2249 local=tcp4://30.99.87.98:31414 "
"remote=tcp4://32.121.182.82:6363 persistency=persistent "
- "reliability=off\n"));
+ "reliability=off congestion-marking=off\n"));
BOOST_CHECK(err.is_empty());
}
@@ -614,6 +837,7 @@
<faceScope>non-local</faceScope>
<facePersistency>permanent</facePersistency>
<linkType>multi-access</linkType>
+ <congestion/>
<flags/>
<packetCounters>
<incomingPackets>
@@ -639,9 +863,14 @@
<faceScope>local</faceScope>
<facePersistency>on-demand</facePersistency>
<linkType>point-to-point</linkType>
+ <congestion>
+ <baseMarkingInterval>PT0.100S</baseMarkingInterval>
+ <defaultThreshold>65536</defaultThreshold>
+ </congestion>
<flags>
<localFieldsEnabled/>
<lpReliabilityEnabled/>
+ <congestionMarkingEnabled/>
</flags>
<packetCounters>
<incomingPackets>
@@ -669,8 +898,9 @@
" counters={in={22562i 22031d 63n 2522915B} out={30121i 20940d 1218n 1353592B}}"
" flags={non-local permanent multi-access}\n"
" faceid=745 remote=fd://75 local=unix:///var/run/nfd.sock"
+ " congestion={base-marking-interval=100ms default-threshold=65536B}"
" counters={in={18998i 26701d 147n 4672308B} out={34779i 17028d 1176n 8957187B}}"
- " flags={local on-demand point-to-point local-fields lp-reliability}\n";
+ " flags={local on-demand point-to-point local-fields lp-reliability congestion-marking}\n";
BOOST_FIXTURE_TEST_CASE(Status, StatusFixture<FaceModule>)
{
@@ -697,8 +927,11 @@
.setFaceScope(ndn::nfd::FACE_SCOPE_LOCAL)
.setFacePersistency(ndn::nfd::FACE_PERSISTENCY_ON_DEMAND)
.setLinkType(ndn::nfd::LINK_TYPE_POINT_TO_POINT)
+ .setBaseCongestionMarkingInterval(100_ms)
+ .setDefaultCongestionThreshold(65536)
.setFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED, true)
.setFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED, true)
+ .setFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED, true)
.setNInInterests(18998)
.setNInData(26701)
.setNInNacks(147)
diff --git a/tests/tools/nfdc/format-helpers.t.cpp b/tests/tools/nfdc/format-helpers.t.cpp
index 6184401..a94d2ba 100644
--- a/tests/tools/nfdc/format-helpers.t.cpp
+++ b/tests/tools/nfdc/format-helpers.t.cpp
@@ -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,
@@ -48,6 +48,30 @@
" surround XML <element> tag name"));
}
+BOOST_AUTO_TEST_CASE(DurationFormatting)
+{
+ time::nanoseconds d1 = 53000_s + 87_ms + 3_us;
+ BOOST_CHECK_EQUAL(xml::formatDuration(d1), "PT53000.087S");
+
+ time::nanoseconds d2 = 56_s;
+ BOOST_CHECK_EQUAL(xml::formatDuration(d2), "PT56S");
+
+ time::nanoseconds d3 = 3_min;
+ BOOST_CHECK_EQUAL(xml::formatDuration(d3), "PT180S");
+
+ time::nanoseconds d4 = 0_ns;
+ BOOST_CHECK_EQUAL(xml::formatDuration(d4), "PT0S");
+
+ time::nanoseconds d5 = 1_ms;
+ BOOST_CHECK_EQUAL(xml::formatDuration(d5), "PT0.001S");
+
+ time::nanoseconds d6 = -53_s - 250_ms;
+ BOOST_CHECK_EQUAL(xml::formatDuration(d6), "-PT53.250S");
+
+ time::nanoseconds d7 = 1_us;
+ BOOST_CHECK_EQUAL(xml::formatDuration(d7), "PT0S");
+}
+
BOOST_AUTO_TEST_SUITE_END() // Xml
BOOST_AUTO_TEST_SUITE(Text)
diff --git a/tools/nfd-status-http-server-files/nfd-status.xsl b/tools/nfd-status-http-server-files/nfd-status.xsl
index d9b8885..9620cba 100644
--- a/tools/nfd-status-http-server-files/nfd-status.xsl
+++ b/tools/nfd-status-http-server-files/nfd-status.xsl
@@ -36,7 +36,26 @@
<xsl:template name="formatDuration">
<xsl:param name="duration" />
- <xsl:variable name="seconds"><xsl:value-of select="substring($duration, 3, string-length($duration)-3)" /></xsl:variable>
+ <xsl:variable name="milliseconds">
+ <xsl:choose>
+ <xsl:when test="contains($duration, '.')">
+ <xsl:value-of select="substring($duration, string-length($duration)-4, 3)" />
+ </xsl:when>
+ <xsl:otherwise>
+ 0
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="seconds">
+ <xsl:choose>
+ <xsl:when test="contains($duration, '.')">
+ <xsl:value-of select="substring($duration, 3, string-length($duration)-7)" />
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="substring($duration, 3, string-length($duration)-3)" />
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
<xsl:variable name="days"><xsl:value-of select="floor($seconds div 86400)" /></xsl:variable>
<xsl:variable name="hours"><xsl:value-of select="floor($seconds div 3600)" /></xsl:variable>
<xsl:variable name="minutes"><xsl:value-of select="floor($seconds div 60)" /></xsl:variable>
@@ -65,6 +84,12 @@
<xsl:otherwise>
<xsl:value-of select="$seconds"/> seconds
</xsl:otherwise>
+ <xsl:when test="$milliseconds > 1">
+ <xsl:value-of select="$milliseconds"/> milliseconds
+ </xsl:when>
+ <xsl:when test="$milliseconds = 1">
+ <xsl:value-of select="$milliseconds"/> millisecond
+ </xsl:when>
</xsl:choose>
</xsl:template>
@@ -183,6 +208,12 @@
<xsl:when test="nfd:flags/nfd:localFieldsEnabled">
local-fields
</xsl:when>
+ <xsl:when test="nfd:flags/nfd:lpReliabilityEnabled">
+ reliability
+ </xsl:when>
+ <xsl:when test="nfd:flags/nfd:congestionMarkingEnabled">
+ congestion-marking
+ </xsl:when>
</xsl:choose>
</td>
<td>
diff --git a/tools/nfdc/face-module.cpp b/tools/nfdc/face-module.cpp
index 1a88229..560b223 100644
--- a/tools/nfdc/face-module.cpp
+++ b/tools/nfdc/face-module.cpp
@@ -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,6 @@
#include "face-module.hpp"
#include "find-face.hpp"
-#include "format-helpers.hpp"
namespace nfd {
namespace tools {
@@ -54,7 +53,10 @@
.addArg("remote", ArgValueType::FACE_URI, Required::YES, Positional::YES)
.addArg("persistency", ArgValueType::FACE_PERSISTENCY, Required::NO, Positional::YES)
.addArg("local", ArgValueType::FACE_URI, Required::NO, Positional::NO)
- .addArg("reliability", ArgValueType::BOOLEAN, Required::NO, Positional::NO);
+ .addArg("reliability", ArgValueType::BOOLEAN, Required::NO, Positional::NO)
+ .addArg("congestion-marking", ArgValueType::BOOLEAN, Required::NO, Positional::NO)
+ .addArg("congestion-marking-interval", ArgValueType::UNSIGNED, Required::NO, Positional::NO)
+ .addArg("default-congestion-threshold", ArgValueType::UNSIGNED, Required::NO, Positional::NO);
parser.addCommand(defFaceCreate, &FaceModule::create);
CommandDefinition defFaceDestroy("face", "destroy");
@@ -153,6 +155,9 @@
auto localUri = ctx.args.getOptional<FaceUri>("local");
auto persistency = ctx.args.get<FacePersistency>("persistency", FacePersistency::FACE_PERSISTENCY_PERSISTENT);
auto lpReliability = ctx.args.getTribool("reliability");
+ auto congestionMarking = ctx.args.getTribool("congestion-marking");
+ auto baseCongestionMarkingIntervalMs = ctx.args.getOptional<uint64_t>("congestion-marking-interval");
+ auto defaultCongestionThreshold = ctx.args.getOptional<uint64_t>("default-congestion-threshold");
FaceUri canonicalRemote;
ndn::optional<FaceUri> canonicalLocal;
@@ -168,9 +173,8 @@
<< ia("id") << resp.getFaceId()
<< ia("local") << resp.getLocalUri()
<< ia("remote") << resp.getUri()
- << ia("persistency") << resp.getFacePersistency()
- << ia("reliability") << (resp.getFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED) ? "on" : "off")
- << '\n';
+ << ia("persistency") << resp.getFacePersistency();
+ printFaceParams(ctx.out, ia, resp);
};
auto updateFace = [&printPositiveResult] (ControlParameters respParams, ControlParameters resp) {
@@ -200,24 +204,36 @@
ctx.makeCommandFailureHandler("upgrading face persistency"),
ctx.makeCommandOptions());
}
- else if (lpReliability && !respParams.getFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED)) {
- // enable reliability
+ else if ((!boost::logic::indeterminate(lpReliability) &&
+ lpReliability != respParams.getFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED)) ||
+ (!boost::logic::indeterminate(congestionMarking) &&
+ congestionMarking != respParams.getFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED)) ||
+ baseCongestionMarkingIntervalMs ||
+ defaultCongestionThreshold) {
ControlParameters params;
- params.setFaceId(respParams.getFaceId()).setFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED, true);
+ params.setFaceId(respParams.getFaceId());
+
+ if (!boost::logic::indeterminate(lpReliability) &&
+ lpReliability != respParams.getFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED)) {
+ params.setFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED, lpReliability);
+ }
+ if (!boost::logic::indeterminate(congestionMarking) &&
+ congestionMarking != respParams.getFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED)) {
+ params.setFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED, congestionMarking);
+ }
+
+ if (baseCongestionMarkingIntervalMs) {
+ params.setBaseCongestionMarkingInterval(time::milliseconds(*baseCongestionMarkingIntervalMs));
+ }
+
+ if (defaultCongestionThreshold) {
+ params.setDefaultCongestionThreshold(*defaultCongestionThreshold);
+ }
+
ctx.controller.start<ndn::nfd::FaceUpdateCommand>(
params,
bind(updateFace, respParams, _1),
- ctx.makeCommandFailureHandler("enabling reliability"),
- ctx.makeCommandOptions());
- }
- else if (!lpReliability && respParams.getFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED)) {
- // disable reliability
- ControlParameters params;
- params.setFaceId(respParams.getFaceId()).setFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED, false);
- ctx.controller.start<ndn::nfd::FaceUpdateCommand>(
- params,
- bind(updateFace, respParams, _1),
- ctx.makeCommandFailureHandler("disabling reliability"),
+ ctx.makeCommandFailureHandler("updating face"),
ctx.makeCommandOptions());
}
else {
@@ -237,6 +253,15 @@
if (!boost::logic::indeterminate(lpReliability)) {
params.setFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED, lpReliability);
}
+ if (!boost::logic::indeterminate(congestionMarking)) {
+ params.setFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED, congestionMarking);
+ }
+ if (baseCongestionMarkingIntervalMs) {
+ params.setBaseCongestionMarkingInterval(time::milliseconds(*baseCongestionMarkingIntervalMs));
+ }
+ if (defaultCongestionThreshold) {
+ params.setDefaultCongestionThreshold(*defaultCongestionThreshold);
+ }
ctx.controller.start<ndn::nfd::FaceCreateCommand>(
params,
@@ -309,9 +334,8 @@
ctx.out << ia("id") << face.getFaceId()
<< ia("local") << face.getLocalUri()
<< ia("remote") << face.getRemoteUri()
- << ia("persistency") << face.getFacePersistency()
- << ia("reliability") << (resp.getFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED) ? "on" : "off")
- << '\n';
+ << ia("persistency") << face.getFacePersistency();
+ printFaceParams(ctx.out, ia, resp);
},
ctx.makeCommandFailureHandler("destroying face"),
ctx.makeCommandOptions());
@@ -360,6 +384,21 @@
os << "<facePersistency>" << item.getFacePersistency() << "</facePersistency>";
os << "<linkType>" << item.getLinkType() << "</linkType>";
+ if (!item.hasBaseCongestionMarkingInterval() && !item.hasDefaultCongestionThreshold()) {
+ os << "<congestion/>";
+ }
+ else {
+ os << "<congestion>";
+ if (item.hasBaseCongestionMarkingInterval()) {
+ os << "<baseMarkingInterval>" << xml::formatDuration(item.getBaseCongestionMarkingInterval())
+ << "</baseMarkingInterval>";
+ }
+ if (item.hasDefaultCongestionThreshold()) {
+ os << "<defaultThreshold>" << item.getDefaultCongestionThreshold() << "</defaultThreshold>";
+ }
+ os << "</congestion>";
+ }
+
if (item.getFlags() == 0) {
os << "<flags/>";
}
@@ -371,6 +410,9 @@
if (item.getFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED)) {
os << "<lpReliabilityEnabled/>";
}
+ if (item.getFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED)) {
+ os << "<congestionMarkingEnabled/>";
+ }
os << "</flags>";
}
@@ -409,14 +451,27 @@
void
FaceModule::formatItemText(std::ostream& os, const FaceStatus& item, bool wantMultiLine)
{
- text::ItemAttributes ia(wantMultiLine, 8);
+ text::ItemAttributes ia(wantMultiLine, 10);
os << ia("faceid") << item.getFaceId();
os << ia("remote") << item.getRemoteUri();
os << ia("local") << item.getLocalUri();
if (item.hasExpirationPeriod()) {
- os << ia("expires") << text::formatDuration(item.getExpirationPeriod());
+ os << ia("expires") << text::formatDuration<time::seconds>(item.getExpirationPeriod());
+ }
+
+ if (item.hasBaseCongestionMarkingInterval() || item.hasDefaultCongestionThreshold()) {
+ os << ia("congestion") << "{";
+ text::Separator congestionSep("", " ");
+ if (item.hasBaseCongestionMarkingInterval()) {
+ os << congestionSep << "base-marking-interval="
+ << text::formatDuration<time::milliseconds>(item.getBaseCongestionMarkingInterval());
+ }
+ if (item.hasDefaultCongestionThreshold()) {
+ os << congestionSep << "default-threshold=" << item.getDefaultCongestionThreshold() << "B";
+ }
+ os << "}";
}
os << ia("counters")
@@ -442,11 +497,29 @@
if (item.getFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED)) {
os << flagSep << "lp-reliability";
}
+ if (item.getFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED)) {
+ os << flagSep << "congestion-marking";
+ }
os << '}';
os << ia.end();
}
+void
+FaceModule::printFaceParams(std::ostream& os, text::ItemAttributes& ia, const ControlParameters& resp)
+{
+ os << ia("reliability") << (resp.getFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED) ? "on" : "off")
+ << ia("congestion-marking") << (resp.getFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED) ? "on" : "off");
+ if (resp.hasBaseCongestionMarkingInterval()) {
+ os << ia("congestion-marking-interval")
+ << text::formatDuration<time::milliseconds>(resp.getBaseCongestionMarkingInterval());
+ }
+ if (resp.hasDefaultCongestionThreshold()) {
+ os << ia("default-congestion-threshold") << resp.getDefaultCongestionThreshold() << "B";
+ }
+ os << '\n';
+}
+
} // namespace nfdc
} // namespace tools
} // namespace nfd
diff --git a/tools/nfdc/face-module.hpp b/tools/nfdc/face-module.hpp
index 6c190a1..9f0ac2a 100644
--- a/tools/nfdc/face-module.hpp
+++ b/tools/nfdc/face-module.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-2018, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -28,6 +28,7 @@
#include "module.hpp"
#include "command-parser.hpp"
+#include "format-helpers.hpp"
namespace nfd {
namespace tools {
@@ -93,6 +94,14 @@
static void
formatItemText(std::ostream& os, const FaceStatus& item, bool wantMultiLine);
+ /** \brief print face response parameters to specified ostream
+ * \param os output stream
+ * \param ia ItemAttributes used to format output
+ * \param resp response control parameters to print
+ */
+ static void
+ printFaceParams(std::ostream& os, text::ItemAttributes& ia, const ControlParameters& resp);
+
private:
std::vector<FaceStatus> m_status;
};
diff --git a/tools/nfdc/format-helpers.cpp b/tools/nfdc/format-helpers.cpp
index 3d851dd..6d5a983 100644
--- a/tools/nfdc/format-helpers.cpp
+++ b/tools/nfdc/format-helpers.cpp
@@ -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,6 +25,9 @@
#include "format-helpers.hpp"
+#include <iomanip>
+#include <sstream>
+
namespace nfd {
namespace tools {
namespace nfdc {
@@ -73,9 +76,28 @@
}
std::string
-formatSeconds(time::seconds d)
+formatDuration(time::nanoseconds d)
{
- return "PT" + to_string(d.count()) + "S";
+ std::ostringstream str;
+
+ if (d < 0_ns) {
+ str << "-";
+ }
+
+ str << "PT";
+
+ time::seconds seconds(time::duration_cast<time::seconds>(time::abs(d)));
+ time::milliseconds ms(time::duration_cast<time::milliseconds>(time::abs(d) - seconds));
+
+ str << seconds.count();
+
+ if (ms >= 1_ms) {
+ str << "." << std::setfill('0') << std::setw(3) << ms.count();
+ }
+
+ str << "S";
+
+ return str.str();
}
std::string
@@ -156,12 +178,6 @@
}
std::string
-formatSeconds(time::seconds d, bool isLong)
-{
- return to_string(d.count()) + (isLong ? " seconds" : "s");
-}
-
-std::string
formatTimestamp(time::system_clock::TimePoint t)
{
return time::toIsoString(t);
diff --git a/tools/nfdc/format-helpers.hpp b/tools/nfdc/format-helpers.hpp
index 9283855..c0f8fd1 100644
--- a/tools/nfdc/format-helpers.hpp
+++ b/tools/nfdc/format-helpers.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-2018, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -50,16 +50,17 @@
std::ostream&
operator<<(std::ostream& os, const Text& text);
+/** \return duration in XML duration format
+ *
+ * Definition of this format: https://www.w3.org/TR/xmlschema11-2/#duration
+ */
std::string
-formatSeconds(time::seconds d);
+formatDuration(time::nanoseconds d);
-template<typename DURATION>
-std::string
-formatDuration(DURATION d)
-{
- return formatSeconds(time::duration_cast<time::seconds>(d));
-}
-
+/** \return timestamp in XML dateTime format
+ *
+ * Definition of this format: https://www.w3.org/TR/xmlschema11-2/#dateTime
+ */
std::string
formatTimestamp(time::system_clock::TimePoint t);
@@ -164,14 +165,69 @@
std::ostream&
operator<<(std::ostream& os, const ItemAttributes::Attribute& attr);
-std::string
-formatSeconds(time::seconds d, bool isLong = false);
+namespace detail {
-template<typename DURATION>
+template<typename DurationT>
std::string
-formatDuration(DURATION d, bool isLong = false)
+getTimeUnit(bool isLong);
+
+template<>
+inline std::string
+getTimeUnit<time::nanoseconds>(bool isLong)
{
- return formatSeconds(time::duration_cast<time::seconds>(d), isLong);
+ return isLong ? "nanoseconds" : "ns";
+}
+
+template<>
+inline std::string
+getTimeUnit<time::microseconds>(bool isLong)
+{
+ return isLong ? "microseconds" : "us";
+}
+
+template<>
+inline std::string
+getTimeUnit<time::milliseconds>(bool isLong)
+{
+ return isLong ? "milliseconds" : "ms";
+}
+
+template<>
+inline std::string
+getTimeUnit<time::seconds>(bool isLong)
+{
+ return isLong ? "seconds" : "s";
+}
+
+template<>
+inline std::string
+getTimeUnit<time::minutes>(bool isLong)
+{
+ return isLong ? "minutes" : "m";
+}
+
+template<>
+inline std::string
+getTimeUnit<time::hours>(bool isLong)
+{
+ return isLong ? "hours" : "h";
+}
+
+template<>
+inline std::string
+getTimeUnit<time::days>(bool isLong)
+{
+ return isLong ? "days" : "d";
+}
+
+} // namespace detail
+
+template<typename OutputPrecision>
+std::string
+formatDuration(time::nanoseconds d, bool isLong = false)
+{
+ return to_string(time::duration_cast<OutputPrecision>(d).count()) +
+ (isLong ? " " : "") + detail::getTimeUnit<OutputPrecision>(isLong);
}
std::string
diff --git a/tools/nfdc/forwarder-general-module.cpp b/tools/nfdc/forwarder-general-module.cpp
index e490892..4a85cdd 100644
--- a/tools/nfdc/forwarder-general-module.cpp
+++ b/tools/nfdc/forwarder-general-module.cpp
@@ -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,
@@ -64,7 +64,8 @@
os << "<version>" << xml::Text{item.getNfdVersion()} << "</version>";
os << "<startTime>" << xml::formatTimestamp(item.getStartTimestamp()) << "</startTime>";
os << "<currentTime>" << xml::formatTimestamp(item.getCurrentTimestamp()) << "</currentTime>";
- os << "<uptime>" << xml::formatDuration(calculateUptime(item)) << "</uptime>";
+ os << "<uptime>" << xml::formatDuration(time::duration_cast<time::seconds>(calculateUptime(item)))
+ << "</uptime>";
os << "<nNameTreeEntries>" << item.getNNameTreeEntries() << "</nNameTreeEntries>";
os << "<nFibEntries>" << item.getNFibEntries() << "</nFibEntries>";
@@ -101,7 +102,7 @@
os << " version=" << item.getNfdVersion() << "\n";
os << " startTime=" << text::formatTimestamp(item.getStartTimestamp()) << "\n";
os << " currentTime=" << text::formatTimestamp(item.getCurrentTimestamp()) << "\n";
- os << " uptime=" << text::formatDuration(calculateUptime(item), true) << "\n";
+ os << " uptime=" << text::formatDuration<time::seconds>(calculateUptime(item), true) << "\n";
os << " nNameTreeEntries=" << item.getNNameTreeEntries() << "\n";
os << " nFibEntries=" << item.getNFibEntries() << "\n";
diff --git a/tools/nfdc/rib-module.cpp b/tools/nfdc/rib-module.cpp
index 5ca7195..f9d888f 100644
--- a/tools/nfdc/rib-module.cpp
+++ b/tools/nfdc/rib-module.cpp
@@ -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,
@@ -195,7 +195,7 @@
<< ia("cost") << resp.getCost()
<< ia("flags") << static_cast<ndn::nfd::RouteFlags>(resp.getFlags());
if (resp.hasExpirationPeriod()) {
- ctx.out << ia("expires") << resp.getExpirationPeriod().count() << "ms\n";
+ ctx.out << ia("expires") << text::formatDuration<time::milliseconds>(resp.getExpirationPeriod()) << "\n";
}
else {
ctx.out<< ia("expires") << "never\n";
@@ -307,7 +307,7 @@
}
if (route.hasExpirationPeriod()) {
os << "<expirationPeriod>"
- << xml::formatDuration(route.getExpirationPeriod())
+ << xml::formatDuration(time::duration_cast<time::seconds>(route.getExpirationPeriod()))
<< "</expirationPeriod>";
}
os << "</route>";
@@ -356,7 +356,7 @@
os << ia("cost") << route.getCost();
os << ia("flags") << static_cast<ndn::nfd::RouteFlags>(route.getFlags());
if (route.hasExpirationPeriod()) {
- os << ia("expires") << text::formatDuration(route.getExpirationPeriod());
+ os << ia("expires") << text::formatDuration<time::seconds>(route.getExpirationPeriod());
}
else {
os << ia("expires") << "never";