• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
Device(Manager * manager,const string & device_name,int identifier)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 
~Device()44 Device::~Device() {}
45 
RegisterInterface(const WiFiInterface & new_interface)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 
DeregisterInterface(const WiFiInterface & interface)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 
ParseWiphyCapability(const shill::Nl80211Message & msg)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 
ClaimDevice(bool full_control)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 
ReleaseDevice()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 
InterfaceExists(const string & interface_name)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 
GetHTCapability(uint16_t channel,string * ht_cap)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 
GetVHTCapability(uint16_t channel,string * vht_cap)279 bool Device::GetVHTCapability(uint16_t channel, string* vht_cap) {
280   // TODO(zqiu): to be implemented.
281   return false;
282 }
283 
SetDeviceName(const std::string & device_name)284 void Device::SetDeviceName(const std::string& device_name) {
285   adaptor_->SetDeviceName(device_name);
286 }
287 
GetDeviceName() const288 string Device::GetDeviceName() const {
289   return adaptor_->GetDeviceName();
290 }
291 
SetPreferredApInterface(const std::string & interface_name)292 void Device::SetPreferredApInterface(const std::string& interface_name) {
293   adaptor_->SetPreferredApInterface(interface_name);
294 }
295 
GetPreferredApInterface() const296 string Device::GetPreferredApInterface() const {
297   return adaptor_->GetPreferredApInterface();
298 }
299 
SetInUse(bool in_use)300 void Device::SetInUse(bool in_use) {
301   return adaptor_->SetInUse(in_use);
302 }
303 
GetInUse() const304 bool Device::GetInUse() const {
305   return adaptor_->GetInUse();
306 }
307 
308 // static
GetHTSecondaryChannelLocation(uint16_t channel,bool * above)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 
GetBandCapability(uint16_t channel,BandCapability * capability)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 
UpdatePreferredAPInterface()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