apmanager: parse ap mode support information
Parse AP mode support information from Wiphy capability message. And do
not set preferred AP mode interface if AP mode is not supported.
BUG=chromium:431763
TEST=USE="asan clang" FEATURES=test emerge-$BOARD apmanager
Manual Test:
1. Verify AP service can be started on a device that supports AP mode.
2. Verify AP service failed to start on a device that doesn't
support AP mode with a "No device available" error message.
Change-Id: Ia77fa3d74b944b978697afcb16aa71f27412fbdb
Reviewed-on: https://chromium-review.googlesource.com/233773
Reviewed-by: Peter Qiu <zqiu@chromium.org>
Commit-Queue: Peter Qiu <zqiu@chromium.org>
Trybot-Ready: Peter Qiu <zqiu@chromium.org>
Tested-by: Peter Qiu <zqiu@chromium.org>
diff --git a/device.cc b/device.cc
index e6489e4..1fbda40 100644
--- a/device.cc
+++ b/device.cc
@@ -22,7 +22,8 @@
Device::Device(Manager* manager, const string& device_name)
: org::chromium::apmanager::DeviceAdaptor(this),
- manager_(manager) {
+ manager_(manager),
+ supports_ap_mode_(false) {
SetDeviceName(device_name);
SetInUsed(false);
}
@@ -76,8 +77,15 @@
}
void Device::ParseWiphyCapability(const shill::Nl80211Message& msg) {
- // TODO(zqiu): Parse NL80211_ATTR_SUPPORTED_IFTYPES for supported interface
- // modes.
+ // Parse NL80211_ATTR_SUPPORTED_IFTYPES for AP mode interface support.
+ shill::AttributeListConstRefPtr supported_iftypes;
+ if (!msg.const_attributes()->ConstGetNestedAttributeList(
+ NL80211_ATTR_SUPPORTED_IFTYPES, &supported_iftypes)) {
+ LOG(ERROR) << "NL80211_CMD_NEW_WIPHY had no NL80211_ATTR_SUPPORTED_IFTYPES";
+ return;
+ }
+ supported_iftypes->GetFlagAttributeValue(NL80211_IFTYPE_AP,
+ &supports_ap_mode_);
// Parse WiFi band capabilities.
shill::AttributeListConstRefPtr wiphy_bands;
@@ -339,7 +347,10 @@
}
void Device::UpdatePreferredAPInterface() {
- // TODO(zqiu): return if device doesn't support AP interface mode.
+ // Return if device doesn't support AP interface mode.
+ if (!supports_ap_mode_) {
+ return;
+ }
// Use the first registered AP mode interface if there is one, otherwise use
// the first registered managed mode interface. If none are available, then
diff --git a/device.h b/device.h
index 9b5e000..20240ab 100644
--- a/device.h
+++ b/device.h
@@ -111,6 +111,9 @@
dbus::ObjectPath dbus_path_;
std::unique_ptr<chromeos::dbus_utils::DBusObject> dbus_object_;
+ // Flag indicating if this device supports AP mode interface or not.
+ bool supports_ap_mode_;
+
// Wiphy band capabilities.
std::vector<BandCapability> band_capability_;
diff --git a/device_unittest.cc b/device_unittest.cc
index ebc38a7..997d94f 100644
--- a/device_unittest.cc
+++ b/device_unittest.cc
@@ -96,6 +96,14 @@
wiphy_bands->SetNestedAttributeHasAValue(band_id);
}
+ void EnableApModeSupport() {
+ device_->supports_ap_mode_ = true;
+ }
+
+ void VerifyApModeSupport(bool supports_ap_mode) {
+ EXPECT_EQ(supports_ap_mode, device_->supports_ap_mode_);
+ }
+
void VerifyFrequencyList(int band_id, std::vector<uint32_t> frequency_list) {
EXPECT_EQ(frequency_list, device_->band_capability_[band_id].frequencies);
}
@@ -137,6 +145,8 @@
}
TEST_F(DeviceTest, PreferredAPInterface) {
+ EnableApModeSupport();
+
// Register a monitor mode interface, no preferred AP mode interface.
device_->RegisterInterface(kMonitorModeInterface);
VerifyPreferredApInterface("");
@@ -177,8 +187,30 @@
VerifyPreferredApInterface("");
}
-TEST_F(DeviceTest, ParseHTCapability) {
+TEST_F(DeviceTest, DeviceWithoutAPModeSupport) {
+ // AP mode support is not enabled for the device, so no preferred AP
+ // mode interface.
+ device_->RegisterInterface(kApModeInterface0);
+ VerifyPreferredApInterface("");
+}
+
+TEST_F(DeviceTest, ParseWiphyCapability) {
shill::NewWiphyMessage message;
+
+ // Supported interface types attribute.
+ message.attributes()->CreateNestedAttribute(
+ NL80211_ATTR_SUPPORTED_IFTYPES, "NL80211_ATTR_SUPPORTED_IFTYPES");
+ shill::AttributeListRefPtr supported_iftypes;
+ message.attributes()->GetNestedAttributeList(
+ NL80211_ATTR_SUPPORTED_IFTYPES, &supported_iftypes);
+ // Add support for AP mode interface.
+ supported_iftypes->CreateFlagAttribute(
+ NL80211_IFTYPE_AP, "NL80211_IFTYPE_AP");
+ supported_iftypes->SetFlagAttributeValue(NL80211_IFTYPE_AP, true);
+ message.attributes()->SetNestedAttributeHasAValue(
+ NL80211_ATTR_SUPPORTED_IFTYPES);
+
+ // Wiphy bands attribute.
message.attributes()->CreateNestedAttribute(
NL80211_ATTR_WIPHY_BANDS, "NL80211_ATTR_WIPHY_BANDS");
shill::AttributeListRefPtr wiphy_bands;
@@ -219,6 +251,9 @@
device_->ParseWiphyCapability(message);
+ // Verify AP mode support.
+ VerifyApModeSupport(true);
+
// Verify frequency list for both bands.
VerifyFrequencyList(0, band_24ghz_freq_list);
VerifyFrequencyList(1, band_5ghz_freq_list);
@@ -238,6 +273,8 @@
}
TEST_F(DeviceTest, ClaimAndReleaseDevice) {
+ EnableApModeSupport();
+
// Register multiple interfaces.
device_->RegisterInterface(kApModeInterface1);
device_->RegisterInterface(kManagedModeInterface1);