blob: 919e3b48180587948af28f792994464328449829 [file] [log] [blame]
Thieu Le3426c8f2012-01-11 17:35:11 -08001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
Paul Stewart0af98bf2011-05-10 17:38:08 -07002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef SHILL_DEVICE_INFO_
6#define SHILL_DEVICE_INFO_
7
Darin Petkove6193c02011-08-11 12:42:40 -07008#include <map>
mukesh agrawal8f317b62011-07-15 11:53:23 -07009#include <set>
10#include <string>
Paul Stewart9a908082011-08-31 12:18:48 -070011#include <vector>
mukesh agrawal8f317b62011-07-15 11:53:23 -070012
Eric Shienbrood3e20a232012-02-16 11:35:56 -050013#include <base/callback.h>
Paul Stewart050cfc02012-07-06 20:38:54 -070014#include <base/cancelable_callback.h>
Paul Stewartca876ee2012-04-21 08:55:58 -070015#include <base/file_path.h>
Paul Stewartb50f0b92011-05-16 16:31:42 -070016#include <base/memory/ref_counted.h>
Chris Masone487b8bf2011-05-13 16:27:57 -070017#include <base/memory/scoped_ptr.h>
Darin Petkov5a850472012-06-06 15:44:24 +020018#include <base/memory/weak_ptr.h>
Darin Petkov0828f5f2011-08-11 10:18:52 -070019#include <gtest/gtest_prod.h> // for FRIEND_TEST
Paul Stewart0af98bf2011-05-10 17:38:08 -070020
Darin Petkove3e1cfa2011-08-11 13:41:17 -070021#include "shill/byte_string.h"
Chris Masone9be4a9d2011-05-16 15:44:09 -070022#include "shill/device.h"
Paul Stewart9a908082011-08-31 12:18:48 -070023#include "shill/ip_address.h"
Paul Stewarta3c56f92011-05-26 07:08:52 -070024#include "shill/rtnl_listener.h"
Paul Stewartcba0f7f2012-02-29 16:33:05 -080025#include "shill/technology.h"
Paul Stewart0af98bf2011-05-10 17:38:08 -070026
27namespace shill {
28
Paul Stewartb50f0b92011-05-16 16:31:42 -070029class Manager;
Thieu Le3426c8f2012-01-11 17:35:11 -080030class Metrics;
Paul Stewart8c116a92012-05-02 18:30:03 -070031class RoutingTable;
Paul Stewart9a908082011-08-31 12:18:48 -070032class RTNLHandler;
Chris Masone2aa97072011-08-09 17:35:08 -070033class RTNLMessage;
Gary Morain41780232012-07-31 15:08:31 -070034class Sockets;
Paul Stewartb50f0b92011-05-16 16:31:42 -070035
Darin Petkov5a850472012-06-06 15:44:24 +020036class DeviceInfo : public base::SupportsWeakPtr<DeviceInfo> {
Paul Stewart0af98bf2011-05-10 17:38:08 -070037 public:
Paul Stewart9a908082011-08-31 12:18:48 -070038 struct AddressData {
39 AddressData()
Paul Stewart7355ce12011-09-02 10:47:01 -070040 : address(IPAddress::kFamilyUnknown), flags(0), scope(0) {}
Paul Stewart9a908082011-08-31 12:18:48 -070041 AddressData(const IPAddress &address_in,
42 unsigned char flags_in,
43 unsigned char scope_in)
44 : address(address_in), flags(flags_in), scope(scope_in) {}
45 IPAddress address;
46 unsigned char flags;
47 unsigned char scope;
48 };
49
Jason Glasgowabc54032012-04-20 16:08:32 -040050 // Device name prefix for modem pseudo devices used in testing.
51 static const char kModemPseudoDeviceNamePrefix[];
Christopher Wileye049cc52012-09-10 14:36:57 -070052 // Device name prefix for virtual ethernet devices used in testing.
53 static const char kEthernetPseudoDeviceNamePrefix[];
Jason Glasgowabc54032012-04-20 16:08:32 -040054
Paul Stewartb50f0b92011-05-16 16:31:42 -070055 DeviceInfo(ControlInterface *control_interface,
56 EventDispatcher *dispatcher,
Thieu Le3426c8f2012-01-11 17:35:11 -080057 Metrics *metrics,
Paul Stewartb50f0b92011-05-16 16:31:42 -070058 Manager *manager);
Darin Petkov5a850472012-06-06 15:44:24 +020059 virtual ~DeviceInfo();
Darin Petkov887f2982011-07-14 16:10:17 -070060
mukesh agrawal8f317b62011-07-15 11:53:23 -070061 void AddDeviceToBlackList(const std::string &device_name);
Eric Shienbrood5e628a52012-03-21 16:56:59 -040062 bool IsDeviceBlackListed(const std::string &device_name);
Paul Stewart0af98bf2011-05-10 17:38:08 -070063 void Start();
64 void Stop();
Darin Petkov887f2982011-07-14 16:10:17 -070065
Ben Chan5086b972013-01-15 21:51:38 -080066 std::vector<std::string> GetUninitializedTechnologies() const;
67
Darin Petkov6f9eaa32011-08-09 15:26:44 -070068 // Adds |device| to this DeviceInfo instance so that we can handle its link
69 // messages, and registers it with the manager.
David Rochbergfa1d31d2012-03-20 10:38:07 -040070 virtual void RegisterDevice(const DeviceRefPtr &device);
Darin Petkov6f9eaa32011-08-09 15:26:44 -070071
Jason Glasgowe9089492012-02-23 17:57:37 -050072 // Remove |device| from this DeviceInfo. This function should only
73 // be called for cellular devices because the lifetime of the
74 // cellular devices is controlled by the Modem object and its
75 // communication to modem manager, rather than by RTNL messages.
David Rochbergfa1d31d2012-03-20 10:38:07 -040076 virtual void DeregisterDevice(const DeviceRefPtr &device);
Jason Glasgowe9089492012-02-23 17:57:37 -050077
Paul Stewartc8f4bef2011-12-13 09:45:51 -080078 virtual DeviceRefPtr GetDevice(int interface_index) const;
Paul Stewart32852962011-08-30 14:06:53 -070079 virtual bool GetMACAddress(int interface_index, ByteString *address) const;
Gary Morainbf74a672012-07-30 16:27:19 -070080
81 // Queries the kernel for a MAC address for |interface_index|. Returns an
82 // empty ByteString on failure.
83 virtual ByteString GetMACAddressFromKernel(int interface_index) const;
Gary Morain41780232012-07-31 15:08:31 -070084
Chris Masone626719f2011-08-18 16:58:48 -070085 virtual bool GetFlags(int interface_index, unsigned int *flags) const;
Paul Stewart1ac4e842012-07-10 12:58:12 -070086 virtual bool GetByteCounts(int interface_index,
87 uint64 *rx_bytes, uint64 *tx_bytes) const;
Paul Stewart9a908082011-08-31 12:18:48 -070088 virtual bool GetAddresses(int interface_index,
89 std::vector<AddressData> *addresses) const;
Paul Stewart05a42c22012-08-02 16:47:21 -070090 // Flush all addresses associated with |interface_index|.
Paul Stewart9a908082011-08-31 12:18:48 -070091 virtual void FlushAddresses(int interface_index) const;
Paul Stewart05a42c22012-08-02 16:47:21 -070092 // Returns whether this interface does not have |this_address|
93 // but has another non-temporary address of the same family.
94 virtual bool HasOtherAddress(
95 int interface_index, const IPAddress &this_address) const;
Paul Stewartca6abd42012-03-01 15:45:29 -080096 virtual bool CreateTunnelInterface(std::string *interface_name) const;
97 virtual bool DeleteInterface(int interface_index) const;
Paul Stewart0af98bf2011-05-10 17:38:08 -070098
Darin Petkovf8046b82012-04-24 16:29:23 +020099 // Returns the interface index for |interface_name| or -1 if unknown.
100 virtual int GetIndex(const std::string &interface_name) const;
101
Paul Stewart0af98bf2011-05-10 17:38:08 -0700102 private:
Paul Stewart050cfc02012-07-06 20:38:54 -0700103 friend class DeviceInfoDelayedCreationTest;
Paul Stewartca876ee2012-04-21 08:55:58 -0700104 friend class DeviceInfoTechnologyTest;
Darin Petkov887f2982011-07-14 16:10:17 -0700105 friend class DeviceInfoTest;
Darin Petkov0828f5f2011-08-11 10:18:52 -0700106 FRIEND_TEST(CellularTest, StartLinked);
Ben Chan4b285862012-10-10 22:52:16 -0700107 FRIEND_TEST(DeviceInfoTest, CreateDeviceWiMax);
Ben Chan5086b972013-01-15 21:51:38 -0800108 FRIEND_TEST(DeviceInfoTest, GetUninitializedTechnologies);
Thieu Leb27beee2012-04-20 09:19:06 -0700109 FRIEND_TEST(DeviceInfoTest, HasSubdir); // For HasSubdir.
Paul Stewart1ac4e842012-07-10 12:58:12 -0700110 FRIEND_TEST(DeviceInfoTest, RequestLinkStatistics);
Paul Stewart8c116a92012-05-02 18:30:03 -0700111 FRIEND_TEST(DeviceInfoTest, StartStop);
Darin Petkov887f2982011-07-14 16:10:17 -0700112
Darin Petkove6193c02011-08-11 12:42:40 -0700113 struct Info {
Ben Chan5086b972013-01-15 21:51:38 -0800114 Info()
115 : flags(0),
116 rx_bytes(0),
117 tx_bytes(0),
118 has_addresses_only(false),
119 technology(Technology::kUnknown)
120 {}
Darin Petkove6193c02011-08-11 12:42:40 -0700121
122 DeviceRefPtr device;
Darin Petkovf8046b82012-04-24 16:29:23 +0200123 std::string name;
Paul Stewart32852962011-08-30 14:06:53 -0700124 ByteString mac_address;
Paul Stewart9a908082011-08-31 12:18:48 -0700125 std::vector<AddressData> ip_addresses;
Darin Petkove6193c02011-08-11 12:42:40 -0700126 unsigned int flags;
Paul Stewart1ac4e842012-07-10 12:58:12 -0700127 uint64 rx_bytes;
128 uint64 tx_bytes;
129
Paul Stewart8c116a92012-05-02 18:30:03 -0700130 // This flag indicates that link information has not been retrieved yet;
131 // only the ip_addresses field is valid.
132 bool has_addresses_only;
Ben Chan5086b972013-01-15 21:51:38 -0800133
134 Technology::Identifier technology;
Darin Petkove6193c02011-08-11 12:42:40 -0700135 };
136
Paul Stewartca876ee2012-04-21 08:55:58 -0700137 // Root of the kernel sysfs directory holding network device info.
138 static const char kDeviceInfoRoot[];
Ben Chan4e64d2d2012-05-16 00:02:25 -0700139 // Name of the "cdc_ether" driver. This driver is not included in the
140 // kModemDrivers list because we need to do additional checking.
141 static const char kDriverCdcEther[];
142 // Name of the GDM WiMAX driver.
143 static const char kDriverGdmWiMax[];
mukesh agrawal93a29ed2012-04-17 16:13:01 -0700144 // Name of the virtio network driver.
145 static const char kDriverVirtioNet[];
Thieu Le8f1c8352012-04-16 11:02:12 -0700146 // Sysfs path to a device uevent file.
Paul Stewartbf1861b2011-08-23 15:45:35 -0700147 static const char kInterfaceUevent[];
Thieu Le8f1c8352012-04-16 11:02:12 -0700148 // Content of a device uevent file that indicates it is a wifi device.
Paul Stewart9364c4c2011-12-06 17:12:42 -0800149 static const char kInterfaceUeventWifiSignature[];
Thieu Le8f1c8352012-04-16 11:02:12 -0700150 // Sysfs path to a device via its interface name.
151 static const char kInterfaceDevice[];
152 // Sysfs path to the driver of a device via its interface name.
Paul Stewartbf1861b2011-08-23 15:45:35 -0700153 static const char kInterfaceDriver[];
Thieu Le8f1c8352012-04-16 11:02:12 -0700154 // Sysfs path to the file that is used to determine if this is tun device.
Paul Stewartcba0f7f2012-02-29 16:33:05 -0800155 static const char kInterfaceTunFlags[];
Thieu Le8f1c8352012-04-16 11:02:12 -0700156 // Sysfs path to the file that is used to determine if a wifi device is
157 // operating in monitor mode.
Paul Stewart2001a422011-12-15 10:20:09 -0800158 static const char kInterfaceType[];
Thieu Le8f1c8352012-04-16 11:02:12 -0700159 // Modem drivers that we support.
Paul Stewartb50f0b92011-05-16 16:31:42 -0700160 static const char *kModemDrivers[];
Thieu Le8f1c8352012-04-16 11:02:12 -0700161 // Path to the tun device.
Paul Stewartcba0f7f2012-02-29 16:33:05 -0800162 static const char kTunDeviceName[];
Paul Stewart050cfc02012-07-06 20:38:54 -0700163 // Time to wait before registering devices which need extra time to detect.
164 static const int kDelayedDeviceCreationSeconds;
Paul Stewart1ac4e842012-07-10 12:58:12 -0700165 // Time interval for polling for link statistics.
166 static const int kRequestLinkStatisticsIntervalSeconds;
Paul Stewartb50f0b92011-05-16 16:31:42 -0700167
Paul Stewart8c116a92012-05-02 18:30:03 -0700168 // Create a Device object for the interface named |linkname|, with a
169 // string-form MAC address |address|, whose kernel interface index
170 // is |interface_index| and detected technology is |technology|.
Paul Stewart050cfc02012-07-06 20:38:54 -0700171 virtual DeviceRefPtr CreateDevice(const std::string &link_name,
172 const std::string &address,
173 int interface_index,
174 Technology::Identifier technology);
Paul Stewart8c116a92012-05-02 18:30:03 -0700175
Paul Stewartca876ee2012-04-21 08:55:58 -0700176 // Return the FilePath for a given |path_name| in the device sysinfo for
177 // a specific interface |iface_name|.
178 FilePath GetDeviceInfoPath(const std::string &iface_name,
179 const std::string &path_name);
180 // Return the contents of the device info file |path_name| for interface
181 // |iface_name| in output parameter |contents_out|. Returns true if file
182 // read succeeded, false otherwise.
183 bool GetDeviceInfoContents(const std::string &iface_name,
184 const std::string &path_name,
185 std::string *contents_out);
186
187 // Return the filepath for the target of the device info symbolic link
188 // |path_name| for interface |iface_name| in output parameter |path_out|.
189 // Returns true if symbolic link read succeeded, false otherwise.
190 bool GetDeviceInfoSymbolicLink(const std::string &iface_name,
191 const std::string &path_name,
192 FilePath *path_out);
193 // Classify the device named |iface_name|, and return an identifier
194 // indicating its type.
Paul Stewart050cfc02012-07-06 20:38:54 -0700195 virtual Technology::Identifier GetDeviceTechnology(
196 const std::string &iface_name);
Thieu Le8f1c8352012-04-16 11:02:12 -0700197 // Checks the device specified by |iface_name| to see if it's a modem device.
198 // This method assumes that |iface_name| has already been determined to be
199 // using the cdc_ether driver.
Paul Stewartca876ee2012-04-21 08:55:58 -0700200 bool IsCdcEtherModemDevice(const std::string &iface_name);
Thieu Leb27beee2012-04-20 09:19:06 -0700201 // Returns true if |base_dir| has a subdirectory named |subdir|.
202 // |subdir| can be an immediate subdirectory of |base_dir| or can be
203 // several levels deep.
204 static bool HasSubdir(const FilePath &base_dir, const FilePath &subdir);
Darin Petkov6f9eaa32011-08-09 15:26:44 -0700205
Chris Masone2aa97072011-08-09 17:35:08 -0700206 void AddLinkMsgHandler(const RTNLMessage &msg);
207 void DelLinkMsgHandler(const RTNLMessage &msg);
208 void LinkMsgHandler(const RTNLMessage &msg);
Paul Stewart9a908082011-08-31 12:18:48 -0700209 void AddressMsgHandler(const RTNLMessage &msg);
Paul Stewart0af98bf2011-05-10 17:38:08 -0700210
Darin Petkove3e1cfa2011-08-11 13:41:17 -0700211 const Info *GetInfo(int interface_index) const;
Darin Petkove6193c02011-08-11 12:42:40 -0700212 void RemoveInfo(int interface_index);
Paul Stewart050cfc02012-07-06 20:38:54 -0700213 void DelayDeviceCreation(int interface_index);
214 void DelayedDeviceCreationTask();
Paul Stewart1ac4e842012-07-10 12:58:12 -0700215 void RetrieveLinkStatistics(int interface_index, const RTNLMessage &msg);
216 void RequestLinkStatistics();
Darin Petkov67d8ecf2011-07-26 16:03:30 -0700217
Gary Morain41780232012-07-31 15:08:31 -0700218 void set_sockets(Sockets* sockets) { sockets_.reset(sockets); }
219
Paul Stewartb50f0b92011-05-16 16:31:42 -0700220 ControlInterface *control_interface_;
Paul Stewart0af98bf2011-05-10 17:38:08 -0700221 EventDispatcher *dispatcher_;
Thieu Le3426c8f2012-01-11 17:35:11 -0800222 Metrics *metrics_;
Paul Stewartb50f0b92011-05-16 16:31:42 -0700223 Manager *manager_;
Darin Petkovf8046b82012-04-24 16:29:23 +0200224
225 std::map<int, Info> infos_; // Maps interface index to Info.
226 std::map<std::string, int> indices_; // Maps interface name to index.
227
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500228 base::Callback<void(const RTNLMessage &)> link_callback_;
229 base::Callback<void(const RTNLMessage &)> address_callback_;
Paul Stewarta3c56f92011-05-26 07:08:52 -0700230 scoped_ptr<RTNLListener> link_listener_;
Paul Stewart9a908082011-08-31 12:18:48 -0700231 scoped_ptr<RTNLListener> address_listener_;
mukesh agrawal8f317b62011-07-15 11:53:23 -0700232 std::set<std::string> black_list_;
Paul Stewartca876ee2012-04-21 08:55:58 -0700233 FilePath device_info_root_;
Darin Petkove6193c02011-08-11 12:42:40 -0700234
Paul Stewart1ac4e842012-07-10 12:58:12 -0700235 // Keep track of devices that require a delayed call to CreateDevice().
Paul Stewart050cfc02012-07-06 20:38:54 -0700236 base::CancelableClosure delayed_devices_callback_;
237 std::set<int> delayed_devices_;
238
Paul Stewart1ac4e842012-07-10 12:58:12 -0700239 // Maintain a callback for the periodic link statistics poll task.
240 base::CancelableClosure request_link_statistics_callback_;
241
Paul Stewart8c116a92012-05-02 18:30:03 -0700242 // Cache copy of singleton pointers.
243 RoutingTable *routing_table_;
Paul Stewart9a908082011-08-31 12:18:48 -0700244 RTNLHandler *rtnl_handler_;
245
Gary Morain41780232012-07-31 15:08:31 -0700246 // A member of the class so that a mock can be injected for testing.
247 scoped_ptr<Sockets> sockets_;
248
Darin Petkove6193c02011-08-11 12:42:40 -0700249 DISALLOW_COPY_AND_ASSIGN(DeviceInfo);
Paul Stewart0af98bf2011-05-10 17:38:08 -0700250};
251
Paul Stewart0af98bf2011-05-10 17:38:08 -0700252} // namespace shill
253
254#endif // SHILL_DEVICE_INFO_