STA/AP Concurrency fails with the wifi which has multiple phy

As the issue tracker: https://issuetracker.google.com/issues/122429718

    The current Android P framework doesn't support the wifi devices with
    multiple phy's.

    Suppose that the wifi has two or more wiphys.
    (e.g. wlan0 - phy#0 - ifindex 6, and wlan1 - phy#1 - ifindex 8)

    And the system is built with
        WIFI_HIDL_FEATURE_DUAL_INTERFACE := true
        PRODUCT_PROPERTY_OVERRIDES += wifi.interface=wlan0
        PRODUCT_PROPERTY_OVERRIDES += wifi.concurrent.interface=wlan1

    At first, we connected to one AP successfully, and then we tried
    to start hotspot, but the hotspot can not be enabled.

    After checking, we found that in the Android P source code,
    setupInterfaceForSoftApMode()
    => mWificond.createApInterface(ifaceName) // wificond/server.cpp
    ==> SetupInterface(iface_name, &interface)
    ===> !RefreshWiphyIndex()
    ====> netlink_utils_->GetWiphyIndex(&wiphy_index_)

    The iface_name here, assigned by upper Android framework,
    is wlan1 as expected.  Meanwhile, in the GetWiphyIndex(),
    it uses NL80211_CMD_GET_WIPHY command, with flag - NLM_F_DUMP,
    it doesn't assign NL80211_ATTR_IFINDEX, so the results have all the wiphy,
    and eventually return the last one phy#0,  instead of phy#1.

    Then in server.cpp::SetupInterface(),  wiphy_index_ is assigned to 0,
    it can not find wlan1, since wlan1's wiphy number is 1, not 0.
    Thus it fails.

    So we would like to suggest to add parameter NL80211_ATTR_IFINDEX
    in the function GetWiphyIndex(), for the command NL80211_CMD_GET_WIPHY,
    then it can find the correct wiphy number phy#1, instead of phy#0,
    when using interface wlan1.

    In the NetlinkUtils::GetWiphyIndex(), we add one more parameter,
    string iface_name. And if the string is empty, it means we use the
    original way to do GetWiphyIndex; If the string is not empty,
    it will add attribute NL80211_ATTR_IFINDEX for NL80211_CMD_GET_WIPHY.

Test: built, tested manually with the wifi which has two phy
Change-Id: I9319633d0ef220b9ba4a226ee5446bef08e4ac78
Signed-off-by: Neo Jou <neojou@gmail.com>
This commit is contained in:
Neo Jou 2019-01-16 14:44:04 +08:00
parent 69da09ec61
commit 3e76438803
4 changed files with 17 additions and 5 deletions

View File

@ -21,6 +21,7 @@
#include <string>
#include <vector>
#include <net/if.h>
#include <linux/netlink.h>
#include <android-base/logging.h>
@ -98,13 +99,18 @@ NetlinkUtils::NetlinkUtils(NetlinkManager* netlink_manager)
NetlinkUtils::~NetlinkUtils() {}
bool NetlinkUtils::GetWiphyIndex(uint32_t* out_wiphy_index) {
bool NetlinkUtils::GetWiphyIndex(uint32_t* out_wiphy_index,
const std::string& iface_name) {
NL80211Packet get_wiphy(
netlink_manager_->GetFamilyId(),
NL80211_CMD_GET_WIPHY,
netlink_manager_->GetSequenceNumber(),
getpid());
get_wiphy.AddFlag(NLM_F_DUMP);
if (!iface_name.empty()) {
int ifindex = if_nametoindex(iface_name.c_str());
get_wiphy.AddAttribute(NL80211Attr<uint32_t>(NL80211_ATTR_IFINDEX, ifindex));
}
vector<unique_ptr<const NL80211Packet>> response;
if (!netlink_manager_->SendMessageAndGetResponses(get_wiphy, &response)) {
LOG(ERROR) << "NL80211_CMD_GET_WIPHY dump failed";
@ -139,6 +145,10 @@ bool NetlinkUtils::GetWiphyIndex(uint32_t* out_wiphy_index) {
return true;
}
bool NetlinkUtils::GetWiphyIndex(uint32_t* out_wiphy_index) {
return GetWiphyIndex(out_wiphy_index, "");
}
bool NetlinkUtils::GetInterfaces(uint32_t wiphy_index,
vector<InterfaceInfo>* interface_info) {
NL80211Packet get_interfaces(

View File

@ -157,6 +157,8 @@ class NetlinkUtils {
// |*out_wiphy_index| returns the wiphy index from kernel.
// Returns true on success.
virtual bool GetWiphyIndex(uint32_t* out_wiphy_index);
virtual bool GetWiphyIndex(uint32_t* out_wiphy_index,
const std::string& iface_name);
// Get wifi interfaces info from kernel.
// |wiphy_index| is the wiphy index we get using GetWiphyIndex().

View File

@ -315,7 +315,7 @@ Status Server::getAvailableDFSChannels(
bool Server::SetupInterface(const std::string& iface_name,
InterfaceInfo* interface) {
if (!RefreshWiphyIndex()) {
if (!RefreshWiphyIndex(iface_name)) {
return false;
}
@ -342,8 +342,8 @@ bool Server::SetupInterface(const std::string& iface_name,
return false;
}
bool Server::RefreshWiphyIndex() {
if (!netlink_utils_->GetWiphyIndex(&wiphy_index_)) {
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;
}

View File

@ -102,7 +102,7 @@ class Server : public android::net::wifi::BnWificond {
// the interface to Ap mode later.
// Returns true on success, false otherwise.
bool SetupInterface(const std::string& iface_name, InterfaceInfo* interface);
bool RefreshWiphyIndex();
bool RefreshWiphyIndex(const std::string& iface_num);
void LogSupportedBands();
void OnRegDomainChanged(std::string& country_code);
void BroadcastClientInterfaceReady(