blob: db09f13016958a29503cde73a48b8d10005ba31d [file] [log] [blame]
mukesh agrawald4ef6772012-02-21 16:28:04 -08001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
Paul Stewart75e89d22011-08-01 10:00:02 -07002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <sys/socket.h>
6#include <linux/rtnetlink.h>
7
Paul Stewart3f68bb12012-03-15 13:33:10 -07008#include <vector>
9
Paul Stewart75e89d22011-08-01 10:00:02 -070010#include <base/logging.h>
Eric Shienbrood3e20a232012-02-16 11:35:56 -050011#include <base/stl_util.h>
Paul Stewart75e89d22011-08-01 10:00:02 -070012#include <gtest/gtest.h>
13#include <gmock/gmock.h>
14
15#include "shill/byte_string.h"
16#include "shill/mock_control.h"
Paul Stewartf748a362012-03-07 12:01:20 -080017#include "shill/mock_rtnl_handler.h"
Paul Stewart75e89d22011-08-01 10:00:02 -070018#include "shill/routing_table.h"
19#include "shill/routing_table_entry.h"
20#include "shill/rtnl_handler.h"
21#include "shill/rtnl_message.h"
22
Darin Petkovabf6d282012-05-08 15:49:05 +020023using base::Bind;
Eric Shienbrood3e20a232012-02-16 11:35:56 -050024using base::Callback;
Darin Petkovabf6d282012-05-08 15:49:05 +020025using base::Unretained;
Paul Stewarte93b0382012-04-24 13:11:28 -070026using base::hash_map;
Darin Petkovabf6d282012-05-08 15:49:05 +020027using std::deque;
Paul Stewart3f68bb12012-03-15 13:33:10 -070028using std::vector;
Paul Stewart75e89d22011-08-01 10:00:02 -070029using testing::_;
Darin Petkovabf6d282012-05-08 15:49:05 +020030using testing::Field;
Paul Stewartf748a362012-03-07 12:01:20 -080031using testing::Invoke;
Paul Stewart75e89d22011-08-01 10:00:02 -070032using testing::Return;
Paul Stewartf748a362012-03-07 12:01:20 -080033using testing::StrictMock;
Paul Stewart75e89d22011-08-01 10:00:02 -070034using testing::Test;
35
36namespace shill {
37
38class TestEventDispatcher : public EventDispatcher {
39 public:
Paul Stewart26b327e2011-10-19 11:38:09 -070040 virtual IOHandler *CreateInputHandler(
mukesh agrawal1830fa12011-09-26 14:31:40 -070041 int /*fd*/,
Eric Shienbrood3e20a232012-02-16 11:35:56 -050042 const Callback<void(InputData*)> &/*callback*/) {
Paul Stewart75e89d22011-08-01 10:00:02 -070043 return NULL;
44 }
45};
46
47class RoutingTableTest : public Test {
48 public:
Paul Stewarte93b0382012-04-24 13:11:28 -070049 RoutingTableTest() : routing_table_(new RoutingTable()) {}
Paul Stewart75e89d22011-08-01 10:00:02 -070050
Paul Stewartf748a362012-03-07 12:01:20 -080051 virtual void SetUp() {
52 routing_table_->rtnl_handler_ = &rtnl_handler_;
53 ON_CALL(rtnl_handler_, SendMessage(_)).WillByDefault(Return(true));
Paul Stewart75e89d22011-08-01 10:00:02 -070054 }
55
Paul Stewart65c40f52011-08-08 07:27:46 -070056 virtual void TearDown() {
57 RTNLHandler::GetInstance()->Stop();
58 }
59
Paul Stewarte93b0382012-04-24 13:11:28 -070060 hash_map<int, vector<RoutingTableEntry> > *GetRoutingTables() {
Paul Stewartf748a362012-03-07 12:01:20 -080061 return &routing_table_->tables_;
62 }
63
Darin Petkovabf6d282012-05-08 15:49:05 +020064 deque<RoutingTable::Query> *GetQueries() {
Paul Stewarte93b0382012-04-24 13:11:28 -070065 return &routing_table_->route_queries_;
Paul Stewartf748a362012-03-07 12:01:20 -080066 }
67
68 void SendRouteEntry(RTNLMessage::Mode mode,
69 uint32 interface_index,
70 const RoutingTableEntry &entry);
71
72 void SendRouteEntryWithSeqAndProto(RTNLMessage::Mode mode,
73 uint32 interface_index,
74 const RoutingTableEntry &entry,
75 uint32 seq,
76 unsigned char proto);
77
78 void SendRouteMessage(const RTNLMessage &msg);
79
80 bool SetSequenceForMessage(RTNLMessage *message) {
81 message->set_seq(RoutingTableTest::kTestRequestSeq);
82 return true;
83 }
84
Paul Stewart75e89d22011-08-01 10:00:02 -070085 protected:
Paul Stewart75e89d22011-08-01 10:00:02 -070086 static const uint32 kTestDeviceIndex0;
87 static const uint32 kTestDeviceIndex1;
88 static const char kTestDeviceName0[];
Thieu Lecaef8932012-02-28 16:06:59 -080089 static const char kTestDeviceNetAddress4[];
90 static const char kTestForeignNetAddress4[];
91 static const char kTestForeignNetGateway4[];
92 static const char kTestForeignNetAddress6[];
93 static const char kTestForeignNetGateway6[];
Paul Stewartf748a362012-03-07 12:01:20 -080094 static const char kTestGatewayAddress4[];
Paul Stewart75e89d22011-08-01 10:00:02 -070095 static const char kTestNetAddress0[];
96 static const char kTestNetAddress1[];
Paul Stewartf748a362012-03-07 12:01:20 -080097 static const char kTestRemoteAddress4[];
Paul Stewart3f68bb12012-03-15 13:33:10 -070098 static const char kTestRemoteNetmask4[];
99 static const char kTestRemoteNetwork4[];
100 static const int kTestRemotePrefix4;
Paul Stewartf748a362012-03-07 12:01:20 -0800101 static const uint32 kTestRequestSeq;
Paul Stewarte93b0382012-04-24 13:11:28 -0700102 static const int kTestRouteTag;
Paul Stewart75e89d22011-08-01 10:00:02 -0700103
Darin Petkovabf6d282012-05-08 15:49:05 +0200104 class QueryCallbackTarget {
105 public:
106 QueryCallbackTarget()
107 : callback_(Bind(&QueryCallbackTarget::CallTarget, Unretained(this))) {}
108
109 MOCK_METHOD2(CallTarget,
110 void(int interface_index, const RoutingTableEntry &entry));
111 const RoutingTable::Query::Callback &callback() { return callback_; }
112
113 private:
114 RoutingTable::Query::Callback callback_;
115 };
116
Paul Stewart75e89d22011-08-01 10:00:02 -0700117 RoutingTable *routing_table_;
118 TestEventDispatcher dispatcher_;
Paul Stewartf748a362012-03-07 12:01:20 -0800119 StrictMock<MockRTNLHandler> rtnl_handler_;
Paul Stewart75e89d22011-08-01 10:00:02 -0700120};
121
Paul Stewart75e89d22011-08-01 10:00:02 -0700122const uint32 RoutingTableTest::kTestDeviceIndex0 = 12345;
123const uint32 RoutingTableTest::kTestDeviceIndex1 = 67890;
124const char RoutingTableTest::kTestDeviceName0[] = "test-device0";
Thieu Lecaef8932012-02-28 16:06:59 -0800125const char RoutingTableTest::kTestDeviceNetAddress4[] = "192.168.2.0/24";
126const char RoutingTableTest::kTestForeignNetAddress4[] = "192.168.2.2";
127const char RoutingTableTest::kTestForeignNetGateway4[] = "192.168.2.1";
128const char RoutingTableTest::kTestForeignNetAddress6[] = "2000::/3";
129const char RoutingTableTest::kTestForeignNetGateway6[] = "fe80:::::1";
Paul Stewartf748a362012-03-07 12:01:20 -0800130const char RoutingTableTest::kTestGatewayAddress4[] = "192.168.2.254";
Paul Stewart75e89d22011-08-01 10:00:02 -0700131const char RoutingTableTest::kTestNetAddress0[] = "192.168.1.1";
132const char RoutingTableTest::kTestNetAddress1[] = "192.168.1.2";
Paul Stewartf748a362012-03-07 12:01:20 -0800133const char RoutingTableTest::kTestRemoteAddress4[] = "192.168.2.254";
Paul Stewart3f68bb12012-03-15 13:33:10 -0700134const char RoutingTableTest::kTestRemoteNetmask4[] = "255.255.255.0";
135const char RoutingTableTest::kTestRemoteNetwork4[] = "192.168.100.0";
136const int RoutingTableTest::kTestRemotePrefix4 = 24;
Paul Stewartf748a362012-03-07 12:01:20 -0800137const uint32 RoutingTableTest::kTestRequestSeq = 456;
Paul Stewarte93b0382012-04-24 13:11:28 -0700138const int RoutingTableTest::kTestRouteTag = 789;
Paul Stewart75e89d22011-08-01 10:00:02 -0700139
Darin Petkovabf6d282012-05-08 15:49:05 +0200140namespace {
141
Paul Stewart75e89d22011-08-01 10:00:02 -0700142MATCHER_P4(IsRoutingPacket, mode, index, entry, flags, "") {
Paul Stewartf748a362012-03-07 12:01:20 -0800143 const RTNLMessage::RouteStatus &status = arg->route_status();
Paul Stewart75e89d22011-08-01 10:00:02 -0700144
145 uint32 oif;
146 uint32 priority;
147
148 return
Paul Stewartf748a362012-03-07 12:01:20 -0800149 arg->type() == RTNLMessage::kTypeRoute &&
150 arg->family() == entry.gateway.family() &&
151 arg->flags() == (NLM_F_REQUEST | flags) &&
152 status.table == RT_TABLE_MAIN &&
153 status.protocol == RTPROT_BOOT &&
154 status.scope == entry.scope &&
155 status.type == RTN_UNICAST &&
156 arg->HasAttribute(RTA_DST) &&
157 IPAddress(arg->family(),
158 arg->GetAttribute(RTA_DST),
159 status.dst_prefix).Equals(entry.dst) &&
160 !arg->HasAttribute(RTA_SRC) &&
161 arg->HasAttribute(RTA_GATEWAY) &&
162 IPAddress(arg->family(),
163 arg->GetAttribute(RTA_GATEWAY)).Equals(entry.gateway) &&
164 arg->GetAttribute(RTA_OIF).ConvertToCPUUInt32(&oif) &&
165 oif == index &&
166 arg->GetAttribute(RTA_PRIORITY).ConvertToCPUUInt32(&priority) &&
167 priority == entry.metric;
Paul Stewart75e89d22011-08-01 10:00:02 -0700168}
169
Darin Petkovabf6d282012-05-08 15:49:05 +0200170} // namespace
171
Paul Stewartf748a362012-03-07 12:01:20 -0800172void RoutingTableTest::SendRouteEntry(RTNLMessage::Mode mode,
173 uint32 interface_index,
174 const RoutingTableEntry &entry) {
175 SendRouteEntryWithSeqAndProto(mode, interface_index, entry, 0, RTPROT_BOOT);
176}
177
178void RoutingTableTest::SendRouteEntryWithSeqAndProto(
179 RTNLMessage::Mode mode,
180 uint32 interface_index,
181 const RoutingTableEntry &entry,
182 uint32 seq,
183 unsigned char proto) {
Paul Stewart75e89d22011-08-01 10:00:02 -0700184 RTNLMessage msg(
Paul Stewart9a908082011-08-31 12:18:48 -0700185 RTNLMessage::kTypeRoute,
Paul Stewart75e89d22011-08-01 10:00:02 -0700186 mode,
187 0,
Paul Stewartf748a362012-03-07 12:01:20 -0800188 seq,
Paul Stewart75e89d22011-08-01 10:00:02 -0700189 0,
190 0,
191 entry.dst.family());
192
193 msg.set_route_status(RTNLMessage::RouteStatus(
Paul Stewart9e3fcd72011-08-26 15:46:16 -0700194 entry.dst.prefix(),
195 entry.src.prefix(),
Paul Stewart75e89d22011-08-01 10:00:02 -0700196 RT_TABLE_MAIN,
Paul Stewartf748a362012-03-07 12:01:20 -0800197 proto,
Paul Stewart75e89d22011-08-01 10:00:02 -0700198 entry.scope,
199 RTN_UNICAST,
200 0));
201
202 msg.SetAttribute(RTA_DST, entry.dst.address());
203 if (!entry.src.IsDefault()) {
204 msg.SetAttribute(RTA_SRC, entry.src.address());
205 }
206 if (!entry.gateway.IsDefault()) {
207 msg.SetAttribute(RTA_GATEWAY, entry.gateway.address());
208 }
209 msg.SetAttribute(RTA_PRIORITY, ByteString::CreateFromCPUUInt32(entry.metric));
210 msg.SetAttribute(RTA_OIF, ByteString::CreateFromCPUUInt32(interface_index));
211
Paul Stewartf748a362012-03-07 12:01:20 -0800212 routing_table_->RouteMsgHandler(msg);
Paul Stewart75e89d22011-08-01 10:00:02 -0700213}
214
Paul Stewartf748a362012-03-07 12:01:20 -0800215void RoutingTableTest::SendRouteMessage(const RTNLMessage &msg) {
216 routing_table_->RouteMsgHandler(msg);
Paul Stewart75e89d22011-08-01 10:00:02 -0700217}
218
Paul Stewartf748a362012-03-07 12:01:20 -0800219TEST_F(RoutingTableTest, Start) {
220 EXPECT_CALL(rtnl_handler_, RequestDump(RTNLHandler::kRequestRoute));
221 routing_table_->Start();
Paul Stewart75e89d22011-08-01 10:00:02 -0700222}
223
224TEST_F(RoutingTableTest, RouteAddDelete) {
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800225 // Expect the tables to be empty by default.
Paul Stewart75e89d22011-08-01 10:00:02 -0700226 EXPECT_EQ(0, GetRoutingTables()->size());
227
Paul Stewart7355ce12011-09-02 10:47:01 -0700228 IPAddress default_address(IPAddress::kFamilyIPv4);
Paul Stewart75e89d22011-08-01 10:00:02 -0700229 default_address.SetAddressToDefault();
230
Paul Stewart7355ce12011-09-02 10:47:01 -0700231 IPAddress gateway_address0(IPAddress::kFamilyIPv4);
Paul Stewart75e89d22011-08-01 10:00:02 -0700232 gateway_address0.SetAddressFromString(kTestNetAddress0);
233
234 int metric = 10;
235
236 RoutingTableEntry entry0(default_address,
Paul Stewart75e89d22011-08-01 10:00:02 -0700237 default_address,
Paul Stewart75e89d22011-08-01 10:00:02 -0700238 gateway_address0,
239 metric,
240 RT_SCOPE_UNIVERSE,
241 true);
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800242 // Add a single entry.
Paul Stewartf748a362012-03-07 12:01:20 -0800243 SendRouteEntry(RTNLMessage::kModeAdd,
244 kTestDeviceIndex0,
245 entry0);
Paul Stewart75e89d22011-08-01 10:00:02 -0700246
Paul Stewarte93b0382012-04-24 13:11:28 -0700247 hash_map<int, vector<RoutingTableEntry> > *tables =
Paul Stewart75e89d22011-08-01 10:00:02 -0700248 GetRoutingTables();
249
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800250 // We should have a single table, which should in turn have a single entry.
Paul Stewart75e89d22011-08-01 10:00:02 -0700251 EXPECT_EQ(1, tables->size());
252 EXPECT_TRUE(ContainsKey(*tables, kTestDeviceIndex0));
253 EXPECT_EQ(1, (*tables)[kTestDeviceIndex0].size());
254
255 RoutingTableEntry test_entry = (*tables)[kTestDeviceIndex0][0];
256 EXPECT_TRUE(entry0.Equals(test_entry));
257
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800258 // Add a second entry for a different interface.
Paul Stewartf748a362012-03-07 12:01:20 -0800259 SendRouteEntry(RTNLMessage::kModeAdd,
260 kTestDeviceIndex1,
261 entry0);
Paul Stewart75e89d22011-08-01 10:00:02 -0700262
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800263 // We should have two tables, which should have a single entry each.
Paul Stewart75e89d22011-08-01 10:00:02 -0700264 EXPECT_EQ(2, tables->size());
265 EXPECT_TRUE(ContainsKey(*tables, kTestDeviceIndex1));
266 EXPECT_EQ(1, (*tables)[kTestDeviceIndex0].size());
267 EXPECT_EQ(1, (*tables)[kTestDeviceIndex1].size());
268
269 test_entry = (*tables)[kTestDeviceIndex1][0];
270 EXPECT_TRUE(entry0.Equals(test_entry));
271
Paul Stewart7355ce12011-09-02 10:47:01 -0700272 IPAddress gateway_address1(IPAddress::kFamilyIPv4);
Paul Stewart75e89d22011-08-01 10:00:02 -0700273 gateway_address1.SetAddressFromString(kTestNetAddress1);
274
275 RoutingTableEntry entry1(default_address,
Paul Stewart75e89d22011-08-01 10:00:02 -0700276 default_address,
Paul Stewart75e89d22011-08-01 10:00:02 -0700277 gateway_address1,
278 metric,
279 RT_SCOPE_UNIVERSE,
280 true);
281
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800282 // Add a second gateway route to the second interface.
Paul Stewartf748a362012-03-07 12:01:20 -0800283 SendRouteEntry(RTNLMessage::kModeAdd,
284 kTestDeviceIndex1,
285 entry1);
Paul Stewart75e89d22011-08-01 10:00:02 -0700286
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800287 // We should have two tables, one of which has a single entry, the other has
288 // two.
Paul Stewart75e89d22011-08-01 10:00:02 -0700289 EXPECT_EQ(2, tables->size());
290 EXPECT_EQ(1, (*tables)[kTestDeviceIndex0].size());
291 EXPECT_EQ(2, (*tables)[kTestDeviceIndex1].size());
292
293 test_entry = (*tables)[kTestDeviceIndex1][1];
294 EXPECT_TRUE(entry1.Equals(test_entry));
295
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800296 // Remove the first gateway route from the second interface.
Paul Stewartf748a362012-03-07 12:01:20 -0800297 SendRouteEntry(RTNLMessage::kModeDelete,
298 kTestDeviceIndex1,
299 entry0);
Paul Stewart75e89d22011-08-01 10:00:02 -0700300
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800301 // We should be back to having one route per table.
Paul Stewart75e89d22011-08-01 10:00:02 -0700302 EXPECT_EQ(2, tables->size());
303 EXPECT_EQ(1, (*tables)[kTestDeviceIndex0].size());
304 EXPECT_EQ(1, (*tables)[kTestDeviceIndex1].size());
305
306 test_entry = (*tables)[kTestDeviceIndex1][0];
307 EXPECT_TRUE(entry1.Equals(test_entry));
308
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700309 // Send a duplicate of the second gateway route message, changing the metric.
Paul Stewart75e89d22011-08-01 10:00:02 -0700310 RoutingTableEntry entry2(entry1);
311 entry2.metric++;
Paul Stewartf748a362012-03-07 12:01:20 -0800312 SendRouteEntry(RTNLMessage::kModeAdd,
313 kTestDeviceIndex1,
314 entry2);
Paul Stewart75e89d22011-08-01 10:00:02 -0700315
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800316 // Routing table size shouldn't change, but the new metric should match.
Paul Stewart75e89d22011-08-01 10:00:02 -0700317 EXPECT_EQ(1, (*tables)[kTestDeviceIndex1].size());
318 test_entry = (*tables)[kTestDeviceIndex1][0];
319 EXPECT_TRUE(entry2.Equals(test_entry));
320
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800321 // Find a matching entry.
Paul Stewart75e89d22011-08-01 10:00:02 -0700322 EXPECT_TRUE(routing_table_->GetDefaultRoute(kTestDeviceIndex1,
Paul Stewart7355ce12011-09-02 10:47:01 -0700323 IPAddress::kFamilyIPv4,
Paul Stewart75e89d22011-08-01 10:00:02 -0700324 &test_entry));
325 EXPECT_TRUE(entry2.Equals(test_entry));
326
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800327 // Test that a search for a non-matching family fails.
Paul Stewart75e89d22011-08-01 10:00:02 -0700328 EXPECT_FALSE(routing_table_->GetDefaultRoute(kTestDeviceIndex1,
Paul Stewart7355ce12011-09-02 10:47:01 -0700329 IPAddress::kFamilyIPv6,
Paul Stewart75e89d22011-08-01 10:00:02 -0700330 &test_entry));
331
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800332 // Remove last entry from an existing interface and test that we now fail.
Paul Stewartf748a362012-03-07 12:01:20 -0800333 SendRouteEntry(RTNLMessage::kModeDelete,
334 kTestDeviceIndex1,
335 entry2);
Paul Stewart75e89d22011-08-01 10:00:02 -0700336
337 EXPECT_FALSE(routing_table_->GetDefaultRoute(kTestDeviceIndex1,
Paul Stewart7355ce12011-09-02 10:47:01 -0700338 IPAddress::kFamilyIPv4,
Paul Stewart75e89d22011-08-01 10:00:02 -0700339 &test_entry));
340
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700341 // Add a route to a gatway address.
342 IPAddress gateway_address(IPAddress::kFamilyIPv4);
343 EXPECT_TRUE(gateway_address.SetAddressFromString(kTestNetAddress0));
Paul Stewart75e89d22011-08-01 10:00:02 -0700344
Paul Stewartf748a362012-03-07 12:01:20 -0800345 EXPECT_CALL(rtnl_handler_,
346 SendMessage(IsRoutingPacket(RTNLMessage::kModeAdd,
347 kTestDeviceIndex1,
348 entry0,
349 NLM_F_CREATE | NLM_F_EXCL)));
Paul Stewart75e89d22011-08-01 10:00:02 -0700350 EXPECT_TRUE(routing_table_->SetDefaultRoute(kTestDeviceIndex1,
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700351 gateway_address,
Paul Stewart75e89d22011-08-01 10:00:02 -0700352 metric));
353
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800354 // The table entry should look much like entry0, except with
355 // from_rtnl = false.
Paul Stewart75e89d22011-08-01 10:00:02 -0700356 RoutingTableEntry entry3(entry0);
357 entry3.from_rtnl = false;
358 EXPECT_TRUE(routing_table_->GetDefaultRoute(kTestDeviceIndex1,
Paul Stewart7355ce12011-09-02 10:47:01 -0700359 IPAddress::kFamilyIPv4,
Paul Stewart75e89d22011-08-01 10:00:02 -0700360 &test_entry));
361 EXPECT_TRUE(entry3.Equals(test_entry));
362
363 // Setting the same route on the interface with a different metric should
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800364 // push the route with different flags to indicate we are replacing it,
365 // then it should delete the old entry.
Paul Stewart75e89d22011-08-01 10:00:02 -0700366 RoutingTableEntry entry4(entry3);
367 entry4.metric += 10;
Paul Stewartf748a362012-03-07 12:01:20 -0800368 EXPECT_CALL(rtnl_handler_,
369 SendMessage(IsRoutingPacket(RTNLMessage::kModeAdd,
370 kTestDeviceIndex1,
371 entry4,
372 NLM_F_CREATE | NLM_F_REPLACE)));
373 EXPECT_CALL(rtnl_handler_,
374 SendMessage(IsRoutingPacket(RTNLMessage::kModeDelete,
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800375 kTestDeviceIndex1,
376 entry3,
Paul Stewartf748a362012-03-07 12:01:20 -0800377 0)));
Paul Stewart75e89d22011-08-01 10:00:02 -0700378 EXPECT_TRUE(routing_table_->SetDefaultRoute(kTestDeviceIndex1,
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700379 gateway_address,
Paul Stewart75e89d22011-08-01 10:00:02 -0700380 entry4.metric));
381
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800382 // Test that removing the table causes the route to disappear.
Paul Stewart75e89d22011-08-01 10:00:02 -0700383 routing_table_->ResetTable(kTestDeviceIndex1);
384 EXPECT_FALSE(ContainsKey(*tables, kTestDeviceIndex1));
385 EXPECT_FALSE(routing_table_->GetDefaultRoute(kTestDeviceIndex1,
Paul Stewart7355ce12011-09-02 10:47:01 -0700386 IPAddress::kFamilyIPv4,
Paul Stewart75e89d22011-08-01 10:00:02 -0700387 &test_entry));
388 EXPECT_EQ(1, GetRoutingTables()->size());
389
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800390 // When we set the metric on an existing route, a new add and delete
391 // operation should occur.
Paul Stewart75e89d22011-08-01 10:00:02 -0700392 RoutingTableEntry entry5(entry4);
393 entry5.metric += 10;
Paul Stewartf748a362012-03-07 12:01:20 -0800394 EXPECT_CALL(rtnl_handler_,
395 SendMessage(IsRoutingPacket(RTNLMessage::kModeAdd,
396 kTestDeviceIndex0,
397 entry5,
398 NLM_F_CREATE | NLM_F_REPLACE)));
399 EXPECT_CALL(rtnl_handler_,
400 SendMessage(IsRoutingPacket(RTNLMessage::kModeDelete,
401 kTestDeviceIndex0,
402 entry0,
403 0)));
Paul Stewart75e89d22011-08-01 10:00:02 -0700404 routing_table_->SetDefaultMetric(kTestDeviceIndex0, entry5.metric);
mukesh agrawald4ef6772012-02-21 16:28:04 -0800405 // Furthermore, the routing table should reflect the change in the metric
406 // for the default route for the interface.
407 RoutingTableEntry default_route;
408 EXPECT_TRUE(routing_table_->GetDefaultRoute(kTestDeviceIndex0,
409 IPAddress::kFamilyIPv4,
410 &default_route));
411 EXPECT_EQ(entry5.metric, default_route.metric);
Paul Stewart75e89d22011-08-01 10:00:02 -0700412
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800413 // Ask to flush table0. We should see a delete message sent.
Paul Stewartf748a362012-03-07 12:01:20 -0800414 EXPECT_CALL(rtnl_handler_,
415 SendMessage(IsRoutingPacket(RTNLMessage::kModeDelete,
416 kTestDeviceIndex0,
417 entry5,
418 0)));
Thieu Lefb46caf2012-03-08 11:57:15 -0800419 routing_table_->FlushRoutes(kTestDeviceIndex0);
420 EXPECT_EQ(0, (*tables)[kTestDeviceIndex0].size());
Paul Stewart75e89d22011-08-01 10:00:02 -0700421
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800422 // Test that the routing table size returns to zero.
Paul Stewartf748a362012-03-07 12:01:20 -0800423 SendRouteEntry(RTNLMessage::kModeAdd,
424 kTestDeviceIndex0,
425 entry5);
Paul Stewart75e89d22011-08-01 10:00:02 -0700426 EXPECT_EQ(1, GetRoutingTables()->size());
427 routing_table_->ResetTable(kTestDeviceIndex0);
428 EXPECT_EQ(0, GetRoutingTables()->size());
429
430 routing_table_->Stop();
Paul Stewartf748a362012-03-07 12:01:20 -0800431}
432
Paul Stewart3f68bb12012-03-15 13:33:10 -0700433TEST_F(RoutingTableTest, ConfigureRoutes) {
434 MockControl control;
435 IPConfigRefPtr ipconfig(new IPConfig(&control, kTestDeviceName0));
436 IPConfig::Properties properties;
437 properties.address_family = IPAddress::kFamilyIPv4;
438 vector<IPConfig::Route> &routes = properties.routes;
439 ipconfig->UpdateProperties(properties, true);
440
441 const int kMetric = 10;
442 EXPECT_TRUE(routing_table_->ConfigureRoutes(kTestDeviceIndex0,
443 ipconfig,
444 kMetric));
445
446 IPConfig::Route route;
447 route.host = kTestRemoteNetwork4;
448 route.netmask = kTestRemoteNetmask4;
449 route.gateway = kTestGatewayAddress4;
450 routes.push_back(route);
451 ipconfig->UpdateProperties(properties, true);
452
453 IPAddress destination_address(IPAddress::kFamilyIPv4);
454 IPAddress source_address(IPAddress::kFamilyIPv4);
455 IPAddress gateway_address(IPAddress::kFamilyIPv4);
456 ASSERT_TRUE(destination_address.SetAddressFromString(kTestRemoteNetwork4));
457 destination_address.set_prefix(kTestRemotePrefix4);
458 ASSERT_TRUE(gateway_address.SetAddressFromString(kTestGatewayAddress4));
459
460 RoutingTableEntry entry(destination_address,
461 source_address,
462 gateway_address,
463 kMetric,
464 RT_SCOPE_UNIVERSE,
465 false);
466
467 EXPECT_CALL(rtnl_handler_,
468 SendMessage(IsRoutingPacket(RTNLMessage::kModeAdd,
469 kTestDeviceIndex0,
470 entry,
471 NLM_F_CREATE | NLM_F_EXCL)));
472 EXPECT_TRUE(routing_table_->ConfigureRoutes(kTestDeviceIndex0,
473 ipconfig,
474 kMetric));
475
476 routes.clear();
477 route.gateway = "xxx"; // Invalid gateway entry -- should be skipped
478 routes.push_back(route);
479 route.host = "xxx"; // Invalid host entry -- should be skipped
480 route.gateway = kTestGatewayAddress4;
481 routes.push_back(route);
482 route.host = kTestRemoteNetwork4;
483 routes.push_back(route);
484 ipconfig->UpdateProperties(properties, true);
485
486 EXPECT_CALL(rtnl_handler_,
487 SendMessage(IsRoutingPacket(RTNLMessage::kModeAdd,
488 kTestDeviceIndex0,
489 entry,
490 NLM_F_CREATE | NLM_F_EXCL)))
491 .Times(1);
492 EXPECT_FALSE(routing_table_->ConfigureRoutes(kTestDeviceIndex0,
493 ipconfig,
494 kMetric));
495}
496
Paul Stewartf748a362012-03-07 12:01:20 -0800497MATCHER_P2(IsRoutingQuery, destination, index, "") {
498 const RTNLMessage::RouteStatus &status = arg->route_status();
499
500 uint32 oif;
501
502 return
503 arg->type() == RTNLMessage::kTypeRoute &&
504 arg->family() == destination.family() &&
505 arg->flags() == NLM_F_REQUEST &&
506 status.table == 0 &&
507 status.protocol == 0 &&
508 status.scope == 0 &&
509 status.type == 0 &&
510 arg->HasAttribute(RTA_DST) &&
511 IPAddress(arg->family(),
512 arg->GetAttribute(RTA_DST),
513 status.dst_prefix).Equals(destination) &&
514 !arg->HasAttribute(RTA_SRC) &&
515 !arg->HasAttribute(RTA_GATEWAY) &&
516 arg->GetAttribute(RTA_OIF).ConvertToCPUUInt32(&oif) &&
517 oif == index &&
518 !arg->HasAttribute(RTA_PRIORITY);
519
520 return false;
521}
522
523TEST_F(RoutingTableTest, RequestHostRoute) {
524 IPAddress destination_address(IPAddress::kFamilyIPv4);
525 destination_address.SetAddressFromString(kTestRemoteAddress4);
526 destination_address.set_prefix(24);
527
528 EXPECT_CALL(rtnl_handler_,
529 SendMessage(IsRoutingQuery(destination_address,
530 kTestDeviceIndex0)))
531 .WillOnce(Invoke(this, &RoutingTableTest::SetSequenceForMessage));
Darin Petkovabf6d282012-05-08 15:49:05 +0200532 EXPECT_TRUE(
533 routing_table_->RequestRouteToHost(destination_address,
534 kTestDeviceIndex0,
535 kTestRouteTag,
536 RoutingTable::Query::Callback()));
Paul Stewartf748a362012-03-07 12:01:20 -0800537
538 IPAddress gateway_address(IPAddress::kFamilyIPv4);
539 gateway_address.SetAddressFromString(kTestGatewayAddress4);
540
541 IPAddress local_address(IPAddress::kFamilyIPv4);
542 local_address.SetAddressFromString(kTestDeviceNetAddress4);
543
544 const int kMetric = 10;
545 RoutingTableEntry entry(destination_address,
546 local_address,
547 gateway_address,
548 kMetric,
549 RT_SCOPE_UNIVERSE,
550 true);
551
552 EXPECT_CALL(rtnl_handler_,
553 SendMessage(IsRoutingPacket(RTNLMessage::kModeAdd,
554 kTestDeviceIndex0,
555 entry,
556 NLM_F_CREATE | NLM_F_EXCL)));
557 SendRouteEntryWithSeqAndProto(RTNLMessage::kModeAdd,
558 kTestDeviceIndex0,
559 entry,
560 kTestRequestSeq,
561 RTPROT_UNSPEC);
Paul Stewarte93b0382012-04-24 13:11:28 -0700562
Darin Petkovabf6d282012-05-08 15:49:05 +0200563 hash_map<int, vector<RoutingTableEntry> > *tables = GetRoutingTables();
Paul Stewarte93b0382012-04-24 13:11:28 -0700564
565 // We should have a single table, which should in turn have a single entry.
566 EXPECT_EQ(1, tables->size());
567 EXPECT_TRUE(ContainsKey(*tables, kTestDeviceIndex0));
568 EXPECT_EQ(1, (*tables)[kTestDeviceIndex0].size());
569
570 // This entry's tag should match the tag we requested.
571 EXPECT_EQ(kTestRouteTag, (*tables)[kTestDeviceIndex0][0].tag);
572
Darin Petkovabf6d282012-05-08 15:49:05 +0200573 EXPECT_TRUE(GetQueries()->empty());
574
Paul Stewarte93b0382012-04-24 13:11:28 -0700575 // Ask to flush routes with our tag. We should see a delete message sent.
576 EXPECT_CALL(rtnl_handler_,
577 SendMessage(IsRoutingPacket(RTNLMessage::kModeDelete,
578 kTestDeviceIndex0,
579 entry,
580 0)));
581
582 routing_table_->FlushRoutesWithTag(kTestRouteTag);
583
584 // After flushing routes for this tag, we should end up with no routes.
585 EXPECT_EQ(0, (*tables)[kTestDeviceIndex0].size());
Paul Stewartf748a362012-03-07 12:01:20 -0800586}
587
Paul Stewartbbed76d2012-04-27 20:02:13 -0700588TEST_F(RoutingTableTest, RequestHostRouteWithoutGateway) {
589 IPAddress destination_address(IPAddress::kFamilyIPv4);
590 destination_address.SetAddressFromString(kTestRemoteAddress4);
591 destination_address.set_prefix(24);
592
593 EXPECT_CALL(rtnl_handler_,
594 SendMessage(IsRoutingQuery(destination_address,
595 kTestDeviceIndex0)))
596 .WillOnce(Invoke(this, &RoutingTableTest::SetSequenceForMessage));
Darin Petkovabf6d282012-05-08 15:49:05 +0200597 EXPECT_TRUE(
598 routing_table_->RequestRouteToHost(destination_address,
599 kTestDeviceIndex0,
600 kTestRouteTag,
601 RoutingTable::Query::Callback()));
Paul Stewartbbed76d2012-04-27 20:02:13 -0700602
603 // Don't specify a gateway address.
604 IPAddress gateway_address(IPAddress::kFamilyIPv4);
605
606 IPAddress local_address(IPAddress::kFamilyIPv4);
607 local_address.SetAddressFromString(kTestDeviceNetAddress4);
608
609 const int kMetric = 10;
610 RoutingTableEntry entry(destination_address,
611 local_address,
612 gateway_address,
613 kMetric,
614 RT_SCOPE_UNIVERSE,
615 true);
616
617 // Ensure that without a gateway entry, we don't create a route.
618 EXPECT_CALL(rtnl_handler_, SendMessage(_)).Times(0);
619 SendRouteEntryWithSeqAndProto(RTNLMessage::kModeAdd,
620 kTestDeviceIndex0,
621 entry,
622 kTestRequestSeq,
623 RTPROT_UNSPEC);
Darin Petkovabf6d282012-05-08 15:49:05 +0200624 EXPECT_TRUE(GetQueries()->empty());
Paul Stewartbbed76d2012-04-27 20:02:13 -0700625}
626
Paul Stewartf748a362012-03-07 12:01:20 -0800627TEST_F(RoutingTableTest, RequestHostRouteBadSequence) {
628 IPAddress destination_address(IPAddress::kFamilyIPv4);
629 destination_address.SetAddressFromString(kTestRemoteAddress4);
Darin Petkovabf6d282012-05-08 15:49:05 +0200630 QueryCallbackTarget target;
631 EXPECT_CALL(target, CallTarget(_, _)).Times(0);
Paul Stewartf748a362012-03-07 12:01:20 -0800632 EXPECT_CALL(rtnl_handler_, SendMessage(_))
633 .WillOnce(Invoke(this, &RoutingTableTest::SetSequenceForMessage));
Darin Petkovabf6d282012-05-08 15:49:05 +0200634 EXPECT_TRUE(
635 routing_table_->RequestRouteToHost(destination_address,
636 kTestDeviceIndex0,
637 kTestRouteTag,
638 target.callback()));
Paul Stewarte93b0382012-04-24 13:11:28 -0700639 EXPECT_FALSE(GetQueries()->empty());
Paul Stewartf748a362012-03-07 12:01:20 -0800640
641 RoutingTableEntry entry(destination_address,
642 destination_address,
643 destination_address,
644 0,
645 RT_SCOPE_UNIVERSE,
646 true);
647
648 // Try a sequence arriving before the one RoutingTable is looking for.
649 // This should be a no-op.
650 SendRouteEntryWithSeqAndProto(RTNLMessage::kModeAdd,
651 kTestDeviceIndex0,
652 entry,
Darin Petkovabf6d282012-05-08 15:49:05 +0200653 kTestRequestSeq - 1,
Paul Stewartf748a362012-03-07 12:01:20 -0800654 RTPROT_UNSPEC);
Paul Stewarte93b0382012-04-24 13:11:28 -0700655 EXPECT_FALSE(GetQueries()->empty());
Paul Stewartf748a362012-03-07 12:01:20 -0800656
657 // Try a sequence arriving after the one RoutingTable is looking for.
658 // This should cause the request to be purged.
659 SendRouteEntryWithSeqAndProto(RTNLMessage::kModeAdd,
660 kTestDeviceIndex0,
661 entry,
Darin Petkovabf6d282012-05-08 15:49:05 +0200662 kTestRequestSeq + 1,
Paul Stewartf748a362012-03-07 12:01:20 -0800663 RTPROT_UNSPEC);
Paul Stewarte93b0382012-04-24 13:11:28 -0700664 EXPECT_TRUE(GetQueries()->empty());
Paul Stewart75e89d22011-08-01 10:00:02 -0700665}
666
Darin Petkovabf6d282012-05-08 15:49:05 +0200667TEST_F(RoutingTableTest, RequestHostRouteWithCallback) {
668 IPAddress destination_address(IPAddress::kFamilyIPv4);
669
670 EXPECT_CALL(rtnl_handler_, SendMessage(_))
671 .WillOnce(Invoke(this, &RoutingTableTest::SetSequenceForMessage));
672 QueryCallbackTarget target;
673 EXPECT_TRUE(
674 routing_table_->RequestRouteToHost(
675 destination_address, -1, kTestRouteTag, target.callback()));
676
677 IPAddress gateway_address(IPAddress::kFamilyIPv4);
678 gateway_address.SetAddressFromString(kTestGatewayAddress4);
679 IPAddress local_address(IPAddress::kFamilyIPv4);
680
681 const int kMetric = 10;
682 RoutingTableEntry entry(destination_address,
683 local_address,
684 gateway_address,
685 kMetric,
686 RT_SCOPE_UNIVERSE,
687 true);
688
689 EXPECT_CALL(rtnl_handler_, SendMessage(_));
690 EXPECT_CALL(target,
691 CallTarget(kTestDeviceIndex0,
692 Field(&RoutingTableEntry::tag, kTestRouteTag)));
693 SendRouteEntryWithSeqAndProto(RTNLMessage::kModeAdd,
694 kTestDeviceIndex0,
695 entry,
696 kTestRequestSeq,
697 RTPROT_UNSPEC);
698}
699
700TEST_F(RoutingTableTest, RequestHostRouteWithoutGatewayWithCallback) {
701 IPAddress destination_address(IPAddress::kFamilyIPv4);
702
703 EXPECT_CALL(rtnl_handler_, SendMessage(_))
704 .WillOnce(Invoke(this, &RoutingTableTest::SetSequenceForMessage));
705 QueryCallbackTarget target;
706 EXPECT_TRUE(
707 routing_table_->RequestRouteToHost(
708 destination_address, -1, kTestRouteTag, target.callback()));
709
710 IPAddress gateway_address(IPAddress::kFamilyIPv4);
711 IPAddress local_address(IPAddress::kFamilyIPv4);
712
713 const int kMetric = 10;
714 RoutingTableEntry entry(destination_address,
715 local_address,
716 gateway_address,
717 kMetric,
718 RT_SCOPE_UNIVERSE,
719 true);
720
721 EXPECT_CALL(target,
722 CallTarget(kTestDeviceIndex0,
723 Field(&RoutingTableEntry::tag, kTestRouteTag)));
724 SendRouteEntryWithSeqAndProto(RTNLMessage::kModeAdd,
725 kTestDeviceIndex0,
726 entry,
727 kTestRequestSeq,
728 RTPROT_UNSPEC);
729}
730
731TEST_F(RoutingTableTest, CancelQueryCallback) {
732 IPAddress destination_address(IPAddress::kFamilyIPv4);
733 destination_address.SetAddressFromString(kTestRemoteAddress4);
734 QueryCallbackTarget target1;
735 QueryCallbackTarget target2;
736 QueryCallbackTarget target3;
737 EXPECT_CALL(rtnl_handler_, SendMessage(_)).Times(4);
738 EXPECT_TRUE(
739 routing_table_->RequestRouteToHost(destination_address,
740 kTestDeviceIndex0,
741 kTestRouteTag,
742 target1.callback()));
743 EXPECT_TRUE(
744 routing_table_->RequestRouteToHost(destination_address,
745 kTestDeviceIndex0,
746 kTestRouteTag,
747 target2.callback()));
748 EXPECT_TRUE(
749 routing_table_->RequestRouteToHost(destination_address,
750 kTestDeviceIndex0,
751 kTestRouteTag,
752 target2.callback()));
753 EXPECT_TRUE(
754 routing_table_->RequestRouteToHost(destination_address,
755 kTestDeviceIndex0,
756 kTestRouteTag,
757 target3.callback()));
758 ASSERT_EQ(4, GetQueries()->size());
759 routing_table_->CancelQueryCallback(target2.callback());
760 EXPECT_TRUE(GetQueries()->at(0).callback.Equals(target1.callback()));
761 EXPECT_TRUE(GetQueries()->at(1).callback.is_null());
762 EXPECT_TRUE(GetQueries()->at(2).callback.is_null());
763 EXPECT_TRUE(GetQueries()->at(3).callback.Equals(target3.callback()));
764}
765
Paul Stewart75e89d22011-08-01 10:00:02 -0700766} // namespace shill