shill: Makes WiFi device get available wifi frequencies from kernel.
Plus a couple of whitespace fixes. This CL is in preparation for
passing the list of wifi frequencies to a scan request.
BUG=chromium:222088
TEST=unittest and manual tests. The manual tests consist of:
- Start shill with log=-10/wifi. On the target, in a shell window,
do the following:
o stop shill
o shill --log-level=-10 --log-scopes=wifi
- Wait five seconds (the code will do everything it needs to at
startup).
- Look in /var/log/net.log and verify the following:
o Found frequency[xx] = yyyy
o There should be several frequencies (at least in the open at Google).
o 'xx' is a number, I'd expect it to start at 0.
o 'yyyy' is a number in the 5000s or the 2000x.
Change-Id: I8f0526abc22a7e9e60fd964c96d05eb95fa10e78
Reviewed-on: https://gerrit.chromium.org/gerrit/49271
Reviewed-by: Wade Guthrie <wdg@chromium.org>
Tested-by: Wade Guthrie <wdg@chromium.org>
Commit-Queue: Wade Guthrie <wdg@chromium.org>
diff --git a/netlink_manager.cc b/netlink_manager.cc
index faa11ce..cef93e3 100644
--- a/netlink_manager.cc
+++ b/netlink_manager.cc
@@ -18,8 +18,8 @@
#include "shill/generic_netlink_message.h"
#include "shill/io_handler.h"
#include "shill/logging.h"
-#include "shill/netlink_socket.h"
#include "shill/netlink_message.h"
+#include "shill/netlink_socket.h"
#include "shill/scope_logger.h"
#include "shill/shill_time.h"
@@ -313,7 +313,7 @@
}
bool NetlinkManager::SendMessage(NetlinkMessage *message,
- const NetlinkMessageHandler &handler) {
+ const NetlinkMessageHandler &handler) {
if (!message) {
LOG(ERROR) << "Message is NULL.";
return false;
diff --git a/netlink_manager_unittest.cc b/netlink_manager_unittest.cc
index f4fb78e..4f9b994 100644
--- a/netlink_manager_unittest.cc
+++ b/netlink_manager_unittest.cc
@@ -8,7 +8,6 @@
// messages.
// This file tests the public interface to NetlinkManager.
-
#include "shill/netlink_manager.h"
#include <gmock/gmock.h>
@@ -189,8 +188,8 @@
netlink_manager_->OnNlMessageReceived(received_message);
// Send the message and give our handler. Verify that we get called back.
- EXPECT_TRUE(netlink_manager_->SendMessage(&sent_message_1,
- handler_sent_1.on_netlink_message()));
+ EXPECT_TRUE(netlink_manager_->SendMessage(
+ &sent_message_1, handler_sent_1.on_netlink_message()));
// Make it appear that this message is in response to our sent message.
received_message->nlmsg_seq = socket_.GetLastSequenceNumber();
EXPECT_CALL(handler_sent_1, OnNetlinkMessage(_)).Times(1);
@@ -203,8 +202,8 @@
// Install and then uninstall message-specific handler; verify broadcast
// handler is called on message receipt.
- EXPECT_TRUE(netlink_manager_->SendMessage(&sent_message_1,
- handler_sent_1.on_netlink_message()));
+ EXPECT_TRUE(netlink_manager_->SendMessage(
+ &sent_message_1, handler_sent_1.on_netlink_message()));
received_message->nlmsg_seq = socket_.GetLastSequenceNumber();
EXPECT_TRUE(netlink_manager_->RemoveMessageHandler(sent_message_1));
EXPECT_CALL(handler_broadcast, OnNetlinkMessage(_)).Times(1);
@@ -212,8 +211,8 @@
// Install handler for different message; verify that broadcast handler is
// called for _this_ message.
- EXPECT_TRUE(netlink_manager_->SendMessage(&sent_message_2,
- handler_sent_2.on_netlink_message()));
+ EXPECT_TRUE(netlink_manager_->SendMessage(
+ &sent_message_2, handler_sent_2.on_netlink_message()));
EXPECT_CALL(handler_broadcast, OnNetlinkMessage(_)).Times(1);
netlink_manager_->OnNlMessageReceived(received_message);
diff --git a/nl80211_message.cc b/nl80211_message.cc
index 3fc8baa..9f53b69 100644
--- a/nl80211_message.cc
+++ b/nl80211_message.cc
@@ -24,10 +24,10 @@
#include "shill/nl80211_message.h"
-#include <limits.h>
#include <netlink/msg.h>
#include <netlink/netlink.h>
+#include <limits>
#include <map>
#include <string>
#include <vector>
@@ -425,7 +425,9 @@
// Nl80211Frame
Nl80211Frame::Nl80211Frame(const ByteString &raw_frame)
- : frame_type_(kIllegalFrameType), reason_(UINT16_MAX), status_(UINT16_MAX),
+ : frame_type_(kIllegalFrameType),
+ reason_(std::numeric_limits<uint16_t>::max()),
+ status_(std::numeric_limits<uint16_t>::max()),
frame_(raw_frame) {
const IEEE_80211::ieee80211_frame *frame =
reinterpret_cast<const IEEE_80211::ieee80211_frame *>(
@@ -563,6 +565,11 @@
const uint8_t GetWiphyMessage::kCommand = NL80211_CMD_GET_WIPHY;
const char GetWiphyMessage::kCommandString[] = "NL80211_CMD_GET_WIPHY";
+GetWiphyMessage::GetWiphyMessage() : Nl80211Message(kCommand, kCommandString) {
+ attributes()->CreateAttribute(
+ NL80211_ATTR_IFINDEX, Bind(&NetlinkAttribute::NewNl80211AttributeFromId));
+}
+
const uint8_t JoinIbssMessage::kCommand = NL80211_CMD_JOIN_IBSS;
const char JoinIbssMessage::kCommandString[] = "NL80211_CMD_JOIN_IBSS";
diff --git a/nl80211_message.h b/nl80211_message.h
index ae65319..d9526a8 100644
--- a/nl80211_message.h
+++ b/nl80211_message.h
@@ -243,7 +243,7 @@
static const uint8_t kCommand;
static const char kCommandString[];
- GetWiphyMessage() : Nl80211Message(kCommand, kCommandString) {}
+ GetWiphyMessage();
private:
DISALLOW_COPY_AND_ASSIGN(GetWiphyMessage);
diff --git a/wifi.cc b/wifi.cc
index 6b440cc..2e35ced 100644
--- a/wifi.cc
+++ b/wifi.cc
@@ -4,10 +4,10 @@
#include "shill/wifi.h"
+#include <linux/if.h> // Needs definitions from netinet/ether.h
+#include <netinet/ether.h>
#include <stdio.h>
#include <string.h>
-#include <netinet/ether.h>
-#include <linux/if.h> // Needs definitions from netinet/ether.h
#include <algorithm>
#include <map>
@@ -178,6 +178,7 @@
NetlinkManager::kEventTypeRegulatory);
netlink_manager_->SubscribeToEvents(Nl80211Message::kMessageTypeString,
NetlinkManager::kEventTypeMlme);
+ ConfigureScanFrequencies();
}
void WiFi::Stop(Error *error, const EnabledStateChangedCallback &callback) {
@@ -1580,4 +1581,96 @@
manager()->RegisterDevice(me);
}
+void WiFi::ConfigureScanFrequencies() {
+ GetWiphyMessage get_wiphy;
+ get_wiphy.attributes()->SetU32AttributeValue(NL80211_ATTR_IFINDEX,
+ interface_index());
+ netlink_manager_->SendMessage(&get_wiphy,
+ Bind(&WiFi::OnNewWiphy,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+void WiFi::OnNewWiphy(const NetlinkMessage &netlink_message) {
+ // Note that we don't fail fatally from this routine because, while it
+ // provides frequencies for a progressive scan, a failed progressive scan is
+ // followed by a full scan (which doesn't use the frequency list provided by
+ // this call).
+ if (netlink_message.message_type() == ErrorAckMessage::kMessageType) {
+ const ErrorAckMessage *error_ack_message =
+ reinterpret_cast<const ErrorAckMessage *>(&netlink_message);
+ if (error_ack_message->error()) {
+ LOG(ERROR) << __func__ << ": Message (seq: "
+ << netlink_message.sequence_number() << ") failed: "
+ << error_ack_message->ToString();
+ } else {
+ SLOG(WiFi, 6) << __func__ << ": Message (seq: "
+ << netlink_message.sequence_number() << ") ACKed";
+ }
+ return;
+ }
+
+ // We only handle a special set of messages, all of which are nl80211
+ // messages.
+ if (netlink_message.message_type() != Nl80211Message::GetMessageType()) {
+ LOG(ERROR) << "Received unexpected message type: "
+ << netlink_message.message_type();
+ return;
+ }
+
+ const Nl80211Message *nl80211_message =
+ dynamic_cast<const Nl80211Message *>(&netlink_message);
+ // Verify NL80211_CMD_NEW_WIPHY
+ if (nl80211_message->command() != NewWiphyMessage::kCommand) {
+ LOG(ERROR) << "Received unexpected command:"
+ << nl80211_message->command();
+ return;
+ }
+
+ // The attributes, for this message, are complicated.
+ // NL80211_ATTR_BANDS contains an array of bands...
+ AttributeListConstRefPtr wiphy_bands;
+ if (!nl80211_message->const_attributes()->ConstGetNestedAttributeList(
+ NL80211_ATTR_WIPHY_BANDS, &wiphy_bands)) {
+ LOG(ERROR) << "NL80211_CMD_NEW_WIPHY had no NL80211_ATTR_WIPHY_BANDS";
+ return;
+ }
+
+ AttributeIdIterator band_iter(*wiphy_bands);
+ for (; !band_iter.AtEnd(); band_iter.Advance()) {
+ AttributeListConstRefPtr wiphy_band;
+ if (!wiphy_bands->ConstGetNestedAttributeList(band_iter.GetId(),
+ &wiphy_band)) {
+ LOG(WARNING) << "WiFi band " << band_iter.GetId() << " not found";
+ continue;
+ }
+
+ // ...Each band has a FREQS attribute...
+ AttributeListConstRefPtr frequencies;
+ if (!wiphy_band->ConstGetNestedAttributeList(NL80211_BAND_ATTR_FREQS,
+ &frequencies)) {
+ LOG(ERROR) << "BAND " << band_iter.GetId()
+ << " had no 'frequencies' attribute";
+ continue;
+ }
+
+ // ...And each FREQS attribute contains an array of information about the
+ // frequency...
+ AttributeIdIterator freq_iter(*frequencies);
+ for (; !freq_iter.AtEnd(); freq_iter.Advance()) {
+ AttributeListConstRefPtr frequency;
+ if (frequencies->ConstGetNestedAttributeList(freq_iter.GetId(),
+ &frequency)) {
+ // ...Including the frequency, itself (the part we want).
+ uint32_t frequency_value = 0;
+ if (frequency->GetU32AttributeValue(NL80211_FREQUENCY_ATTR_FREQ,
+ &frequency_value)) {
+ SLOG(WiFi, 5) << "Found frequency[" << freq_iter.GetId()
+ << "] = " << frequency_value;
+ all_scan_frequencies_.insert(frequency_value);
+ }
+ }
+ }
+ }
+}
+
} // namespace shill
diff --git a/wifi.h b/wifi.h
index 8ce8828..6639828 100644
--- a/wifi.h
+++ b/wifi.h
@@ -76,6 +76,7 @@
#include <time.h>
#include <map>
+#include <set>
#include <string>
#include <vector>
@@ -100,6 +101,7 @@
class GeolocationInfo;
class KeyValueStore;
class NetlinkManager;
+class NetlinkMessage;
class ProxyFactory;
class SupplicantEAPStateHandler;
class SupplicantInterfaceProxyInterface;
@@ -221,6 +223,8 @@
static const int kPendingTimeoutSeconds;
static const int kReconnectTimeoutSeconds;
+ // Gets the list of frequencies supported by this device.
+ void ConfigureScanFrequencies();
void AppendBgscan(WiFiService *service,
std::map<std::string, DBus::Variant> *service_params) const;
std::string GetBgscanMethod(const int &argument, Error *error);
@@ -341,6 +345,11 @@
std::string GetServiceLeaseName(const WiFiService &service);
+ // Netlink message handler for NL80211_CMD_NEW_WIPHY messages; copies
+ // device's supported frequencies from that message into
+ // |all_scan_frequencies_|.
+ void OnNewWiphy(const NetlinkMessage &netlink_message);
+
// Pointer to the provider object that maintains WiFiService objects.
WiFiProvider *provider_;
@@ -402,6 +411,7 @@
uint16 scan_interval_seconds_;
NetlinkManager *netlink_manager_;
+ std::set<uint16_t> all_scan_frequencies_;
DISALLOW_COPY_AND_ASSIGN(WiFi);
};