blob: 27faba432aa5ffff543beaf5106d50409cdba4a3 [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 Shienbrood3e20a232012-02-16 11:35:56 -05009#include <base/stl_util.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
Eric Shienbrood3e20a232012-02-16 11:35:56 -050021using base::Callback;
Paul Stewart75e89d22011-08-01 10:00:02 -070022using testing::_;
Paul Stewartf748a362012-03-07 12:01:20 -080023using testing::Invoke;
Paul Stewart75e89d22011-08-01 10:00:02 -070024using testing::Return;
Paul Stewartf748a362012-03-07 12:01:20 -080025using testing::StrictMock;
Paul Stewart75e89d22011-08-01 10:00:02 -070026using testing::Test;
27
28namespace shill {
29
30class TestEventDispatcher : public EventDispatcher {
31 public:
Paul Stewart26b327e2011-10-19 11:38:09 -070032 virtual IOHandler *CreateInputHandler(
mukesh agrawal1830fa12011-09-26 14:31:40 -070033 int /*fd*/,
Eric Shienbrood3e20a232012-02-16 11:35:56 -050034 const Callback<void(InputData*)> &/*callback*/) {
Paul Stewart75e89d22011-08-01 10:00:02 -070035 return NULL;
36 }
37};
38
39class RoutingTableTest : public Test {
40 public:
41 RoutingTableTest() : routing_table_(RoutingTable::GetInstance()) {}
42
Paul Stewartf748a362012-03-07 12:01:20 -080043 virtual void SetUp() {
44 routing_table_->rtnl_handler_ = &rtnl_handler_;
45 ON_CALL(rtnl_handler_, SendMessage(_)).WillByDefault(Return(true));
Paul Stewart75e89d22011-08-01 10:00:02 -070046 }
47
Paul Stewart65c40f52011-08-08 07:27:46 -070048 virtual void TearDown() {
49 RTNLHandler::GetInstance()->Stop();
50 }
51
Paul Stewartf748a362012-03-07 12:01:20 -080052 base::hash_map<int, std::vector<RoutingTableEntry> > *GetRoutingTables() {
53 return &routing_table_->tables_;
54 }
55
56 std::queue<uint32> *GetQuerySequences() {
57 return &routing_table_->route_query_sequences_;
58 }
59
60 void SendRouteEntry(RTNLMessage::Mode mode,
61 uint32 interface_index,
62 const RoutingTableEntry &entry);
63
64 void SendRouteEntryWithSeqAndProto(RTNLMessage::Mode mode,
65 uint32 interface_index,
66 const RoutingTableEntry &entry,
67 uint32 seq,
68 unsigned char proto);
69
70 void SendRouteMessage(const RTNLMessage &msg);
71
72 bool SetSequenceForMessage(RTNLMessage *message) {
73 message->set_seq(RoutingTableTest::kTestRequestSeq);
74 return true;
75 }
76
Paul Stewart75e89d22011-08-01 10:00:02 -070077 protected:
Paul Stewart75e89d22011-08-01 10:00:02 -070078 static const uint32 kTestDeviceIndex0;
79 static const uint32 kTestDeviceIndex1;
80 static const char kTestDeviceName0[];
Thieu Lecaef8932012-02-28 16:06:59 -080081 static const char kTestDeviceNetAddress4[];
82 static const char kTestForeignNetAddress4[];
83 static const char kTestForeignNetGateway4[];
84 static const char kTestForeignNetAddress6[];
85 static const char kTestForeignNetGateway6[];
Paul Stewartf748a362012-03-07 12:01:20 -080086 static const char kTestGatewayAddress4[];
Paul Stewart75e89d22011-08-01 10:00:02 -070087 static const char kTestNetAddress0[];
88 static const char kTestNetAddress1[];
Paul Stewartf748a362012-03-07 12:01:20 -080089 static const char kTestRemoteAddress4[];
90 static const uint32 kTestRequestSeq;
Paul Stewart75e89d22011-08-01 10:00:02 -070091
Paul Stewart75e89d22011-08-01 10:00:02 -070092 RoutingTable *routing_table_;
93 TestEventDispatcher dispatcher_;
Paul Stewartf748a362012-03-07 12:01:20 -080094 StrictMock<MockRTNLHandler> rtnl_handler_;
Paul Stewart75e89d22011-08-01 10:00:02 -070095};
96
Paul Stewart75e89d22011-08-01 10:00:02 -070097const uint32 RoutingTableTest::kTestDeviceIndex0 = 12345;
98const uint32 RoutingTableTest::kTestDeviceIndex1 = 67890;
99const char RoutingTableTest::kTestDeviceName0[] = "test-device0";
Thieu Lecaef8932012-02-28 16:06:59 -0800100const char RoutingTableTest::kTestDeviceNetAddress4[] = "192.168.2.0/24";
101const char RoutingTableTest::kTestForeignNetAddress4[] = "192.168.2.2";
102const char RoutingTableTest::kTestForeignNetGateway4[] = "192.168.2.1";
103const char RoutingTableTest::kTestForeignNetAddress6[] = "2000::/3";
104const char RoutingTableTest::kTestForeignNetGateway6[] = "fe80:::::1";
Paul Stewartf748a362012-03-07 12:01:20 -0800105const char RoutingTableTest::kTestGatewayAddress4[] = "192.168.2.254";
Paul Stewart75e89d22011-08-01 10:00:02 -0700106const char RoutingTableTest::kTestNetAddress0[] = "192.168.1.1";
107const char RoutingTableTest::kTestNetAddress1[] = "192.168.1.2";
Paul Stewartf748a362012-03-07 12:01:20 -0800108const char RoutingTableTest::kTestRemoteAddress4[] = "192.168.2.254";
109const uint32 RoutingTableTest::kTestRequestSeq = 456;
Paul Stewart75e89d22011-08-01 10:00:02 -0700110
111MATCHER_P4(IsRoutingPacket, mode, index, entry, flags, "") {
Paul Stewartf748a362012-03-07 12:01:20 -0800112 const RTNLMessage::RouteStatus &status = arg->route_status();
Paul Stewart75e89d22011-08-01 10:00:02 -0700113
114 uint32 oif;
115 uint32 priority;
116
117 return
Paul Stewartf748a362012-03-07 12:01:20 -0800118 arg->type() == RTNLMessage::kTypeRoute &&
119 arg->family() == entry.gateway.family() &&
120 arg->flags() == (NLM_F_REQUEST | flags) &&
121 status.table == RT_TABLE_MAIN &&
122 status.protocol == RTPROT_BOOT &&
123 status.scope == entry.scope &&
124 status.type == RTN_UNICAST &&
125 arg->HasAttribute(RTA_DST) &&
126 IPAddress(arg->family(),
127 arg->GetAttribute(RTA_DST),
128 status.dst_prefix).Equals(entry.dst) &&
129 !arg->HasAttribute(RTA_SRC) &&
130 arg->HasAttribute(RTA_GATEWAY) &&
131 IPAddress(arg->family(),
132 arg->GetAttribute(RTA_GATEWAY)).Equals(entry.gateway) &&
133 arg->GetAttribute(RTA_OIF).ConvertToCPUUInt32(&oif) &&
134 oif == index &&
135 arg->GetAttribute(RTA_PRIORITY).ConvertToCPUUInt32(&priority) &&
136 priority == entry.metric;
Paul Stewart75e89d22011-08-01 10:00:02 -0700137}
138
Paul Stewartf748a362012-03-07 12:01:20 -0800139void RoutingTableTest::SendRouteEntry(RTNLMessage::Mode mode,
140 uint32 interface_index,
141 const RoutingTableEntry &entry) {
142 SendRouteEntryWithSeqAndProto(mode, interface_index, entry, 0, RTPROT_BOOT);
143}
144
145void RoutingTableTest::SendRouteEntryWithSeqAndProto(
146 RTNLMessage::Mode mode,
147 uint32 interface_index,
148 const RoutingTableEntry &entry,
149 uint32 seq,
150 unsigned char proto) {
Paul Stewart75e89d22011-08-01 10:00:02 -0700151 RTNLMessage msg(
Paul Stewart9a908082011-08-31 12:18:48 -0700152 RTNLMessage::kTypeRoute,
Paul Stewart75e89d22011-08-01 10:00:02 -0700153 mode,
154 0,
Paul Stewartf748a362012-03-07 12:01:20 -0800155 seq,
Paul Stewart75e89d22011-08-01 10:00:02 -0700156 0,
157 0,
158 entry.dst.family());
159
160 msg.set_route_status(RTNLMessage::RouteStatus(
Paul Stewart9e3fcd72011-08-26 15:46:16 -0700161 entry.dst.prefix(),
162 entry.src.prefix(),
Paul Stewart75e89d22011-08-01 10:00:02 -0700163 RT_TABLE_MAIN,
Paul Stewartf748a362012-03-07 12:01:20 -0800164 proto,
Paul Stewart75e89d22011-08-01 10:00:02 -0700165 entry.scope,
166 RTN_UNICAST,
167 0));
168
169 msg.SetAttribute(RTA_DST, entry.dst.address());
170 if (!entry.src.IsDefault()) {
171 msg.SetAttribute(RTA_SRC, entry.src.address());
172 }
173 if (!entry.gateway.IsDefault()) {
174 msg.SetAttribute(RTA_GATEWAY, entry.gateway.address());
175 }
176 msg.SetAttribute(RTA_PRIORITY, ByteString::CreateFromCPUUInt32(entry.metric));
177 msg.SetAttribute(RTA_OIF, ByteString::CreateFromCPUUInt32(interface_index));
178
Paul Stewartf748a362012-03-07 12:01:20 -0800179 routing_table_->RouteMsgHandler(msg);
Paul Stewart75e89d22011-08-01 10:00:02 -0700180}
181
Paul Stewartf748a362012-03-07 12:01:20 -0800182void RoutingTableTest::SendRouteMessage(const RTNLMessage &msg) {
183 routing_table_->RouteMsgHandler(msg);
Paul Stewart75e89d22011-08-01 10:00:02 -0700184}
185
Paul Stewartf748a362012-03-07 12:01:20 -0800186TEST_F(RoutingTableTest, Start) {
187 EXPECT_CALL(rtnl_handler_, RequestDump(RTNLHandler::kRequestRoute));
188 routing_table_->Start();
Paul Stewart75e89d22011-08-01 10:00:02 -0700189}
190
191TEST_F(RoutingTableTest, RouteAddDelete) {
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800192 // Expect the tables to be empty by default.
Paul Stewart75e89d22011-08-01 10:00:02 -0700193 EXPECT_EQ(0, GetRoutingTables()->size());
194
Paul Stewart7355ce12011-09-02 10:47:01 -0700195 IPAddress default_address(IPAddress::kFamilyIPv4);
Paul Stewart75e89d22011-08-01 10:00:02 -0700196 default_address.SetAddressToDefault();
197
Paul Stewart7355ce12011-09-02 10:47:01 -0700198 IPAddress gateway_address0(IPAddress::kFamilyIPv4);
Paul Stewart75e89d22011-08-01 10:00:02 -0700199 gateway_address0.SetAddressFromString(kTestNetAddress0);
200
201 int metric = 10;
202
203 RoutingTableEntry entry0(default_address,
Paul Stewart75e89d22011-08-01 10:00:02 -0700204 default_address,
Paul Stewart75e89d22011-08-01 10:00:02 -0700205 gateway_address0,
206 metric,
207 RT_SCOPE_UNIVERSE,
208 true);
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800209 // Add a single entry.
Paul Stewartf748a362012-03-07 12:01:20 -0800210 SendRouteEntry(RTNLMessage::kModeAdd,
211 kTestDeviceIndex0,
212 entry0);
Paul Stewart75e89d22011-08-01 10:00:02 -0700213
214 base::hash_map<int, std::vector<RoutingTableEntry> > *tables =
215 GetRoutingTables();
216
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800217 // We should have a single table, which should in turn have a single entry.
Paul Stewart75e89d22011-08-01 10:00:02 -0700218 EXPECT_EQ(1, tables->size());
219 EXPECT_TRUE(ContainsKey(*tables, kTestDeviceIndex0));
220 EXPECT_EQ(1, (*tables)[kTestDeviceIndex0].size());
221
222 RoutingTableEntry test_entry = (*tables)[kTestDeviceIndex0][0];
223 EXPECT_TRUE(entry0.Equals(test_entry));
224
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800225 // Add a second entry for a different interface.
Paul Stewartf748a362012-03-07 12:01:20 -0800226 SendRouteEntry(RTNLMessage::kModeAdd,
227 kTestDeviceIndex1,
228 entry0);
Paul Stewart75e89d22011-08-01 10:00:02 -0700229
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800230 // We should have two tables, which should have a single entry each.
Paul Stewart75e89d22011-08-01 10:00:02 -0700231 EXPECT_EQ(2, tables->size());
232 EXPECT_TRUE(ContainsKey(*tables, kTestDeviceIndex1));
233 EXPECT_EQ(1, (*tables)[kTestDeviceIndex0].size());
234 EXPECT_EQ(1, (*tables)[kTestDeviceIndex1].size());
235
236 test_entry = (*tables)[kTestDeviceIndex1][0];
237 EXPECT_TRUE(entry0.Equals(test_entry));
238
Paul Stewart7355ce12011-09-02 10:47:01 -0700239 IPAddress gateway_address1(IPAddress::kFamilyIPv4);
Paul Stewart75e89d22011-08-01 10:00:02 -0700240 gateway_address1.SetAddressFromString(kTestNetAddress1);
241
242 RoutingTableEntry entry1(default_address,
Paul Stewart75e89d22011-08-01 10:00:02 -0700243 default_address,
Paul Stewart75e89d22011-08-01 10:00:02 -0700244 gateway_address1,
245 metric,
246 RT_SCOPE_UNIVERSE,
247 true);
248
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800249 // Add a second gateway route to the second interface.
Paul Stewartf748a362012-03-07 12:01:20 -0800250 SendRouteEntry(RTNLMessage::kModeAdd,
251 kTestDeviceIndex1,
252 entry1);
Paul Stewart75e89d22011-08-01 10:00:02 -0700253
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800254 // We should have two tables, one of which has a single entry, the other has
255 // two.
Paul Stewart75e89d22011-08-01 10:00:02 -0700256 EXPECT_EQ(2, tables->size());
257 EXPECT_EQ(1, (*tables)[kTestDeviceIndex0].size());
258 EXPECT_EQ(2, (*tables)[kTestDeviceIndex1].size());
259
260 test_entry = (*tables)[kTestDeviceIndex1][1];
261 EXPECT_TRUE(entry1.Equals(test_entry));
262
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800263 // Remove the first gateway route from the second interface.
Paul Stewartf748a362012-03-07 12:01:20 -0800264 SendRouteEntry(RTNLMessage::kModeDelete,
265 kTestDeviceIndex1,
266 entry0);
Paul Stewart75e89d22011-08-01 10:00:02 -0700267
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800268 // We should be back to having one route per table.
Paul Stewart75e89d22011-08-01 10:00:02 -0700269 EXPECT_EQ(2, tables->size());
270 EXPECT_EQ(1, (*tables)[kTestDeviceIndex0].size());
271 EXPECT_EQ(1, (*tables)[kTestDeviceIndex1].size());
272
273 test_entry = (*tables)[kTestDeviceIndex1][0];
274 EXPECT_TRUE(entry1.Equals(test_entry));
275
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800276 // Send a duplicate of the second gatway route message, changing the metric.
Paul Stewart75e89d22011-08-01 10:00:02 -0700277 RoutingTableEntry entry2(entry1);
278 entry2.metric++;
Paul Stewartf748a362012-03-07 12:01:20 -0800279 SendRouteEntry(RTNLMessage::kModeAdd,
280 kTestDeviceIndex1,
281 entry2);
Paul Stewart75e89d22011-08-01 10:00:02 -0700282
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800283 // Routing table size shouldn't change, but the new metric should match.
Paul Stewart75e89d22011-08-01 10:00:02 -0700284 EXPECT_EQ(1, (*tables)[kTestDeviceIndex1].size());
285 test_entry = (*tables)[kTestDeviceIndex1][0];
286 EXPECT_TRUE(entry2.Equals(test_entry));
287
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800288 // Find a matching entry.
Paul Stewart75e89d22011-08-01 10:00:02 -0700289 EXPECT_TRUE(routing_table_->GetDefaultRoute(kTestDeviceIndex1,
Paul Stewart7355ce12011-09-02 10:47:01 -0700290 IPAddress::kFamilyIPv4,
Paul Stewart75e89d22011-08-01 10:00:02 -0700291 &test_entry));
292 EXPECT_TRUE(entry2.Equals(test_entry));
293
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800294 // Test that a search for a non-matching family fails.
Paul Stewart75e89d22011-08-01 10:00:02 -0700295 EXPECT_FALSE(routing_table_->GetDefaultRoute(kTestDeviceIndex1,
Paul Stewart7355ce12011-09-02 10:47:01 -0700296 IPAddress::kFamilyIPv6,
Paul Stewart75e89d22011-08-01 10:00:02 -0700297 &test_entry));
298
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800299 // Remove last entry from an existing interface and test that we now fail.
Paul Stewartf748a362012-03-07 12:01:20 -0800300 SendRouteEntry(RTNLMessage::kModeDelete,
301 kTestDeviceIndex1,
302 entry2);
Paul Stewart75e89d22011-08-01 10:00:02 -0700303
304 EXPECT_FALSE(routing_table_->GetDefaultRoute(kTestDeviceIndex1,
Paul Stewart7355ce12011-09-02 10:47:01 -0700305 IPAddress::kFamilyIPv4,
Paul Stewart75e89d22011-08-01 10:00:02 -0700306 &test_entry));
307
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800308 // Add a route from an IPConfig entry.
Paul Stewart75e89d22011-08-01 10:00:02 -0700309 MockControl control;
310 IPConfigRefPtr ipconfig(new IPConfig(&control, kTestDeviceName0));
311 IPConfig::Properties properties;
Paul Stewart7355ce12011-09-02 10:47:01 -0700312 properties.address_family = IPAddress::kFamilyIPv4;
Paul Stewart75e89d22011-08-01 10:00:02 -0700313 properties.gateway = kTestNetAddress0;
314 properties.address = kTestNetAddress1;
315 ipconfig->UpdateProperties(properties, true);
316
Paul Stewartf748a362012-03-07 12:01:20 -0800317 EXPECT_CALL(rtnl_handler_,
318 SendMessage(IsRoutingPacket(RTNLMessage::kModeAdd,
319 kTestDeviceIndex1,
320 entry0,
321 NLM_F_CREATE | NLM_F_EXCL)));
Paul Stewart75e89d22011-08-01 10:00:02 -0700322 EXPECT_TRUE(routing_table_->SetDefaultRoute(kTestDeviceIndex1,
323 ipconfig,
324 metric));
325
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800326 // The table entry should look much like entry0, except with
327 // from_rtnl = false.
Paul Stewart75e89d22011-08-01 10:00:02 -0700328 RoutingTableEntry entry3(entry0);
329 entry3.from_rtnl = false;
330 EXPECT_TRUE(routing_table_->GetDefaultRoute(kTestDeviceIndex1,
Paul Stewart7355ce12011-09-02 10:47:01 -0700331 IPAddress::kFamilyIPv4,
Paul Stewart75e89d22011-08-01 10:00:02 -0700332 &test_entry));
333 EXPECT_TRUE(entry3.Equals(test_entry));
334
335 // Setting the same route on the interface with a different metric should
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800336 // push the route with different flags to indicate we are replacing it,
337 // then it should delete the old entry.
Paul Stewart75e89d22011-08-01 10:00:02 -0700338 RoutingTableEntry entry4(entry3);
339 entry4.metric += 10;
Paul Stewartf748a362012-03-07 12:01:20 -0800340 EXPECT_CALL(rtnl_handler_,
341 SendMessage(IsRoutingPacket(RTNLMessage::kModeAdd,
342 kTestDeviceIndex1,
343 entry4,
344 NLM_F_CREATE | NLM_F_REPLACE)));
345 EXPECT_CALL(rtnl_handler_,
346 SendMessage(IsRoutingPacket(RTNLMessage::kModeDelete,
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800347 kTestDeviceIndex1,
348 entry3,
Paul Stewartf748a362012-03-07 12:01:20 -0800349 0)));
Paul Stewart75e89d22011-08-01 10:00:02 -0700350 EXPECT_TRUE(routing_table_->SetDefaultRoute(kTestDeviceIndex1,
351 ipconfig,
352 entry4.metric));
353
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800354 // Test that removing the table causes the route to disappear.
Paul Stewart75e89d22011-08-01 10:00:02 -0700355 routing_table_->ResetTable(kTestDeviceIndex1);
356 EXPECT_FALSE(ContainsKey(*tables, kTestDeviceIndex1));
357 EXPECT_FALSE(routing_table_->GetDefaultRoute(kTestDeviceIndex1,
Paul Stewart7355ce12011-09-02 10:47:01 -0700358 IPAddress::kFamilyIPv4,
Paul Stewart75e89d22011-08-01 10:00:02 -0700359 &test_entry));
360 EXPECT_EQ(1, GetRoutingTables()->size());
361
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800362 // When we set the metric on an existing route, a new add and delete
363 // operation should occur.
Paul Stewart75e89d22011-08-01 10:00:02 -0700364 RoutingTableEntry entry5(entry4);
365 entry5.metric += 10;
Paul Stewartf748a362012-03-07 12:01:20 -0800366 EXPECT_CALL(rtnl_handler_,
367 SendMessage(IsRoutingPacket(RTNLMessage::kModeAdd,
368 kTestDeviceIndex0,
369 entry5,
370 NLM_F_CREATE | NLM_F_REPLACE)));
371 EXPECT_CALL(rtnl_handler_,
372 SendMessage(IsRoutingPacket(RTNLMessage::kModeDelete,
373 kTestDeviceIndex0,
374 entry0,
375 0)));
Paul Stewart75e89d22011-08-01 10:00:02 -0700376 routing_table_->SetDefaultMetric(kTestDeviceIndex0, entry5.metric);
mukesh agrawald4ef6772012-02-21 16:28:04 -0800377 // Furthermore, the routing table should reflect the change in the metric
378 // for the default route for the interface.
379 RoutingTableEntry default_route;
380 EXPECT_TRUE(routing_table_->GetDefaultRoute(kTestDeviceIndex0,
381 IPAddress::kFamilyIPv4,
382 &default_route));
383 EXPECT_EQ(entry5.metric, default_route.metric);
Paul Stewart75e89d22011-08-01 10:00:02 -0700384
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800385 // Ask to flush table0. We should see a delete message sent.
Paul Stewartf748a362012-03-07 12:01:20 -0800386 EXPECT_CALL(rtnl_handler_,
387 SendMessage(IsRoutingPacket(RTNLMessage::kModeDelete,
388 kTestDeviceIndex0,
389 entry5,
390 0)));
Thieu Lefb46caf2012-03-08 11:57:15 -0800391 routing_table_->FlushRoutes(kTestDeviceIndex0);
392 EXPECT_EQ(0, (*tables)[kTestDeviceIndex0].size());
Paul Stewart75e89d22011-08-01 10:00:02 -0700393
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800394 // Test that the routing table size returns to zero.
Paul Stewartf748a362012-03-07 12:01:20 -0800395 SendRouteEntry(RTNLMessage::kModeAdd,
396 kTestDeviceIndex0,
397 entry5);
Paul Stewart75e89d22011-08-01 10:00:02 -0700398 EXPECT_EQ(1, GetRoutingTables()->size());
399 routing_table_->ResetTable(kTestDeviceIndex0);
400 EXPECT_EQ(0, GetRoutingTables()->size());
401
402 routing_table_->Stop();
Paul Stewartf748a362012-03-07 12:01:20 -0800403}
404
405MATCHER_P2(IsRoutingQuery, destination, index, "") {
406 const RTNLMessage::RouteStatus &status = arg->route_status();
407
408 uint32 oif;
409
410 return
411 arg->type() == RTNLMessage::kTypeRoute &&
412 arg->family() == destination.family() &&
413 arg->flags() == NLM_F_REQUEST &&
414 status.table == 0 &&
415 status.protocol == 0 &&
416 status.scope == 0 &&
417 status.type == 0 &&
418 arg->HasAttribute(RTA_DST) &&
419 IPAddress(arg->family(),
420 arg->GetAttribute(RTA_DST),
421 status.dst_prefix).Equals(destination) &&
422 !arg->HasAttribute(RTA_SRC) &&
423 !arg->HasAttribute(RTA_GATEWAY) &&
424 arg->GetAttribute(RTA_OIF).ConvertToCPUUInt32(&oif) &&
425 oif == index &&
426 !arg->HasAttribute(RTA_PRIORITY);
427
428 return false;
429}
430
431TEST_F(RoutingTableTest, RequestHostRoute) {
432 IPAddress destination_address(IPAddress::kFamilyIPv4);
433 destination_address.SetAddressFromString(kTestRemoteAddress4);
434 destination_address.set_prefix(24);
435
436 EXPECT_CALL(rtnl_handler_,
437 SendMessage(IsRoutingQuery(destination_address,
438 kTestDeviceIndex0)))
439 .WillOnce(Invoke(this, &RoutingTableTest::SetSequenceForMessage));
440 EXPECT_TRUE(routing_table_->RequestRouteToHost(destination_address,
441 kTestDeviceIndex0));
442
443 IPAddress gateway_address(IPAddress::kFamilyIPv4);
444 gateway_address.SetAddressFromString(kTestGatewayAddress4);
445
446 IPAddress local_address(IPAddress::kFamilyIPv4);
447 local_address.SetAddressFromString(kTestDeviceNetAddress4);
448
449 const int kMetric = 10;
450 RoutingTableEntry entry(destination_address,
451 local_address,
452 gateway_address,
453 kMetric,
454 RT_SCOPE_UNIVERSE,
455 true);
456
457 EXPECT_CALL(rtnl_handler_,
458 SendMessage(IsRoutingPacket(RTNLMessage::kModeAdd,
459 kTestDeviceIndex0,
460 entry,
461 NLM_F_CREATE | NLM_F_EXCL)));
462 SendRouteEntryWithSeqAndProto(RTNLMessage::kModeAdd,
463 kTestDeviceIndex0,
464 entry,
465 kTestRequestSeq,
466 RTPROT_UNSPEC);
467}
468
469TEST_F(RoutingTableTest, RequestHostRouteBadSequence) {
470 IPAddress destination_address(IPAddress::kFamilyIPv4);
471 destination_address.SetAddressFromString(kTestRemoteAddress4);
472 EXPECT_CALL(rtnl_handler_, SendMessage(_))
473 .WillOnce(Invoke(this, &RoutingTableTest::SetSequenceForMessage));
474 EXPECT_TRUE(routing_table_->RequestRouteToHost(destination_address,
475 kTestDeviceIndex0));
476 EXPECT_FALSE(GetQuerySequences()->empty());
477
478 RoutingTableEntry entry(destination_address,
479 destination_address,
480 destination_address,
481 0,
482 RT_SCOPE_UNIVERSE,
483 true);
484
485 // Try a sequence arriving before the one RoutingTable is looking for.
486 // This should be a no-op.
487 SendRouteEntryWithSeqAndProto(RTNLMessage::kModeAdd,
488 kTestDeviceIndex0,
489 entry,
490 kTestRequestSeq-1,
491 RTPROT_UNSPEC);
492 EXPECT_FALSE(GetQuerySequences()->empty());
493
494 // Try a sequence arriving after the one RoutingTable is looking for.
495 // This should cause the request to be purged.
496 SendRouteEntryWithSeqAndProto(RTNLMessage::kModeAdd,
497 kTestDeviceIndex0,
498 entry,
499 kTestRequestSeq+1,
500 RTPROT_UNSPEC);
501 EXPECT_TRUE(GetQuerySequences()->empty());
Paul Stewart75e89d22011-08-01 10:00:02 -0700502}
503
Paul Stewart75e89d22011-08-01 10:00:02 -0700504} // namespace shill