blob: 9f97413ee1aee2ac280303bf50b1a7230424895e [file] [log] [blame]
Junxiao Shi80ee7cb2014-12-14 10:53:05 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Junxiao Shifab9e0d2017-02-02 06:04:59 +00003 * Copyright (c) 2014-2017, Regents of the University of California,
Junxiao Shi80ee7cb2014-12-14 10:53:05 -07004 * Arizona Board of Regents,
5 * Colorado State University,
6 * University Pierre & Marie Curie, Sorbonne University,
7 * Washington University in St. Louis,
8 * Beijing Institute of Technology,
9 * The University of Memphis.
10 *
11 * This file is part of NFD (Named Data Networking Forwarding Daemon).
12 * See AUTHORS.md for complete list of NFD authors and contributors.
13 *
14 * NFD is free software: you can redistribute it and/or modify it under the terms
15 * of the GNU General Public License as published by the Free Software Foundation,
16 * either version 3 of the License, or (at your option) any later version.
17 *
18 * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
19 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
20 * PURPOSE. See the GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along with
23 * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
24 */
25
26/** \file
27 * \brief allows testing forwarding in a network topology
28 */
29
Davide Pesavento97210d52016-10-14 15:45:48 +020030#ifndef NFD_TESTS_DAEMON_FW_TOPOLOGY_TESTER_HPP
31#define NFD_TESTS_DAEMON_FW_TOPOLOGY_TESTER_HPP
Junxiao Shi80ee7cb2014-12-14 10:53:05 -070032
Junxiao Shi6535f1e2015-10-08 13:02:18 -070033#include "face/internal-transport.hpp"
Junxiao Shicde37ad2015-12-24 01:02:05 -070034#include "face/face.hpp"
Junxiao Shi80ee7cb2014-12-14 10:53:05 -070035#include "fw/strategy.hpp"
Junxiao Shi0e4a1f12016-12-24 02:39:01 +000036#include "choose-strategy.hpp"
Junxiao Shi80ee7cb2014-12-14 10:53:05 -070037#include "tests/test-common.hpp"
Junxiao Shi80ee7cb2014-12-14 10:53:05 -070038
Davide Pesavento97210d52016-10-14 15:45:48 +020039#include <ndn-cxx/face.hpp>
40
Junxiao Shi80ee7cb2014-12-14 10:53:05 -070041namespace nfd {
Spyridon Mastorakisd0381c02015-02-19 10:29:41 -080042namespace fw {
Junxiao Shi80ee7cb2014-12-14 10:53:05 -070043namespace tests {
44
Spyridon Mastorakisd0381c02015-02-19 10:29:41 -080045using namespace nfd::tests;
Junxiao Shi80ee7cb2014-12-14 10:53:05 -070046
47/** \brief identifies a node (forwarder) in the topology
48 */
49typedef size_t TopologyNode;
50
Junxiao Shi6535f1e2015-10-08 13:02:18 -070051/** \brief represents a network link in the topology which connects two or more nodes
Junxiao Shi80ee7cb2014-12-14 10:53:05 -070052 */
Junxiao Shi6535f1e2015-10-08 13:02:18 -070053class TopologyLink : noncopyable
Junxiao Shi80ee7cb2014-12-14 10:53:05 -070054{
55public:
Junxiao Shi6535f1e2015-10-08 13:02:18 -070056 explicit
57 TopologyLink(const time::nanoseconds& delay);
Junxiao Shi80ee7cb2014-12-14 10:53:05 -070058
59 /** \brief fail the link, cause packets to be dropped silently
60 */
61 void
62 fail()
63 {
64 m_isUp = false;
65 }
66
67 /** \brief recover the link from a failure
68 */
69 void
70 recover()
71 {
72 m_isUp = true;
73 }
74
Hila Ben Abraham39a79be2016-03-30 22:00:55 -070075 /** \brief change the link delay
76 * \param delay link delay, must be positive
77 */
78 void
79 setDelay(const time::nanoseconds& delay);
80
Junxiao Shicde37ad2015-12-24 01:02:05 -070081 /** \brief attach a face to the link
82 * \param i forwarder index
83 * \param face a Face with InternalForwarderTransport
84 */
Junxiao Shi5e5e4452015-09-24 16:56:52 -070085 void
Junxiao Shicde37ad2015-12-24 01:02:05 -070086 addFace(TopologyNode i, shared_ptr<Face> face);
Junxiao Shi5e5e4452015-09-24 16:56:52 -070087
Junxiao Shi80ee7cb2014-12-14 10:53:05 -070088 /** \return a face of forwarder \p i which is attached to this link
89 */
Junxiao Shi5e5e4452015-09-24 16:56:52 -070090 Face&
Junxiao Shi80ee7cb2014-12-14 10:53:05 -070091 getFace(TopologyNode i)
92 {
Junxiao Shi5e5e4452015-09-24 16:56:52 -070093 return *m_faces.at(i);
Junxiao Shi80ee7cb2014-12-14 10:53:05 -070094 }
95
Junxiao Shi6535f1e2015-10-08 13:02:18 -070096protected:
97 /** \brief attach a Transport onto this link
98 */
99 void
100 attachTransport(TopologyNode i, face::InternalTransportBase* transport);
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700101
102private:
Junxiao Shi6535f1e2015-10-08 13:02:18 -0700103 void
104 transmit(TopologyNode i, const Block& packet);
105
106 void
107 scheduleReceive(face::InternalTransportBase* recipient, const Block& packet);
108
109private:
110 bool m_isUp;
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700111 time::nanoseconds m_delay;
Junxiao Shi6535f1e2015-10-08 13:02:18 -0700112 std::unordered_map<TopologyNode, face::InternalTransportBase*> m_transports;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700113 std::unordered_map<TopologyNode, shared_ptr<Face>> m_faces;
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700114};
115
116/** \brief represents a link to a local application
117 */
Junxiao Shi6535f1e2015-10-08 13:02:18 -0700118class TopologyAppLink : noncopyable
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700119{
120public:
Junxiao Shicde37ad2015-12-24 01:02:05 -0700121 /** \brief constructor
122 * \param forwarderFace a Face with InternalForwarderTransport
123 */
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700124 explicit
Junxiao Shicde37ad2015-12-24 01:02:05 -0700125 TopologyAppLink(shared_ptr<Face> forwarderFace);
Junxiao Shi6535f1e2015-10-08 13:02:18 -0700126
127 /** \brief fail the link, cause packets to be dropped silently
128 */
129 void
130 fail();
131
132 /** \brief recover the link from a failure
133 */
134 void
135 recover();
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700136
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700137 /** \return face on forwarder side
138 */
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700139 Face&
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700140 getForwarderFace()
141 {
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700142 return *m_face;
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700143 }
144
145 /** \return face on application side
146 */
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700147 ndn::Face&
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700148 getClientFace()
149 {
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700150 return *m_client;
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700151 }
152
153private:
Junxiao Shi6535f1e2015-10-08 13:02:18 -0700154 shared_ptr<Face> m_face;
155 face::InternalForwarderTransport* m_forwarderTransport;
156 shared_ptr<face::InternalClientTransport> m_clientTransport;
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700157 shared_ptr<ndn::Face> m_client;
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700158};
159
Junxiao Shifab9e0d2017-02-02 06:04:59 +0000160/** \brief captured packets on a face
161 */
162class TopologyPcap : noncopyable
163{
164public:
165 std::vector<Interest> sentInterests;
166 std::vector<Data> sentData;
167 std::vector<lp::Nack> sentNacks;
168};
169
170/** \brief captured packet timestamp tag
171 */
172using TopologyPcapTimestamp = ndn::SimpleTag<time::steady_clock::TimePoint, 0>;
173
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700174/** \brief builds a topology for forwarding tests
175 */
176class TopologyTester : noncopyable
177{
178public:
179 /** \brief creates a forwarder
180 * \return index of new forwarder
181 */
182 TopologyNode
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700183 addForwarder(const std::string& label);
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700184
185 /** \return forwarder instance \p i
186 */
187 Forwarder&
188 getForwarder(TopologyNode i)
189 {
190 return *m_forwarders.at(i);
191 }
192
193 /** \brief sets strategy on forwarder \p i
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000194 * \tparam S the strategy type
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700195 * \note Test scenario can also access StrategyChoice table directly.
196 */
197 template<typename S>
198 void
199 setStrategy(TopologyNode i, Name prefix = Name("ndn:/"))
200 {
201 Forwarder& forwarder = this->getForwarder(i);
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000202 choose<S>(forwarder, prefix);
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700203 }
204
205 /** \brief makes a link that interconnects two or more forwarders
206 *
207 * A face is created on each of \p forwarders .
208 * When a packet is sent onto one of the faces on this link,
209 * this packet will be received by all other faces on this link after \p delay .
210 */
211 shared_ptr<TopologyLink>
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700212 addLink(const std::string& label, const time::nanoseconds& delay,
213 std::initializer_list<TopologyNode> forwarders,
214 bool forceMultiAccessFace = false);
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700215
216 /** \brief makes a link to local application
217 */
218 shared_ptr<TopologyAppLink>
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700219 addAppFace(const std::string& label, TopologyNode i);
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700220
221 /** \brief makes a link to local application, and register a prefix
222 */
223 shared_ptr<TopologyAppLink>
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700224 addAppFace(const std::string& label, TopologyNode i, const Name& prefix, uint64_t cost = 0);
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700225
Junxiao Shifab9e0d2017-02-02 06:04:59 +0000226 /** \brief enables packet capture on every forwarder face
227 */
228 void
229 enablePcap(bool isEnabled = true);
230
231 /** \return captured packets on a forwarder face
232 * \pre enablePcap(true) is in effect when the face was created
233 */
234 TopologyPcap&
235 getPcap(const Face& face);
236
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700237 /** \brief registers a prefix on a forwarder face
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700238 */
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700239 void
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700240 registerPrefix(TopologyNode i, const Face& face, const Name& prefix, uint64_t cost = 0);
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700241
242 /** \brief creates a producer application that answers every Interest with Data of same Name
243 */
244 void
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700245 addEchoProducer(ndn::Face& face, const Name& prefix = "/");
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700246
247 /** \brief creates a consumer application that sends \p n Interests under \p prefix
248 * at \p interval fixed rate.
249 */
250 void
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700251 addIntervalConsumer(ndn::Face& face, const Name& prefix,
252 const time::nanoseconds& interval, size_t n);
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700253
254private:
Junxiao Shifab9e0d2017-02-02 06:04:59 +0000255 bool m_wantPcap = false;
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700256 std::vector<unique_ptr<Forwarder>> m_forwarders;
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700257 std::vector<std::string> m_forwarderLabels;
258 std::vector<shared_ptr<TopologyLink>> m_links;
259 std::vector<shared_ptr<TopologyAppLink>> m_appLinks;
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700260};
261
262} // namespace tests
Spyridon Mastorakisd0381c02015-02-19 10:29:41 -0800263} // namespace fw
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700264} // namespace nfd
265
Davide Pesavento97210d52016-10-14 15:45:48 +0200266#endif // NFD_TESTS_DAEMON_FW_TOPOLOGY_TESTER_HPP