fib-entry.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2013-2019 Regents of the University of California.
4  *
5  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
6  *
7  * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8  * terms of the GNU Lesser General Public License as published by the Free Software
9  * Foundation, either version 3 of the License, or (at your option) any later version.
10  *
11  * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13  * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14  *
15  * You should have received copies of the GNU General Public License and GNU Lesser
16  * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17  * <http://www.gnu.org/licenses/>.
18  *
19  * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
20  */
21 
28 
29 #include <boost/range/adaptor/reversed.hpp>
30 
31 namespace ndn {
32 namespace nfd {
33 
34 BOOST_CONCEPT_ASSERT((StatusDatasetItem<NextHopRecord>));
35 BOOST_CONCEPT_ASSERT((StatusDatasetItem<FibEntry>));
36 
38  : m_faceId(INVALID_FACE_ID)
39  , m_cost(0)
40 {
41 }
42 
44 {
45  this->wireDecode(block);
46 }
47 
49 NextHopRecord::setFaceId(uint64_t faceId)
50 {
51  m_faceId = faceId;
52  m_wire.reset();
53  return *this;
54 }
55 
57 NextHopRecord::setCost(uint64_t cost)
58 {
59  m_cost = cost;
60  m_wire.reset();
61  return *this;
62 }
63 
64 template<encoding::Tag TAG>
65 size_t
67 {
68  size_t totalLength = 0;
69 
70  totalLength += prependNonNegativeIntegerBlock(block, ndn::tlv::nfd::Cost, m_cost);
71  totalLength += prependNonNegativeIntegerBlock(block, ndn::tlv::nfd::FaceId, m_faceId);
72 
73  totalLength += block.prependVarNumber(totalLength);
74  totalLength += block.prependVarNumber(ndn::tlv::nfd::NextHopRecord);
75  return totalLength;
76 }
77 
79 
80 const Block&
82 {
83  if (m_wire.hasWire())
84  return m_wire;
85 
86  EncodingEstimator estimator;
87  size_t estimatedSize = wireEncode(estimator);
88 
89  EncodingBuffer buffer(estimatedSize, 0);
90  wireEncode(buffer);
91 
92  m_wire = buffer.block();
93  return m_wire;
94 }
95 
96 void
98 {
99  if (block.type() != tlv::nfd::NextHopRecord) {
100  NDN_THROW(Error("NextHopRecord", block.type()));
101  }
102 
103  m_wire = block;
104  m_wire.parse();
105  auto val = m_wire.elements_begin();
106 
107  if (val == m_wire.elements_end()) {
108  NDN_THROW(Error("unexpected end of NextHopRecord"));
109  }
110  else if (val->type() != tlv::nfd::FaceId) {
111  NDN_THROW(Error("FaceId", val->type()));
112  }
113  m_faceId = readNonNegativeInteger(*val);
114  ++val;
115 
116  if (val == m_wire.elements_end()) {
117  NDN_THROW(Error("unexpected end of NextHopRecord"));
118  }
119  else if (val->type() != tlv::nfd::Cost) {
120  NDN_THROW(Error("Cost", val->type()));
121  }
122  m_cost = readNonNegativeInteger(*val);
123  ++val;
124 }
125 
126 bool
128 {
129  return a.getFaceId() == b.getFaceId() &&
130  a.getCost() == b.getCost();
131 }
132 
133 std::ostream&
134 operator<<(std::ostream& os, const NextHopRecord& nh)
135 {
136  return os << "NextHopRecord("
137  << "FaceId: " << nh.getFaceId() << ", "
138  << "Cost: " << nh.getCost()
139  << ")";
140 }
141 
143 
144 FibEntry::FibEntry() = default;
145 
147 {
148  this->wireDecode(block);
149 }
150 
151 FibEntry&
152 FibEntry::setPrefix(const Name& prefix)
153 {
154  m_prefix = prefix;
155  m_wire.reset();
156  return *this;
157 }
158 
159 FibEntry&
161 {
162  m_nextHopRecords.push_back(nh);
163  m_wire.reset();
164  return *this;
165 }
166 
167 FibEntry&
169 {
170  m_nextHopRecords.clear();
171  m_wire.reset();
172  return *this;
173 }
174 
175 template<encoding::Tag TAG>
176 size_t
178 {
179  size_t totalLength = 0;
180 
181  for (const auto& nh : m_nextHopRecords | boost::adaptors::reversed) {
182  totalLength += nh.wireEncode(block);
183  }
184  totalLength += m_prefix.wireEncode(block);
185 
186  totalLength += block.prependVarNumber(totalLength);
187  totalLength += block.prependVarNumber(tlv::nfd::FibEntry);
188  return totalLength;
189 }
190 
192 
193 const Block&
195 {
196  if (m_wire.hasWire())
197  return m_wire;
198 
199  EncodingEstimator estimator;
200  size_t estimatedSize = wireEncode(estimator);
201 
202  EncodingBuffer buffer(estimatedSize, 0);
203  wireEncode(buffer);
204 
205  m_wire = buffer.block();
206  return m_wire;
207 }
208 
209 void
211 {
212  if (block.type() != tlv::nfd::FibEntry) {
213  NDN_THROW(Error("FibEntry", block.type()));
214  }
215 
216  m_wire = block;
217  m_wire.parse();
218  auto val = m_wire.elements_begin();
219 
220  if (val == m_wire.elements_end()) {
221  NDN_THROW(Error("unexpected end of FibEntry"));
222  }
223  else if (val->type() != tlv::Name) {
224  NDN_THROW(Error("Name", val->type()));
225  }
226  m_prefix.wireDecode(*val);
227  ++val;
228 
229  m_nextHopRecords.clear();
230  for (; val != m_wire.elements_end(); ++val) {
231  if (val->type() != tlv::nfd::NextHopRecord) {
232  NDN_THROW(Error("NextHopRecord", val->type()));
233  }
234  m_nextHopRecords.emplace_back(*val);
235  }
236 }
237 
238 bool
239 operator==(const FibEntry& a, const FibEntry& b)
240 {
241  const auto& aNextHops = a.getNextHopRecords();
242  const auto& bNextHops = b.getNextHopRecords();
243 
244  if (a.getPrefix() != b.getPrefix() ||
245  aNextHops.size() != bNextHops.size())
246  return false;
247 
248  std::vector<bool> matched(bNextHops.size(), false);
249  return std::all_of(aNextHops.begin(), aNextHops.end(),
250  [&] (const NextHopRecord& nh) {
251  for (size_t i = 0; i < bNextHops.size(); ++i) {
252  if (!matched[i] && bNextHops[i] == nh) {
253  matched[i] = true;
254  return true;
255  }
256  }
257  return false;
258  });
259 }
260 
261 std::ostream&
262 operator<<(std::ostream& os, const FibEntry& entry)
263 {
264  os << "FibEntry(Prefix: " << entry.getPrefix() << ",\n"
265  << " NextHops: [";
266 
267  std::copy(entry.getNextHopRecords().begin(), entry.getNextHopRecords().end(),
268  make_ostream_joiner(os, ",\n "));
269 
270  os << "]\n";
271 
272  return os << " )";
273 }
274 
275 } // namespace nfd
276 } // namespace ndn
Represents a TLV element of the NDN packet format.
Definition: block.hpp:45
uint32_t type() const
Return the TLV-TYPE of the Block.
Definition: block.hpp:285
bool hasWire() const noexcept
Check if the Block contains a fully encoded wire representation.
Definition: block.hpp:241
element_const_iterator elements_end() const
Equivalent to elements().end()
Definition: block.hpp:418
element_const_iterator elements_begin() const
Equivalent to elements().begin()
Definition: block.hpp:410
void reset() noexcept
Reset the Block to a default-constructed state.
Definition: block.cpp:265
void parse() const
Parse TLV-VALUE into sub-elements.
Definition: block.cpp:341
Represents an absolute name.
Definition: name.hpp:46
size_t wireEncode(EncodingImpl< TAG > &encoder) const
Fast encoding or block size estimation.
Definition: name.cpp:117
size_t size() const
Returns the number of components.
Definition: name.hpp:155
void wireDecode(const Block &wire)
Decode name from wire encoding.
Definition: name.cpp:150
FibEntry & clearNextHopRecords()
Definition: fib-entry.cpp:168
const Block & wireEncode() const
Definition: fib-entry.cpp:194
FibEntry & setPrefix(const Name &prefix)
Definition: fib-entry.cpp:152
void wireDecode(const Block &block)
Definition: fib-entry.cpp:210
FibEntry & addNextHopRecord(const NextHopRecord &nh)
Definition: fib-entry.cpp:160
const Name & getPrefix() const
Definition: fib-entry.hpp:116
const std::vector< NextHopRecord > & getNextHopRecords() const
Definition: fib-entry.hpp:125
NextHopRecord & setFaceId(uint64_t faceId)
Definition: fib-entry.cpp:49
void wireDecode(const Block &block)
Definition: fib-entry.cpp:97
NextHopRecord & setCost(uint64_t cost)
Definition: fib-entry.cpp:57
uint64_t getFaceId() const
Definition: fib-entry.hpp:49
uint64_t getCost() const
Definition: fib-entry.hpp:58
const Block & wireEncode() const
Definition: fib-entry.cpp:81
#define NDN_CXX_DEFINE_WIRE_ENCODE_INSTANTIATIONS(ClassName)
#define NDN_THROW(e)
Definition: exception.hpp:61
EncodingImpl< EstimatorTag > EncodingEstimator
uint64_t readNonNegativeInteger(const Block &block)
Read a non-negative integer from a TLV element.
size_t prependNonNegativeIntegerBlock(EncodingImpl< TAG > &encoder, uint32_t type, uint64_t value)
Prepend a TLV element containing a non-negative integer.
EncodingImpl< EncoderTag > EncodingBuffer
const uint64_t INVALID_FACE_ID
std::ostream & operator<<(std::ostream &os, FaceScope faceScope)
bool operator==(const ChannelStatus &a, const ChannelStatus &b)
@ Name
Definition: tlv.hpp:67
Definition: data.cpp:25
std::ostream & operator<<(std::ostream &os, const Data &data)
Definition: data.cpp:376
ostream_joiner< std::decay_t< DelimT >, CharT, Traits > make_ostream_joiner(std::basic_ostream< CharT, Traits > &os, DelimT &&delimiter)
Backport of ostream_joiner from the Library Fundamentals v2 TS.