blob: 1cf49867920a29a67ddee71bc76755c2cf524c98 [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
Eric Shienbrood3e20a232012-02-16 11:35:56 -050023using base::Callback;
Paul Stewart3f68bb12012-03-15 13:33:10 -070024using std::vector;
Paul Stewart75e89d22011-08-01 10:00:02 -070025using testing::_;
Paul Stewartf748a362012-03-07 12:01:20 -080026using testing::Invoke;
Paul Stewart75e89d22011-08-01 10:00:02 -070027using testing::Return;
Paul Stewartf748a362012-03-07 12:01:20 -080028using testing::StrictMock;
Paul Stewart75e89d22011-08-01 10:00:02 -070029using testing::Test;
30
31namespace shill {
32
33class TestEventDispatcher : public EventDispatcher {
34 public:
Paul Stewart26b327e2011-10-19 11:38:09 -070035 virtual IOHandler *CreateInputHandler(
mukesh agrawal1830fa12011-09-26 14:31:40 -070036 int /*fd*/,
Eric Shienbrood3e20a232012-02-16 11:35:56 -050037 const Callback<void(InputData*)> &/*callback*/) {
Paul Stewart75e89d22011-08-01 10:00:02 -070038 return NULL;
39 }
40};
41
42class RoutingTableTest : public Test {
43 public:
44 RoutingTableTest() : routing_table_(RoutingTable::GetInstance()) {}
45
Paul Stewartf748a362012-03-07 12:01:20 -080046 virtual void SetUp() {
47 routing_table_->rtnl_handler_ = &rtnl_handler_;
48 ON_CALL(rtnl_handler_, SendMessage(_)).WillByDefault(Return(true));
Paul Stewart75e89d22011-08-01 10:00:02 -070049 }
50
Paul Stewart65c40f52011-08-08 07:27:46 -070051 virtual void TearDown() {
52 RTNLHandler::GetInstance()->Stop();
53 }
54
Paul Stewartf748a362012-03-07 12:01:20 -080055 base::hash_map<int, std::vector<RoutingTableEntry> > *GetRoutingTables() {
56 return &routing_table_->tables_;
57 }
58
59 std::queue<uint32> *GetQuerySequences() {
60 return &routing_table_->route_query_sequences_;
61 }
62
63 void SendRouteEntry(RTNLMessage::Mode mode,
64 uint32 interface_index,
65 const RoutingTableEntry &entry);
66
67 void SendRouteEntryWithSeqAndProto(RTNLMessage::Mode mode,
68 uint32 interface_index,
69 const RoutingTableEntry &entry,
70 uint32 seq,
71 unsigned char proto);
72
73 void SendRouteMessage(const RTNLMessage &msg);
74
75 bool SetSequenceForMessage(RTNLMessage *message) {
76 message->set_seq(RoutingTableTest::kTestRequestSeq);
77 return true;
78 }
79
Paul Stewart75e89d22011-08-01 10:00:02 -070080 protected:
Paul Stewart75e89d22011-08-01 10:00:02 -070081 static const uint32 kTestDeviceIndex0;
82 static const uint32 kTestDeviceIndex1;
83 static const char kTestDeviceName0[];
Thieu Lecaef8932012-02-28 16:06:59 -080084 static const char kTestDeviceNetAddress4[];
85 static const char kTestForeignNetAddress4[];
86 static const char kTestForeignNetGateway4[];
87 static const char kTestForeignNetAddress6[];
88 static const char kTestForeignNetGateway6[];
Paul Stewartf748a362012-03-07 12:01:20 -080089 static const char kTestGatewayAddress4[];
Paul Stewart75e89d22011-08-01 10:00:02 -070090 static const char kTestNetAddress0[];
91 static const char kTestNetAddress1[];
Paul Stewartf748a362012-03-07 12:01:20 -080092 static const char kTestRemoteAddress4[];
Paul Stewart3f68bb12012-03-15 13:33:10 -070093 static const char kTestRemoteNetmask4[];
94 static const char kTestRemoteNetwork4[];
95 static const int kTestRemotePrefix4;
Paul Stewartf748a362012-03-07 12:01:20 -080096 static const uint32 kTestRequestSeq;
Paul Stewart75e89d22011-08-01 10:00:02 -070097
Paul Stewart75e89d22011-08-01 10:00:02 -070098 RoutingTable *routing_table_;
99 TestEventDispatcher dispatcher_;
Paul Stewartf748a362012-03-07 12:01:20 -0800100 StrictMock<MockRTNLHandler> rtnl_handler_;
Paul Stewart75e89d22011-08-01 10:00:02 -0700101};
102
Paul Stewart75e89d22011-08-01 10:00:02 -0700103const uint32 RoutingTableTest::kTestDeviceIndex0 = 12345;
104const uint32 RoutingTableTest::kTestDeviceIndex1 = 67890;
105const char RoutingTableTest::kTestDeviceName0[] = "test-device0";
Thieu Lecaef8932012-02-28 16:06:59 -0800106const char RoutingTableTest::kTestDeviceNetAddress4[] = "192.168.2.0/24";
107const char RoutingTableTest::kTestForeignNetAddress4[] = "192.168.2.2";
108const char RoutingTableTest::kTestForeignNetGateway4[] = "192.168.2.1";
109const char RoutingTableTest::kTestForeignNetAddress6[] = "2000::/3";
110const char RoutingTableTest::kTestForeignNetGateway6[] = "fe80:::::1";
Paul Stewartf748a362012-03-07 12:01:20 -0800111const char RoutingTableTest::kTestGatewayAddress4[] = "192.168.2.254";
Paul Stewart75e89d22011-08-01 10:00:02 -0700112const char RoutingTableTest::kTestNetAddress0[] = "192.168.1.1";
113const char RoutingTableTest::kTestNetAddress1[] = "192.168.1.2";
Paul Stewartf748a362012-03-07 12:01:20 -0800114const char RoutingTableTest::kTestRemoteAddress4[] = "192.168.2.254";
Paul Stewart3f68bb12012-03-15 13:33:10 -0700115const char RoutingTableTest::kTestRemoteNetmask4[] = "255.255.255.0";
116const char RoutingTableTest::kTestRemoteNetwork4[] = "192.168.100.0";
117const int RoutingTableTest::kTestRemotePrefix4 = 24;
Paul Stewartf748a362012-03-07 12:01:20 -0800118const uint32 RoutingTableTest::kTestRequestSeq = 456;
Paul Stewart75e89d22011-08-01 10:00:02 -0700119
120MATCHER_P4(IsRoutingPacket, mode, index, entry, flags, "") {
Paul Stewartf748a362012-03-07 12:01:20 -0800121 const RTNLMessage::RouteStatus &status = arg->route_status();
Paul Stewart75e89d22011-08-01 10:00:02 -0700122
123 uint32 oif;
124 uint32 priority;
125
126 return
Paul Stewartf748a362012-03-07 12:01:20 -0800127 arg->type() == RTNLMessage::kTypeRoute &&
128 arg->family() == entry.gateway.family() &&
129 arg->flags() == (NLM_F_REQUEST | flags) &&
130 status.table == RT_TABLE_MAIN &&
131 status.protocol == RTPROT_BOOT &&
132 status.scope == entry.scope &&
133 status.type == RTN_UNICAST &&
134 arg->HasAttribute(RTA_DST) &&
135 IPAddress(arg->family(),
136 arg->GetAttribute(RTA_DST),
137 status.dst_prefix).Equals(entry.dst) &&
138 !arg->HasAttribute(RTA_SRC) &&
139 arg->HasAttribute(RTA_GATEWAY) &&
140 IPAddress(arg->family(),
141 arg->GetAttribute(RTA_GATEWAY)).Equals(entry.gateway) &&
142 arg->GetAttribute(RTA_OIF).ConvertToCPUUInt32(&oif) &&
143 oif == index &&
144 arg->GetAttribute(RTA_PRIORITY).ConvertToCPUUInt32(&priority) &&
145 priority == entry.metric;
Paul Stewart75e89d22011-08-01 10:00:02 -0700146}
147
Paul Stewartf748a362012-03-07 12:01:20 -0800148void RoutingTableTest::SendRouteEntry(RTNLMessage::Mode mode,
149 uint32 interface_index,
150 const RoutingTableEntry &entry) {
151 SendRouteEntryWithSeqAndProto(mode, interface_index, entry, 0, RTPROT_BOOT);
152}
153
154void RoutingTableTest::SendRouteEntryWithSeqAndProto(
155 RTNLMessage::Mode mode,
156 uint32 interface_index,
157 const RoutingTableEntry &entry,
158 uint32 seq,
159 unsigned char proto) {
Paul Stewart75e89d22011-08-01 10:00:02 -0700160 RTNLMessage msg(
Paul Stewart9a908082011-08-31 12:18:48 -0700161 RTNLMessage::kTypeRoute,
Paul Stewart75e89d22011-08-01 10:00:02 -0700162 mode,
163 0,
Paul Stewartf748a362012-03-07 12:01:20 -0800164 seq,
Paul Stewart75e89d22011-08-01 10:00:02 -0700165 0,
166 0,
167 entry.dst.family());
168
169 msg.set_route_status(RTNLMessage::RouteStatus(
Paul Stewart9e3fcd72011-08-26 15:46:16 -0700170 entry.dst.prefix(),
171 entry.src.prefix(),
Paul Stewart75e89d22011-08-01 10:00:02 -0700172 RT_TABLE_MAIN,
Paul Stewartf748a362012-03-07 12:01:20 -0800173 proto,
Paul Stewart75e89d22011-08-01 10:00:02 -0700174 entry.scope,
175 RTN_UNICAST,
176 0));
177
178 msg.SetAttribute(RTA_DST, entry.dst.address());
179 if (!entry.src.IsDefault()) {
180 msg.SetAttribute(RTA_SRC, entry.src.address());
181 }
182 if (!entry.gateway.IsDefault()) {
183 msg.SetAttribute(RTA_GATEWAY, entry.gateway.address());
184 }
185 msg.SetAttribute(RTA_PRIORITY, ByteString::CreateFromCPUUInt32(entry.metric));
186 msg.SetAttribute(RTA_OIF, ByteString::CreateFromCPUUInt32(interface_index));
187
Paul Stewartf748a362012-03-07 12:01:20 -0800188 routing_table_->RouteMsgHandler(msg);
Paul Stewart75e89d22011-08-01 10:00:02 -0700189}
190
Paul Stewartf748a362012-03-07 12:01:20 -0800191void RoutingTableTest::SendRouteMessage(const RTNLMessage &msg) {
192 routing_table_->RouteMsgHandler(msg);
Paul Stewart75e89d22011-08-01 10:00:02 -0700193}
194
Paul Stewartf748a362012-03-07 12:01:20 -0800195TEST_F(RoutingTableTest, Start) {
196 EXPECT_CALL(rtnl_handler_, RequestDump(RTNLHandler::kRequestRoute));
197 routing_table_->Start();
Paul Stewart75e89d22011-08-01 10:00:02 -0700198}
199
200TEST_F(RoutingTableTest, RouteAddDelete) {
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800201 // Expect the tables to be empty by default.
Paul Stewart75e89d22011-08-01 10:00:02 -0700202 EXPECT_EQ(0, GetRoutingTables()->size());
203
Paul Stewart7355ce12011-09-02 10:47:01 -0700204 IPAddress default_address(IPAddress::kFamilyIPv4);
Paul Stewart75e89d22011-08-01 10:00:02 -0700205 default_address.SetAddressToDefault();
206
Paul Stewart7355ce12011-09-02 10:47:01 -0700207 IPAddress gateway_address0(IPAddress::kFamilyIPv4);
Paul Stewart75e89d22011-08-01 10:00:02 -0700208 gateway_address0.SetAddressFromString(kTestNetAddress0);
209
210 int metric = 10;
211
212 RoutingTableEntry entry0(default_address,
Paul Stewart75e89d22011-08-01 10:00:02 -0700213 default_address,
Paul Stewart75e89d22011-08-01 10:00:02 -0700214 gateway_address0,
215 metric,
216 RT_SCOPE_UNIVERSE,
217 true);
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800218 // Add a single entry.
Paul Stewartf748a362012-03-07 12:01:20 -0800219 SendRouteEntry(RTNLMessage::kModeAdd,
220 kTestDeviceIndex0,
221 entry0);
Paul Stewart75e89d22011-08-01 10:00:02 -0700222
223 base::hash_map<int, std::vector<RoutingTableEntry> > *tables =
224 GetRoutingTables();
225
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800226 // We should have a single table, which should in turn have a single entry.
Paul Stewart75e89d22011-08-01 10:00:02 -0700227 EXPECT_EQ(1, tables->size());
228 EXPECT_TRUE(ContainsKey(*tables, kTestDeviceIndex0));
229 EXPECT_EQ(1, (*tables)[kTestDeviceIndex0].size());
230
231 RoutingTableEntry test_entry = (*tables)[kTestDeviceIndex0][0];
232 EXPECT_TRUE(entry0.Equals(test_entry));
233
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800234 // Add a second entry for a different interface.
Paul Stewartf748a362012-03-07 12:01:20 -0800235 SendRouteEntry(RTNLMessage::kModeAdd,
236 kTestDeviceIndex1,
237 entry0);
Paul Stewart75e89d22011-08-01 10:00:02 -0700238
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800239 // We should have two tables, which should have a single entry each.
Paul Stewart75e89d22011-08-01 10:00:02 -0700240 EXPECT_EQ(2, tables->size());
241 EXPECT_TRUE(ContainsKey(*tables, kTestDeviceIndex1));
242 EXPECT_EQ(1, (*tables)[kTestDeviceIndex0].size());
243 EXPECT_EQ(1, (*tables)[kTestDeviceIndex1].size());
244
245 test_entry = (*tables)[kTestDeviceIndex1][0];
246 EXPECT_TRUE(entry0.Equals(test_entry));
247
Paul Stewart7355ce12011-09-02 10:47:01 -0700248 IPAddress gateway_address1(IPAddress::kFamilyIPv4);
Paul Stewart75e89d22011-08-01 10:00:02 -0700249 gateway_address1.SetAddressFromString(kTestNetAddress1);
250
251 RoutingTableEntry entry1(default_address,
Paul Stewart75e89d22011-08-01 10:00:02 -0700252 default_address,
Paul Stewart75e89d22011-08-01 10:00:02 -0700253 gateway_address1,
254 metric,
255 RT_SCOPE_UNIVERSE,
256 true);
257
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800258 // Add a second gateway route to the second interface.
Paul Stewartf748a362012-03-07 12:01:20 -0800259 SendRouteEntry(RTNLMessage::kModeAdd,
260 kTestDeviceIndex1,
261 entry1);
Paul Stewart75e89d22011-08-01 10:00:02 -0700262
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800263 // We should have two tables, one of which has a single entry, the other has
264 // two.
Paul Stewart75e89d22011-08-01 10:00:02 -0700265 EXPECT_EQ(2, tables->size());
266 EXPECT_EQ(1, (*tables)[kTestDeviceIndex0].size());
267 EXPECT_EQ(2, (*tables)[kTestDeviceIndex1].size());
268
269 test_entry = (*tables)[kTestDeviceIndex1][1];
270 EXPECT_TRUE(entry1.Equals(test_entry));
271
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800272 // Remove the first gateway route from the second interface.
Paul Stewartf748a362012-03-07 12:01:20 -0800273 SendRouteEntry(RTNLMessage::kModeDelete,
274 kTestDeviceIndex1,
275 entry0);
Paul Stewart75e89d22011-08-01 10:00:02 -0700276
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800277 // We should be back to having one route per table.
Paul Stewart75e89d22011-08-01 10:00:02 -0700278 EXPECT_EQ(2, tables->size());
279 EXPECT_EQ(1, (*tables)[kTestDeviceIndex0].size());
280 EXPECT_EQ(1, (*tables)[kTestDeviceIndex1].size());
281
282 test_entry = (*tables)[kTestDeviceIndex1][0];
283 EXPECT_TRUE(entry1.Equals(test_entry));
284
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800285 // Send a duplicate of the second gatway route message, changing the metric.
Paul Stewart75e89d22011-08-01 10:00:02 -0700286 RoutingTableEntry entry2(entry1);
287 entry2.metric++;
Paul Stewartf748a362012-03-07 12:01:20 -0800288 SendRouteEntry(RTNLMessage::kModeAdd,
289 kTestDeviceIndex1,
290 entry2);
Paul Stewart75e89d22011-08-01 10:00:02 -0700291
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800292 // Routing table size shouldn't change, but the new metric should match.
Paul Stewart75e89d22011-08-01 10:00:02 -0700293 EXPECT_EQ(1, (*tables)[kTestDeviceIndex1].size());
294 test_entry = (*tables)[kTestDeviceIndex1][0];
295 EXPECT_TRUE(entry2.Equals(test_entry));
296
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800297 // Find a matching entry.
Paul Stewart75e89d22011-08-01 10:00:02 -0700298 EXPECT_TRUE(routing_table_->GetDefaultRoute(kTestDeviceIndex1,
Paul Stewart7355ce12011-09-02 10:47:01 -0700299 IPAddress::kFamilyIPv4,
Paul Stewart75e89d22011-08-01 10:00:02 -0700300 &test_entry));
301 EXPECT_TRUE(entry2.Equals(test_entry));
302
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800303 // Test that a search for a non-matching family fails.
Paul Stewart75e89d22011-08-01 10:00:02 -0700304 EXPECT_FALSE(routing_table_->GetDefaultRoute(kTestDeviceIndex1,
Paul Stewart7355ce12011-09-02 10:47:01 -0700305 IPAddress::kFamilyIPv6,
Paul Stewart75e89d22011-08-01 10:00:02 -0700306 &test_entry));
307
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800308 // Remove last entry from an existing interface and test that we now fail.
Paul Stewartf748a362012-03-07 12:01:20 -0800309 SendRouteEntry(RTNLMessage::kModeDelete,
310 kTestDeviceIndex1,
311 entry2);
Paul Stewart75e89d22011-08-01 10:00:02 -0700312
313 EXPECT_FALSE(routing_table_->GetDefaultRoute(kTestDeviceIndex1,
Paul Stewart7355ce12011-09-02 10:47:01 -0700314 IPAddress::kFamilyIPv4,
Paul Stewart75e89d22011-08-01 10:00:02 -0700315 &test_entry));
316
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800317 // Add a route from an IPConfig entry.
Paul Stewart75e89d22011-08-01 10:00:02 -0700318 MockControl control;
319 IPConfigRefPtr ipconfig(new IPConfig(&control, kTestDeviceName0));
320 IPConfig::Properties properties;
Paul Stewart7355ce12011-09-02 10:47:01 -0700321 properties.address_family = IPAddress::kFamilyIPv4;
Paul Stewart75e89d22011-08-01 10:00:02 -0700322 properties.gateway = kTestNetAddress0;
323 properties.address = kTestNetAddress1;
324 ipconfig->UpdateProperties(properties, true);
325
Paul Stewartf748a362012-03-07 12:01:20 -0800326 EXPECT_CALL(rtnl_handler_,
327 SendMessage(IsRoutingPacket(RTNLMessage::kModeAdd,
328 kTestDeviceIndex1,
329 entry0,
330 NLM_F_CREATE | NLM_F_EXCL)));
Paul Stewart75e89d22011-08-01 10:00:02 -0700331 EXPECT_TRUE(routing_table_->SetDefaultRoute(kTestDeviceIndex1,
332 ipconfig,
333 metric));
334
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800335 // The table entry should look much like entry0, except with
336 // from_rtnl = false.
Paul Stewart75e89d22011-08-01 10:00:02 -0700337 RoutingTableEntry entry3(entry0);
338 entry3.from_rtnl = false;
339 EXPECT_TRUE(routing_table_->GetDefaultRoute(kTestDeviceIndex1,
Paul Stewart7355ce12011-09-02 10:47:01 -0700340 IPAddress::kFamilyIPv4,
Paul Stewart75e89d22011-08-01 10:00:02 -0700341 &test_entry));
342 EXPECT_TRUE(entry3.Equals(test_entry));
343
344 // Setting the same route on the interface with a different metric should
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800345 // push the route with different flags to indicate we are replacing it,
346 // then it should delete the old entry.
Paul Stewart75e89d22011-08-01 10:00:02 -0700347 RoutingTableEntry entry4(entry3);
348 entry4.metric += 10;
Paul Stewartf748a362012-03-07 12:01:20 -0800349 EXPECT_CALL(rtnl_handler_,
350 SendMessage(IsRoutingPacket(RTNLMessage::kModeAdd,
351 kTestDeviceIndex1,
352 entry4,
353 NLM_F_CREATE | NLM_F_REPLACE)));
354 EXPECT_CALL(rtnl_handler_,
355 SendMessage(IsRoutingPacket(RTNLMessage::kModeDelete,
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800356 kTestDeviceIndex1,
357 entry3,
Paul Stewartf748a362012-03-07 12:01:20 -0800358 0)));
Paul Stewart75e89d22011-08-01 10:00:02 -0700359 EXPECT_TRUE(routing_table_->SetDefaultRoute(kTestDeviceIndex1,
360 ipconfig,
361 entry4.metric));
362
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800363 // Test that removing the table causes the route to disappear.
Paul Stewart75e89d22011-08-01 10:00:02 -0700364 routing_table_->ResetTable(kTestDeviceIndex1);
365 EXPECT_FALSE(ContainsKey(*tables, kTestDeviceIndex1));
366 EXPECT_FALSE(routing_table_->GetDefaultRoute(kTestDeviceIndex1,
Paul Stewart7355ce12011-09-02 10:47:01 -0700367 IPAddress::kFamilyIPv4,
Paul Stewart75e89d22011-08-01 10:00:02 -0700368 &test_entry));
369 EXPECT_EQ(1, GetRoutingTables()->size());
370
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800371 // When we set the metric on an existing route, a new add and delete
372 // operation should occur.
Paul Stewart75e89d22011-08-01 10:00:02 -0700373 RoutingTableEntry entry5(entry4);
374 entry5.metric += 10;
Paul Stewartf748a362012-03-07 12:01:20 -0800375 EXPECT_CALL(rtnl_handler_,
376 SendMessage(IsRoutingPacket(RTNLMessage::kModeAdd,
377 kTestDeviceIndex0,
378 entry5,
379 NLM_F_CREATE | NLM_F_REPLACE)));
380 EXPECT_CALL(rtnl_handler_,
381 SendMessage(IsRoutingPacket(RTNLMessage::kModeDelete,
382 kTestDeviceIndex0,
383 entry0,
384 0)));
Paul Stewart75e89d22011-08-01 10:00:02 -0700385 routing_table_->SetDefaultMetric(kTestDeviceIndex0, entry5.metric);
mukesh agrawald4ef6772012-02-21 16:28:04 -0800386 // Furthermore, the routing table should reflect the change in the metric
387 // for the default route for the interface.
388 RoutingTableEntry default_route;
389 EXPECT_TRUE(routing_table_->GetDefaultRoute(kTestDeviceIndex0,
390 IPAddress::kFamilyIPv4,
391 &default_route));
392 EXPECT_EQ(entry5.metric, default_route.metric);
Paul Stewart75e89d22011-08-01 10:00:02 -0700393
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800394 // Ask to flush table0. We should see a delete message sent.
Paul Stewartf748a362012-03-07 12:01:20 -0800395 EXPECT_CALL(rtnl_handler_,
396 SendMessage(IsRoutingPacket(RTNLMessage::kModeDelete,
397 kTestDeviceIndex0,
398 entry5,
399 0)));
Thieu Lefb46caf2012-03-08 11:57:15 -0800400 routing_table_->FlushRoutes(kTestDeviceIndex0);
401 EXPECT_EQ(0, (*tables)[kTestDeviceIndex0].size());
Paul Stewart75e89d22011-08-01 10:00:02 -0700402
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800403 // Test that the routing table size returns to zero.
Paul Stewartf748a362012-03-07 12:01:20 -0800404 SendRouteEntry(RTNLMessage::kModeAdd,
405 kTestDeviceIndex0,
406 entry5);
Paul Stewart75e89d22011-08-01 10:00:02 -0700407 EXPECT_EQ(1, GetRoutingTables()->size());
408 routing_table_->ResetTable(kTestDeviceIndex0);
409 EXPECT_EQ(0, GetRoutingTables()->size());
410
411 routing_table_->Stop();
Paul Stewartf748a362012-03-07 12:01:20 -0800412}
413
Paul Stewart3f68bb12012-03-15 13:33:10 -0700414TEST_F(RoutingTableTest, ConfigureRoutes) {
415 MockControl control;
416 IPConfigRefPtr ipconfig(new IPConfig(&control, kTestDeviceName0));
417 IPConfig::Properties properties;
418 properties.address_family = IPAddress::kFamilyIPv4;
419 vector<IPConfig::Route> &routes = properties.routes;
420 ipconfig->UpdateProperties(properties, true);
421
422 const int kMetric = 10;
423 EXPECT_TRUE(routing_table_->ConfigureRoutes(kTestDeviceIndex0,
424 ipconfig,
425 kMetric));
426
427 IPConfig::Route route;
428 route.host = kTestRemoteNetwork4;
429 route.netmask = kTestRemoteNetmask4;
430 route.gateway = kTestGatewayAddress4;
431 routes.push_back(route);
432 ipconfig->UpdateProperties(properties, true);
433
434 IPAddress destination_address(IPAddress::kFamilyIPv4);
435 IPAddress source_address(IPAddress::kFamilyIPv4);
436 IPAddress gateway_address(IPAddress::kFamilyIPv4);
437 ASSERT_TRUE(destination_address.SetAddressFromString(kTestRemoteNetwork4));
438 destination_address.set_prefix(kTestRemotePrefix4);
439 ASSERT_TRUE(gateway_address.SetAddressFromString(kTestGatewayAddress4));
440
441 RoutingTableEntry entry(destination_address,
442 source_address,
443 gateway_address,
444 kMetric,
445 RT_SCOPE_UNIVERSE,
446 false);
447
448 EXPECT_CALL(rtnl_handler_,
449 SendMessage(IsRoutingPacket(RTNLMessage::kModeAdd,
450 kTestDeviceIndex0,
451 entry,
452 NLM_F_CREATE | NLM_F_EXCL)));
453 EXPECT_TRUE(routing_table_->ConfigureRoutes(kTestDeviceIndex0,
454 ipconfig,
455 kMetric));
456
457 routes.clear();
458 route.gateway = "xxx"; // Invalid gateway entry -- should be skipped
459 routes.push_back(route);
460 route.host = "xxx"; // Invalid host entry -- should be skipped
461 route.gateway = kTestGatewayAddress4;
462 routes.push_back(route);
463 route.host = kTestRemoteNetwork4;
464 routes.push_back(route);
465 ipconfig->UpdateProperties(properties, true);
466
467 EXPECT_CALL(rtnl_handler_,
468 SendMessage(IsRoutingPacket(RTNLMessage::kModeAdd,
469 kTestDeviceIndex0,
470 entry,
471 NLM_F_CREATE | NLM_F_EXCL)))
472 .Times(1);
473 EXPECT_FALSE(routing_table_->ConfigureRoutes(kTestDeviceIndex0,
474 ipconfig,
475 kMetric));
476}
477
Paul Stewartf748a362012-03-07 12:01:20 -0800478MATCHER_P2(IsRoutingQuery, destination, index, "") {
479 const RTNLMessage::RouteStatus &status = arg->route_status();
480
481 uint32 oif;
482
483 return
484 arg->type() == RTNLMessage::kTypeRoute &&
485 arg->family() == destination.family() &&
486 arg->flags() == NLM_F_REQUEST &&
487 status.table == 0 &&
488 status.protocol == 0 &&
489 status.scope == 0 &&
490 status.type == 0 &&
491 arg->HasAttribute(RTA_DST) &&
492 IPAddress(arg->family(),
493 arg->GetAttribute(RTA_DST),
494 status.dst_prefix).Equals(destination) &&
495 !arg->HasAttribute(RTA_SRC) &&
496 !arg->HasAttribute(RTA_GATEWAY) &&
497 arg->GetAttribute(RTA_OIF).ConvertToCPUUInt32(&oif) &&
498 oif == index &&
499 !arg->HasAttribute(RTA_PRIORITY);
500
501 return false;
502}
503
504TEST_F(RoutingTableTest, RequestHostRoute) {
505 IPAddress destination_address(IPAddress::kFamilyIPv4);
506 destination_address.SetAddressFromString(kTestRemoteAddress4);
507 destination_address.set_prefix(24);
508
509 EXPECT_CALL(rtnl_handler_,
510 SendMessage(IsRoutingQuery(destination_address,
511 kTestDeviceIndex0)))
512 .WillOnce(Invoke(this, &RoutingTableTest::SetSequenceForMessage));
513 EXPECT_TRUE(routing_table_->RequestRouteToHost(destination_address,
514 kTestDeviceIndex0));
515
516 IPAddress gateway_address(IPAddress::kFamilyIPv4);
517 gateway_address.SetAddressFromString(kTestGatewayAddress4);
518
519 IPAddress local_address(IPAddress::kFamilyIPv4);
520 local_address.SetAddressFromString(kTestDeviceNetAddress4);
521
522 const int kMetric = 10;
523 RoutingTableEntry entry(destination_address,
524 local_address,
525 gateway_address,
526 kMetric,
527 RT_SCOPE_UNIVERSE,
528 true);
529
530 EXPECT_CALL(rtnl_handler_,
531 SendMessage(IsRoutingPacket(RTNLMessage::kModeAdd,
532 kTestDeviceIndex0,
533 entry,
534 NLM_F_CREATE | NLM_F_EXCL)));
535 SendRouteEntryWithSeqAndProto(RTNLMessage::kModeAdd,
536 kTestDeviceIndex0,
537 entry,
538 kTestRequestSeq,
539 RTPROT_UNSPEC);
540}
541
542TEST_F(RoutingTableTest, RequestHostRouteBadSequence) {
543 IPAddress destination_address(IPAddress::kFamilyIPv4);
544 destination_address.SetAddressFromString(kTestRemoteAddress4);
545 EXPECT_CALL(rtnl_handler_, SendMessage(_))
546 .WillOnce(Invoke(this, &RoutingTableTest::SetSequenceForMessage));
547 EXPECT_TRUE(routing_table_->RequestRouteToHost(destination_address,
548 kTestDeviceIndex0));
549 EXPECT_FALSE(GetQuerySequences()->empty());
550
551 RoutingTableEntry entry(destination_address,
552 destination_address,
553 destination_address,
554 0,
555 RT_SCOPE_UNIVERSE,
556 true);
557
558 // Try a sequence arriving before the one RoutingTable is looking for.
559 // This should be a no-op.
560 SendRouteEntryWithSeqAndProto(RTNLMessage::kModeAdd,
561 kTestDeviceIndex0,
562 entry,
563 kTestRequestSeq-1,
564 RTPROT_UNSPEC);
565 EXPECT_FALSE(GetQuerySequences()->empty());
566
567 // Try a sequence arriving after the one RoutingTable is looking for.
568 // This should cause the request to be purged.
569 SendRouteEntryWithSeqAndProto(RTNLMessage::kModeAdd,
570 kTestDeviceIndex0,
571 entry,
572 kTestRequestSeq+1,
573 RTPROT_UNSPEC);
574 EXPECT_TRUE(GetQuerySequences()->empty());
Paul Stewart75e89d22011-08-01 10:00:02 -0700575}
576
Paul Stewart75e89d22011-08-01 10:00:02 -0700577} // namespace shill