blob: 88d73da3a9a0a591c3f1b9dcc16da7dc226abecc [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>
Junxiao Shi6535f1e2015-10-08 13:02:18 -070034#include "face/internal-transport.hpp"
Junxiao Shicde37ad2015-12-24 01:02:05 -070035#include "face/face.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
45/** \brief identifies a node (forwarder) in the topology
46 */
47typedef size_t TopologyNode;
48
Junxiao Shi6535f1e2015-10-08 13:02:18 -070049/** \brief represents a network link in the topology which connects two or more nodes
Junxiao Shi80ee7cb2014-12-14 10:53:05 -070050 */
Junxiao Shi6535f1e2015-10-08 13:02:18 -070051class TopologyLink : noncopyable
Junxiao Shi80ee7cb2014-12-14 10:53:05 -070052{
53public:
Junxiao Shi6535f1e2015-10-08 13:02:18 -070054 explicit
55 TopologyLink(const time::nanoseconds& delay);
Junxiao Shi80ee7cb2014-12-14 10:53:05 -070056
57 /** \brief fail the link, cause packets to be dropped silently
58 */
59 void
60 fail()
61 {
62 m_isUp = false;
63 }
64
65 /** \brief recover the link from a failure
66 */
67 void
68 recover()
69 {
70 m_isUp = true;
71 }
72
Junxiao Shicde37ad2015-12-24 01:02:05 -070073 /** \brief attach a face to the link
74 * \param i forwarder index
75 * \param face a Face with InternalForwarderTransport
76 */
Junxiao Shi5e5e4452015-09-24 16:56:52 -070077 void
Junxiao Shicde37ad2015-12-24 01:02:05 -070078 addFace(TopologyNode i, shared_ptr<Face> face);
Junxiao Shi5e5e4452015-09-24 16:56:52 -070079
Junxiao Shi80ee7cb2014-12-14 10:53:05 -070080 /** \return a face of forwarder \p i which is attached to this link
81 */
Junxiao Shi5e5e4452015-09-24 16:56:52 -070082 Face&
Junxiao Shi80ee7cb2014-12-14 10:53:05 -070083 getFace(TopologyNode i)
84 {
Junxiao Shi5e5e4452015-09-24 16:56:52 -070085 return *m_faces.at(i);
Junxiao Shi80ee7cb2014-12-14 10:53:05 -070086 }
87
Junxiao Shi6535f1e2015-10-08 13:02:18 -070088protected:
89 /** \brief attach a Transport onto this link
90 */
91 void
92 attachTransport(TopologyNode i, face::InternalTransportBase* transport);
Junxiao Shi80ee7cb2014-12-14 10:53:05 -070093
94private:
Junxiao Shi6535f1e2015-10-08 13:02:18 -070095 void
96 transmit(TopologyNode i, const Block& packet);
97
98 void
99 scheduleReceive(face::InternalTransportBase* recipient, const Block& packet);
100
101private:
102 bool m_isUp;
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700103 time::nanoseconds m_delay;
Junxiao Shi6535f1e2015-10-08 13:02:18 -0700104 std::unordered_map<TopologyNode, face::InternalTransportBase*> m_transports;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700105 std::unordered_map<TopologyNode, shared_ptr<Face>> m_faces;
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700106};
107
108/** \brief represents a link to a local application
109 */
Junxiao Shi6535f1e2015-10-08 13:02:18 -0700110class TopologyAppLink : noncopyable
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700111{
112public:
Junxiao Shicde37ad2015-12-24 01:02:05 -0700113 /** \brief constructor
114 * \param forwarderFace a Face with InternalForwarderTransport
115 */
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700116 explicit
Junxiao Shicde37ad2015-12-24 01:02:05 -0700117 TopologyAppLink(shared_ptr<Face> forwarderFace);
Junxiao Shi6535f1e2015-10-08 13:02:18 -0700118
119 /** \brief fail the link, cause packets to be dropped silently
120 */
121 void
122 fail();
123
124 /** \brief recover the link from a failure
125 */
126 void
127 recover();
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700128
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700129 /** \return face on forwarder side
130 */
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700131 Face&
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700132 getForwarderFace()
133 {
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700134 return *m_face;
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700135 }
136
137 /** \return face on application side
138 */
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700139 ndn::Face&
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700140 getClientFace()
141 {
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700142 return *m_client;
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700143 }
144
145private:
Junxiao Shi6535f1e2015-10-08 13:02:18 -0700146 shared_ptr<Face> m_face;
147 face::InternalForwarderTransport* m_forwarderTransport;
148 shared_ptr<face::InternalClientTransport> m_clientTransport;
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700149 shared_ptr<ndn::Face> m_client;
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700150};
151
152/** \brief builds a topology for forwarding tests
153 */
154class TopologyTester : noncopyable
155{
156public:
157 /** \brief creates a forwarder
158 * \return index of new forwarder
159 */
160 TopologyNode
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700161 addForwarder(const std::string& label);
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700162
163 /** \return forwarder instance \p i
164 */
165 Forwarder&
166 getForwarder(TopologyNode i)
167 {
168 return *m_forwarders.at(i);
169 }
170
171 /** \brief sets strategy on forwarder \p i
172 * \tparam the strategy type
173 * \note Test scenario can also access StrategyChoice table directly.
174 */
175 template<typename S>
176 void
177 setStrategy(TopologyNode i, Name prefix = Name("ndn:/"))
178 {
179 Forwarder& forwarder = this->getForwarder(i);
180 StrategyChoice& strategyChoice = forwarder.getStrategyChoice();
181 shared_ptr<S> strategy = make_shared<S>(ref(forwarder));
182 strategyChoice.install(strategy);
183 strategyChoice.insert(prefix, strategy->getName());
184 }
185
186 /** \brief makes a link that interconnects two or more forwarders
187 *
188 * A face is created on each of \p forwarders .
189 * When a packet is sent onto one of the faces on this link,
190 * this packet will be received by all other faces on this link after \p delay .
191 */
192 shared_ptr<TopologyLink>
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700193 addLink(const std::string& label, const time::nanoseconds& delay,
194 std::initializer_list<TopologyNode> forwarders,
195 bool forceMultiAccessFace = false);
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700196
197 /** \brief makes a link to local application
198 */
199 shared_ptr<TopologyAppLink>
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700200 addAppFace(const std::string& label, TopologyNode i);
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700201
202 /** \brief makes a link to local application, and register a prefix
203 */
204 shared_ptr<TopologyAppLink>
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700205 addAppFace(const std::string& label, TopologyNode i, const Name& prefix, uint64_t cost = 0);
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700206
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700207 /** \brief registers a prefix on a forwarder face
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700208 */
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700209 void
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700210 registerPrefix(TopologyNode i, const Face& face, const Name& prefix, uint64_t cost = 0);
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700211
212 /** \brief creates a producer application that answers every Interest with Data of same Name
213 */
214 void
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700215 addEchoProducer(ndn::Face& face, const Name& prefix = "/");
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700216
217 /** \brief creates a consumer application that sends \p n Interests under \p prefix
218 * at \p interval fixed rate.
219 */
220 void
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700221 addIntervalConsumer(ndn::Face& face, const Name& prefix,
222 const time::nanoseconds& interval, size_t n);
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700223
224private:
225 std::vector<unique_ptr<Forwarder>> m_forwarders;
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700226 std::vector<std::string> m_forwarderLabels;
227 std::vector<shared_ptr<TopologyLink>> m_links;
228 std::vector<shared_ptr<TopologyAppLink>> m_appLinks;
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700229};
230
231} // namespace tests
Spyridon Mastorakisd0381c02015-02-19 10:29:41 -0800232} // namespace fw
Junxiao Shi80ee7cb2014-12-14 10:53:05 -0700233} // namespace nfd
234
235#endif // NFD_TESTS_NFD_FW_TOPOLOGY_TESTER_HPP