aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Pedersen <c_tpeder@qca.qualcomm.com>2012-07-12 19:17:33 -0400
committerJohannes Berg <johannes.berg@intel.com>2012-07-17 05:57:23 -0400
commit84f10708f73254878246772cead70a2eb6a123f2 (patch)
tree39a4ca2f6cc3ab5b33320e3a62d2a8f7c4901b7a
parent00f5335079689cd65a9430b5df8974dc35c7914b (diff)
cfg80211: support TX error rate CQM
Let the user configure serveral TX error conection quality monitoring parameters: % error rate, survey interval, and # of attempted packets. On exceeding the TX failure rate over the given interval, the driver will send a CQM notify event with the actual TX failure rate and packets attempted. Signed-off-by: Thomas Pedersen <c_tpeder@qca.qualcomm.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--include/linux/nl80211.h16
-rw-r--r--include/net/cfg80211.h21
-rw-r--r--net/wireless/mlme.c13
-rw-r--r--net/wireless/nl80211.c85
-rw-r--r--net/wireless/nl80211.h5
5 files changed, 140 insertions, 0 deletions
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index e791487ead37..d6cfacc3ce4d 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -1550,6 +1550,8 @@ enum nl80211_attrs {
1550/* default RSSI threshold for scan results if none specified. */ 1550/* default RSSI threshold for scan results if none specified. */
1551#define NL80211_SCAN_RSSI_THOLD_OFF -300 1551#define NL80211_SCAN_RSSI_THOLD_OFF -300
1552 1552
1553#define NL80211_CQM_TXE_MAX_INTVL 1800
1554
1553/** 1555/**
1554 * enum nl80211_iftype - (virtual) interface types 1556 * enum nl80211_iftype - (virtual) interface types
1555 * 1557 *
@@ -2589,6 +2591,17 @@ enum nl80211_ps_state {
2589 * @NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT: RSSI threshold event 2591 * @NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT: RSSI threshold event
2590 * @NL80211_ATTR_CQM_PKT_LOSS_EVENT: a u32 value indicating that this many 2592 * @NL80211_ATTR_CQM_PKT_LOSS_EVENT: a u32 value indicating that this many
2591 * consecutive packets were not acknowledged by the peer 2593 * consecutive packets were not acknowledged by the peer
2594 * @NL80211_ATTR_CQM_TXE_RATE: TX error rate in %. Minimum % of TX failures
2595 * during the given %NL80211_ATTR_CQM_TXE_INTVL before an
2596 * %NL80211_CMD_NOTIFY_CQM with reported %NL80211_ATTR_CQM_TXE_RATE and
2597 * %NL80211_ATTR_CQM_TXE_PKTS is generated.
2598 * @NL80211_ATTR_CQM_TXE_PKTS: number of attempted packets in a given
2599 * %NL80211_ATTR_CQM_TXE_INTVL before %NL80211_ATTR_CQM_TXE_RATE is
2600 * checked.
2601 * @NL80211_ATTR_CQM_TXE_INTVL: interval in seconds. Specifies the periodic
2602 * interval in which %NL80211_ATTR_CQM_TXE_PKTS and
2603 * %NL80211_ATTR_CQM_TXE_RATE must be satisfied before generating an
2604 * %NL80211_CMD_NOTIFY_CQM. Set to 0 to turn off TX error reporting.
2592 * @__NL80211_ATTR_CQM_AFTER_LAST: internal 2605 * @__NL80211_ATTR_CQM_AFTER_LAST: internal
2593 * @NL80211_ATTR_CQM_MAX: highest key attribute 2606 * @NL80211_ATTR_CQM_MAX: highest key attribute
2594 */ 2607 */
@@ -2598,6 +2611,9 @@ enum nl80211_attr_cqm {
2598 NL80211_ATTR_CQM_RSSI_HYST, 2611 NL80211_ATTR_CQM_RSSI_HYST,
2599 NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT, 2612 NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT,
2600 NL80211_ATTR_CQM_PKT_LOSS_EVENT, 2613 NL80211_ATTR_CQM_PKT_LOSS_EVENT,
2614 NL80211_ATTR_CQM_TXE_RATE,
2615 NL80211_ATTR_CQM_TXE_PKTS,
2616 NL80211_ATTR_CQM_TXE_INTVL,
2601 2617
2602 /* keep last */ 2618 /* keep last */
2603 __NL80211_ATTR_CQM_AFTER_LAST, 2619 __NL80211_ATTR_CQM_AFTER_LAST,
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 0245208c2978..493fa0c79005 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1573,6 +1573,8 @@ struct cfg80211_gtk_rekey_data {
1573 * @set_power_mgmt: Configure WLAN power management. A timeout value of -1 1573 * @set_power_mgmt: Configure WLAN power management. A timeout value of -1
1574 * allows the driver to adjust the dynamic ps timeout value. 1574 * allows the driver to adjust the dynamic ps timeout value.
1575 * @set_cqm_rssi_config: Configure connection quality monitor RSSI threshold. 1575 * @set_cqm_rssi_config: Configure connection quality monitor RSSI threshold.
1576 * @set_cqm_txe_config: Configure connection quality monitor TX error
1577 * thresholds.
1576 * @sched_scan_start: Tell the driver to start a scheduled scan. 1578 * @sched_scan_start: Tell the driver to start a scheduled scan.
1577 * @sched_scan_stop: Tell the driver to stop an ongoing scheduled 1579 * @sched_scan_stop: Tell the driver to stop an ongoing scheduled
1578 * scan. The driver_initiated flag specifies whether the driver 1580 * scan. The driver_initiated flag specifies whether the driver
@@ -1783,6 +1785,10 @@ struct cfg80211_ops {
1783 struct net_device *dev, 1785 struct net_device *dev,
1784 s32 rssi_thold, u32 rssi_hyst); 1786 s32 rssi_thold, u32 rssi_hyst);
1785 1787
1788 int (*set_cqm_txe_config)(struct wiphy *wiphy,
1789 struct net_device *dev,
1790 u32 rate, u32 pkts, u32 intvl);
1791
1786 void (*mgmt_frame_register)(struct wiphy *wiphy, 1792 void (*mgmt_frame_register)(struct wiphy *wiphy,
1787 struct wireless_dev *wdev, 1793 struct wireless_dev *wdev,
1788 u16 frame_type, bool reg); 1794 u16 frame_type, bool reg);
@@ -3396,6 +3402,21 @@ void cfg80211_cqm_pktloss_notify(struct net_device *dev,
3396 const u8 *peer, u32 num_packets, gfp_t gfp); 3402 const u8 *peer, u32 num_packets, gfp_t gfp);
3397 3403
3398/** 3404/**
3405 * cfg80211_cqm_txe_notify - TX error rate event
3406 * @dev: network device
3407 * @peer: peer's MAC address
3408 * @num_packets: how many packets were lost
3409 * @rate: % of packets which failed transmission
3410 * @intvl: interval (in s) over which the TX failure threshold was breached.
3411 * @gfp: context flags
3412 *
3413 * Notify userspace when configured % TX failures over number of packets in a
3414 * given interval is exceeded.
3415 */
3416void cfg80211_cqm_txe_notify(struct net_device *dev, const u8 *peer,
3417 u32 num_packets, u32 rate, u32 intvl, gfp_t gfp);
3418
3419/**
3399 * cfg80211_gtk_rekey_notify - notify userspace about driver rekeying 3420 * cfg80211_gtk_rekey_notify - notify userspace about driver rekeying
3400 * @dev: network device 3421 * @dev: network device
3401 * @bssid: BSSID of AP (to avoid races) 3422 * @bssid: BSSID of AP (to avoid races)
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index abe9f82d5a82..1cdb1d5e6b0f 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -919,6 +919,19 @@ void cfg80211_cqm_pktloss_notify(struct net_device *dev,
919} 919}
920EXPORT_SYMBOL(cfg80211_cqm_pktloss_notify); 920EXPORT_SYMBOL(cfg80211_cqm_pktloss_notify);
921 921
922void cfg80211_cqm_txe_notify(struct net_device *dev,
923 const u8 *peer, u32 num_packets,
924 u32 rate, u32 intvl, gfp_t gfp)
925{
926 struct wireless_dev *wdev = dev->ieee80211_ptr;
927 struct wiphy *wiphy = wdev->wiphy;
928 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
929
930 nl80211_send_cqm_txe_notify(rdev, dev, peer, num_packets,
931 rate, intvl, gfp);
932}
933EXPORT_SYMBOL(cfg80211_cqm_txe_notify);
934
922void cfg80211_gtk_rekey_notify(struct net_device *dev, const u8 *bssid, 935void cfg80211_gtk_rekey_notify(struct net_device *dev, const u8 *bssid,
923 const u8 *replay_ctr, gfp_t gfp) 936 const u8 *replay_ctr, gfp_t gfp)
924{ 937{
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index be8750f91d78..9216e45e53a0 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -6267,8 +6267,35 @@ nl80211_attr_cqm_policy[NL80211_ATTR_CQM_MAX + 1] __read_mostly = {
6267 [NL80211_ATTR_CQM_RSSI_THOLD] = { .type = NLA_U32 }, 6267 [NL80211_ATTR_CQM_RSSI_THOLD] = { .type = NLA_U32 },
6268 [NL80211_ATTR_CQM_RSSI_HYST] = { .type = NLA_U32 }, 6268 [NL80211_ATTR_CQM_RSSI_HYST] = { .type = NLA_U32 },
6269 [NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] = { .type = NLA_U32 }, 6269 [NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] = { .type = NLA_U32 },
6270 [NL80211_ATTR_CQM_TXE_RATE] = { .type = NLA_U32 },
6271 [NL80211_ATTR_CQM_TXE_PKTS] = { .type = NLA_U32 },
6272 [NL80211_ATTR_CQM_TXE_INTVL] = { .type = NLA_U32 },
6270}; 6273};
6271 6274
6275static int nl80211_set_cqm_txe(struct genl_info *info,
6276 u32 rate, u32 pkts, u32 intvl)
6277{
6278 struct cfg80211_registered_device *rdev = info->user_ptr[0];
6279 struct wireless_dev *wdev;
6280 struct net_device *dev = info->user_ptr[1];
6281
6282 if ((rate < 0 || rate > 100) ||
6283 (intvl < 0 || intvl > NL80211_CQM_TXE_MAX_INTVL))
6284 return -EINVAL;
6285
6286 wdev = dev->ieee80211_ptr;
6287
6288 if (!rdev->ops->set_cqm_txe_config)
6289 return -EOPNOTSUPP;
6290
6291 if (wdev->iftype != NL80211_IFTYPE_STATION &&
6292 wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
6293 return -EOPNOTSUPP;
6294
6295 return rdev->ops->set_cqm_txe_config(wdev->wiphy, dev,
6296 rate, pkts, intvl);
6297}
6298
6272static int nl80211_set_cqm_rssi(struct genl_info *info, 6299static int nl80211_set_cqm_rssi(struct genl_info *info,
6273 s32 threshold, u32 hysteresis) 6300 s32 threshold, u32 hysteresis)
6274{ 6301{
@@ -6316,6 +6343,14 @@ static int nl80211_set_cqm(struct sk_buff *skb, struct genl_info *info)
6316 threshold = nla_get_u32(attrs[NL80211_ATTR_CQM_RSSI_THOLD]); 6343 threshold = nla_get_u32(attrs[NL80211_ATTR_CQM_RSSI_THOLD]);
6317 hysteresis = nla_get_u32(attrs[NL80211_ATTR_CQM_RSSI_HYST]); 6344 hysteresis = nla_get_u32(attrs[NL80211_ATTR_CQM_RSSI_HYST]);
6318 err = nl80211_set_cqm_rssi(info, threshold, hysteresis); 6345 err = nl80211_set_cqm_rssi(info, threshold, hysteresis);
6346 } else if (attrs[NL80211_ATTR_CQM_TXE_RATE] &&
6347 attrs[NL80211_ATTR_CQM_TXE_PKTS] &&
6348 attrs[NL80211_ATTR_CQM_TXE_INTVL]) {
6349 u32 rate, pkts, intvl;
6350 rate = nla_get_u32(attrs[NL80211_ATTR_CQM_TXE_RATE]);
6351 pkts = nla_get_u32(attrs[NL80211_ATTR_CQM_TXE_PKTS]);
6352 intvl = nla_get_u32(attrs[NL80211_ATTR_CQM_TXE_INTVL]);
6353 err = nl80211_set_cqm_txe(info, rate, pkts, intvl);
6319 } else 6354 } else
6320 err = -EINVAL; 6355 err = -EINVAL;
6321 6356
@@ -8496,6 +8531,56 @@ void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev,
8496} 8531}
8497 8532
8498void 8533void
8534nl80211_send_cqm_txe_notify(struct cfg80211_registered_device *rdev,
8535 struct net_device *netdev, const u8 *peer,
8536 u32 num_packets, u32 rate, u32 intvl, gfp_t gfp)
8537{
8538 struct sk_buff *msg;
8539 struct nlattr *pinfoattr;
8540 void *hdr;
8541
8542 msg = nlmsg_new(NLMSG_GOODSIZE, gfp);
8543 if (!msg)
8544 return;
8545
8546 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_NOTIFY_CQM);
8547 if (!hdr) {
8548 nlmsg_free(msg);
8549 return;
8550 }
8551
8552 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
8553 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
8554 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, peer))
8555 goto nla_put_failure;
8556
8557 pinfoattr = nla_nest_start(msg, NL80211_ATTR_CQM);
8558 if (!pinfoattr)
8559 goto nla_put_failure;
8560
8561 if (nla_put_u32(msg, NL80211_ATTR_CQM_TXE_PKTS, num_packets))
8562 goto nla_put_failure;
8563
8564 if (nla_put_u32(msg, NL80211_ATTR_CQM_TXE_RATE, rate))
8565 goto nla_put_failure;
8566
8567 if (nla_put_u32(msg, NL80211_ATTR_CQM_TXE_INTVL, intvl))
8568 goto nla_put_failure;
8569
8570 nla_nest_end(msg, pinfoattr);
8571
8572 genlmsg_end(msg, hdr);
8573
8574 genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
8575 nl80211_mlme_mcgrp.id, gfp);
8576 return;
8577
8578 nla_put_failure:
8579 genlmsg_cancel(msg, hdr);
8580 nlmsg_free(msg);
8581}
8582
8583void
8499nl80211_send_cqm_pktloss_notify(struct cfg80211_registered_device *rdev, 8584nl80211_send_cqm_pktloss_notify(struct cfg80211_registered_device *rdev,
8500 struct net_device *netdev, const u8 *peer, 8585 struct net_device *netdev, const u8 *peer,
8501 u32 num_packets, gfp_t gfp) 8586 u32 num_packets, gfp_t gfp)
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h
index 89ce99675e61..9f2616fffb40 100644
--- a/net/wireless/nl80211.h
+++ b/net/wireless/nl80211.h
@@ -110,6 +110,11 @@ nl80211_send_cqm_pktloss_notify(struct cfg80211_registered_device *rdev,
110 struct net_device *netdev, const u8 *peer, 110 struct net_device *netdev, const u8 *peer,
111 u32 num_packets, gfp_t gfp); 111 u32 num_packets, gfp_t gfp);
112 112
113void
114nl80211_send_cqm_txe_notify(struct cfg80211_registered_device *rdev,
115 struct net_device *netdev, const u8 *peer,
116 u32 num_packets, u32 rate, u32 intvl, gfp_t gfp);
117
113void nl80211_gtk_rekey_notify(struct cfg80211_registered_device *rdev, 118void nl80211_gtk_rekey_notify(struct cfg80211_registered_device *rdev,
114 struct net_device *netdev, const u8 *bssid, 119 struct net_device *netdev, const u8 *bssid,
115 const u8 *replay_ctr, gfp_t gfp); 120 const u8 *replay_ctr, gfp_t gfp);