28 #include <ndn-cxx/lp/pit-token.hpp> 29 #include <ndn-cxx/lp/tags.hpp> 39 tlv::sizeOfVarNumber(
sizeof(uint64_t)) +
40 tlv::sizeOfNonNegativeInteger(UINT64_MAX);
44 , m_fragmenter(m_options.fragmenterOptions, this)
45 , m_reassembler(m_options.reassemblerOptions, this)
46 , m_reliability(m_options.reliabilityOptions, this)
48 , m_nextMarkTime(time::steady_clock::TimePoint::max())
49 , m_nMarkedSinceInMarkingState(0)
66 GenericLinkService::requestIdlePacket(
const EndpointId& endpointId)
70 this->sendLpPacket({}, endpointId);
74 GenericLinkService::sendLpPacket(lp::Packet&& pkt,
const EndpointId& endpointId)
83 checkCongestionLevel(pkt);
86 auto block = pkt.wireEncode();
87 if (mtu !=
MTU_UNLIMITED && block.size() >
static_cast<size_t>(mtu)) {
96 GenericLinkService::doSendInterest(
const Interest& interest,
const EndpointId& endpointId)
98 lp::Packet lpPacket(interest.wireEncode());
100 encodeLpFields(interest, lpPacket);
102 this->sendNetPacket(std::move(lpPacket), endpointId,
true);
106 GenericLinkService::doSendData(
const Data& data,
const EndpointId& endpointId)
108 lp::Packet lpPacket(data.wireEncode());
110 encodeLpFields(data, lpPacket);
112 this->sendNetPacket(std::move(lpPacket), endpointId,
false);
116 GenericLinkService::doSendNack(
const lp::Nack& nack,
const EndpointId& endpointId)
118 lp::Packet lpPacket(nack.getInterest().wireEncode());
119 lpPacket.add<lp::NackField>(nack.getHeader());
121 encodeLpFields(nack, lpPacket);
123 this->sendNetPacket(std::move(lpPacket), endpointId,
false);
127 GenericLinkService::encodeLpFields(
const ndn::PacketBase& netPkt, lp::Packet& lpPacket)
130 auto incomingFaceIdTag = netPkt.getTag<lp::IncomingFaceIdTag>();
131 if (incomingFaceIdTag !=
nullptr) {
132 lpPacket.add<lp::IncomingFaceIdField>(*incomingFaceIdTag);
136 auto congestionMarkTag = netPkt.getTag<lp::CongestionMarkTag>();
137 if (congestionMarkTag !=
nullptr) {
138 lpPacket.add<lp::CongestionMarkField>(*congestionMarkTag);
142 auto nonDiscoveryTag = netPkt.getTag<lp::NonDiscoveryTag>();
143 if (nonDiscoveryTag !=
nullptr) {
144 lpPacket.add<lp::NonDiscoveryField>(*nonDiscoveryTag);
147 auto prefixAnnouncementTag = netPkt.getTag<lp::PrefixAnnouncementTag>();
148 if (prefixAnnouncementTag !=
nullptr) {
149 lpPacket.add<lp::PrefixAnnouncementField>(*prefixAnnouncementTag);
153 auto pitToken = netPkt.getTag<lp::PitToken>();
154 if (pitToken !=
nullptr) {
155 lpPacket.add<lp::PitTokenField>(*pitToken);
160 GenericLinkService::sendNetPacket(lp::Packet&& pkt,
const EndpointId& endpointId,
bool isInterest)
162 std::vector<lp::Packet> frags;
187 frags.push_back(pkt);
190 frags.push_back(std::move(pkt));
194 if (frags.size() == 1) {
197 BOOST_ASSERT(!frags.front().has<lp::FragIndexField>());
198 BOOST_ASSERT(!frags.front().has<lp::FragCountField>());
202 if (frags.size() > 1) {
204 this->assignSequences(frags);
211 for (lp::Packet& frag : frags) {
212 this->sendLpPacket(std::move(frag), endpointId);
217 GenericLinkService::assignSequence(lp::Packet& pkt)
219 pkt.set<lp::SequenceField>(++m_lastSeqNo);
223 GenericLinkService::assignSequences(std::vector<lp::Packet>& pkts)
225 std::for_each(pkts.begin(), pkts.end(), [
this] (
auto& pkt) { this->assignSequence(pkt); });
229 GenericLinkService::checkCongestionLevel(lp::Packet& pkt)
233 if (sendQueueLength < 0) {
237 if (sendQueueLength > 0) {
245 const auto now = time::steady_clock::now();
247 if (m_nextMarkTime == time::steady_clock::TimePoint::max()) {
251 else if (now >= m_nextMarkTime) {
252 pkt.set<lp::CongestionMarkField>(1);
256 ++m_nMarkedSinceInMarkingState;
259 time::nanoseconds interval(static_cast<time::nanoseconds::rep>(
261 std::sqrt(m_nMarkedSinceInMarkingState + 1)));
262 m_nextMarkTime += interval;
265 else if (m_nextMarkTime != time::steady_clock::TimePoint::max()) {
268 m_nextMarkTime = time::steady_clock::TimePoint::max();
269 m_nMarkedSinceInMarkingState = 0;
274 GenericLinkService::doReceivePacket(
const Block& packet,
const EndpointId& endpoint)
277 lp::Packet pkt(packet);
283 if (!pkt.has<lp::FragmentField>()) {
288 if ((pkt.has<lp::FragIndexField>() || pkt.has<lp::FragCountField>()) &&
294 bool isReassembled =
false;
297 std::tie(isReassembled, netPkt, firstPkt) = m_reassembler.
receiveFragment(endpoint, pkt);
299 this->decodeNetPacket(netPkt, firstPkt, endpoint);
302 catch (
const tlv::Error& e) {
309 GenericLinkService::decodeNetPacket(
const Block& netPkt,
const lp::Packet& firstPkt,
313 switch (netPkt.type()) {
315 if (firstPkt.has<lp::NackField>()) {
316 this->decodeNack(netPkt, firstPkt, endpointId);
319 this->decodeInterest(netPkt, firstPkt, endpointId);
323 this->decodeData(netPkt, firstPkt, endpointId);
327 NFD_LOG_FACE_WARN(
"unrecognized network-layer packet TLV-TYPE " << netPkt.type() <<
": DROP");
331 catch (
const tlv::Error& e) {
338 GenericLinkService::decodeInterest(
const Block& netPkt,
const lp::Packet& firstPkt,
341 BOOST_ASSERT(netPkt.type() == tlv::Interest);
342 BOOST_ASSERT(!firstPkt.has<lp::NackField>());
345 auto interest = make_shared<Interest>(netPkt);
347 if (firstPkt.has<lp::NextHopFaceIdField>()) {
349 interest->setTag(make_shared<lp::NextHopFaceIdTag>(firstPkt.get<lp::NextHopFaceIdField>()));
357 if (firstPkt.has<lp::CachePolicyField>()) {
363 if (firstPkt.has<lp::IncomingFaceIdField>()) {
367 if (firstPkt.has<lp::CongestionMarkField>()) {
368 interest->setTag(make_shared<lp::CongestionMarkTag>(firstPkt.get<lp::CongestionMarkField>()));
371 if (firstPkt.has<lp::NonDiscoveryField>()) {
373 interest->setTag(make_shared<lp::NonDiscoveryTag>(firstPkt.get<lp::NonDiscoveryField>()));
380 if (firstPkt.has<lp::PrefixAnnouncementField>()) {
386 if (firstPkt.has<lp::PitTokenField>()) {
387 interest->setTag(make_shared<lp::PitToken>(firstPkt.get<lp::PitTokenField>()));
394 GenericLinkService::decodeData(
const Block& netPkt,
const lp::Packet& firstPkt,
397 BOOST_ASSERT(netPkt.type() == tlv::Data);
400 auto data = make_shared<Data>(netPkt);
402 if (firstPkt.has<lp::NackField>()) {
408 if (firstPkt.has<lp::NextHopFaceIdField>()) {
414 if (firstPkt.has<lp::CachePolicyField>()) {
418 data->setTag(make_shared<lp::CachePolicyTag>(firstPkt.get<lp::CachePolicyField>()));
421 if (firstPkt.has<lp::IncomingFaceIdField>()) {
425 if (firstPkt.has<lp::CongestionMarkField>()) {
426 data->setTag(make_shared<lp::CongestionMarkTag>(firstPkt.get<lp::CongestionMarkField>()));
429 if (firstPkt.has<lp::NonDiscoveryField>()) {
435 if (firstPkt.has<lp::PrefixAnnouncementField>()) {
437 data->setTag(make_shared<lp::PrefixAnnouncementTag>(firstPkt.get<lp::PrefixAnnouncementField>()));
440 NFD_LOG_FACE_WARN(
"received PrefixAnnouncement, but self-learning disabled: IGNORE");
448 GenericLinkService::decodeNack(
const Block& netPkt,
const lp::Packet& firstPkt,
451 BOOST_ASSERT(netPkt.type() == tlv::Interest);
452 BOOST_ASSERT(firstPkt.has<lp::NackField>());
454 lp::Nack nack((Interest(netPkt)));
455 nack.setHeader(firstPkt.get<lp::NackField>());
457 if (firstPkt.has<lp::NextHopFaceIdField>()) {
463 if (firstPkt.has<lp::CachePolicyField>()) {
469 if (firstPkt.has<lp::IncomingFaceIdField>()) {
473 if (firstPkt.has<lp::CongestionMarkField>()) {
474 nack.setTag(make_shared<lp::CongestionMarkTag>(firstPkt.get<lp::CongestionMarkField>()));
477 if (firstPkt.has<lp::NonDiscoveryField>()) {
483 if (firstPkt.has<lp::PrefixAnnouncementField>()) {
void setOptions(const Options &options)
sets Options used by GenericLinkService
void processIncomingPacket(const lp::Packet &pkt)
extract and parse all Acks and add Ack for contained Fragment (if any) to AckQueue ...
#define NFD_LOG_FACE_TRACE(msg)
Log a message at TRACE level.
virtual ssize_t getSendQueueLength()
SizeCounter< LpReassembler > nReassembling
count of network-layer packets currently being reassembled
PacketCounter nInLpInvalid
count of invalid LpPackets dropped before reassembly
const ssize_t MTU_UNLIMITED
indicates the transport has no limit on payload size
#define NFD_LOG_FACE_DEBUG(msg)
Log a message at DEBUG level.
PacketCounter nFragmentationErrors
count of failed fragmentations
bool allowFragmentation
enables fragmentation
void piggyback(lp::Packet &pkt, ssize_t mtu)
called by GenericLinkService to attach Acks onto an outgoing LpPacket
std::tuple< bool, Block, lp::Packet > receiveFragment(EndpointId remoteEndpoint, const lp::Packet &packet)
adds received fragment to the buffer
const Transport * getTransport() const
bool isEnabled
enables link-layer reliability
GenericLinkService(const Options &options={})
void sendPacket(const Block &packet, const EndpointId &endpoint)
send a lower-layer packet via Transport to endpoint
uint64_t EndpointId
Identifies a remote endpoint on the link.
void setOptions(const Options &options)
set options for fragmenter
PacketCounter nInNetInvalid
count of invalid reassembled network-layer packets dropped
void receiveData(const Data &data, const EndpointId &endpoint)
delivers received Data to forwarding
LpReassembler::Options reassemblerOptions
options for reassembly
#define NFD_LOG_FACE_WARN(msg)
Log a message at WARN level.
static constexpr size_t RESERVED_HEADER_SPACE
TxSequence TLV-TYPE (3 octets) + TLV-LENGTH (1 octet) + lp::Sequence (8 octets)
bool allowSelfLearning
enables self-learning forwarding support
PacketCounter nCongestionMarked
count of outgoing LpPackets that were marked with congestion marks
void receiveNack(const lp::Nack &nack, const EndpointId &endpoint)
delivers received Nack to forwarding
Copyright (c) 2014-2015, Regents of the University of California, Arizona Board of Regents...
signal::Signal< LpReassembler, EndpointId, size_t > beforeTimeout
signals before a partial packet is dropped due to timeout
std::tuple< bool, std::vector< lp::Packet > > fragmentPacket(const lp::Packet &packet, size_t mtu)
fragments a network-layer packet into link-layer packets
void receiveInterest(const Interest &interest, const EndpointId &endpoint)
delivers received Interest to forwarding
PacketCounter nOutOverMtu
count of outgoing LpPackets dropped due to exceeding MTU limit
LpReliability::Options reliabilityOptions
options for reliability
void handleOutgoing(std::vector< lp::Packet > &frags, lp::Packet &&pkt, bool isInterest)
observe outgoing fragment(s) of a network packet and store for potential retransmission ...
Options that control the behavior of GenericLinkService.
void setOptions(const Options &options)
set options for reliability
#define NFD_LOG_INIT(name)
signal::Signal< LpReliability, Interest > onDroppedInterest
signals on Interest dropped by reliability system for exceeding allowed number of retx ...
time::nanoseconds baseCongestionMarkingInterval
starting value for congestion marking interval
size_t defaultCongestionThreshold
default congestion threshold in bytes
void notifyDroppedInterest(const Interest &packet)
bool allowLocalFields
enables encoding of IncomingFaceId, and decoding of NextHopFaceId and CachePolicy ...
bool allowCongestionMarking
enables send queue congestion detection and marking
constexpr size_t CONGESTION_MARK_SIZE
bool allowReassembly
enables reassembly
PacketCounter nReassemblyTimeouts
count of dropped partial network-layer packets due to reassembly timeout
void setOptions(const Options &options)
set options for reassembler
LpFragmenter::Options fragmenterOptions
options for fragmentation