qcacld-3.0: Get deleted remote station info in SAP case

Add support to get information of deleted station in case of SAP.

Change-Id: Id61ae1b36b923898237d55aa8c57d2e49815c8af
CRs-Fixed: 2126240
This commit is contained in:
Hanumanth Reddy Pothula
2017-10-23 20:10:46 +05:30
committed by snandini
parent 2e01abcc20
commit f79fbdfd01
2 changed files with 400 additions and 11 deletions

View File

@@ -815,7 +815,7 @@ struct hdd_station_info {
bool sgi_enable;
bool tx_stbc;
bool rx_stbc;
uint8_t ch_width;
tSirMacHTChannelWidth ch_width;
uint8_t mode;
uint8_t max_supp_idx;
uint8_t max_ext_idx;

View File

@@ -4960,32 +4960,384 @@ static inline int32_t remote_station_put_u64(struct sk_buff *skb,
#endif
/**
* hdd_get_station_remote() - get remote peer's info
* hdd_add_survey_info_sap_get_len - get data length used in
* hdd_add_survey_info_sap()
*
* This function calculates the data length used in hdd_add_survey_info_sap()
*
* Return: total data length used in hdd_add_survey_info_sap()
*/
static uint32_t hdd_add_survey_info_sap_get_len(void)
{
return ((NLA_HDRLEN) + (sizeof(uint32_t) + NLA_HDRLEN));
}
/**
* hdd_add_survey_info - add survey info attribute
* @skb: pointer to response skb buffer
* @stainfo: station information
* @idx: attribute type index for nla_next_start()
*
* This function adds survey info attribute to response skb buffer
*
* Return : 0 on success and errno on failure
*/
static int32_t hdd_add_survey_info_sap(struct sk_buff *skb,
struct hdd_station_info *stainfo,
int idx)
{
struct nlattr *nla_attr;
nla_attr = nla_nest_start(skb, idx);
if (!nla_attr)
goto fail;
if (nla_put_u32(skb, NL80211_SURVEY_INFO_FREQUENCY,
stainfo->freq)) {
hdd_err("put fail");
goto fail;
}
nla_nest_end(skb, nla_attr);
return 0;
fail:
return -EINVAL;
}
/**
* hdd_add_tx_bitrate_sap_get_len - get data length used in
* hdd_add_tx_bitrate_sap()
*
* This function calculates the data length used in hdd_add_tx_bitrate_sap()
*
* Return: total data length used in hdd_add_tx_bitrate_sap()
*/
static uint32_t hdd_add_tx_bitrate_sap_get_len(void)
{
return ((NLA_HDRLEN) + (sizeof(uint8_t) + NLA_HDRLEN));
}
/**
* hdd_add_tx_bitrate_sap - add vhs nss info attribute
* @skb: pointer to response skb buffer
* @stainfo: station information
* @idx: attribute type index for nla_next_start()
*
* This function adds vht nss attribute to response skb buffer
*
* Return : 0 on success and errno on failure
*/
static int hdd_add_tx_bitrate_sap(struct sk_buff *skb,
struct hdd_station_info *stainfo,
int idx)
{
struct nlattr *nla_attr;
nla_attr = nla_nest_start(skb, idx);
if (!nla_attr)
goto fail;
if (nla_put_u8(skb, NL80211_RATE_INFO_VHT_NSS,
stainfo->nss)) {
hdd_err("put fail");
goto fail;
}
nla_nest_end(skb, nla_attr);
return 0;
fail:
return -EINVAL;
}
/**
* hdd_add_sta_info_sap_get_len - get data length used in
* hdd_add_sta_info_sap()
*
* This function calculates the data length used in hdd_add_sta_info_sap()
*
* Return: total data length used in hdd_add_sta_info_sap()
*/
static uint32_t hdd_add_sta_info_sap_get_len(void)
{
return ((NLA_HDRLEN) + (sizeof(uint8_t) + NLA_HDRLEN) +
hdd_add_tx_bitrate_sap_get_len());
}
/**
* hdd_add_sta_info_sap - add sta signal info attribute
* @skb: pointer to response skb buffer
* @stainfo: station information
* @idx: attribute type index for nla_next_start()
*
* This function adds sta signal attribute to response skb buffer
*
* Return : 0 on success and errno on failure
*/
static int32_t hdd_add_sta_info_sap(struct sk_buff *skb, int8_t rssi,
struct hdd_station_info *stainfo, int idx)
{
struct nlattr *nla_attr;
nla_attr = nla_nest_start(skb, idx);
if (!nla_attr)
goto fail;
if (nla_put_u8(skb, NL80211_STA_INFO_SIGNAL, rssi)) {
hdd_err("put fail");
goto fail;
}
if (hdd_add_tx_bitrate_sap(skb, stainfo, NL80211_STA_INFO_TX_BITRATE))
goto fail;
nla_nest_end(skb, nla_attr);
return 0;
fail:
return -EINVAL;
}
/**
* hdd_add_link_standard_info_sap_get_len - get data length used in
* hdd_add_link_standard_info_sap()
*
* This function calculates the data length used in
* hdd_add_link_standard_info_sap()
*
* Return: total data length used in hdd_add_link_standard_info_sap()
*/
static uint32_t hdd_add_link_standard_info_sap_get_len(void)
{
return ((NLA_HDRLEN) +
hdd_add_survey_info_sap_get_len() +
hdd_add_sta_info_sap_get_len() +
(sizeof(uint32_t) + NLA_HDRLEN));
}
/**
* hdd_add_link_standard_info_sap - add add link info attribut
* @skb: pointer to response skb buffer
* @stainfo: station information
* @idx: attribute type index for nla_next_start()
*
* This function adds link info attribut to response skb buffer
*
* Return : 0 on success and errno on failure
*/
static int hdd_add_link_standard_info_sap(struct sk_buff *skb, int8_t rssi,
struct hdd_station_info *stainfo,
int idx)
{
struct nlattr *nla_attr;
nla_attr = nla_nest_start(skb, idx);
if (!nla_attr)
goto fail;
if (hdd_add_survey_info_sap(skb, stainfo, NL80211_ATTR_SURVEY_INFO))
goto fail;
if (hdd_add_sta_info_sap(skb, rssi, stainfo, NL80211_ATTR_STA_INFO))
goto fail;
if (nla_put_u32(skb, NL80211_ATTR_REASON_CODE, stainfo->reason_code)) {
hdd_err("Reason code put fail");
goto fail;
}
nla_nest_end(skb, nla_attr);
return 0;
fail:
return -EINVAL;
}
/**
* hdd_add_ap_standard_info_sap_get_len - get data length used in
* hdd_add_ap_standard_info_sap()
* @stainfo: station information
*
* This function calculates the data length used in
* hdd_add_ap_standard_info_sap()
*
* Return: total data length used in hdd_add_ap_standard_info_sap()
*/
static uint32_t hdd_add_ap_standard_info_sap_get_len(
struct hdd_station_info *stainfo)
{
uint32_t len;
len = NLA_HDRLEN;
if (stainfo->vht_present)
len += (sizeof(stainfo->vht_caps) + NLA_HDRLEN);
if (stainfo->ht_present)
len += (sizeof(stainfo->ht_caps) + NLA_HDRLEN);
return len;
}
/**
* hdd_add_ap_standard_info_sap - add HT and VHT info attributes
* @skb: pointer to response skb buffer
* @stainfo: station information
* @idx: attribute type index for nla_next_start()
*
* This function adds HT and VHT info attributes to response skb buffer
*
* Return : 0 on success and errno on failure
*/
static int hdd_add_ap_standard_info_sap(struct sk_buff *skb,
struct hdd_station_info *stainfo,
int idx)
{
struct nlattr *nla_attr;
nla_attr = nla_nest_start(skb, idx);
if (!nla_attr)
goto fail;
if (stainfo->vht_present) {
if (nla_put(skb, NL80211_ATTR_VHT_CAPABILITY,
sizeof(stainfo->vht_caps),
&stainfo->vht_caps)) {
hdd_err("put fail");
goto fail;
}
}
if (stainfo->ht_present) {
if (nla_put(skb, NL80211_ATTR_HT_CAPABILITY,
sizeof(stainfo->ht_caps),
&stainfo->ht_caps)) {
hdd_err("put fail");
goto fail;
}
}
nla_nest_end(skb, nla_attr);
return 0;
fail:
return -EINVAL;
}
/**
* hdd_decode_ch_width - decode channel band width based
* @ch_width: encoded enum value holding channel band width
*
* This function decodes channel band width from the given encoded enum value.
*
* Returns: decoded channel band width.
*/
static uint8_t hdd_decode_ch_width(tSirMacHTChannelWidth ch_width)
{
switch (ch_width) {
case 0:
return 20;
case 1:
return 40;
case 2:
return 80;
case 3:
case 4:
return 160;
default:
hdd_debug("invalid enum: %d", ch_width);
return 20;
}
}
/**
* hdd_get_cached_station_remote() - get cached(deleted) peer's info
* @hdd_ctx: hdd context
* @adapter: hostapd interface
* @mac_addr: mac address of requested peer
*
* This function collect and indicate the remote peer's info
* This function collect and indicate the cached(deleted) peer's info
*
* Return: 0 on success, otherwise error value
*/
static int hdd_get_station_remote(struct hdd_context *hdd_ctx,
struct hdd_adapter *adapter,
struct qdf_mac_addr mac_addr)
static int hdd_get_cached_station_remote(struct hdd_context *hdd_ctx,
struct hdd_adapter *adapter,
struct qdf_mac_addr mac_addr)
{
struct hdd_station_info *stainfo = hdd_get_stainfo(adapter->sta_info,
mac_addr);
struct hdd_station_info *stainfo = hdd_get_stainfo(
adapter->cache_sta_info,
mac_addr);
struct sk_buff *skb = NULL;
struct sir_peer_info_ext peer_info;
uint32_t nl_buf_len;
bool txrx_rate = true;
uint32_t nl_buf_len = NLMSG_HDRLEN;
uint8_t channel_width;
if (!stainfo) {
hdd_err("peer " MAC_ADDRESS_STR " not found",
MAC_ADDR_ARRAY(mac_addr.bytes));
return -EINVAL;
}
nl_buf_len += hdd_add_link_standard_info_sap_get_len() +
hdd_add_ap_standard_info_sap_get_len(stainfo) +
(sizeof(stainfo->mode) + NLA_HDRLEN) +
(sizeof(stainfo->ch_width) + NLA_HDRLEN) +
(sizeof(stainfo->tx_rate) + NLA_HDRLEN) +
(sizeof(stainfo->rx_rate) + NLA_HDRLEN);
skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
if (!skb) {
hdd_err(FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
return -ENOMEM;
}
if (hdd_add_link_standard_info_sap(skb, stainfo->rssi, stainfo,
LINK_INFO_STANDARD_NL80211_ATTR)) {
hdd_err("link standard put fail");
goto fail;
}
if (hdd_add_ap_standard_info_sap(skb, stainfo,
AP_INFO_STANDARD_NL80211_ATTR)) {
hdd_err("ap standard put fail");
goto fail;
}
/* upper layer expects decoded channel BW */
channel_width = hdd_decode_ch_width(stainfo->ch_width);
if (nla_put_u32(skb, REMOTE_SUPPORTED_MODE,
hdd_convert_dot11mode(
stainfo->mode)) ||
nla_put_u8(skb, REMOTE_CH_WIDTH, channel_width)) {
hdd_err("remote ch put fail");
goto fail;
}
if (nla_put_u32(skb, REMOTE_LAST_TX_RATE, stainfo->tx_rate)) {
hdd_err("tx rate put fail");
goto fail;
}
if (nla_put_u32(skb, REMOTE_LAST_RX_RATE, stainfo->rx_rate)) {
hdd_err("rx rate put fail");
goto fail;
}
qdf_mem_zero(stainfo, sizeof(*stainfo));
return cfg80211_vendor_cmd_reply(skb);
fail:
if (skb)
kfree_skb(skb);
return -EINVAL;
}
/**
* hdd_get_cached_station_remote() - get connected peer's info
* @hdd_ctx: hdd context
* @adapter: hostapd interface
* @mac_addr: mac address of requested peer
*
* This function collect and indicate the connected peer's info
*
* Return: 0 on success, otherwise error value
*/
static int hdd_get_connected_station_info(struct hdd_context *hdd_ctx,
struct hdd_adapter *adapter,
struct qdf_mac_addr mac_addr,
struct hdd_station_info *stainfo)
{
struct sk_buff *skb = NULL;
uint32_t nl_buf_len;
struct sir_peer_info_ext peer_info;
bool txrx_rate = true;
nl_buf_len = NLMSG_HDRLEN;
nl_buf_len += (sizeof(stainfo->max_phy_rate) + NLA_HDRLEN) +
(sizeof(stainfo->tx_packets) + NLA_HDRLEN) +
@@ -5082,6 +5434,43 @@ fail:
return -EINVAL;
}
/**
* hdd_get_station_remote() - get remote peer's info
* @hdd_ctx: hdd context
* @adapter: hostapd interface
* @mac_addr: mac address of requested peer
*
* This function collect and indicate the remote peer's info
*
* Return: 0 on success, otherwise error value
*/
static int hdd_get_station_remote(struct hdd_context *hdd_ctx,
struct hdd_adapter *adapter,
struct qdf_mac_addr mac_addr)
{
struct hdd_station_info *stainfo = hdd_get_stainfo(adapter->sta_info,
mac_addr);
int status = 0;
bool is_associated = false;
if (!stainfo) {
status = hdd_get_cached_station_remote(hdd_ctx, adapter,
mac_addr);
return status;
}
is_associated = hdd_is_peer_associated(adapter, &mac_addr);
if (!is_associated) {
status = hdd_get_cached_station_remote(hdd_ctx, adapter,
mac_addr);
return status;
}
status = hdd_get_connected_station_info(hdd_ctx, adapter,
mac_addr, stainfo);
return status;
}
/**
* __hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
* @wiphy: corestack handler