blob: 6e36cb5f68234845b0b2e60ff5f916331f6f687b [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
8#include <base/logging.h>
Eric Shienbroodb5c89402012-03-13 08:29:25 -07009#include <base/stl_util-inl.h>
Paul Stewart75e89d22011-08-01 10:00:02 -070010#include <gtest/gtest.h>
11#include <gmock/gmock.h>
12
13#include "shill/byte_string.h"
14#include "shill/mock_control.h"
Paul Stewartf748a362012-03-07 12:01:20 -080015#include "shill/mock_rtnl_handler.h"
Paul Stewart75e89d22011-08-01 10:00:02 -070016#include "shill/routing_table.h"
17#include "shill/routing_table_entry.h"
18#include "shill/rtnl_handler.h"
19#include "shill/rtnl_message.h"
20
21using testing::_;
Paul Stewartf748a362012-03-07 12:01:20 -080022using testing::Invoke;
Paul Stewart75e89d22011-08-01 10:00:02 -070023using testing::Return;
Paul Stewartf748a362012-03-07 12:01:20 -080024using testing::StrictMock;
Paul Stewart75e89d22011-08-01 10:00:02 -070025using testing::Test;
26
27namespace shill {
28
29class TestEventDispatcher : public EventDispatcher {
30 public:
Paul Stewart26b327e2011-10-19 11:38:09 -070031 virtual IOHandler *CreateInputHandler(
mukesh agrawal1830fa12011-09-26 14:31:40 -070032 int /*fd*/,
Eric Shienbroodb5c89402012-03-13 08:29:25 -070033 Callback1<InputData*>::Type */*callback*/) {
Paul Stewart75e89d22011-08-01 10:00:02 -070034 return NULL;
35 }
36};
37
38class RoutingTableTest : public Test {
39 public:
40 RoutingTableTest() : routing_table_(RoutingTable::GetInstance()) {}
41
Paul Stewartf748a362012-03-07 12:01:20 -080042 virtual void SetUp() {
43 routing_table_->rtnl_handler_ = &rtnl_handler_;
44 ON_CALL(rtnl_handler_, SendMessage(_)).WillByDefault(Return(true));
Paul Stewart75e89d22011-08-01 10:00:02 -070045 }
46
Paul Stewart65c40f52011-08-08 07:27:46 -070047 virtual void TearDown() {
48 RTNLHandler::GetInstance()->Stop();
49 }
50
Paul Stewartf748a362012-03-07 12:01:20 -080051 base::hash_map<int, std::vector<RoutingTableEntry> > *GetRoutingTables() {
52 return &routing_table_->tables_;
53 }
54
55 std::queue<uint32> *GetQuerySequences() {
56 return &routing_table_->route_query_sequences_;
57 }
58
59 void SendRouteEntry(RTNLMessage::Mode mode,
60 uint32 interface_index,
61 const RoutingTableEntry &entry);
62
63 void SendRouteEntryWithSeqAndProto(RTNLMessage::Mode mode,
64 uint32 interface_index,
65 const RoutingTableEntry &entry,
66 uint32 seq,
67 unsigned char proto);
68
69 void SendRouteMessage(const RTNLMessage &msg);
70
71 bool SetSequenceForMessage(RTNLMessage *message) {
72 message->set_seq(RoutingTableTest::kTestRequestSeq);
73 return true;
74 }
75
Paul Stewart75e89d22011-08-01 10:00:02 -070076 protected:
Paul Stewart75e89d22011-08-01 10:00:02 -070077 static const uint32 kTestDeviceIndex0;
78 static const uint32 kTestDeviceIndex1;
79 static const char kTestDeviceName0[];
Thieu Lecaef8932012-02-28 16:06:59 -080080 static const char kTestDeviceNetAddress4[];
81 static const char kTestForeignNetAddress4[];
82 static const char kTestForeignNetGateway4[];
83 static const char kTestForeignNetAddress6[];
84 static const char kTestForeignNetGateway6[];
Paul Stewartf748a362012-03-07 12:01:20 -080085 static const char kTestGatewayAddress4[];
Paul Stewart75e89d22011-08-01 10:00:02 -070086 static const char kTestNetAddress0[];
87 static const char kTestNetAddress1[];
Paul Stewartf748a362012-03-07 12:01:20 -080088 static const char kTestRemoteAddress4[];
89 static const uint32 kTestRequestSeq;
Paul Stewart75e89d22011-08-01 10:00:02 -070090
Paul Stewart75e89d22011-08-01 10:00:02 -070091 RoutingTable *routing_table_;
92 TestEventDispatcher dispatcher_;
Paul Stewartf748a362012-03-07 12:01:20 -080093 StrictMock<MockRTNLHandler> rtnl_handler_;
Paul Stewart75e89d22011-08-01 10:00:02 -070094};
95
Paul Stewart75e89d22011-08-01 10:00:02 -070096const uint32 RoutingTableTest::kTestDeviceIndex0 = 12345;
97const uint32 RoutingTableTest::kTestDeviceIndex1 = 67890;
98const char RoutingTableTest::kTestDeviceName0[] = "test-device0";
Thieu Lecaef8932012-02-28 16:06:59 -080099const char RoutingTableTest::kTestDeviceNetAddress4[] = "192.168.2.0/24";
100const char RoutingTableTest::kTestForeignNetAddress4[] = "192.168.2.2";
101const char RoutingTableTest::kTestForeignNetGateway4[] = "192.168.2.1";
102const char RoutingTableTest::kTestForeignNetAddress6[] = "2000::/3";
103const char RoutingTableTest::kTestForeignNetGateway6[] = "fe80:::::1";
Paul Stewartf748a362012-03-07 12:01:20 -0800104const char RoutingTableTest::kTestGatewayAddress4[] = "192.168.2.254";
Paul Stewart75e89d22011-08-01 10:00:02 -0700105const char RoutingTableTest::kTestNetAddress0[] = "192.168.1.1";
106const char RoutingTableTest::kTestNetAddress1[] = "192.168.1.2";
Paul Stewartf748a362012-03-07 12:01:20 -0800107const char RoutingTableTest::kTestRemoteAddress4[] = "192.168.2.254";
108const uint32 RoutingTableTest::kTestRequestSeq = 456;
Paul Stewart75e89d22011-08-01 10:00:02 -0700109
110MATCHER_P4(IsRoutingPacket, mode, index, entry, flags, "") {
Paul Stewartf748a362012-03-07 12:01:20 -0800111 const RTNLMessage::RouteStatus &status = arg->route_status();
Paul Stewart75e89d22011-08-01 10:00:02 -0700112
113 uint32 oif;
114 uint32 priority;
115
116 return
Paul Stewartf748a362012-03-07 12:01:20 -0800117 arg->type() == RTNLMessage::kTypeRoute &&
118 arg->family() == entry.gateway.family() &&
119 arg->flags() == (NLM_F_REQUEST | flags) &&
120 status.table == RT_TABLE_MAIN &&
121 status.protocol == RTPROT_BOOT &&
122 status.scope == entry.scope &&
123 status.type == RTN_UNICAST &&
124 arg->HasAttribute(RTA_DST) &&
125 IPAddress(arg->family(),
126 arg->GetAttribute(RTA_DST),
127 status.dst_prefix).Equals(entry.dst) &&
128 !arg->HasAttribute(RTA_SRC) &&
129 arg->HasAttribute(RTA_GATEWAY) &&
130 IPAddress(arg->family(),
131 arg->GetAttribute(RTA_GATEWAY)).Equals(entry.gateway) &&
132 arg->GetAttribute(RTA_OIF).ConvertToCPUUInt32(&oif) &&
133 oif == index &&
134 arg->GetAttribute(RTA_PRIORITY).ConvertToCPUUInt32(&priority) &&
135 priority == entry.metric;
Paul Stewart75e89d22011-08-01 10:00:02 -0700136}
137
Paul Stewartf748a362012-03-07 12:01:20 -0800138void RoutingTableTest::SendRouteEntry(RTNLMessage::Mode mode,
139 uint32 interface_index,
140 const RoutingTableEntry &entry) {
141 SendRouteEntryWithSeqAndProto(mode, interface_index, entry, 0, RTPROT_BOOT);
142}
143
144void RoutingTableTest::SendRouteEntryWithSeqAndProto(
145 RTNLMessage::Mode mode,
146 uint32 interface_index,
147 const RoutingTableEntry &entry,
148 uint32 seq,
149 unsigned char proto) {
Paul Stewart75e89d22011-08-01 10:00:02 -0700150 RTNLMessage msg(
Paul Stewart9a908082011-08-31 12:18:48 -0700151 RTNLMessage::kTypeRoute,
Paul Stewart75e89d22011-08-01 10:00:02 -0700152 mode,
153 0,
Paul Stewartf748a362012-03-07 12:01:20 -0800154 seq,
Paul Stewart75e89d22011-08-01 10:00:02 -0700155 0,
156 0,
157 entry.dst.family());
158
159 msg.set_route_status(RTNLMessage::RouteStatus(
Paul Stewart9e3fcd72011-08-26 15:46:16 -0700160 entry.dst.prefix(),
161 entry.src.prefix(),
Paul Stewart75e89d22011-08-01 10:00:02 -0700162 RT_TABLE_MAIN,
Paul Stewartf748a362012-03-07 12:01:20 -0800163 proto,
Paul Stewart75e89d22011-08-01 10:00:02 -0700164 entry.scope,
165 RTN_UNICAST,
166 0));
167
168 msg.SetAttribute(RTA_DST, entry.dst.address());
169 if (!entry.src.IsDefault()) {
170 msg.SetAttribute(RTA_SRC, entry.src.address());
171 }
172 if (!entry.gateway.IsDefault()) {
173 msg.SetAttribute(RTA_GATEWAY, entry.gateway.address());
174 }
175 msg.SetAttribute(RTA_PRIORITY, ByteString::CreateFromCPUUInt32(entry.metric));
176 msg.SetAttribute(RTA_OIF, ByteString::CreateFromCPUUInt32(interface_index));
177
Paul Stewartf748a362012-03-07 12:01:20 -0800178 routing_table_->RouteMsgHandler(msg);
Paul Stewart75e89d22011-08-01 10:00:02 -0700179}
180
Paul Stewartf748a362012-03-07 12:01:20 -0800181void RoutingTableTest::SendRouteMessage(const RTNLMessage &msg) {
182 routing_table_->RouteMsgHandler(msg);
Paul Stewart75e89d22011-08-01 10:00:02 -0700183}
184
Paul Stewartf748a362012-03-07 12:01:20 -0800185TEST_F(RoutingTableTest, Start) {
186 EXPECT_CALL(rtnl_handler_, RequestDump(RTNLHandler::kRequestRoute));
187 routing_table_->Start();
Paul Stewart75e89d22011-08-01 10:00:02 -0700188}
189
190TEST_F(RoutingTableTest, RouteAddDelete) {
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800191 // Expect the tables to be empty by default.
Paul Stewart75e89d22011-08-01 10:00:02 -0700192 EXPECT_EQ(0, GetRoutingTables()->size());
193
Paul Stewart7355ce12011-09-02 10:47:01 -0700194 IPAddress default_address(IPAddress::kFamilyIPv4);
Paul Stewart75e89d22011-08-01 10:00:02 -0700195 default_address.SetAddressToDefault();
196
Paul Stewart7355ce12011-09-02 10:47:01 -0700197 IPAddress gateway_address0(IPAddress::kFamilyIPv4);
Paul Stewart75e89d22011-08-01 10:00:02 -0700198 gateway_address0.SetAddressFromString(kTestNetAddress0);
199
200 int metric = 10;
201
202 RoutingTableEntry entry0(default_address,
Paul Stewart75e89d22011-08-01 10:00:02 -0700203 default_address,
Paul Stewart75e89d22011-08-01 10:00:02 -0700204 gateway_address0,
205 metric,
206 RT_SCOPE_UNIVERSE,
207 true);
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800208 // Add a single entry.
Paul Stewartf748a362012-03-07 12:01:20 -0800209 SendRouteEntry(RTNLMessage::kModeAdd,
210 kTestDeviceIndex0,
211 entry0);
Paul Stewart75e89d22011-08-01 10:00:02 -0700212
213 base::hash_map<int, std::vector<RoutingTableEntry> > *tables =
214 GetRoutingTables();
215
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800216 // We should have a single table, which should in turn have a single entry.
Paul Stewart75e89d22011-08-01 10:00:02 -0700217 EXPECT_EQ(1, tables->size());
218 EXPECT_TRUE(ContainsKey(*tables, kTestDeviceIndex0));
219 EXPECT_EQ(1, (*tables)[kTestDeviceIndex0].size());
220
221 RoutingTableEntry test_entry = (*tables)[kTestDeviceIndex0][0];
222 EXPECT_TRUE(entry0.Equals(test_entry));
223
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800224 // Add a second entry for a different interface.
Paul Stewartf748a362012-03-07 12:01:20 -0800225 SendRouteEntry(RTNLMessage::kModeAdd,
226 kTestDeviceIndex1,
227 entry0);
Paul Stewart75e89d22011-08-01 10:00:02 -0700228
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800229 // We should have two tables, which should have a single entry each.
Paul Stewart75e89d22011-08-01 10:00:02 -0700230 EXPECT_EQ(2, tables->size());
231 EXPECT_TRUE(ContainsKey(*tables, kTestDeviceIndex1));
232 EXPECT_EQ(1, (*tables)[kTestDeviceIndex0].size());
233 EXPECT_EQ(1, (*tables)[kTestDeviceIndex1].size());
234
235 test_entry = (*tables)[kTestDeviceIndex1][0];
236 EXPECT_TRUE(entry0.Equals(test_entry));
237
Paul Stewart7355ce12011-09-02 10:47:01 -0700238 IPAddress gateway_address1(IPAddress::kFamilyIPv4);
Paul Stewart75e89d22011-08-01 10:00:02 -0700239 gateway_address1.SetAddressFromString(kTestNetAddress1);
240
241 RoutingTableEntry entry1(default_address,
Paul Stewart75e89d22011-08-01 10:00:02 -0700242 default_address,
Paul Stewart75e89d22011-08-01 10:00:02 -0700243 gateway_address1,
244 metric,
245 RT_SCOPE_UNIVERSE,
246 true);
247
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800248 // Add a second gateway route to the second interface.
Paul Stewartf748a362012-03-07 12:01:20 -0800249 SendRouteEntry(RTNLMessage::kModeAdd,
250 kTestDeviceIndex1,
251 entry1);
Paul Stewart75e89d22011-08-01 10:00:02 -0700252
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800253 // We should have two tables, one of which has a single entry, the other has
254 // two.
Paul Stewart75e89d22011-08-01 10:00:02 -0700255 EXPECT_EQ(2, tables->size());
256 EXPECT_EQ(1, (*tables)[kTestDeviceIndex0].size());
257 EXPECT_EQ(2, (*tables)[kTestDeviceIndex1].size());
258
259 test_entry = (*tables)[kTestDeviceIndex1][1];
260 EXPECT_TRUE(entry1.Equals(test_entry));
261
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800262 // Remove the first gateway route from the second interface.
Paul Stewartf748a362012-03-07 12:01:20 -0800263 SendRouteEntry(RTNLMessage::kModeDelete,
264 kTestDeviceIndex1,
265 entry0);
Paul Stewart75e89d22011-08-01 10:00:02 -0700266
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800267 // We should be back to having one route per table.
Paul Stewart75e89d22011-08-01 10:00:02 -0700268 EXPECT_EQ(2, tables->size());
269 EXPECT_EQ(1, (*tables)[kTestDeviceIndex0].size());
270 EXPECT_EQ(1, (*tables)[kTestDeviceIndex1].size());
271
272 test_entry = (*tables)[kTestDeviceIndex1][0];
273 EXPECT_TRUE(entry1.Equals(test_entry));
274
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800275 // Send a duplicate of the second gatway route message, changing the metric.
Paul Stewart75e89d22011-08-01 10:00:02 -0700276 RoutingTableEntry entry2(entry1);
277 entry2.metric++;
Paul Stewartf748a362012-03-07 12:01:20 -0800278 SendRouteEntry(RTNLMessage::kModeAdd,
279 kTestDeviceIndex1,
280 entry2);
Paul Stewart75e89d22011-08-01 10:00:02 -0700281
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800282 // Routing table size shouldn't change, but the new metric should match.
Paul Stewart75e89d22011-08-01 10:00:02 -0700283 EXPECT_EQ(1, (*tables)[kTestDeviceIndex1].size());
284 test_entry = (*tables)[kTestDeviceIndex1][0];
285 EXPECT_TRUE(entry2.Equals(test_entry));
286
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800287 // Find a matching entry.
Paul Stewart75e89d22011-08-01 10:00:02 -0700288 EXPECT_TRUE(routing_table_->GetDefaultRoute(kTestDeviceIndex1,
Paul Stewart7355ce12011-09-02 10:47:01 -0700289 IPAddress::kFamilyIPv4,
Paul Stewart75e89d22011-08-01 10:00:02 -0700290 &test_entry));
291 EXPECT_TRUE(entry2.Equals(test_entry));
292
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800293 // Test that a search for a non-matching family fails.
Paul Stewart75e89d22011-08-01 10:00:02 -0700294 EXPECT_FALSE(routing_table_->GetDefaultRoute(kTestDeviceIndex1,
Paul Stewart7355ce12011-09-02 10:47:01 -0700295 IPAddress::kFamilyIPv6,
Paul Stewart75e89d22011-08-01 10:00:02 -0700296 &test_entry));
297
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800298 // Remove last entry from an existing interface and test that we now fail.
Paul Stewartf748a362012-03-07 12:01:20 -0800299 SendRouteEntry(RTNLMessage::kModeDelete,
300 kTestDeviceIndex1,
301 entry2);
Paul Stewart75e89d22011-08-01 10:00:02 -0700302
303 EXPECT_FALSE(routing_table_->GetDefaultRoute(kTestDeviceIndex1,
Paul Stewart7355ce12011-09-02 10:47:01 -0700304 IPAddress::kFamilyIPv4,
Paul Stewart75e89d22011-08-01 10:00:02 -0700305 &test_entry));
306
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800307 // Add a route from an IPConfig entry.
Paul Stewart75e89d22011-08-01 10:00:02 -0700308 MockControl control;
309 IPConfigRefPtr ipconfig(new IPConfig(&control, kTestDeviceName0));
310 IPConfig::Properties properties;
Paul Stewart7355ce12011-09-02 10:47:01 -0700311 properties.address_family = IPAddress::kFamilyIPv4;
Paul Stewart75e89d22011-08-01 10:00:02 -0700312 properties.gateway = kTestNetAddress0;
313 properties.address = kTestNetAddress1;
314 ipconfig->UpdateProperties(properties, true);
315
Paul Stewartf748a362012-03-07 12:01:20 -0800316 EXPECT_CALL(rtnl_handler_,
317 SendMessage(IsRoutingPacket(RTNLMessage::kModeAdd,
318 kTestDeviceIndex1,
319 entry0,
320 NLM_F_CREATE | NLM_F_EXCL)));
Paul Stewart75e89d22011-08-01 10:00:02 -0700321 EXPECT_TRUE(routing_table_->SetDefaultRoute(kTestDeviceIndex1,
322 ipconfig,
323 metric));
324
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800325 // The table entry should look much like entry0, except with
326 // from_rtnl = false.
Paul Stewart75e89d22011-08-01 10:00:02 -0700327 RoutingTableEntry entry3(entry0);
328 entry3.from_rtnl = false;
329 EXPECT_TRUE(routing_table_->GetDefaultRoute(kTestDeviceIndex1,
Paul Stewart7355ce12011-09-02 10:47:01 -0700330 IPAddress::kFamilyIPv4,
Paul Stewart75e89d22011-08-01 10:00:02 -0700331 &test_entry));
332 EXPECT_TRUE(entry3.Equals(test_entry));
333
334 // Setting the same route on the interface with a different metric should
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800335 // push the route with different flags to indicate we are replacing it,
336 // then it should delete the old entry.
Paul Stewart75e89d22011-08-01 10:00:02 -0700337 RoutingTableEntry entry4(entry3);
338 entry4.metric += 10;
Paul Stewartf748a362012-03-07 12:01:20 -0800339 EXPECT_CALL(rtnl_handler_,
340 SendMessage(IsRoutingPacket(RTNLMessage::kModeAdd,
341 kTestDeviceIndex1,
342 entry4,
343 NLM_F_CREATE | NLM_F_REPLACE)));
344 EXPECT_CALL(rtnl_handler_,
345 SendMessage(IsRoutingPacket(RTNLMessage::kModeDelete,
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800346 kTestDeviceIndex1,
347 entry3,
Paul Stewartf748a362012-03-07 12:01:20 -0800348 0)));
Paul Stewart75e89d22011-08-01 10:00:02 -0700349 EXPECT_TRUE(routing_table_->SetDefaultRoute(kTestDeviceIndex1,
350 ipconfig,
351 entry4.metric));
352
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800353 // Test that removing the table causes the route to disappear.
Paul Stewart75e89d22011-08-01 10:00:02 -0700354 routing_table_->ResetTable(kTestDeviceIndex1);
355 EXPECT_FALSE(ContainsKey(*tables, kTestDeviceIndex1));
356 EXPECT_FALSE(routing_table_->GetDefaultRoute(kTestDeviceIndex1,
Paul Stewart7355ce12011-09-02 10:47:01 -0700357 IPAddress::kFamilyIPv4,
Paul Stewart75e89d22011-08-01 10:00:02 -0700358 &test_entry));
359 EXPECT_EQ(1, GetRoutingTables()->size());
360
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800361 // When we set the metric on an existing route, a new add and delete
362 // operation should occur.
Paul Stewart75e89d22011-08-01 10:00:02 -0700363 RoutingTableEntry entry5(entry4);
364 entry5.metric += 10;
Paul Stewartf748a362012-03-07 12:01:20 -0800365 EXPECT_CALL(rtnl_handler_,
366 SendMessage(IsRoutingPacket(RTNLMessage::kModeAdd,
367 kTestDeviceIndex0,
368 entry5,
369 NLM_F_CREATE | NLM_F_REPLACE)));
370 EXPECT_CALL(rtnl_handler_,
371 SendMessage(IsRoutingPacket(RTNLMessage::kModeDelete,
372 kTestDeviceIndex0,
373 entry0,
374 0)));
Paul Stewart75e89d22011-08-01 10:00:02 -0700375 routing_table_->SetDefaultMetric(kTestDeviceIndex0, entry5.metric);
mukesh agrawald4ef6772012-02-21 16:28:04 -0800376 // Furthermore, the routing table should reflect the change in the metric
377 // for the default route for the interface.
378 RoutingTableEntry default_route;
379 EXPECT_TRUE(routing_table_->GetDefaultRoute(kTestDeviceIndex0,
380 IPAddress::kFamilyIPv4,
381 &default_route));
382 EXPECT_EQ(entry5.metric, default_route.metric);
Paul Stewart75e89d22011-08-01 10:00:02 -0700383
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800384 // Ask to flush table0. We should see a delete message sent.
Paul Stewartf748a362012-03-07 12:01:20 -0800385 EXPECT_CALL(rtnl_handler_,
386 SendMessage(IsRoutingPacket(RTNLMessage::kModeDelete,
387 kTestDeviceIndex0,
388 entry5,
389 0)));
Thieu Lefb46caf2012-03-08 11:57:15 -0800390 routing_table_->FlushRoutes(kTestDeviceIndex0);
391 EXPECT_EQ(0, (*tables)[kTestDeviceIndex0].size());
Paul Stewart75e89d22011-08-01 10:00:02 -0700392
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800393 // Test that the routing table size returns to zero.
Paul Stewartf748a362012-03-07 12:01:20 -0800394 SendRouteEntry(RTNLMessage::kModeAdd,
395 kTestDeviceIndex0,
396 entry5);
Paul Stewart75e89d22011-08-01 10:00:02 -0700397 EXPECT_EQ(1, GetRoutingTables()->size());
398 routing_table_->ResetTable(kTestDeviceIndex0);
399 EXPECT_EQ(0, GetRoutingTables()->size());
400
401 routing_table_->Stop();
Paul Stewartf748a362012-03-07 12:01:20 -0800402}
403
404MATCHER_P2(IsRoutingQuery, destination, index, "") {
405 const RTNLMessage::RouteStatus &status = arg->route_status();
406
407 uint32 oif;
408
409 return
410 arg->type() == RTNLMessage::kTypeRoute &&
411 arg->family() == destination.family() &&
412 arg->flags() == NLM_F_REQUEST &&
413 status.table == 0 &&
414 status.protocol == 0 &&
415 status.scope == 0 &&
416 status.type == 0 &&
417 arg->HasAttribute(RTA_DST) &&
418 IPAddress(arg->family(),
419 arg->GetAttribute(RTA_DST),
420 status.dst_prefix).Equals(destination) &&
421 !arg->HasAttribute(RTA_SRC) &&
422 !arg->HasAttribute(RTA_GATEWAY) &&
423 arg->GetAttribute(RTA_OIF).ConvertToCPUUInt32(&oif) &&
424 oif == index &&
425 !arg->HasAttribute(RTA_PRIORITY);
426
427 return false;
428}
429
430TEST_F(RoutingTableTest, RequestHostRoute) {
431 IPAddress destination_address(IPAddress::kFamilyIPv4);
432 destination_address.SetAddressFromString(kTestRemoteAddress4);
433 destination_address.set_prefix(24);
434
435 EXPECT_CALL(rtnl_handler_,
436 SendMessage(IsRoutingQuery(destination_address,
437 kTestDeviceIndex0)))
438 .WillOnce(Invoke(this, &RoutingTableTest::SetSequenceForMessage));
439 EXPECT_TRUE(routing_table_->RequestRouteToHost(destination_address,
440 kTestDeviceIndex0));
441
442 IPAddress gateway_address(IPAddress::kFamilyIPv4);
443 gateway_address.SetAddressFromString(kTestGatewayAddress4);
444
445 IPAddress local_address(IPAddress::kFamilyIPv4);
446 local_address.SetAddressFromString(kTestDeviceNetAddress4);
447
448 const int kMetric = 10;
449 RoutingTableEntry entry(destination_address,
450 local_address,
451 gateway_address,
452 kMetric,
453 RT_SCOPE_UNIVERSE,
454 true);
455
456 EXPECT_CALL(rtnl_handler_,
457 SendMessage(IsRoutingPacket(RTNLMessage::kModeAdd,
458 kTestDeviceIndex0,
459 entry,
460 NLM_F_CREATE | NLM_F_EXCL)));
461 SendRouteEntryWithSeqAndProto(RTNLMessage::kModeAdd,
462 kTestDeviceIndex0,
463 entry,
464 kTestRequestSeq,
465 RTPROT_UNSPEC);
466}
467
468TEST_F(RoutingTableTest, RequestHostRouteBadSequence) {
469 IPAddress destination_address(IPAddress::kFamilyIPv4);
470 destination_address.SetAddressFromString(kTestRemoteAddress4);
471 EXPECT_CALL(rtnl_handler_, SendMessage(_))
472 .WillOnce(Invoke(this, &RoutingTableTest::SetSequenceForMessage));
473 EXPECT_TRUE(routing_table_->RequestRouteToHost(destination_address,
474 kTestDeviceIndex0));
475 EXPECT_FALSE(GetQuerySequences()->empty());
476
477 RoutingTableEntry entry(destination_address,
478 destination_address,
479 destination_address,
480 0,
481 RT_SCOPE_UNIVERSE,
482 true);
483
484 // Try a sequence arriving before the one RoutingTable is looking for.
485 // This should be a no-op.
486 SendRouteEntryWithSeqAndProto(RTNLMessage::kModeAdd,
487 kTestDeviceIndex0,
488 entry,
489 kTestRequestSeq-1,
490 RTPROT_UNSPEC);
491 EXPECT_FALSE(GetQuerySequences()->empty());
492
493 // Try a sequence arriving after the one RoutingTable is looking for.
494 // This should cause the request to be purged.
495 SendRouteEntryWithSeqAndProto(RTNLMessage::kModeAdd,
496 kTestDeviceIndex0,
497 entry,
498 kTestRequestSeq+1,
499 RTPROT_UNSPEC);
500 EXPECT_TRUE(GetQuerySequences()->empty());
Paul Stewart75e89d22011-08-01 10:00:02 -0700501}
502
Paul Stewart75e89d22011-08-01 10:00:02 -0700503} // namespace shill