blob: 7ce42ed8ab6833806ee8adb67bc8d89d896e4a82 [file] [log] [blame]
Wade Guthrie5020b572012-10-12 15:51:14 -07001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "shill/callback80211_metrics.h"
6
Wade Guthrie5020b572012-10-12 15:51:14 -07007#include "shill/ieee80211.h"
Wade Guthrie5020b572012-10-12 15:51:14 -07008#include "shill/logging.h"
9#include "shill/metrics.h"
Wade Guthriebb9fca22013-04-10 17:21:42 -070010#include "shill/netlink_manager.h"
repo syncdc085c82012-12-28 08:54:41 -080011#include "shill/nl80211_message.h"
Wade Guthrie5020b572012-10-12 15:51:14 -070012
Wade Guthrie5020b572012-10-12 15:51:14 -070013namespace shill {
14
Wade Guthriec2728962013-07-10 09:32:16 -070015Callback80211Metrics::Callback80211Metrics(Metrics *metrics)
Wade Guthrie318445d2013-05-16 14:05:28 -070016 : metrics_(metrics) {}
Wade Guthrie5020b572012-10-12 15:51:14 -070017
Wade Guthriec2728962013-07-10 09:32:16 -070018IEEE_80211::WiFiReasonCode Callback80211Metrics::WiFiReasonCodeFromUint16(
19 uint16_t reason) const {
20 IEEE_80211::WiFiReasonCode reason_enum = IEEE_80211::kReasonCodeInvalid;
21 if (reason == IEEE_80211::kReasonCodeReserved0 ||
22 reason == IEEE_80211::kReasonCodeReserved12 ||
23 (reason >= IEEE_80211::kReasonCodeReservedBegin25 &&
24 reason <= IEEE_80211::kReasonCodeReservedEnd31) ||
25 (reason >= IEEE_80211::kReasonCodeReservedBegin40 &&
26 reason <= IEEE_80211::kReasonCodeReservedEnd44) ||
27 reason >= IEEE_80211::kReasonCodeMax) {
28 SLOG(WiFi, 1) << "Invalid reason code in disconnect message";
29 reason_enum = IEEE_80211::kReasonCodeInvalid;
30 } else {
31 reason_enum = static_cast<IEEE_80211::WiFiReasonCode>(reason);
32 }
33 return reason_enum;
34}
35
Wade Guthriec6c81962013-03-06 15:47:13 -080036void Callback80211Metrics::CollectDisconnectStatistics(
37 const NetlinkMessage &netlink_message) {
Wade Guthriec2728962013-07-10 09:32:16 -070038 if (!metrics_) {
39 return;
40 }
41 // We only handle disconnect and deauthenticate messages, both of which are
42 // nl80211 messages.
Wade Guthrie318445d2013-05-16 14:05:28 -070043 if (netlink_message.message_type() != Nl80211Message::GetMessageType()) {
Wade Guthriec6c81962013-03-06 15:47:13 -080044 return;
45 }
46 const Nl80211Message &message =
47 * reinterpret_cast<const Nl80211Message *>(&netlink_message);
48
Wade Guthriec2728962013-07-10 09:32:16 -070049 // Station-instigated disconnects provide their information in the
50 // deauthenticate message but AP-instigated disconnects provide it in the
51 // disconnect message.
52 uint16_t reason = IEEE_80211::kReasonCodeUnspecified;
53 if (message.command() == DeauthenticateMessage::kCommand) {
Wade Guthrie0b1ebf12013-04-12 09:53:33 -070054 SLOG(WiFi, 3) << "Handling Deauthenticate Message";
Wade Guthriec2728962013-07-10 09:32:16 -070055 message.Print(3, 3);
56 // If there's no frame, this is probably an AP-caused disconnect and
57 // there'll be a disconnect message to tell us about that.
Wade Guthrie8343f7f2012-12-04 13:52:32 -080058 ByteString rawdata;
Wade Guthriec2728962013-07-10 09:32:16 -070059 if (!message.const_attributes()->GetRawAttributeValue(NL80211_ATTR_FRAME,
Wade Guthriec6c81962013-03-06 15:47:13 -080060 &rawdata)) {
Wade Guthriec2728962013-07-10 09:32:16 -070061 SLOG(WiFi, 5) << "No frame in deauthenticate message, ignoring";
62 return;
Wade Guthrie5020b572012-10-12 15:51:14 -070063 }
Wade Guthriec2728962013-07-10 09:32:16 -070064 Nl80211Frame frame(rawdata);
65 reason = frame.reason();
66 } else if (message.command() == DisconnectMessage::kCommand) {
67 SLOG(WiFi, 3) << "Handling Disconnect Message";
68 message.Print(3, 3);
69 // If there's no reason code, this is probably a STA-caused disconnect and
70 // there was be a disconnect message to tell us about that.
71 if (!message.const_attributes()->GetU16AttributeValue(
72 NL80211_ATTR_REASON_CODE, &reason)) {
73 SLOG(WiFi, 5) << "No reason code in disconnect message, ignoring";
74 return;
75 }
76 } else {
77 return;
Wade Guthrie5020b572012-10-12 15:51:14 -070078 }
Wade Guthriec2728962013-07-10 09:32:16 -070079
80 IEEE_80211::WiFiReasonCode reason_enum = WiFiReasonCodeFromUint16(reason);
81
82 Metrics::WiFiDisconnectByWhom by_whom =
83 message.const_attributes()->IsFlagAttributeTrue(
84 NL80211_ATTR_DISCONNECTED_BY_AP) ? Metrics::kDisconnectedByAp :
85 Metrics::kDisconnectedNotByAp;
86 SLOG(WiFi, 1) << "Notify80211Disconnect by " << (by_whom ? "station" : "AP")
87 << " because:" << reason_enum;
88 metrics_->Notify80211Disconnect(by_whom, reason_enum);
Wade Guthrie5020b572012-10-12 15:51:14 -070089}
90
Wade Guthrie5020b572012-10-12 15:51:14 -070091} // namespace shill.