blob: dd6d77d7f95b0b2f777b52777f129119e7bc2a3e [file] [log] [blame]
Junxiao Shi80ee7cb2014-12-14 10:53:05 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (c) 2014-2015, Regents of the University of California,
4 * 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
30#ifndef NFD_TESTS_NFD_FW_TOPOLOGY_TESTER_HPP
31#define NFD_TESTS_NFD_FW_TOPOLOGY_TESTER_HPP
32
Junxiao Shi5e5e4452015-09-24 16:56:52 -070033#include <ndn-cxx/face.hpp>
34#include <ndn-cxx/transport/transport.hpp>
35#include "face/lp-face-wrapper.hpp"
Junxiao Shi80ee7cb2014-12-14 10:53:05 -070036#include "fw/strategy.hpp"
37#include "tests/test-common.hpp"
Junxiao Shi80ee7cb2014-12-14 10:53:05 -070038
39namespace nfd {
Spyridon Mastorakisd0381c02015-02-19 10:29:41 -080040namespace fw {
Junxiao Shi80ee7cb2014-12-14 10:53:05 -070041namespace tests {
42
Spyridon Mastorakisd0381c02015-02-19 10:29:41 -080043using namespace nfd::tests;
Junxiao Shi80ee7cb2014-12-14 10:53:05 -070044
Junxiao Shi5e5e4452015-09-24 16:56:52 -070045/** \brief abstracts a Transport used in TopologyTester
46 */
47class TopologyTransportBase
48{
49public:
50 /** \brief causes the transport to receive a link-layer packet
51 */
52 virtual void
53 receiveFromTopology(const Block& packet) = 0;
54
55 signal::Signal<TopologyTransportBase, Block> afterSend;
56
57protected:
58 DECLARE_SIGNAL_EMIT(afterSend)
59};
60
61/** \brief implements a forwarder-side Transport used in TopologyTester
62 */
63class TopologyForwarderTransport : public face::Transport, public TopologyTransportBase
64{
65public:
66 TopologyForwarderTransport(const FaceUri& localUri, const FaceUri& remoteUri,
67 ndn::nfd::FaceScope scope, ndn::nfd::LinkType linkType);
68
69 virtual void
70 receiveFromTopology(const Block& packet) DECL_OVERRIDE;
71
72protected:
73 virtual void
74 doClose() DECL_OVERRIDE
75 {
76 }
77
78private:
79 virtual void
80 doSend(Packet&& packet) DECL_OVERRIDE;
81};
82
83/** \brief implements a client-side Transport used in TopologyTester
84 */
85class TopologyClientTransport : public ndn::Transport, public TopologyTransportBase
86{
87public:
88 virtual void
89 receiveFromTopology(const Block& packet) DECL_OVERRIDE;
90
91 virtual void
92 close() DECL_OVERRIDE
93 {
94 }
95
96 virtual void
97 pause() DECL_OVERRIDE
98 {
99 }
100
101 virtual void
102 resume() DECL_OVERRIDE
103 {
104 }
105
106 virtual void
107 send(const Block& wire) DECL_OVERRIDE;
108
109 virtual void
110 send(const Block& header, const Block& payload) DECL_OVERRIDE;
111};
112
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700113/** \brief identifies a node (forwarder) in the topology
114 */
115typedef size_t TopologyNode;
116
117/** \brief represents a network or local-app link
118 */
119class TopologyLinkBase : noncopyable
120{
121public:
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700122 TopologyLinkBase();
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700123
124 /** \brief fail the link, cause packets to be dropped silently
125 */
126 void
127 fail()
128 {
129 m_isUp = false;
130 }
131
132 /** \brief recover the link from a failure
133 */
134 void
135 recover()
136 {
137 m_isUp = true;
138 }
139
140protected:
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700141 /** \brief attach a Transport onto this link
142 */
143 void
144 attachTransport(TopologyNode i, TopologyTransportBase* transport);
145
146private:
147 void
148 transmit(TopologyNode i, const Block& packet);
149
150 virtual void
151 scheduleReceive(TopologyTransportBase* recipient, const Block& packet) = 0;
152
153protected:
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700154 bool m_isUp;
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700155 std::unordered_map<TopologyNode, TopologyTransportBase*> m_transports;
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700156};
157
158/** \brief represents a network link in the topology which connects two or more nodes
159 */
160class TopologyLink : public TopologyLinkBase
161{
162public:
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700163 explicit
164 TopologyLink(const time::nanoseconds& delay);
165
166 void
167 addFace(TopologyNode i, shared_ptr<face::LpFaceWrapper> face);
168
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700169 /** \return a face of forwarder \p i which is attached to this link
170 */
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700171 Face&
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700172 getFace(TopologyNode i)
173 {
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700174 return *m_faces.at(i);
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700175 }
176
177private:
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700178 virtual void
179 scheduleReceive(TopologyTransportBase* recipient, const Block& packet) DECL_OVERRIDE;
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700180
181private:
182 time::nanoseconds m_delay;
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700183 std::unordered_map<TopologyNode, shared_ptr<face::LpFaceWrapper>> m_faces;
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700184};
185
186/** \brief represents a link to a local application
187 */
188class TopologyAppLink : public TopologyLinkBase
189{
190public:
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700191 explicit
192 TopologyAppLink(shared_ptr<face::LpFaceWrapper> face);
193
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700194 /** \return face on forwarder side
195 */
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700196 Face&
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700197 getForwarderFace()
198 {
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700199 return *m_face;
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700200 }
201
202 /** \return face on application side
203 */
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700204 ndn::Face&
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700205 getClientFace()
206 {
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700207 return *m_client;
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700208 }
209
210private:
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700211 virtual void
212 scheduleReceive(TopologyTransportBase* recipient, const Block& packet) DECL_OVERRIDE;
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700213
214private:
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700215 shared_ptr<face::LpFaceWrapper> m_face;
216 shared_ptr<ndn::Face> m_client;
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700217};
218
219/** \brief builds a topology for forwarding tests
220 */
221class TopologyTester : noncopyable
222{
223public:
224 /** \brief creates a forwarder
225 * \return index of new forwarder
226 */
227 TopologyNode
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700228 addForwarder(const std::string& label);
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700229
230 /** \return forwarder instance \p i
231 */
232 Forwarder&
233 getForwarder(TopologyNode i)
234 {
235 return *m_forwarders.at(i);
236 }
237
238 /** \brief sets strategy on forwarder \p i
239 * \tparam the strategy type
240 * \note Test scenario can also access StrategyChoice table directly.
241 */
242 template<typename S>
243 void
244 setStrategy(TopologyNode i, Name prefix = Name("ndn:/"))
245 {
246 Forwarder& forwarder = this->getForwarder(i);
247 StrategyChoice& strategyChoice = forwarder.getStrategyChoice();
248 shared_ptr<S> strategy = make_shared<S>(ref(forwarder));
249 strategyChoice.install(strategy);
250 strategyChoice.insert(prefix, strategy->getName());
251 }
252
253 /** \brief makes a link that interconnects two or more forwarders
254 *
255 * A face is created on each of \p forwarders .
256 * When a packet is sent onto one of the faces on this link,
257 * this packet will be received by all other faces on this link after \p delay .
258 */
259 shared_ptr<TopologyLink>
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700260 addLink(const std::string& label, const time::nanoseconds& delay,
261 std::initializer_list<TopologyNode> forwarders,
262 bool forceMultiAccessFace = false);
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700263
264 /** \brief makes a link to local application
265 */
266 shared_ptr<TopologyAppLink>
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700267 addAppFace(const std::string& label, TopologyNode i);
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700268
269 /** \brief makes a link to local application, and register a prefix
270 */
271 shared_ptr<TopologyAppLink>
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700272 addAppFace(const std::string& label, TopologyNode i, const Name& prefix, uint64_t cost = 0);
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700273
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700274 /** \brief registers a prefix on a forwarder face
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700275 */
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700276 void
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700277 registerPrefix(TopologyNode i, const Face& face, const Name& prefix, uint64_t cost = 0);
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700278
279 /** \brief creates a producer application that answers every Interest with Data of same Name
280 */
281 void
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700282 addEchoProducer(ndn::Face& face, const Name& prefix = "/");
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700283
284 /** \brief creates a consumer application that sends \p n Interests under \p prefix
285 * at \p interval fixed rate.
286 */
287 void
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700288 addIntervalConsumer(ndn::Face& face, const Name& prefix,
289 const time::nanoseconds& interval, size_t n);
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700290
291private:
292 std::vector<unique_ptr<Forwarder>> m_forwarders;
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700293 std::vector<std::string> m_forwarderLabels;
294 std::vector<shared_ptr<TopologyLink>> m_links;
295 std::vector<shared_ptr<TopologyAppLink>> m_appLinks;
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700296};
297
298} // namespace tests
Spyridon Mastorakisd0381c02015-02-19 10:29:41 -0800299} // namespace fw
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700300} // namespace nfd
301
302#endif // NFD_TESTS_NFD_FW_TOPOLOGY_TESTER_HPP