blob: 687b0e2ded2191f33a193974a04235b294bb398e [file] [log] [blame]
Vince Lehman8a4c29e2016-07-11 08:49:35 +00001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (c) 2014-2016, 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#include "fw/asf-strategy.hpp"
27
28#include "tests/test-common.hpp"
29#include "topology-tester.hpp"
30
31namespace nfd {
32namespace fw {
33namespace asf {
34namespace tests {
35
36using namespace nfd::fw::tests;
37
38BOOST_AUTO_TEST_SUITE(Fw)
39BOOST_FIXTURE_TEST_SUITE(TestAsfStrategy, UnitTestTimeFixture)
40
41class AsfGridFixture : public UnitTestTimeFixture
42{
43protected:
44 AsfGridFixture()
45 {
46 /*
47 * +---------+
48 * +----->| nodeB |<------+
49 * | +---------+ |
50 * 10ms | | 10ms
51 * v v
52 * +---------+ +---------+
53 * | nodeA | | nodeC |
54 * +---------+ +---------+
55 * ^ ^
56 * 100ms | | 100ms
57 * | +---------+ |
58 * +----->| nodeD |<------+
59 * +---------+
60 */
61
62 nodeA = topo.addForwarder("A");
63 nodeB = topo.addForwarder("B");
64 nodeC = topo.addForwarder("C");
65 nodeD = topo.addForwarder("D");
66
67 topo.setStrategy<fw::AsfStrategy>(nodeA);
68 topo.setStrategy<fw::AsfStrategy>(nodeB);
69 topo.setStrategy<fw::AsfStrategy>(nodeC);
70 topo.setStrategy<fw::AsfStrategy>(nodeD);
71
72 linkAB = topo.addLink("AB", time::milliseconds(10), {nodeA, nodeB});
73 linkAD = topo.addLink("AD", time::milliseconds(100), {nodeA, nodeD});
74 linkBC = topo.addLink("BC", time::milliseconds(10), {nodeB, nodeC});
75 linkCD = topo.addLink("CD", time::milliseconds(100), {nodeC, nodeD});
76
77 consumer = topo.addAppFace("c", nodeA);
78 producer = topo.addAppFace("p", nodeC, PRODUCER_PREFIX);
79 topo.addEchoProducer(producer->getClientFace());
80
81 // Register producer prefix on consumer node
82 topo.registerPrefix(nodeA, linkAB->getFace(nodeA), PRODUCER_PREFIX, 10);
83 topo.registerPrefix(nodeA, linkAD->getFace(nodeA), PRODUCER_PREFIX, 5);
84 }
85
86 void
87 runConsumer()
88 {
89 topo.addIntervalConsumer(consumer->getClientFace(), PRODUCER_PREFIX, time::seconds(1), 30);
90 this->advanceClocks(time::milliseconds(1), time::seconds(30));
91 }
92
93protected:
94 TopologyTester topo;
95
96 TopologyNode nodeA;
97 TopologyNode nodeB;
98 TopologyNode nodeC;
99 TopologyNode nodeD;
100
101 shared_ptr<TopologyLink> linkAB;
102 shared_ptr<TopologyLink> linkAD;
103 shared_ptr<TopologyLink> linkBC;
104 shared_ptr<TopologyLink> linkCD;
105
106 shared_ptr<TopologyAppLink> consumer;
107 shared_ptr<TopologyAppLink> producer;
108
109 static const Name PRODUCER_PREFIX;
110};
111
112const Name AsfGridFixture::PRODUCER_PREFIX = Name("ndn:/hr/C");
113
114BOOST_FIXTURE_TEST_CASE(Basic, AsfGridFixture)
115{
116 // Both nodeB and nodeD have FIB entries to reach the producer
117 topo.registerPrefix(nodeB, linkBC->getFace(nodeB), PRODUCER_PREFIX);
118 topo.registerPrefix(nodeD, linkCD->getFace(nodeD), PRODUCER_PREFIX);
119
120 runConsumer();
121
122 // ASF should use the Face to nodeD because it has lower routing cost.
123 // After 5 seconds, a probe Interest should be sent to the Face to nodeB,
124 // and the probe should return Data quicker. ASF should then use the Face
125 // to nodeB to forward the remaining Interests.
126 BOOST_CHECK_EQUAL(consumer->getForwarderFace().getCounters().nOutData, 30);
127 BOOST_CHECK_GE(linkAB->getFace(nodeA).getCounters().nOutInterests, 24);
128 BOOST_CHECK_LE(linkAD->getFace(nodeA).getCounters().nOutInterests, 6);
129
130 // If the link from nodeA to nodeB fails, ASF should start using the Face
131 // to nodeD again.
132 linkAB->fail();
133
134 runConsumer();
135
136 // Only 59 Data because the first Interest to nodeB after the failure should timeout
137 BOOST_CHECK_EQUAL(consumer->getForwarderFace().getCounters().nOutData, 59);
138 BOOST_CHECK_LE(linkAB->getFace(nodeA).getCounters().nOutInterests, 30);
139 BOOST_CHECK_GE(linkAD->getFace(nodeA).getCounters().nOutInterests, 30);
140
141 // If the link from nodeA to nodeB recovers, ASF should probe the Face
142 // to nodeB and start using it again.
143 linkAB->recover();
144
145 // Advance time to ensure probing is due
146 this->advanceClocks(time::milliseconds(1), time::seconds(10));
147
148 runConsumer();
149
150 BOOST_CHECK_EQUAL(consumer->getForwarderFace().getCounters().nOutData, 89);
151 BOOST_CHECK_GE(linkAB->getFace(nodeA).getCounters().nOutInterests, 50);
152 BOOST_CHECK_LE(linkAD->getFace(nodeA).getCounters().nOutInterests, 40);
153
154 // If both links fail, nodeA should forward to the next hop with the lowest cost
155 linkAB->fail();
156 linkAD->fail();
157
158 runConsumer();
159
160 BOOST_CHECK_EQUAL(consumer->getForwarderFace().getCounters().nOutData, 89);
161 BOOST_CHECK_LE(linkAB->getFace(nodeA).getCounters().nOutInterests, 60);
162 BOOST_CHECK_GE(linkAD->getFace(nodeA).getCounters().nOutInterests, 60);
163}
164
165BOOST_FIXTURE_TEST_CASE(Nack, AsfGridFixture)
166{
167 // nodeB has a FIB entry to reach the producer, but nodeD does not
168 topo.registerPrefix(nodeB, linkBC->getFace(nodeB), PRODUCER_PREFIX);
169
170 // The strategy should first try to send to nodeD. But since nodeD does not have a route for
171 // the producer's prefix, it should return a NO_ROUTE Nack. The strategy should then start using the Face to
172 // nodeB.
173 runConsumer();
174
175 BOOST_CHECK_GE(linkAD->getFace(nodeA).getCounters().nInNacks, 1);
176 BOOST_CHECK_EQUAL(consumer->getForwarderFace().getCounters().nOutData, 29);
177 BOOST_CHECK_EQUAL(linkAB->getFace(nodeA).getCounters().nOutInterests, 29);
178
179 // nodeD should receive 2 Interests: one for the very first Interest and
180 // another from a probe
181 BOOST_CHECK_GE(linkAD->getFace(nodeA).getCounters().nOutInterests, 2);
182}
183
184BOOST_AUTO_TEST_SUITE_END() // TestAsfStrategy
185BOOST_AUTO_TEST_SUITE_END() // Fw
186
187} // namespace tests
188} // namespace asf
189} // namespace fw
190} // namespace nfd