Home | History | Annotate | Download | only in apmanager
      1 //
      2 // Copyright (C) 2014 The Android Open Source Project
      3 //
      4 // Licensed under the Apache License, Version 2.0 (the "License");
      5 // you may not use this file except in compliance with the License.
      6 // You may obtain a copy of the License at
      7 //
      8 //      http://www.apache.org/licenses/LICENSE-2.0
      9 //
     10 // Unless required by applicable law or agreed to in writing, software
     11 // distributed under the License is distributed on an "AS IS" BASIS,
     12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 // See the License for the specific language governing permissions and
     14 // limitations under the License.
     15 //
     16 
     17 #include "apmanager/device.h"
     18 
     19 #include <base/strings/stringprintf.h>
     20 #include <brillo/strings/string_utils.h>
     21 #include <shill/net/attribute_list.h>
     22 #include <shill/net/ieee80211.h>
     23 
     24 #include "apmanager/config.h"
     25 #include "apmanager/control_interface.h"
     26 #include "apmanager/manager.h"
     27 
     28 using shill::ByteString;
     29 using std::string;
     30 
     31 namespace apmanager {
     32 
     33 Device::Device(Manager* manager,
     34                const string& device_name,
     35                int identifier)
     36     : manager_(manager),
     37       supports_ap_mode_(false),
     38       identifier_(identifier),
     39       adaptor_(manager->control_interface()->CreateDeviceAdaptor(this)) {
     40   SetDeviceName(device_name);
     41   SetInUse(false);
     42 }
     43 
     44 Device::~Device() {}
     45 
     46 void Device::RegisterInterface(const WiFiInterface& new_interface) {
     47   LOG(INFO) << "RegisteringInterface " << new_interface.iface_name
     48             << " on device " << GetDeviceName();
     49   for (const auto& interface : interface_list_) {
     50     // Done if interface already in the list.
     51     if (interface.iface_index == new_interface.iface_index) {
     52       LOG(INFO) << "Interface " << new_interface.iface_name
     53                 << " already registered.";
     54       return;
     55     }
     56   }
     57   interface_list_.push_back(new_interface);
     58   UpdatePreferredAPInterface();
     59 }
     60 
     61 void Device::DeregisterInterface(const WiFiInterface& interface) {
     62   LOG(INFO) << "DeregisteringInterface " << interface.iface_name
     63             << " on device " << GetDeviceName();
     64   for (auto it = interface_list_.begin(); it != interface_list_.end(); ++it) {
     65     if (it->iface_index == interface.iface_index) {
     66       interface_list_.erase(it);
     67       UpdatePreferredAPInterface();
     68       return;
     69     }
     70   }
     71 }
     72 
     73 void Device::ParseWiphyCapability(const shill::Nl80211Message& msg) {
     74   // Parse NL80211_ATTR_SUPPORTED_IFTYPES for AP mode interface support.
     75   shill::AttributeListConstRefPtr supported_iftypes;
     76   if (!msg.const_attributes()->ConstGetNestedAttributeList(
     77       NL80211_ATTR_SUPPORTED_IFTYPES, &supported_iftypes)) {
     78     LOG(ERROR) << "NL80211_CMD_NEW_WIPHY had no NL80211_ATTR_SUPPORTED_IFTYPES";
     79     return;
     80   }
     81   supported_iftypes->GetFlagAttributeValue(NL80211_IFTYPE_AP,
     82                                            &supports_ap_mode_);
     83 
     84   // Parse WiFi band capabilities.
     85   shill::AttributeListConstRefPtr wiphy_bands;
     86   if (!msg.const_attributes()->ConstGetNestedAttributeList(
     87       NL80211_ATTR_WIPHY_BANDS, &wiphy_bands)) {
     88     LOG(ERROR) << "NL80211_CMD_NEW_WIPHY had no NL80211_ATTR_WIPHY_BANDS";
     89     return;
     90   }
     91 
     92   shill::AttributeIdIterator band_iter(*wiphy_bands);
     93   for (; !band_iter.AtEnd(); band_iter.Advance()) {
     94     BandCapability band_cap;
     95 
     96     shill::AttributeListConstRefPtr wiphy_band;
     97     if (!wiphy_bands->ConstGetNestedAttributeList(band_iter.GetId(),
     98                                                   &wiphy_band)) {
     99       LOG(WARNING) << "WiFi band " << band_iter.GetId() << " not found";
    100       continue;
    101     }
    102 
    103     // ...Each band has a FREQS attribute...
    104     shill::AttributeListConstRefPtr frequencies;
    105     if (!wiphy_band->ConstGetNestedAttributeList(NL80211_BAND_ATTR_FREQS,
    106                                                  &frequencies)) {
    107       LOG(ERROR) << "BAND " << band_iter.GetId()
    108                  << " had no 'frequencies' attribute";
    109       continue;
    110     }
    111 
    112     // ...And each FREQS attribute contains an array of information about the
    113     // frequency...
    114     shill::AttributeIdIterator freq_iter(*frequencies);
    115     for (; !freq_iter.AtEnd(); freq_iter.Advance()) {
    116       shill::AttributeListConstRefPtr frequency;
    117       if (frequencies->ConstGetNestedAttributeList(freq_iter.GetId(),
    118                                                    &frequency)) {
    119         // ...Including the frequency, itself (the part we want).
    120         uint32_t frequency_value = 0;
    121         if (frequency->GetU32AttributeValue(NL80211_FREQUENCY_ATTR_FREQ,
    122                                             &frequency_value)) {
    123           band_cap.frequencies.push_back(frequency_value);
    124         }
    125       }
    126     }
    127 
    128     wiphy_band->GetU16AttributeValue(NL80211_BAND_ATTR_HT_CAPA,
    129                                      &band_cap.ht_capability_mask);
    130     wiphy_band->GetU16AttributeValue(NL80211_BAND_ATTR_VHT_CAPA,
    131                                      &band_cap.vht_capability_mask);
    132     band_capability_.push_back(band_cap);
    133   }
    134 }
    135 
    136 bool Device::ClaimDevice(bool full_control) {
    137   if (GetInUse()) {
    138     LOG(ERROR) << "Failed to claim device [" << GetDeviceName()
    139                << "]: already in used.";
    140     return false;
    141   }
    142 
    143   if (full_control) {
    144     for (const auto& interface : interface_list_) {
    145       manager_->ClaimInterface(interface.iface_name);
    146       claimed_interfaces_.insert(interface.iface_name);
    147     }
    148   } else {
    149     manager_->ClaimInterface(GetPreferredApInterface());
    150     claimed_interfaces_.insert(GetPreferredApInterface());
    151   }
    152   SetInUse(true);
    153   return true;
    154 }
    155 
    156 bool Device::ReleaseDevice() {
    157   if (!GetInUse()) {
    158     LOG(ERROR) << "Failed to release device [" << GetDeviceName()
    159                << "]: not currently in-used.";
    160     return false;
    161   }
    162 
    163   for (const auto& interface : claimed_interfaces_) {
    164     manager_->ReleaseInterface(interface);
    165   }
    166   claimed_interfaces_.clear();
    167   SetInUse(false);
    168   return true;
    169 }
    170 
    171 bool Device::InterfaceExists(const string& interface_name) {
    172   for (const auto& interface : interface_list_) {
    173     if (interface.iface_name == interface_name) {
    174       return true;
    175     }
    176   }
    177   return false;
    178 }
    179 
    180 bool Device::GetHTCapability(uint16_t channel, string* ht_cap) {
    181   // Get the band capability based on the channel.
    182   BandCapability band_cap;
    183   if (!GetBandCapability(channel, &band_cap)) {
    184     LOG(ERROR) << "No band capability found for channel " << channel;
    185     return false;
    186   }
    187 
    188   std::vector<string> ht_capability;
    189   // LDPC coding capability.
    190   if (band_cap.ht_capability_mask & shill::IEEE_80211::kHTCapMaskLdpcCoding) {
    191     ht_capability.push_back("LDPC");
    192   }
    193 
    194   // Supported channel width set.
    195   if (band_cap.ht_capability_mask &
    196       shill::IEEE_80211::kHTCapMaskSupWidth2040) {
    197     // Determine secondary channel is below or above the primary.
    198     bool above = false;
    199     if (!GetHTSecondaryChannelLocation(channel, &above)) {
    200       LOG(ERROR) << "Unable to determine secondary channel location for "
    201                  << "channel " << channel;
    202       return false;
    203     }
    204     if (above) {
    205       ht_capability.push_back("HT40+");
    206     } else {
    207       ht_capability.push_back("HT40-");
    208     }
    209   }
    210 
    211   // Spatial Multiplexing (SM) Power Save.
    212   uint16_t power_save_mask =
    213       (band_cap.ht_capability_mask >>
    214           shill::IEEE_80211::kHTCapMaskSmPsShift) & 0x3;
    215   if (power_save_mask == 0) {
    216     ht_capability.push_back("SMPS-STATIC");
    217   } else if (power_save_mask == 1) {
    218     ht_capability.push_back("SMPS-DYNAMIC");
    219   }
    220 
    221   // HT-greenfield.
    222   if (band_cap.ht_capability_mask & shill::IEEE_80211::kHTCapMaskGrnFld) {
    223     ht_capability.push_back("GF");
    224   }
    225 
    226   // Short GI for 20 MHz.
    227   if (band_cap.ht_capability_mask & shill::IEEE_80211::kHTCapMaskSgi20) {
    228     ht_capability.push_back("SHORT-GI-20");
    229   }
    230 
    231   // Short GI for 40 MHz.
    232   if (band_cap.ht_capability_mask & shill::IEEE_80211::kHTCapMaskSgi40) {
    233     ht_capability.push_back("SHORT-GI-40");
    234   }
    235 
    236   // Tx STBC.
    237   if (band_cap.ht_capability_mask & shill::IEEE_80211::kHTCapMaskTxStbc) {
    238     ht_capability.push_back("TX-STBC");
    239   }
    240 
    241   // Rx STBC.
    242   uint16_t rx_stbc =
    243       (band_cap.ht_capability_mask >>
    244           shill::IEEE_80211::kHTCapMaskRxStbcShift) & 0x3;
    245   if (rx_stbc == 1) {
    246     ht_capability.push_back("RX-STBC1");
    247   } else if (rx_stbc == 2) {
    248     ht_capability.push_back("RX-STBC12");
    249   } else if (rx_stbc == 3) {
    250     ht_capability.push_back("RX-STBC123");
    251   }
    252 
    253   // HT-delayed Block Ack.
    254   if (band_cap.ht_capability_mask & shill::IEEE_80211::kHTCapMaskDelayBA) {
    255     ht_capability.push_back("DELAYED-BA");
    256   }
    257 
    258   // Maximum A-MSDU length.
    259   if (band_cap.ht_capability_mask & shill::IEEE_80211::kHTCapMaskMaxAmsdu) {
    260     ht_capability.push_back("MAX-AMSDU-7935");
    261   }
    262 
    263   // DSSS/CCK Mode in 40 MHz.
    264   if (band_cap.ht_capability_mask & shill::IEEE_80211::kHTCapMaskDsssCck40) {
    265     ht_capability.push_back("DSSS_CCK-40");
    266   }
    267 
    268   // 40 MHz intolerant.
    269   if (band_cap.ht_capability_mask &
    270       shill::IEEE_80211::kHTCapMask40MHzIntolerant) {
    271     ht_capability.push_back("40-INTOLERANT");
    272   }
    273 
    274   *ht_cap = base::StringPrintf("[%s]",
    275       brillo::string_utils::Join(" ", ht_capability).c_str());
    276   return true;
    277 }
    278 
    279 bool Device::GetVHTCapability(uint16_t channel, string* vht_cap) {
    280   // TODO(zqiu): to be implemented.
    281   return false;
    282 }
    283 
    284 void Device::SetDeviceName(const std::string& device_name) {
    285   adaptor_->SetDeviceName(device_name);
    286 }
    287 
    288 string Device::GetDeviceName() const {
    289   return adaptor_->GetDeviceName();
    290 }
    291 
    292 void Device::SetPreferredApInterface(const std::string& interface_name) {
    293   adaptor_->SetPreferredApInterface(interface_name);
    294 }
    295 
    296 string Device::GetPreferredApInterface() const {
    297   return adaptor_->GetPreferredApInterface();
    298 }
    299 
    300 void Device::SetInUse(bool in_use) {
    301   return adaptor_->SetInUse(in_use);
    302 }
    303 
    304 bool Device::GetInUse() const {
    305   return adaptor_->GetInUse();
    306 }
    307 
    308 // static
    309 bool Device::GetHTSecondaryChannelLocation(uint16_t channel, bool* above) {
    310   bool ret_val = true;
    311 
    312   // Determine secondary channel location base on the channel. Refer to
    313   // ht_cap section in hostapd.conf documentation.
    314   switch (channel) {
    315     case 7:
    316     case 8:
    317     case 9:
    318     case 10:
    319     case 11:
    320     case 12:
    321     case 13:
    322     case 40:
    323     case 48:
    324     case 56:
    325     case 64:
    326       *above = false;
    327       break;
    328 
    329     case 1:
    330     case 2:
    331     case 3:
    332     case 4:
    333     case 5:
    334     case 6:
    335     case 36:
    336     case 44:
    337     case 52:
    338     case 60:
    339       *above = true;
    340       break;
    341 
    342     default:
    343       ret_val = false;
    344       break;
    345   }
    346 
    347   return ret_val;
    348 }
    349 
    350 bool Device::GetBandCapability(uint16_t channel, BandCapability* capability) {
    351   uint32_t frequency;
    352   if (!Config::GetFrequencyFromChannel(channel, &frequency)) {
    353     LOG(ERROR) << "Invalid channel " << channel;
    354     return false;
    355   }
    356 
    357   for (const auto& band : band_capability_) {
    358     if (std::find(band.frequencies.begin(),
    359                   band.frequencies.end(),
    360                   frequency) != band.frequencies.end()) {
    361       *capability = band;
    362       return true;
    363     }
    364   }
    365   return false;
    366 }
    367 
    368 void Device::UpdatePreferredAPInterface() {
    369   // Return if device doesn't support AP interface mode.
    370   if (!supports_ap_mode_) {
    371     return;
    372   }
    373 
    374   // Use the first registered AP mode interface if there is one, otherwise use
    375   // the first registered managed mode interface. If none are available, then
    376   // no interface can be used for AP operation on this device.
    377   WiFiInterface preferred_interface;
    378   for (const auto& interface : interface_list_) {
    379     if (interface.iface_type == NL80211_IFTYPE_AP) {
    380       preferred_interface = interface;
    381       break;
    382     } else if (interface.iface_type == NL80211_IFTYPE_STATION &&
    383                preferred_interface.iface_name.empty()) {
    384       preferred_interface = interface;
    385     }
    386     // Ignore all other interface types.
    387   }
    388   // Update preferred AP interface property.
    389   SetPreferredApInterface(preferred_interface.iface_name);
    390 }
    391 
    392 }  // namespace apmanager
    393