OSDN Git Service

Support fetching packet counters for wificond
authorNingyuan Wang <nywang@google.com>
Thu, 15 Sep 2016 17:53:07 +0000 (10:53 -0700)
committerNingyuan Wang <nywang@google.com>
Fri, 16 Sep 2016 20:32:28 +0000 (13:32 -0700)
BUG=30978872
TEST=compile, manual tests

Change-Id: Ifa0dd9ce794a1cdb6da7e357d6873992091e3ea0

aidl/android/net/wifi/IClientInterface.aidl
client_interface_binder.cpp
client_interface_binder.h
client_interface_impl.cpp
client_interface_impl.h
net/netlink_utils.cpp
net/netlink_utils.h
server.cpp
tests/client_interface_impl_unittest.cpp

index 1ba7e36..27f15e7 100644 (file)
@@ -27,4 +27,9 @@ interface IClientInterface {
   // Remove this interface from wpa_supplicant's control.
   // Returns true if removal was successful.
   boolean disableSupplicant();
+
+  // Get packet counters for this interface.
+  // First element in array is the number of successfully transmitted packets.
+  // Second element in array is the number of tramsmission failure.
+  int[] getPacketCounters();
 }
index 557b673..52fb820 100644 (file)
 
 #include "wificond/client_interface_binder.h"
 
+#include <vector>
+
 #include <binder/Status.h>
 
 #include "wificond/client_interface_impl.h"
 
 using android::binder::Status;
+using std::vector;
 
 namespace android {
 namespace wificond {
@@ -42,5 +45,15 @@ Status ClientInterfaceBinder::disableSupplicant(bool* success) {
   return Status::ok();
 }
 
+Status ClientInterfaceBinder::getPacketCounters(
+    vector<int32_t>* out_packet_counters) {
+  if (impl_ == nullptr) {
+    return Status::ok();
+  }
+  impl_->GetPacketCounters(out_packet_counters);
+  return Status::ok();
+}
+
+
 }  // namespace wificond
 }  // namespace android
