diff options
author | Johannes Berg <johannes.berg@intel.com> | 2010-11-24 02:10:05 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-11-24 16:19:36 -0500 |
commit | c063dbf52b998b852122dff07a8b8dd430b38437 (patch) | |
tree | b27cc73fa8a1d9ed8fb5b0a1306e8194e18662a9 | |
parent | 79b1c460a0b55e55981c25c56597c4d5d2872de3 (diff) |
cfg80211: allow using CQM event to notify packet loss
This adds the ability for drivers to use CQM events
to notify about packet loss for specific stations
(which could be the AP for the managed mode case).
Since the threshold might be determined by the
driver (it isn't passed in right now) it will be
passed out of the driver to userspace in the event.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | include/linux/nl80211.h | 3 | ||||
-rw-r--r-- | include/net/cfg80211.h | 12 | ||||
-rw-r--r-- | net/wireless/mlme.c | 12 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 45 | ||||
-rw-r--r-- | net/wireless/nl80211.h | 4 |
5 files changed, 76 insertions, 0 deletions
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 037b4e498890..d706bf3badc8 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h | |||
@@ -1819,6 +1819,8 @@ enum nl80211_ps_state { | |||
1819 | * the minimum amount the RSSI level must change after an event before a | 1819 | * the minimum amount the RSSI level must change after an event before a |
1820 | * new event may be issued (to reduce effects of RSSI oscillation). | 1820 | * new event may be issued (to reduce effects of RSSI oscillation). |
1821 | * @NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT: RSSI threshold event | 1821 | * @NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT: RSSI threshold event |
1822 | * @NL80211_ATTR_CQM_PKT_LOSS_EVENT: a u32 value indicating that this many | ||
1823 | * consecutive packets were not acknowledged by the peer | ||
1822 | * @__NL80211_ATTR_CQM_AFTER_LAST: internal | 1824 | * @__NL80211_ATTR_CQM_AFTER_LAST: internal |
1823 | * @NL80211_ATTR_CQM_MAX: highest key attribute | 1825 | * @NL80211_ATTR_CQM_MAX: highest key attribute |
1824 | */ | 1826 | */ |
@@ -1827,6 +1829,7 @@ enum nl80211_attr_cqm { | |||
1827 | NL80211_ATTR_CQM_RSSI_THOLD, | 1829 | NL80211_ATTR_CQM_RSSI_THOLD, |
1828 | NL80211_ATTR_CQM_RSSI_HYST, | 1830 | NL80211_ATTR_CQM_RSSI_HYST, |
1829 | NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT, | 1831 | NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT, |
1832 | NL80211_ATTR_CQM_PKT_LOSS_EVENT, | ||
1830 | 1833 | ||
1831 | /* keep last */ | 1834 | /* keep last */ |
1832 | __NL80211_ATTR_CQM_AFTER_LAST, | 1835 | __NL80211_ATTR_CQM_AFTER_LAST, |
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index dd4c43f512e2..0663945cfa48 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
@@ -2601,6 +2601,18 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev, | |||
2601 | enum nl80211_cqm_rssi_threshold_event rssi_event, | 2601 | enum nl80211_cqm_rssi_threshold_event rssi_event, |
2602 | gfp_t gfp); | 2602 | gfp_t gfp); |
2603 | 2603 | ||
2604 | /** | ||
2605 | * cfg80211_cqm_pktloss_notify - notify userspace about packetloss to peer | ||
2606 | * @dev: network device | ||
2607 | * @peer: peer's MAC address | ||
2608 | * @num_packets: how many packets were lost -- should be a fixed threshold | ||
2609 | * but probably no less than maybe 50, or maybe a throughput dependent | ||
2610 | * threshold (to account for temporary interference) | ||
2611 | * @gfp: context flags | ||
2612 | */ | ||
2613 | void cfg80211_cqm_pktloss_notify(struct net_device *dev, | ||
2614 | const u8 *peer, u32 num_packets, gfp_t gfp); | ||
2615 | |||
2604 | /* Logging, debugging and troubleshooting/diagnostic helpers. */ | 2616 | /* Logging, debugging and troubleshooting/diagnostic helpers. */ |
2605 | 2617 | ||
2606 | /* wiphy_printk helpers, similar to dev_printk */ | 2618 | /* wiphy_printk helpers, similar to dev_printk */ |
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 26838d903b9a..6980a0c315b2 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c | |||
@@ -1028,3 +1028,15 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev, | |||
1028 | nl80211_send_cqm_rssi_notify(rdev, dev, rssi_event, gfp); | 1028 | nl80211_send_cqm_rssi_notify(rdev, dev, rssi_event, gfp); |
1029 | } | 1029 | } |
1030 | EXPORT_SYMBOL(cfg80211_cqm_rssi_notify); | 1030 | EXPORT_SYMBOL(cfg80211_cqm_rssi_notify); |
1031 | |||
1032 | void cfg80211_cqm_pktloss_notify(struct net_device *dev, | ||
1033 | const u8 *peer, u32 num_packets, gfp_t gfp) | ||
1034 | { | ||
1035 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
1036 | struct wiphy *wiphy = wdev->wiphy; | ||
1037 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
1038 | |||
1039 | /* Indicate roaming trigger event to user space */ | ||
1040 | nl80211_send_cqm_pktloss_notify(rdev, dev, peer, num_packets, gfp); | ||
1041 | } | ||
1042 | EXPORT_SYMBOL(cfg80211_cqm_pktloss_notify); | ||
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 8734efa663d1..67ff7e92cb99 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -5715,6 +5715,51 @@ nl80211_send_cqm_rssi_notify(struct cfg80211_registered_device *rdev, | |||
5715 | nlmsg_free(msg); | 5715 | nlmsg_free(msg); |
5716 | } | 5716 | } |
5717 | 5717 | ||
5718 | void | ||
5719 | nl80211_send_cqm_pktloss_notify(struct cfg80211_registered_device *rdev, | ||
5720 | struct net_device *netdev, const u8 *peer, | ||
5721 | u32 num_packets, gfp_t gfp) | ||
5722 | { | ||
5723 | struct sk_buff *msg; | ||
5724 | struct nlattr *pinfoattr; | ||
5725 | void *hdr; | ||
5726 | |||
5727 | msg = nlmsg_new(NLMSG_GOODSIZE, gfp); | ||
5728 | if (!msg) | ||
5729 | return; | ||
5730 | |||
5731 | hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_NOTIFY_CQM); | ||
5732 | if (!hdr) { | ||
5733 | nlmsg_free(msg); | ||
5734 | return; | ||
5735 | } | ||
5736 | |||
5737 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); | ||
5738 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); | ||
5739 | NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, peer); | ||
5740 | |||
5741 | pinfoattr = nla_nest_start(msg, NL80211_ATTR_CQM); | ||
5742 | if (!pinfoattr) | ||
5743 | goto nla_put_failure; | ||
5744 | |||
5745 | NLA_PUT_U32(msg, NL80211_ATTR_CQM_PKT_LOSS_EVENT, num_packets); | ||
5746 | |||
5747 | nla_nest_end(msg, pinfoattr); | ||
5748 | |||
5749 | if (genlmsg_end(msg, hdr) < 0) { | ||
5750 | nlmsg_free(msg); | ||
5751 | return; | ||
5752 | } | ||
5753 | |||
5754 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, | ||
5755 | nl80211_mlme_mcgrp.id, gfp); | ||
5756 | return; | ||
5757 | |||
5758 | nla_put_failure: | ||
5759 | genlmsg_cancel(msg, hdr); | ||
5760 | nlmsg_free(msg); | ||
5761 | } | ||
5762 | |||
5718 | static int nl80211_netlink_notify(struct notifier_block * nb, | 5763 | static int nl80211_netlink_notify(struct notifier_block * nb, |
5719 | unsigned long state, | 5764 | unsigned long state, |
5720 | void *_notify) | 5765 | void *_notify) |
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h index 30d2f939150d..16c2f7190768 100644 --- a/net/wireless/nl80211.h +++ b/net/wireless/nl80211.h | |||
@@ -87,5 +87,9 @@ nl80211_send_cqm_rssi_notify(struct cfg80211_registered_device *rdev, | |||
87 | struct net_device *netdev, | 87 | struct net_device *netdev, |
88 | enum nl80211_cqm_rssi_threshold_event rssi_event, | 88 | enum nl80211_cqm_rssi_threshold_event rssi_event, |
89 | gfp_t gfp); | 89 | gfp_t gfp); |
90 | void | ||
91 | nl80211_send_cqm_pktloss_notify(struct cfg80211_registered_device *rdev, | ||
92 | struct net_device *netdev, const u8 *peer, | ||
93 | u32 num_packets, gfp_t gfp); | ||
90 | 94 | ||
91 | #endif /* __NET_WIRELESS_NL80211_H */ | 95 | #endif /* __NET_WIRELESS_NL80211_H */ |