blob: e74f02da07cff4988fc2073a8906916f3f112b22 [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 Stewarte93b0382012-04-24 13:11:28 -070024using base::hash_map;
25using std::queue;
Paul Stewart3f68bb12012-03-15 13:33:10 -070026using std::vector;
Paul Stewart75e89d22011-08-01 10:00:02 -070027using testing::_;
Paul Stewartf748a362012-03-07 12:01:20 -080028using testing::Invoke;
Paul Stewart75e89d22011-08-01 10:00:02 -070029using testing::Return;
Paul Stewartf748a362012-03-07 12:01:20 -080030using testing::StrictMock;
Paul Stewart75e89d22011-08-01 10:00:02 -070031using testing::Test;
32
33namespace shill {
34
35class TestEventDispatcher : public EventDispatcher {
36 public:
Paul Stewart26b327e2011-10-19 11:38:09 -070037 virtual IOHandler *CreateInputHandler(
mukesh agrawal1830fa12011-09-26 14:31:40 -070038 int /*fd*/,
Eric Shienbrood3e20a232012-02-16 11:35:56 -050039 const Callback<void(InputData*)> &/*callback*/) {
Paul Stewart75e89d22011-08-01 10:00:02 -070040 return NULL;
41 }
42};
43
44class RoutingTableTest : public Test {
45 public:
Paul Stewarte93b0382012-04-24 13:11:28 -070046 RoutingTableTest() : routing_table_(new RoutingTable()) {}
Paul Stewart75e89d22011-08-01 10:00:02 -070047
Paul Stewartf748a362012-03-07 12:01:20 -080048 virtual void SetUp() {
49 routing_table_->rtnl_handler_ = &rtnl_handler_;
50 ON_CALL(rtnl_handler_, SendMessage(_)).WillByDefault(Return(true));
Paul Stewart75e89d22011-08-01 10:00:02 -070051 }
52
Paul Stewart65c40f52011-08-08 07:27:46 -070053 virtual void TearDown() {
54 RTNLHandler::GetInstance()->Stop();
55 }
56
Paul Stewarte93b0382012-04-24 13:11:28 -070057 hash_map<int, vector<RoutingTableEntry> > *GetRoutingTables() {
Paul Stewartf748a362012-03-07 12:01:20 -080058 return &routing_table_->tables_;
59 }
60
Paul Stewarte93b0382012-04-24 13:11:28 -070061 queue<RoutingTable::Query> *GetQueries() {
62 return &routing_table_->route_queries_;
Paul Stewartf748a362012-03-07 12:01:20 -080063 }
64
65 void SendRouteEntry(RTNLMessage::Mode mode,
66 uint32 interface_index,
67 const RoutingTableEntry &entry);
68
69 void SendRouteEntryWithSeqAndProto(RTNLMessage::Mode mode,
70 uint32 interface_index,
71 const RoutingTableEntry &entry,
72 uint32 seq,
73 unsigned char proto);
74
75 void SendRouteMessage(const RTNLMessage &msg);
76
77 bool SetSequenceForMessage(RTNLMessage *message) {
78 message->set_seq(RoutingTableTest::kTestRequestSeq);
79 return true;
80 }
81
Paul Stewart75e89d22011-08-01 10:00:02 -070082 protected:
Paul Stewart75e89d22011-08-01 10:00:02 -070083 static const uint32 kTestDeviceIndex0;
84 static const uint32 kTestDeviceIndex1;
85 static const char kTestDeviceName0[];
Thieu Lecaef8932012-02-28 16:06:59 -080086 static const char kTestDeviceNetAddress4[];
87 static const char kTestForeignNetAddress4[];
88 static const char kTestForeignNetGateway4[];
89 static const char kTestForeignNetAddress6[];
90 static const char kTestForeignNetGateway6[];
Paul Stewartf748a362012-03-07 12:01:20 -080091 static const char kTestGatewayAddress4[];
Paul Stewart75e89d22011-08-01 10:00:02 -070092 static const char kTestNetAddress0[];
93 static const char kTestNetAddress1[];
Paul Stewartf748a362012-03-07 12:01:20 -080094 static const char kTestRemoteAddress4[];
Paul Stewart3f68bb12012-03-15 13:33:10 -070095 static const char kTestRemoteNetmask4[];
96 static const char kTestRemoteNetwork4[];
97 static const int kTestRemotePrefix4;
Paul Stewartf748a362012-03-07 12:01:20 -080098 static const uint32 kTestRequestSeq;
Paul Stewarte93b0382012-04-24 13:11:28 -070099 static const int kTestRouteTag;
Paul Stewart75e89d22011-08-01 10:00:02 -0700100
Paul Stewart75e89d22011-08-01 10:00:02 -0700101 RoutingTable *routing_table_;
102 TestEventDispatcher dispatcher_;
Paul Stewartf748a362012-03-07 12:01:20 -0800103 StrictMock<MockRTNLHandler> rtnl_handler_;
Paul Stewart75e89d22011-08-01 10:00:02 -0700104};
105
Paul Stewart75e89d22011-08-01 10:00:02 -0700106const uint32 RoutingTableTest::kTestDeviceIndex0 = 12345;
107const uint32 RoutingTableTest::kTestDeviceIndex1 = 67890;
108const char RoutingTableTest::kTestDeviceName0[] = "test-device0";
Thieu Lecaef8932012-02-28 16:06:59 -0800109const char RoutingTableTest::kTestDeviceNetAddress4[] = "192.168.2.0/24";
110const char RoutingTableTest::kTestForeignNetAddress4[] = "192.168.2.2";
111const char RoutingTableTest::kTestForeignNetGateway4[] = "192.168.2.1";
112const char RoutingTableTest::kTestForeignNetAddress6[] = "2000::/3";
113const char RoutingTableTest::kTestForeignNetGateway6[] = "fe80:::::1";
Paul Stewartf748a362012-03-07 12:01:20 -0800114const char RoutingTableTest::kTestGatewayAddress4[] = "192.168.2.254";
Paul Stewart75e89d22011-08-01 10:00:02 -0700115const char RoutingTableTest::kTestNetAddress0[] = "192.168.1.1";
116const char RoutingTableTest::kTestNetAddress1[] = "192.168.1.2";
Paul Stewartf748a362012-03-07 12:01:20 -0800117const char RoutingTableTest::kTestRemoteAddress4[] = "192.168.2.254";
Paul Stewart3f68bb12012-03-15 13:33:10 -0700118const char RoutingTableTest::kTestRemoteNetmask4[] = "255.255.255.0";
119const char RoutingTableTest::kTestRemoteNetwork4[] = "192.168.100.0";
120const int RoutingTableTest::kTestRemotePrefix4 = 24;
Paul Stewartf748a362012-03-07 12:01:20 -0800121const uint32 RoutingTableTest::kTestRequestSeq = 456;
Paul Stewarte93b0382012-04-24 13:11:28 -0700122const int RoutingTableTest::kTestRouteTag = 789;
Paul Stewart75e89d22011-08-01 10:00:02 -0700123
124MATCHER_P4(IsRoutingPacket, mode, index, entry, flags, "") {
Paul Stewartf748a362012-03-07 12:01:20 -0800125 const RTNLMessage::RouteStatus &status = arg->route_status();
Paul Stewart75e89d22011-08-01 10:00:02 -0700126
127 uint32 oif;
128 uint32 priority;
129
130 return
Paul Stewartf748a362012-03-07 12:01:20 -0800131 arg->type() == RTNLMessage::kTypeRoute &&
132 arg->family() == entry.gateway.family() &&
133 arg->flags() == (NLM_F_REQUEST | flags) &&
134 status.table == RT_TABLE_MAIN &&
135 status.protocol == RTPROT_BOOT &&
136 status.scope == entry.scope &&
137 status.type == RTN_UNICAST &&
138 arg->HasAttribute(RTA_DST) &&
139 IPAddress(arg->family(),
140 arg->GetAttribute(RTA_DST),
141 status.dst_prefix).Equals(entry.dst) &&
142 !arg->HasAttribute(RTA_SRC) &&
143 arg->HasAttribute(RTA_GATEWAY) &&
144 IPAddress(arg->family(),
145 arg->GetAttribute(RTA_GATEWAY)).Equals(entry.gateway) &&
146 arg->GetAttribute(RTA_OIF).ConvertToCPUUInt32(&oif) &&
147 oif == index &&
148 arg->GetAttribute(RTA_PRIORITY).ConvertToCPUUInt32(&priority) &&
149 priority == entry.metric;
Paul Stewart75e89d22011-08-01 10:00:02 -0700150}
151
Paul Stewartf748a362012-03-07 12:01:20 -0800152void RoutingTableTest::SendRouteEntry(RTNLMessage::Mode mode,
153 uint32 interface_index,
154 const RoutingTableEntry &entry) {
155 SendRouteEntryWithSeqAndProto(mode, interface_index, entry, 0, RTPROT_BOOT);
156}
157
158void RoutingTableTest::SendRouteEntryWithSeqAndProto(
159 RTNLMessage::Mode mode,
160 uint32 interface_index,
161 const RoutingTableEntry &entry,
162 uint32 seq,
163 unsigned char proto) {
Paul Stewart75e89d22011-08-01 10:00:02 -0700164 RTNLMessage msg(
Paul Stewart9a908082011-08-31 12:18:48 -0700165 RTNLMessage::kTypeRoute,
Paul Stewart75e89d22011-08-01 10:00:02 -0700166 mode,
167 0,
Paul Stewartf748a362012-03-07 12:01:20 -0800168 seq,
Paul Stewart75e89d22011-08-01 10:00:02 -0700169 0,
170 0,
171 entry.dst.family());
172
173 msg.set_route_status(RTNLMessage::RouteStatus(
Paul Stewart9e3fcd72011-08-26 15:46:16 -0700174 entry.dst.prefix(),
175 entry.src.prefix(),
Paul Stewart75e89d22011-08-01 10:00:02 -0700176 RT_TABLE_MAIN,
Paul Stewartf748a362012-03-07 12:01:20 -0800177 proto,
Paul Stewart75e89d22011-08-01 10:00:02 -0700178 entry.scope,
179 RTN_UNICAST,
180 0));
181
182 msg.SetAttribute(RTA_DST, entry.dst.address());
183 if (!entry.src.IsDefault()) {
184 msg.SetAttribute(RTA_SRC, entry.src.address());
185 }
186 if (!entry.gateway.IsDefault()) {
187 msg.SetAttribute(RTA_GATEWAY, entry.gateway.address());
188 }
189 msg.SetAttribute(RTA_PRIORITY, ByteString::CreateFromCPUUInt32(entry.metric));
190 msg.SetAttribute(RTA_OIF, ByteString::CreateFromCPUUInt32(interface_index));
191
Paul Stewartf748a362012-03-07 12:01:20 -0800192 routing_table_->RouteMsgHandler(msg);
Paul Stewart75e89d22011-08-01 10:00:02 -0700193}
194
Paul Stewartf748a362012-03-07 12:01:20 -0800195void RoutingTableTest::SendRouteMessage(const RTNLMessage &msg) {
196 routing_table_->RouteMsgHandler(msg);
Paul Stewart75e89d22011-08-01 10:00:02 -0700197}
198
Paul Stewartf748a362012-03-07 12:01:20 -0800199TEST_F(RoutingTableTest, Start) {
200 EXPECT_CALL(rtnl_handler_, RequestDump(RTNLHandler::kRequestRoute));
201 routing_table_->Start();
Paul Stewart75e89d22011-08-01 10:00:02 -0700202}
203
204TEST_F(RoutingTableTest, RouteAddDelete) {
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800205 // Expect the tables to be empty by default.
Paul Stewart75e89d22011-08-01 10:00:02 -0700206 EXPECT_EQ(0, GetRoutingTables()->size());
207
Paul Stewart7355ce12011-09-02 10:47:01 -0700208 IPAddress default_address(IPAddress::kFamilyIPv4);
Paul Stewart75e89d22011-08-01 10:00:02 -0700209 default_address.SetAddressToDefault();
210
Paul Stewart7355ce12011-09-02 10:47:01 -0700211 IPAddress gateway_address0(IPAddress::kFamilyIPv4);
Paul Stewart75e89d22011-08-01 10:00:02 -0700212 gateway_address0.SetAddressFromString(kTestNetAddress0);
213
214 int metric = 10;
215
216 RoutingTableEntry entry0(default_address,
Paul Stewart75e89d22011-08-01 10:00:02 -0700217 default_address,
Paul Stewart75e89d22011-08-01 10:00:02 -0700218 gateway_address0,
219 metric,
220 RT_SCOPE_UNIVERSE,
221 true);
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800222 // Add a single entry.
Paul Stewartf748a362012-03-07 12:01:20 -0800223 SendRouteEntry(RTNLMessage::kModeAdd,
224 kTestDeviceIndex0,
225 entry0);
Paul Stewart75e89d22011-08-01 10:00:02 -0700226
Paul Stewarte93b0382012-04-24 13:11:28 -0700227 hash_map<int, vector<RoutingTableEntry> > *tables =
Paul Stewart75e89d22011-08-01 10:00:02 -0700228 GetRoutingTables();
229
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800230 // We should have a single table, which should in turn have a single entry.
Paul Stewart75e89d22011-08-01 10:00:02 -0700231 EXPECT_EQ(1, tables->size());
232 EXPECT_TRUE(ContainsKey(*tables, kTestDeviceIndex0));
233 EXPECT_EQ(1, (*tables)[kTestDeviceIndex0].size());
234
235 RoutingTableEntry test_entry = (*tables)[kTestDeviceIndex0][0];
236 EXPECT_TRUE(entry0.Equals(test_entry));
237
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800238 // Add a second entry for a different interface.
Paul Stewartf748a362012-03-07 12:01:20 -0800239 SendRouteEntry(RTNLMessage::kModeAdd,
240 kTestDeviceIndex1,
241 entry0);
Paul Stewart75e89d22011-08-01 10:00:02 -0700242
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800243 // We should have two tables, which should have a single entry each.
Paul Stewart75e89d22011-08-01 10:00:02 -0700244 EXPECT_EQ(2, tables->size());
245 EXPECT_TRUE(ContainsKey(*tables, kTestDeviceIndex1));
246 EXPECT_EQ(1, (*tables)[kTestDeviceIndex0].size());
247 EXPECT_EQ(1, (*tables)[kTestDeviceIndex1].size());
248
249 test_entry = (*tables)[kTestDeviceIndex1][0];
250 EXPECT_TRUE(entry0.Equals(test_entry));
251
Paul Stewart7355ce12011-09-02 10:47:01 -0700252 IPAddress gateway_address1(IPAddress::kFamilyIPv4);
Paul Stewart75e89d22011-08-01 10:00:02 -0700253 gateway_address1.SetAddressFromString(kTestNetAddress1);
254
255 RoutingTableEntry entry1(default_address,
Paul Stewart75e89d22011-08-01 10:00:02 -0700256 default_address,
Paul Stewart75e89d22011-08-01 10:00:02 -0700257 gateway_address1,
258 metric,
259 RT_SCOPE_UNIVERSE,
260 true);
261
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800262 // Add a second gateway route to the second interface.
Paul Stewartf748a362012-03-07 12:01:20 -0800263 SendRouteEntry(RTNLMessage::kModeAdd,
264 kTestDeviceIndex1,
265 entry1);
Paul Stewart75e89d22011-08-01 10:00:02 -0700266
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800267 // We should have two tables, one of which has a single entry, the other has
268 // two.
Paul Stewart75e89d22011-08-01 10:00:02 -0700269 EXPECT_EQ(2, tables->size());
270 EXPECT_EQ(1, (*tables)[kTestDeviceIndex0].size());
271 EXPECT_EQ(2, (*tables)[kTestDeviceIndex1].size());
272
273 test_entry = (*tables)[kTestDeviceIndex1][1];
274 EXPECT_TRUE(entry1.Equals(test_entry));
275
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800276 // Remove the first gateway route from the second interface.
Paul Stewartf748a362012-03-07 12:01:20 -0800277 SendRouteEntry(RTNLMessage::kModeDelete,
278 kTestDeviceIndex1,
279 entry0);
Paul Stewart75e89d22011-08-01 10:00:02 -0700280
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800281 // We should be back to having one route per table.
Paul Stewart75e89d22011-08-01 10:00:02 -0700282 EXPECT_EQ(2, tables->size());
283 EXPECT_EQ(1, (*tables)[kTestDeviceIndex0].size());
284 EXPECT_EQ(1, (*tables)[kTestDeviceIndex1].size());
285
286 test_entry = (*tables)[kTestDeviceIndex1][0];
287 EXPECT_TRUE(entry1.Equals(test_entry));
288
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700289 // Send a duplicate of the second gateway route message, changing the metric.
Paul Stewart75e89d22011-08-01 10:00:02 -0700290 RoutingTableEntry entry2(entry1);
291 entry2.metric++;
Paul Stewartf748a362012-03-07 12:01:20 -0800292 SendRouteEntry(RTNLMessage::kModeAdd,
293 kTestDeviceIndex1,
294 entry2);
Paul Stewart75e89d22011-08-01 10:00:02 -0700295
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800296 // Routing table size shouldn't change, but the new metric should match.
Paul Stewart75e89d22011-08-01 10:00:02 -0700297 EXPECT_EQ(1, (*tables)[kTestDeviceIndex1].size());
298 test_entry = (*tables)[kTestDeviceIndex1][0];
299 EXPECT_TRUE(entry2.Equals(test_entry));
300
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800301 // Find a matching entry.
Paul Stewart75e89d22011-08-01 10:00:02 -0700302 EXPECT_TRUE(routing_table_->GetDefaultRoute(kTestDeviceIndex1,
Paul Stewart7355ce12011-09-02 10:47:01 -0700303 IPAddress::kFamilyIPv4,
Paul Stewart75e89d22011-08-01 10:00:02 -0700304 &test_entry));
305 EXPECT_TRUE(entry2.Equals(test_entry));
306
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800307 // Test that a search for a non-matching family fails.
Paul Stewart75e89d22011-08-01 10:00:02 -0700308 EXPECT_FALSE(routing_table_->GetDefaultRoute(kTestDeviceIndex1,
Paul Stewart7355ce12011-09-02 10:47:01 -0700309 IPAddress::kFamilyIPv6,
Paul Stewart75e89d22011-08-01 10:00:02 -0700310 &test_entry));
311
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800312 // Remove last entry from an existing interface and test that we now fail.
Paul Stewartf748a362012-03-07 12:01:20 -0800313 SendRouteEntry(RTNLMessage::kModeDelete,
314 kTestDeviceIndex1,
315 entry2);
Paul Stewart75e89d22011-08-01 10:00:02 -0700316
317 EXPECT_FALSE(routing_table_->GetDefaultRoute(kTestDeviceIndex1,
Paul Stewart7355ce12011-09-02 10:47:01 -0700318 IPAddress::kFamilyIPv4,
Paul Stewart75e89d22011-08-01 10:00:02 -0700319 &test_entry));
320
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700321 // Add a route to a gatway address.
322 IPAddress gateway_address(IPAddress::kFamilyIPv4);
323 EXPECT_TRUE(gateway_address.SetAddressFromString(kTestNetAddress0));
Paul Stewart75e89d22011-08-01 10:00:02 -0700324
Paul Stewartf748a362012-03-07 12:01:20 -0800325 EXPECT_CALL(rtnl_handler_,
326 SendMessage(IsRoutingPacket(RTNLMessage::kModeAdd,
327 kTestDeviceIndex1,
328 entry0,
329 NLM_F_CREATE | NLM_F_EXCL)));
Paul Stewart75e89d22011-08-01 10:00:02 -0700330 EXPECT_TRUE(routing_table_->SetDefaultRoute(kTestDeviceIndex1,
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700331 gateway_address,
Paul Stewart75e89d22011-08-01 10:00:02 -0700332 metric));
333
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800334 // The table entry should look much like entry0, except with
335 // from_rtnl = false.
Paul Stewart75e89d22011-08-01 10:00:02 -0700336 RoutingTableEntry entry3(entry0);
337 entry3.from_rtnl = false;
338 EXPECT_TRUE(routing_table_->GetDefaultRoute(kTestDeviceIndex1,
Paul Stewart7355ce12011-09-02 10:47:01 -0700339 IPAddress::kFamilyIPv4,
Paul Stewart75e89d22011-08-01 10:00:02 -0700340 &test_entry));
341 EXPECT_TRUE(entry3.Equals(test_entry));
342
343 // Setting the same route on the interface with a different metric should
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800344 // push the route with different flags to indicate we are replacing it,
345 // then it should delete the old entry.
Paul Stewart75e89d22011-08-01 10:00:02 -0700346 RoutingTableEntry entry4(entry3);
347 entry4.metric += 10;
Paul Stewartf748a362012-03-07 12:01:20 -0800348 EXPECT_CALL(rtnl_handler_,
349 SendMessage(IsRoutingPacket(RTNLMessage::kModeAdd,
350 kTestDeviceIndex1,
351 entry4,
352 NLM_F_CREATE | NLM_F_REPLACE)));
353 EXPECT_CALL(rtnl_handler_,
354 SendMessage(IsRoutingPacket(RTNLMessage::kModeDelete,
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800355 kTestDeviceIndex1,
356 entry3,
Paul Stewartf748a362012-03-07 12:01:20 -0800357 0)));
Paul Stewart75e89d22011-08-01 10:00:02 -0700358 EXPECT_TRUE(routing_table_->SetDefaultRoute(kTestDeviceIndex1,
Paul Stewart5b7ba8c2012-04-18 09:08:00 -0700359 gateway_address,
Paul Stewart75e89d22011-08-01 10:00:02 -0700360 entry4.metric));
361
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800362 // Test that removing the table causes the route to disappear.
Paul Stewart75e89d22011-08-01 10:00:02 -0700363 routing_table_->ResetTable(kTestDeviceIndex1);
364 EXPECT_FALSE(ContainsKey(*tables, kTestDeviceIndex1));
365 EXPECT_FALSE(routing_table_->GetDefaultRoute(kTestDeviceIndex1,
Paul Stewart7355ce12011-09-02 10:47:01 -0700366 IPAddress::kFamilyIPv4,
Paul Stewart75e89d22011-08-01 10:00:02 -0700367 &test_entry));
368 EXPECT_EQ(1, GetRoutingTables()->size());
369
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800370 // When we set the metric on an existing route, a new add and delete
371 // operation should occur.
Paul Stewart75e89d22011-08-01 10:00:02 -0700372 RoutingTableEntry entry5(entry4);
373 entry5.metric += 10;
Paul Stewartf748a362012-03-07 12:01:20 -0800374 EXPECT_CALL(rtnl_handler_,
375 SendMessage(IsRoutingPacket(RTNLMessage::kModeAdd,
376 kTestDeviceIndex0,
377 entry5,
378 NLM_F_CREATE | NLM_F_REPLACE)));
379 EXPECT_CALL(rtnl_handler_,
380 SendMessage(IsRoutingPacket(RTNLMessage::kModeDelete,
381 kTestDeviceIndex0,
382 entry0,
383 0)));
Paul Stewart75e89d22011-08-01 10:00:02 -0700384 routing_table_->SetDefaultMetric(kTestDeviceIndex0, entry5.metric);
mukesh agrawald4ef6772012-02-21 16:28:04 -0800385 // Furthermore, the routing table should reflect the change in the metric
386 // for the default route for the interface.
387 RoutingTableEntry default_route;
388 EXPECT_TRUE(routing_table_->GetDefaultRoute(kTestDeviceIndex0,
389 IPAddress::kFamilyIPv4,
390 &default_route));
391 EXPECT_EQ(entry5.metric, default_route.metric);
Paul Stewart75e89d22011-08-01 10:00:02 -0700392
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800393 // Ask to flush table0. We should see a delete message sent.
Paul Stewartf748a362012-03-07 12:01:20 -0800394 EXPECT_CALL(rtnl_handler_,
395 SendMessage(IsRoutingPacket(RTNLMessage::kModeDelete,
396 kTestDeviceIndex0,
397 entry5,
398 0)));
Thieu Lefb46caf2012-03-08 11:57:15 -0800399 routing_table_->FlushRoutes(kTestDeviceIndex0);
400 EXPECT_EQ(0, (*tables)[kTestDeviceIndex0].size());
Paul Stewart75e89d22011-08-01 10:00:02 -0700401
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800402 // Test that the routing table size returns to zero.
Paul Stewartf748a362012-03-07 12:01:20 -0800403 SendRouteEntry(RTNLMessage::kModeAdd,
404 kTestDeviceIndex0,
405 entry5);
Paul Stewart75e89d22011-08-01 10:00:02 -0700406 EXPECT_EQ(1, GetRoutingTables()->size());
407 routing_table_->ResetTable(kTestDeviceIndex0);
408 EXPECT_EQ(0, GetRoutingTables()->size());
409
410 routing_table_->Stop();
Paul Stewartf748a362012-03-07 12:01:20 -0800411}
412
Paul Stewart3f68bb12012-03-15 13:33:10 -0700413TEST_F(RoutingTableTest, ConfigureRoutes) {
414 MockControl control;
415 IPConfigRefPtr ipconfig(new IPConfig(&control, kTestDeviceName0));
416 IPConfig::Properties properties;
417 properties.address_family = IPAddress::kFamilyIPv4;
418 vector<IPConfig::Route> &routes = properties.routes;
419 ipconfig->UpdateProperties(properties, true);
420
421 const int kMetric = 10;
422 EXPECT_TRUE(routing_table_->ConfigureRoutes(kTestDeviceIndex0,
423 ipconfig,
424 kMetric));
425
426 IPConfig::Route route;
427 route.host = kTestRemoteNetwork4;
428 route.netmask = kTestRemoteNetmask4;
429 route.gateway = kTestGatewayAddress4;
430 routes.push_back(route);
431 ipconfig->UpdateProperties(properties, true);
432
433 IPAddress destination_address(IPAddress::kFamilyIPv4);
434 IPAddress source_address(IPAddress::kFamilyIPv4);
435 IPAddress gateway_address(IPAddress::kFamilyIPv4);
436 ASSERT_TRUE(destination_address.SetAddressFromString(kTestRemoteNetwork4));
437 destination_address.set_prefix(kTestRemotePrefix4);
438 ASSERT_TRUE(gateway_address.SetAddressFromString(kTestGatewayAddress4));
439
440 RoutingTableEntry entry(destination_address,
441 source_address,
442 gateway_address,
443 kMetric,
444 RT_SCOPE_UNIVERSE,
445 false);
446
447 EXPECT_CALL(rtnl_handler_,
448 SendMessage(IsRoutingPacket(RTNLMessage::kModeAdd,
449 kTestDeviceIndex0,
450 entry,
451 NLM_F_CREATE | NLM_F_EXCL)));
452 EXPECT_TRUE(routing_table_->ConfigureRoutes(kTestDeviceIndex0,
453 ipconfig,
454 kMetric));
455
456 routes.clear();
457 route.gateway = "xxx"; // Invalid gateway entry -- should be skipped
458 routes.push_back(route);
459 route.host = "xxx"; // Invalid host entry -- should be skipped
460 route.gateway = kTestGatewayAddress4;
461 routes.push_back(route);
462 route.host = kTestRemoteNetwork4;
463 routes.push_back(route);
464 ipconfig->UpdateProperties(properties, true);
465
466 EXPECT_CALL(rtnl_handler_,
467 SendMessage(IsRoutingPacket(RTNLMessage::kModeAdd,
468 kTestDeviceIndex0,
469 entry,
470 NLM_F_CREATE | NLM_F_EXCL)))
471 .Times(1);
472 EXPECT_FALSE(routing_table_->ConfigureRoutes(kTestDeviceIndex0,
473 ipconfig,
474 kMetric));
475}
476
Paul Stewartf748a362012-03-07 12:01:20 -0800477MATCHER_P2(IsRoutingQuery, destination, index, "") {
478 const RTNLMessage::RouteStatus &status = arg->route_status();
479
480 uint32 oif;
481
482 return
483 arg->type() == RTNLMessage::kTypeRoute &&
484 arg->family() == destination.family() &&
485 arg->flags() == NLM_F_REQUEST &&
486 status.table == 0 &&
487 status.protocol == 0 &&
488 status.scope == 0 &&
489 status.type == 0 &&
490 arg->HasAttribute(RTA_DST) &&
491 IPAddress(arg->family(),
492 arg->GetAttribute(RTA_DST),
493 status.dst_prefix).Equals(destination) &&
494 !arg->HasAttribute(RTA_SRC) &&
495 !arg->HasAttribute(RTA_GATEWAY) &&
496 arg->GetAttribute(RTA_OIF).ConvertToCPUUInt32(&oif) &&
497 oif == index &&
498 !arg->HasAttribute(RTA_PRIORITY);
499
500 return false;
501}
502
503TEST_F(RoutingTableTest, RequestHostRoute) {
504 IPAddress destination_address(IPAddress::kFamilyIPv4);
505 destination_address.SetAddressFromString(kTestRemoteAddress4);
506 destination_address.set_prefix(24);
507
508 EXPECT_CALL(rtnl_handler_,
509 SendMessage(IsRoutingQuery(destination_address,
510 kTestDeviceIndex0)))
511 .WillOnce(Invoke(this, &RoutingTableTest::SetSequenceForMessage));
512 EXPECT_TRUE(routing_table_->RequestRouteToHost(destination_address,
Paul Stewarte93b0382012-04-24 13:11:28 -0700513 kTestDeviceIndex0,
514 kTestRouteTag));
Paul Stewartf748a362012-03-07 12:01:20 -0800515
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);
Paul Stewarte93b0382012-04-24 13:11:28 -0700540
541 hash_map<int, vector<RoutingTableEntry> > *tables =
542 GetRoutingTables();
543
544 // We should have a single table, which should in turn have a single entry.
545 EXPECT_EQ(1, tables->size());
546 EXPECT_TRUE(ContainsKey(*tables, kTestDeviceIndex0));
547 EXPECT_EQ(1, (*tables)[kTestDeviceIndex0].size());
548
549 // This entry's tag should match the tag we requested.
550 EXPECT_EQ(kTestRouteTag, (*tables)[kTestDeviceIndex0][0].tag);
551
552 // Ask to flush routes with our tag. We should see a delete message sent.
553 EXPECT_CALL(rtnl_handler_,
554 SendMessage(IsRoutingPacket(RTNLMessage::kModeDelete,
555 kTestDeviceIndex0,
556 entry,
557 0)));
558
559 routing_table_->FlushRoutesWithTag(kTestRouteTag);
560
561 // After flushing routes for this tag, we should end up with no routes.
562 EXPECT_EQ(0, (*tables)[kTestDeviceIndex0].size());
Paul Stewartf748a362012-03-07 12:01:20 -0800563}
564
565TEST_F(RoutingTableTest, RequestHostRouteBadSequence) {
566 IPAddress destination_address(IPAddress::kFamilyIPv4);
567 destination_address.SetAddressFromString(kTestRemoteAddress4);
568 EXPECT_CALL(rtnl_handler_, SendMessage(_))
569 .WillOnce(Invoke(this, &RoutingTableTest::SetSequenceForMessage));
570 EXPECT_TRUE(routing_table_->RequestRouteToHost(destination_address,
Paul Stewarte93b0382012-04-24 13:11:28 -0700571 kTestDeviceIndex0,
572 kTestRouteTag));
573 EXPECT_FALSE(GetQueries()->empty());
Paul Stewartf748a362012-03-07 12:01:20 -0800574
575 RoutingTableEntry entry(destination_address,
576 destination_address,
577 destination_address,
578 0,
579 RT_SCOPE_UNIVERSE,
580 true);
581
582 // Try a sequence arriving before the one RoutingTable is looking for.
583 // This should be a no-op.
584 SendRouteEntryWithSeqAndProto(RTNLMessage::kModeAdd,
585 kTestDeviceIndex0,
586 entry,
587 kTestRequestSeq-1,
588 RTPROT_UNSPEC);
Paul Stewarte93b0382012-04-24 13:11:28 -0700589 EXPECT_FALSE(GetQueries()->empty());
Paul Stewartf748a362012-03-07 12:01:20 -0800590
591 // Try a sequence arriving after the one RoutingTable is looking for.
592 // This should cause the request to be purged.
593 SendRouteEntryWithSeqAndProto(RTNLMessage::kModeAdd,
594 kTestDeviceIndex0,
595 entry,
596 kTestRequestSeq+1,
597 RTPROT_UNSPEC);
Paul Stewarte93b0382012-04-24 13:11:28 -0700598 EXPECT_TRUE(GetQueries()->empty());
Paul Stewart75e89d22011-08-01 10:00:02 -0700599}
600
Paul Stewart75e89d22011-08-01 10:00:02 -0700601} // namespace shill