index cd2a6fe..5bb2576 100644 (file)
@@ -39,6 +39,8 @@ class ClientInterfaceBinder : public android::net::wifi::BnClientInterface {
 
   ::android::binder::Status enableSupplicant(bool* success) override;
   ::android::binder::Status disableSupplicant(bool* success) override;
+  ::android::binder::Status getPacketCounters(
+      std::vector<int32_t>* out_packet_counters) override;
 
  private:
   ClientInterfaceImpl* impl_;
index 30b12e5..11927aa 100644 (file)
@@ -23,6 +23,7 @@
 #include <wifi_system/wifi.h>
 
 #include "wificond/client_interface_binder.h"
+#include "wificond/net/netlink_utils.h"
 #include "wificond/scanning/scan_result.h"
 #include "wificond/scanning/scan_utils.h"
 
@@ -32,6 +33,7 @@ using android::wifi_system::SupplicantManager;
 
 using namespace std::placeholders;
 using std::string;
+using std::unique_ptr;
 using std::vector;
 
 namespace android {
@@ -42,11 +44,13 @@ ClientInterfaceImpl::ClientInterfaceImpl(
     uint32_t interface_index,
     const std::vector<uint8_t>& interface_mac_addr,
     SupplicantManager* supplicant_manager,
+    NetlinkUtils* netlink_utils,
     ScanUtils* scan_utils)
     : interface_name_(interface_name),
       interface_index_(interface_index),
       interface_mac_addr_(interface_mac_addr),
       supplicant_manager_(supplicant_manager),
+      netlink_utils_(netlink_utils),
       scan_utils_(scan_utils),
       binder_(new ClientInterfaceBinder(this)) {
   scan_utils_->SubscribeScanResultNotification(
@@ -72,6 +76,18 @@ bool ClientInterfaceImpl::DisableSupplicant() {
   return supplicant_manager_->StopSupplicant();
 }
 
+bool ClientInterfaceImpl::GetPacketCounters(vector<int32_t>* out_packet_counters) {
+  StationInfo station_info;
+  if(!netlink_utils_->GetStationInfo(interface_index_,
+                                     interface_mac_addr_,
+                                     &station_info)) {
+    return false;
+  }
+  out_packet_counters->push_back(station_info.station_tx_packets);
+  out_packet_counters->push_back(station_info.station_tx_failed);
+  return true;
+}
+
 void ClientInterfaceImpl::OnScanResultsReady(
                          uint32_t interface_index,
                          std::vector<std::vector<uint8_t>>& ssids,
index b6334cb..af1c316 100644 (file)
@@ -29,6 +29,7 @@ namespace android {
 namespace wificond {
 
 class ClientInterfaceBinder;
+class NetlinkUtils;
 class ScanUtils;
 
 // Holds the guts of how we control network interfaces capable of connecting to
@@ -44,6 +45,7 @@ class ClientInterfaceImpl {
       uint32_t interface_index,
       const std::vector<uint8_t>& interface_mac_addr,
       android::wifi_system::SupplicantManager* supplicant_manager,
+      NetlinkUtils* netlink_utils,
       ScanUtils* scan_utils);
   ~ClientInterfaceImpl();
 
@@ -52,6 +54,7 @@ class ClientInterfaceImpl {
 
   bool EnableSupplicant();
   bool DisableSupplicant();
+  bool GetPacketCounters(std::vector<int32_t>* out_packet_counters);
 
  private:
   void OnScanResultsReady(uint32_t interface_index,
@@ -62,6 +65,7 @@ class ClientInterfaceImpl {
   const uint32_t interface_index_;
   const std::vector<uint8_t> interface_mac_addr_;
   android::wifi_system::SupplicantManager* const supplicant_manager_;
+  NetlinkUtils* const netlink_utils_;
   ScanUtils* const scan_utils_;
   const android::sp<ClientInterfaceBinder> binder_;
 
index f79a6cd..a1a4e24 100644 (file)
@@ -191,7 +191,8 @@ bool NetlinkUtils::GetWiphyInfo(
   }
   if (response->GetMessageType() == NLMSG_ERROR) {
     LOG(ERROR) << "Receive ERROR message: "
-               << strerror(response->GetErrorCode()) << "in response to a GetWiphy request";
+               << strerror(response->GetErrorCode())
+               << "in response to a GetWiphy request";
     return false;
   }
   if (response->GetCommand() != NL80211_CMD_NEW_WIPHY) {
@@ -287,7 +288,7 @@ bool NetlinkUtils::ParseBandInfo(const NL80211Packet* const packet,
         // Since there is no guarantee for the order of band attributes,
         // we do some math here.
         if (frequency_value > k2GHzFrequencyLowerBound &&
-            frequency_value < k2GHzFrequencyUpperBound ) {
+            frequency_value < k2GHzFrequencyUpperBound) {
           frequencies_2g.push_back(frequency_value);
         } else {
           frequencies_5g.push_back(frequency_value);
@@ -299,5 +300,54 @@ bool NetlinkUtils::ParseBandInfo(const NL80211Packet* const packet,
   return true;
 }
 
+bool NetlinkUtils::GetStationInfo(uint32_t interface_index,
+                                  const vector<uint8_t>& mac_address,
+                                  StationInfo* out_station_info) {
+  NL80211Packet get_station(
+      netlink_manager_->GetFamilyId(),
+      NL80211_CMD_GET_STATION,
+      netlink_manager_->GetSequenceNumber(),
+      getpid());
+  get_station.AddAttribute(NL80211Attr<uint32_t>(NL80211_ATTR_IFINDEX,
+                                                 interface_index));
+  get_station.AddAttribute(NL80211Attr<vector<uint8_t>>(NL80211_ATTR_MAC,
+                                                        mac_address));
+
+  unique_ptr<const NL80211Packet> response;
+  if (!netlink_manager_->SendMessageAndGetSingleResponse(get_station,
+                                                         &response)) {
+    LOG(ERROR) << "Failed to get packet counters";
+    return false;
+  }
+  if (response->GetMessageType() == NLMSG_ERROR) {
+    LOG(ERROR) << "Receive ERROR message: "
+               << strerror(response->GetErrorCode())
+               << "in response to a get station request";
+    return false;
+  }
+
+  if (response->GetCommand() != NL80211_CMD_NEW_STATION) {
+    LOG(ERROR) << "Wrong command in response to a get station request: "
+               << static_cast<int>(response->GetCommand());
+    return false;
+  }
+  NL80211NestedAttr sta_info(0);
+  if (!response->GetAttribute(NL80211_ATTR_STA_INFO, &sta_info)) {
+    LOG(ERROR) << "Failed to get NL80211_ATTR_STA_INFO";
+    return false;
+  }
+  int32_t tx_good, tx_bad;
+  if (!sta_info.GetAttributeValue(NL80211_STA_INFO_TX_PACKETS, &tx_good)) {
+    LOG(ERROR) << "Failed to get NL80211_STA_INFO_TX_PACKETS";
+    return false;
+  }
+  if (!sta_info.GetAttributeValue(NL80211_STA_INFO_TX_FAILED, &tx_bad)) {
+    LOG(ERROR) << "Failed to get NL80211_STA_INFO_TX_FAILED";
+    return false;
+  }
+  *out_station_info = StationInfo(tx_good, tx_bad);
+  return true;
+}
+
 }  // namespace wificond
 }  // namespace android
index 41cb41b..91690f9 100644 (file)
@@ -57,6 +57,20 @@ struct ScanCapabilities {
   uint8_t max_match_sets;
 };
 
+struct StationInfo {
+  StationInfo() = default;
+  StationInfo(uint32_t station_tx_packets_,
+              uint32_t station_tx_failed_)
+      : station_tx_packets(station_tx_packets_),
+        station_tx_failed(station_tx_failed_) {}
+  // Number of successfully transmitted packets.
+  int32_t station_tx_packets;
+  // number of tramsmission failures.
+  int32_t station_tx_failed;
+  // There are many other counters/parameters included in station info.
+  // We will add them once we find them useful.
+};
+
 class NetlinkManager;
 class NL80211Packet;
 
@@ -79,10 +93,22 @@ class NetlinkUtils {
                                 uint32_t* index,
                                 std::vector<uint8_t>* mac_addr);
 
+  // Get wifi wiphy info from kernel.
+  // |*out_band_info| is the lists of frequencies in specific bands.
+  // |*out_scan_capabilities| is the lists of parameters specifying the
+  // scanning capability of underlying implementation.
+  // Returns true on success.
   virtual bool GetWiphyInfo(uint32_t wiphy_index,
                             BandInfo* out_band_info,
                             ScanCapabilities* out_scan_capabilities);
 
+  // Get station info from kernel.
+  // |*out_station_info]| is the struct of available station information.
+  // Returns true on success.
+  virtual bool GetStationInfo(uint32_t interface_index,
+                              const std::vector<uint8_t>& mac_address,
+                              StationInfo* out_station_info);
+
  private:
   bool ParseBandInfo(const NL80211Packet* const packet,
                      BandInfo* out_band_info);
index 1813e20..9eef6f4 100644 (file)
@@ -122,6 +122,7 @@ Status Server::createClientInterface(sp<IClientInterface>* created_interface) {
       interface_index,
       interface_mac_addr,
       supplicant_manager_.get(),
+      netlink_utils_,
       scan_utils_));
   *created_interface = client_interface->GetBinder();
   client_interfaces_.push_back(std::move(client_interface));
index c43b62f..7dd0f23 100644 (file)
@@ -24,6 +24,7 @@
 
 #include "wificond/client_interface_impl.h"
 #include "wificond/tests/mock_netlink_manager.h"
+#include "wificond/tests/mock_netlink_utils.h"
 #include "wificond/tests/mock_scan_utils.h"
 
 using android::wifi_system::MockSupplicantManager;
@@ -53,6 +54,7 @@ class ClientInterfaceImplTest : public ::testing::Test {
         kTestInterfaceIndex,
         vector<uint8_t>{0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
         supplicant_manager_.get(),
+        &netlink_utils_,
         &scan_utils_});
   }
 
@@ -68,6 +70,7 @@ class ClientInterfaceImplTest : public ::testing::Test {
       new NiceMock<MockSupplicantManager>};
   unique_ptr<NiceMock<MockNetlinkManager>> netlink_manager_{
       new NiceMock<MockNetlinkManager>()};
+  MockNetlinkUtils netlink_utils_{netlink_manager_.get()};
   MockScanUtils scan_utils_{netlink_manager_.get()};
   unique_ptr<ClientInterfaceImpl> client_interface_;
 };  // class ClientInterfaceImplTest