wificond: support multiple scan interfaces

Add a map for keeping unique wiphy index per interface.
This is needed in order to support multiple interfaces
from different chips, since each chip will have a
different wiphy index.

Bug: 147522434
Test: system/connectivity/wificond/runtests.sh
Change-Id: I2bdea0547aa145e52507c788a46390514f582d25
This commit is contained in:
Jimmy Chen 2019-07-23 17:49:07 +03:00
parent 2debe26d24
commit 30a31286aa
5 changed files with 191 additions and 74 deletions

View File

@ -589,7 +589,7 @@ void NetlinkManager::OnRegChangeEvent(unique_ptr<const NL80211Packet> packet) {
}
for (const auto& handler : on_reg_domain_changed_handler_) {
handler.second(country_code);
handler.second(handler.first, country_code);
}
}

View File

@ -85,7 +85,7 @@ typedef std::function<void(
// domain or a intersection regulatory domain.
// See details in defination of |nl80211_reg_type| from nl80211.h.
typedef std::function<void(
std::string& country_code)> OnRegDomainChangedHandler;
uint32_t wiphy_index, std::string& country_code)> OnRegDomainChangedHandler;
// Enum used for identifying channel bandwidth.
// This is used by function |OnChannelSwitchEventHandler|.

View File

@ -41,6 +41,7 @@ using android::wifi_system::InterfaceTool;
using std::endl;
using std::optional;
using std::placeholders::_1;
using std::placeholders::_2;
using std::string;
using std::stringstream;
using std::unique_ptr;
@ -93,10 +94,14 @@ Status Server::UnregisterCallback(const sp<IInterfaceEventCallback>& callback) {
Status Server::createApInterface(const std::string& iface_name,
sp<IApInterface>* created_interface) {
InterfaceInfo interface;
if (!SetupInterface(iface_name, &interface)) {
uint32_t wiphy_index;
if (!SetupInterface(iface_name, &interface, &wiphy_index)) {
return Status::ok(); // Logging was done internally
}
LOG(INFO) << "createApInterface: wiphy_index " << wiphy_index << " iface_name " << iface_name;
unique_ptr<ApInterfaceImpl> ap_interface(new ApInterfaceImpl(
interface.name,
interface.index,
@ -105,6 +110,7 @@ Status Server::createApInterface(const std::string& iface_name,
*created_interface = ap_interface->GetBinder();
BroadcastApInterfaceReady(ap_interface->GetBinder());
ap_interfaces_[iface_name] = std::move(ap_interface);
iface_to_wiphy_index_map_[iface_name] = wiphy_index;
return Status::ok();
}
@ -118,18 +124,29 @@ Status Server::tearDownApInterface(const std::string& iface_name,
ap_interfaces_.erase(iter);
*out_success = true;
}
const auto iter_wi = iface_to_wiphy_index_map_.find(iface_name);
if (iter_wi != iface_to_wiphy_index_map_.end()) {
LOG(DEBUG) << "tearDownApInterface: erasing wiphy_index for iface_name " << iface_name;
iface_to_wiphy_index_map_.erase(iter_wi);
}
return Status::ok();
}
Status Server::createClientInterface(const std::string& iface_name,
sp<IClientInterface>* created_interface) {
InterfaceInfo interface;
if (!SetupInterface(iface_name, &interface)) {
uint32_t wiphy_index;
if (!SetupInterface(iface_name, &interface, &wiphy_index)) {
return Status::ok(); // Logging was done internally
}
LOG(INFO) << "createClientInterface: wiphy_index " << wiphy_index << " iface_name " << iface_name;
unique_ptr<ClientInterfaceImpl> client_interface(new ClientInterfaceImpl(
wiphy_index_,
wiphy_index,
interface.name,
interface.index,
interface.mac_address,
@ -139,6 +156,8 @@ Status Server::createClientInterface(const std::string& iface_name,
*created_interface = client_interface->GetBinder();
BroadcastClientInterfaceReady(client_interface->GetBinder());
client_interfaces_[iface_name] = std::move(client_interface);
iface_to_wiphy_index_map_[iface_name] = wiphy_index;
UpdateBandWiphyIndexMap(wiphy_index);
return Status::ok();
}
@ -152,6 +171,14 @@ Status Server::tearDownClientInterface(const std::string& iface_name,
client_interfaces_.erase(iter);
*out_success = true;
}
const auto iter_wi = iface_to_wiphy_index_map_.find(iface_name);
if (iter_wi != iface_to_wiphy_index_map_.end()) {
LOG(DEBUG) << "tearDownClientInterface: erasing wiphy_index for iface_name " << iface_name;
EraseBandWiphyIndexMap(iter_wi->second);
iface_to_wiphy_index_map_.erase(iter_wi);
}
return Status::ok();
}
@ -168,7 +195,11 @@ Status Server::tearDownInterfaces() {
MarkDownAllInterfaces();
netlink_utils_->UnsubscribeRegDomainChange(wiphy_index_);
for (auto& it : iface_to_wiphy_index_map_) {
netlink_utils_->UnsubscribeRegDomainChange(it.second);
EraseBandWiphyIndexMap(it.second);
}
iface_to_wiphy_index_map_.clear();
return Status::ok();
}
@ -198,11 +229,11 @@ status_t Server::dump(int fd, const Vector<String16>& /*args*/) {
}
stringstream ss;
ss << "Current wiphy index: " << wiphy_index_ << endl;
ss << "Cached interfaces list from kernel message: " << endl;
for (const auto& iface : interfaces_) {
ss << "Interface index: " << iface.index
<< ", name: " << iface.name
<< ", wiphy index: " << iface_to_wiphy_index_map_[iface.name]
<< ", mac address: "
<< LoggingUtils::GetMacString(iface.mac_address) << endl;
}
@ -222,6 +253,11 @@ status_t Server::dump(int fd, const Vector<String16>& /*args*/) {
iface.second->Dump(&ss);
}
ss << "Channel Type / Wiphy Index Mapping:" << endl;
for (const auto& it : band_to_wiphy_index_map_) {
ss << "Channel type " << it.first << ": " << it.second << endl;
}
if (!WriteStringToFd(ss.str(), fd)) {
PLOG(ERROR) << "Failed to dump state to fd " << fd;
return FAILED_TRANSACTION;
@ -231,93 +267,88 @@ status_t Server::dump(int fd, const Vector<String16>& /*args*/) {
}
void Server::MarkDownAllInterfaces() {
uint32_t wiphy_index;
vector<InterfaceInfo> interfaces;
if (netlink_utils_->GetWiphyIndex(&wiphy_index) &&
netlink_utils_->GetInterfaces(wiphy_index, &interfaces)) {
for (InterfaceInfo& interface : interfaces) {
if_tool_->SetUpState(interface.name.c_str(), false);
}
std::string iface_name;
for (auto& it : iface_to_wiphy_index_map_) {
iface_name = it.first;
if_tool_->SetUpState(iface_name.c_str(), false);
}
}
Status Server::getAvailable2gChannels(
std::optional<vector<int32_t>>* out_frequencies) {
BandInfo band_info;
ScanCapabilities scan_capabilities_ignored;
WiphyFeatures wiphy_features_ignored;
if (!netlink_utils_->GetWiphyInfo(wiphy_index_, &band_info,
&scan_capabilities_ignored,
&wiphy_features_ignored)) {
LOG(ERROR) << "Failed to get wiphy info from kernel";
int wiphy_index = GetWiphyIndexFromBand(NL80211_BAND_2GHZ);
BandInfo band_info;
if (!GetBandInfo(wiphy_index, &band_info)) {
out_frequencies->reset();
return Status::ok();
}
out_frequencies->emplace(band_info.band_2g.begin(), band_info.band_2g.end());
if (band_info.band_2g.size() == 0)
out_frequencies->reset();
else
out_frequencies->emplace(band_info.band_2g.begin(), band_info.band_2g.end());
return Status::ok();
}
Status Server::getAvailable5gNonDFSChannels(
std::optional<vector<int32_t>>* out_frequencies) {
int wiphy_index = GetWiphyIndexFromBand(NL80211_BAND_5GHZ);
BandInfo band_info;
ScanCapabilities scan_capabilities_ignored;
WiphyFeatures wiphy_features_ignored;
if (!netlink_utils_->GetWiphyInfo(wiphy_index_, &band_info,
&scan_capabilities_ignored,
&wiphy_features_ignored)) {
LOG(ERROR) << "Failed to get wiphy info from kernel";
if (!GetBandInfo(wiphy_index, &band_info)) {
out_frequencies->reset();
return Status::ok();
}
out_frequencies->emplace(band_info.band_5g.begin(), band_info.band_5g.end());
if (band_info.band_5g.size() == 0)
out_frequencies->reset();
else
out_frequencies->emplace(band_info.band_5g.begin(), band_info.band_5g.end());
return Status::ok();
}
Status Server::getAvailableDFSChannels(
std::optional<vector<int32_t>>* out_frequencies) {
int wiphy_index = GetWiphyIndexFromBand(NL80211_BAND_5GHZ);
BandInfo band_info;
ScanCapabilities scan_capabilities_ignored;
WiphyFeatures wiphy_features_ignored;
if (!netlink_utils_->GetWiphyInfo(wiphy_index_, &band_info,
&scan_capabilities_ignored,
&wiphy_features_ignored)) {
LOG(ERROR) << "Failed to get wiphy info from kernel";
if (!GetBandInfo(wiphy_index, &band_info)) {
out_frequencies->reset();
return Status::ok();
}
out_frequencies->emplace(band_info.band_dfs.begin(),
if (band_info.band_dfs.size() == 0)
out_frequencies->reset();
else
out_frequencies->emplace(band_info.band_dfs.begin(),
band_info.band_dfs.end());
return Status::ok();
}
Status Server::getAvailable6gChannels(
std::optional<vector<int32_t>>* out_frequencies) {
int wiphy_index = GetWiphyIndexFromBand(NL80211_BAND_6GHZ);
BandInfo band_info;
ScanCapabilities scan_capabilities_ignored;
WiphyFeatures wiphy_features_ignored;
if (!netlink_utils_->GetWiphyInfo(wiphy_index_, &band_info,
&scan_capabilities_ignored,
&wiphy_features_ignored)) {
LOG(ERROR) << "Failed to get wiphy info from kernel";
if (!GetBandInfo(wiphy_index, &band_info)) {
out_frequencies->reset();
return Status::ok();
}
out_frequencies->emplace(band_info.band_6g.begin(), band_info.band_6g.end());
if (band_info.band_6g.size() == 0)
out_frequencies->reset();
else
out_frequencies->emplace(band_info.band_6g.begin(), band_info.band_6g.end());
return Status::ok();
}
Status Server::getDeviceWiphyCapabilities(
const std::string& iface_name,
std::optional<DeviceWiphyCapabilities>* capabilities) {
if (!RefreshWiphyIndex(iface_name)) {
int wiphy_index = FindWiphyIndex(iface_name);
if (wiphy_index == -1) {
LOG(ERROR) << "Failed to find iface_name " << iface_name;
capabilities = nullptr;
return Status::ok();
}
@ -326,7 +357,7 @@ Status Server::getDeviceWiphyCapabilities(
ScanCapabilities scan_capabilities_ignored;
WiphyFeatures wiphy_features_ignored;
if (!netlink_utils_->GetWiphyInfo(wiphy_index_, &band_info,
if (!netlink_utils_->GetWiphyInfo(wiphy_index, &band_info,
&scan_capabilities_ignored,
&wiphy_features_ignored)) {
LOG(ERROR) << "Failed to get wiphy info from kernel";
@ -348,20 +379,23 @@ Status Server::getDeviceWiphyCapabilities(
}
bool Server::SetupInterface(const std::string& iface_name,
InterfaceInfo* interface) {
if (!RefreshWiphyIndex(iface_name)) {
InterfaceInfo* interface,
uint32_t *wiphy_index) {
if (!netlink_utils_->GetWiphyIndex(wiphy_index, iface_name)) {
LOG(ERROR) << "Failed to get wiphy index";
return false;
}
netlink_utils_->SubscribeRegDomainChange(
wiphy_index_,
std::bind(&Server::OnRegDomainChanged,
this,
_1));
*wiphy_index,
std::bind(&Server::OnRegDomainChanged,
this,
_1,
_2));
interfaces_.clear();
if (!netlink_utils_->GetInterfaces(wiphy_index_, &interfaces_)) {
LOG(ERROR) << "Failed to get interfaces info from kernel";
if (!netlink_utils_->GetInterfaces(*wiphy_index, &interfaces_)) {
LOG(ERROR) << "Failed to get interfaces info from kernel for iface_name " << iface_name << " wiphy_index " << *wiphy_index;
return false;
}
@ -376,28 +410,20 @@ bool Server::SetupInterface(const std::string& iface_name,
return false;
}
bool Server::RefreshWiphyIndex(const std::string& iface_name) {
if (!netlink_utils_->GetWiphyIndex(&wiphy_index_, iface_name)) {
LOG(ERROR) << "Failed to get wiphy index";
return false;
}
return true;
}
void Server::OnRegDomainChanged(std::string& country_code) {
void Server::OnRegDomainChanged(uint32_t wiphy_index, std::string& country_code) {
if (country_code.empty()) {
LOG(INFO) << "Regulatory domain changed";
} else {
LOG(INFO) << "Regulatory domain changed to country: " << country_code;
}
LogSupportedBands();
LogSupportedBands(wiphy_index);
}
void Server::LogSupportedBands() {
void Server::LogSupportedBands(uint32_t wiphy_index) {
BandInfo band_info;
ScanCapabilities scan_capabilities;
WiphyFeatures wiphy_features;
netlink_utils_->GetWiphyInfo(wiphy_index_,
netlink_utils_->GetWiphyInfo(wiphy_index,
&band_info,
&scan_capabilities,
&wiphy_features);
@ -419,11 +445,13 @@ void Server::LogSupportedBands() {
ss << " " << band_info.band_dfs[i];
}
LOG(INFO) << "5Ghz DFS frequencies:"<< ss.str();
ss.str("");
for (unsigned int i = 0; i < band_info.band_6g.size(); i++) {
ss << " " << band_info.band_6g[i];
}
LOG(INFO) << "6Ghz frequencies:"<< ss.str();
ss.str("");
}
void Server::BroadcastClientInterfaceReady(
@ -454,5 +482,88 @@ void Server::BroadcastApInterfaceTornDown(
}
}
int Server::FindWiphyIndex(
const std::string& iface_name) {
int wiphy_index = -1;
for (auto& it : iface_to_wiphy_index_map_) {
if (it.first == iface_name) {
wiphy_index = it.second;
break;
}
}
return wiphy_index;
}
bool Server::GetBandInfo(
int wiphy_index,
BandInfo* band_info) {
if (wiphy_index == -1) return false;
ScanCapabilities scan_capabilities_ignored;
WiphyFeatures wiphy_features_ignored;
if (!netlink_utils_->GetWiphyInfo(wiphy_index, band_info,
&scan_capabilities_ignored,
&wiphy_features_ignored)) {
LOG(ERROR) << "Failed to get wiphy index " << wiphy_index << " info from kernel";
return false;
}
return true;
}
int Server::GetWiphyIndexFromBand(int band) {
auto iter = band_to_wiphy_index_map_.find(band);
return (iter != band_to_wiphy_index_map_.end()) ? iter->second : -1;
}
void Server::UpdateBandWiphyIndexMap(int wiphy_index) {
BandInfo band_info;
GetBandInfo(wiphy_index, &band_info);
if (!GetBandInfo(wiphy_index, &band_info)) return;
if (band_info.band_2g.size() != 0
&& band_to_wiphy_index_map_.find(NL80211_BAND_2GHZ) == band_to_wiphy_index_map_.end()) {
band_to_wiphy_index_map_[NL80211_BAND_2GHZ] = wiphy_index;
LOG(INFO) << "add channel type " << NL80211_BAND_2GHZ
<< " support at wiphy index: " << wiphy_index;
}
if (band_info.band_5g.size() != 0
&& band_to_wiphy_index_map_.find(NL80211_BAND_5GHZ) == band_to_wiphy_index_map_.end()) {
band_to_wiphy_index_map_[NL80211_BAND_5GHZ] = wiphy_index;
LOG(INFO) << "add channel type " << NL80211_BAND_5GHZ
<< " support at wiphy index: " << wiphy_index;
}
if (band_info.band_dfs.size() != 0
&& band_to_wiphy_index_map_.find(NL80211_BAND_5GHZ) == band_to_wiphy_index_map_.end()) {
band_to_wiphy_index_map_[NL80211_BAND_5GHZ] = wiphy_index;
LOG(INFO) << "add channel type " << NL80211_BAND_5GHZ
<< " support at wiphy index: " << wiphy_index;
}
if (band_info.band_6g.size() != 0
&& band_to_wiphy_index_map_.find(NL80211_BAND_6GHZ) == band_to_wiphy_index_map_.end()) {
band_to_wiphy_index_map_[NL80211_BAND_6GHZ] = wiphy_index;
LOG(INFO) << "add channel type " << NL80211_BAND_6GHZ
<< " support at wiphy index: " << wiphy_index;
}
}
void Server::EraseBandWiphyIndexMap(int wiphy_index) {
for (auto it_end = band_to_wiphy_index_map_.end(),
it_next = band_to_wiphy_index_map_.begin(),
it = (it_next == it_end) ? it_next : it_next++;
it != it_next;
it = (it_next == it_end) ? it_next : it_next++) {
if (it->second == wiphy_index) {
band_to_wiphy_index_map_.erase(it);
LOG(INFO) << "remove channel type " << it->first
<< " support at wiphy index " << it->second;
}
}
}
} // namespace wificond
} // namespace android

View File

@ -104,10 +104,10 @@ class Server : public android::net::wifi::nl80211::BnWificond {
// interface on behalf of createApInterace(), it is Hostapd that configure
// the interface to Ap mode later.
// Returns true on success, false otherwise.
bool SetupInterface(const std::string& iface_name, InterfaceInfo* interface);
bool RefreshWiphyIndex(const std::string& iface_num);
void LogSupportedBands();
void OnRegDomainChanged(std::string& country_code);
bool SetupInterface(const std::string& iface_name, InterfaceInfo* interface,
uint32_t *wiphy_index);
void LogSupportedBands(uint32_t wiphy_index);
void OnRegDomainChanged(uint32_t wiphy_index, std::string& country_code);
void BroadcastClientInterfaceReady(
android::sp<android::net::wifi::nl80211::IClientInterface> network_interface);
void BroadcastApInterfaceReady(
@ -117,12 +117,19 @@ class Server : public android::net::wifi::nl80211::BnWificond {
void BroadcastApInterfaceTornDown(
android::sp<android::net::wifi::nl80211::IApInterface> network_interface);
void MarkDownAllInterfaces();
int FindWiphyIndex(const std::string& iface_name);
bool GetBandInfo(int wiphy_index, BandInfo* band_info);
int GetWiphyIndexFromBand(int band);
void UpdateBandWiphyIndexMap(int wiphy_index);
void EraseBandWiphyIndexMap(int wiphy_index);
const std::unique_ptr<wifi_system::InterfaceTool> if_tool_;
NetlinkUtils* const netlink_utils_;
ScanUtils* const scan_utils_;
uint32_t wiphy_index_;
// Chips serves mutually exclusive bands.
std::map<uint32_t, uint32_t> band_to_wiphy_index_map_;
std::map<std::string, uint32_t> iface_to_wiphy_index_map_;
std::map<std::string, std::unique_ptr<ApInterfaceImpl>> ap_interfaces_;
std::map<std::string, std::unique_ptr<ClientInterfaceImpl>> client_interfaces_;
std::vector<android::sp<android::net::wifi::nl80211::IInterfaceEventCallback>>

View File

@ -229,7 +229,6 @@ TEST_F(ServerTest, CanDestroyApAndClientInterfaces) {
// When we tear down the interfaces, we expect the iface to be unloaded.
EXPECT_CALL(*if_tool_, SetUpState(StrEq(kFakeInterfaceName), Eq(false))).Times(2);
EXPECT_CALL(*if_tool_, SetUpState(StrEq(kFakeInterfaceName1), Eq(false))).Times(2);
EXPECT_CALL(*if_tool_, SetUpState(StrEq(kFakeInterfaceNameP2p), Eq(false)));
EXPECT_TRUE(server_.tearDownInterfaces().isOk());
}