mirror of
https://github.com/Telecominfraproject/wlan-ap.git
synced 2025-12-17 17:31:27 +00:00
opensync: add average STA RSSI tracking
Track the average RSSI of associated stations. This information can be used to deauth stations if their rssi gets too low. Signed-off-by: John Crispin <john@phrozen.org>
This commit is contained in:
parent
24a3c6e6e7
commit
fdf5bb6e96
@ -33,6 +33,7 @@ struct wifi_phy {
|
|||||||
struct wifi_iface {
|
struct wifi_iface {
|
||||||
struct avl_node avl;
|
struct avl_node avl;
|
||||||
uint8_t addr[6];
|
uint8_t addr[6];
|
||||||
|
int ifidx;
|
||||||
int noise;
|
int noise;
|
||||||
char name[IF_NAMESIZE];
|
char name[IF_NAMESIZE];
|
||||||
struct wifi_phy *parent;
|
struct wifi_phy *parent;
|
||||||
@ -45,6 +46,12 @@ struct wifi_station {
|
|||||||
uint8_t addr[6];
|
uint8_t addr[6];
|
||||||
struct wifi_iface *parent;
|
struct wifi_iface *parent;
|
||||||
struct list_head iface;
|
struct list_head iface;
|
||||||
|
|
||||||
|
int8_t rssi;
|
||||||
|
uint32_t rx_packets;
|
||||||
|
uint32_t tx_packets;
|
||||||
|
uint32_t rx_bytes;
|
||||||
|
uint32_t tx_bytes;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern int radio_nl80211_init(void);
|
extern int radio_nl80211_init(void);
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <evsched.h>
|
||||||
|
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
|
|
||||||
@ -124,6 +125,44 @@ static void vif_del_sta_rate_rule(uint8_t *addr, char *ifname)
|
|||||||
free(rule);
|
free(rule);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void vif_update_stats(struct wifi_station *sta, struct nlattr **tb)
|
||||||
|
{
|
||||||
|
static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
|
||||||
|
[NL80211_STA_INFO_INACTIVE_TIME] = { .type = NLA_U32 },
|
||||||
|
[NL80211_STA_INFO_RX_PACKETS] = { .type = NLA_U32 },
|
||||||
|
[NL80211_STA_INFO_TX_PACKETS] = { .type = NLA_U32 },
|
||||||
|
[NL80211_STA_INFO_RX_BITRATE] = { .type = NLA_NESTED },
|
||||||
|
[NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED },
|
||||||
|
[NL80211_STA_INFO_SIGNAL] = { .type = NLA_U8 },
|
||||||
|
[NL80211_STA_INFO_SIGNAL_AVG] = { .type = NLA_U8 },
|
||||||
|
[NL80211_STA_INFO_RX_BYTES] = { .type = NLA_U32 },
|
||||||
|
[NL80211_STA_INFO_TX_BYTES] = { .type = NLA_U32 },
|
||||||
|
[NL80211_STA_INFO_TX_RETRIES] = { .type = NLA_U32 },
|
||||||
|
[NL80211_STA_INFO_TX_FAILED] = { .type = NLA_U32 },
|
||||||
|
[NL80211_STA_INFO_T_OFFSET] = { .type = NLA_U64 },
|
||||||
|
[NL80211_STA_INFO_STA_FLAGS] =
|
||||||
|
{ .minlen = sizeof(struct nl80211_sta_flag_update) },
|
||||||
|
};
|
||||||
|
|
||||||
|
struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1] = { };
|
||||||
|
|
||||||
|
if (!tb[NL80211_ATTR_STA_INFO])
|
||||||
|
return;
|
||||||
|
if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
|
||||||
|
tb[NL80211_ATTR_STA_INFO], stats_policy))
|
||||||
|
return;
|
||||||
|
if (sinfo[NL80211_STA_INFO_SIGNAL_AVG])
|
||||||
|
sta->rssi = (int32_t) nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
|
||||||
|
if (sinfo[NL80211_STA_INFO_RX_PACKETS])
|
||||||
|
sta->rx_packets = nla_get_u32(sinfo[NL80211_STA_INFO_RX_PACKETS]);
|
||||||
|
if (sinfo[NL80211_STA_INFO_TX_PACKETS])
|
||||||
|
sta->tx_packets = nla_get_u32(sinfo[NL80211_STA_INFO_TX_PACKETS]);
|
||||||
|
if (sinfo[NL80211_STA_INFO_RX_BYTES])
|
||||||
|
sta->rx_bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
|
||||||
|
if (sinfo[NL80211_STA_INFO_TX_BYTES])
|
||||||
|
sta->tx_bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
|
||||||
|
}
|
||||||
|
|
||||||
static void nl80211_add_station(struct nlattr **tb, char *ifname)
|
static void nl80211_add_station(struct nlattr **tb, char *ifname)
|
||||||
{
|
{
|
||||||
struct wifi_station *sta;
|
struct wifi_station *sta;
|
||||||
@ -135,8 +174,10 @@ static void nl80211_add_station(struct nlattr **tb, char *ifname)
|
|||||||
|
|
||||||
addr = nla_data(tb[NL80211_ATTR_MAC]);
|
addr = nla_data(tb[NL80211_ATTR_MAC]);
|
||||||
sta = avl_find_element(&sta_tree, addr, sta, avl);
|
sta = avl_find_element(&sta_tree, addr, sta, avl);
|
||||||
if (sta)
|
if (sta) {
|
||||||
|
vif_update_stats(sta, tb);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
wif = avl_find_element(&wif_tree, ifname, wif, avl);
|
wif = avl_find_element(&wif_tree, ifname, wif, avl);
|
||||||
if (!wif)
|
if (!wif)
|
||||||
@ -154,6 +195,7 @@ static void nl80211_add_station(struct nlattr **tb, char *ifname)
|
|||||||
|
|
||||||
vif_add_station(sta, ifname, 1);
|
vif_add_station(sta, ifname, 1);
|
||||||
vif_add_sta_rate_rule(addr, ifname);
|
vif_add_sta_rate_rule(addr, ifname);
|
||||||
|
vif_update_stats(sta, tb);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _nl80211_del_station(struct wifi_station *sta)
|
static void _nl80211_del_station(struct wifi_station *sta)
|
||||||
@ -182,7 +224,7 @@ static void nl80211_del_station(struct nlattr **tb, char *ifname)
|
|||||||
_nl80211_del_station(sta);
|
_nl80211_del_station(sta);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void nl80211_add_iface(struct nlattr **tb, char *ifname, char *phyname)
|
static void nl80211_add_iface(struct nlattr **tb, char *ifname, char *phyname, int ifidx)
|
||||||
{
|
{
|
||||||
struct wifi_iface *wif;
|
struct wifi_iface *wif;
|
||||||
uint8_t *addr;
|
uint8_t *addr;
|
||||||
@ -206,6 +248,7 @@ static void nl80211_add_iface(struct nlattr **tb, char *ifname, char *phyname)
|
|||||||
INIT_LIST_HEAD(&wif->stas);
|
INIT_LIST_HEAD(&wif->stas);
|
||||||
avl_insert(&wif_tree, &wif->avl);
|
avl_insert(&wif_tree, &wif->avl);
|
||||||
memcpy(wif->addr, addr, 6);
|
memcpy(wif->addr, addr, 6);
|
||||||
|
wif->ifidx = ifidx;
|
||||||
wif->parent = avl_find_element(&phy_tree, phyname, wif->parent, avl);
|
wif->parent = avl_find_element(&phy_tree, phyname, wif->parent, avl);
|
||||||
if (wif->parent)
|
if (wif->parent)
|
||||||
list_add(&wif->phy, &wif->parent->wifs);
|
list_add(&wif->phy, &wif->parent->wifs);
|
||||||
@ -378,7 +421,7 @@ static int nl80211_recv(struct nl_msg *msg, void *arg)
|
|||||||
nl80211_del_station(tb, ifname);
|
nl80211_del_station(tb, ifname);
|
||||||
break;
|
break;
|
||||||
case NL80211_CMD_NEW_INTERFACE:
|
case NL80211_CMD_NEW_INTERFACE:
|
||||||
nl80211_add_iface(tb, ifname, phyname);
|
nl80211_add_iface(tb, ifname, phyname, ifidx);
|
||||||
break;
|
break;
|
||||||
case NL80211_CMD_DEL_INTERFACE:
|
case NL80211_CMD_DEL_INTERFACE:
|
||||||
nl80211_del_iface(tb, ifname);
|
nl80211_del_iface(tb, ifname);
|
||||||
@ -391,7 +434,7 @@ static int nl80211_recv(struct nl_msg *msg, void *arg)
|
|||||||
nl80211_add_phy(tb, phyname);
|
nl80211_add_phy(tb, phyname);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
//syslog(0, "%s:%s[%d]%d\n", __FILE__, __func__, __LINE__, gnlh->cmd);
|
syslog(0, "%s:%s[%d]%d\n", __FILE__, __func__, __LINE__, gnlh->cmd);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -426,6 +469,20 @@ static void nl80211_ev(struct ev_loop *ev, struct ev_io *io, int event)
|
|||||||
nl_cb_put(cb);
|
nl_cb_put(cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void vif_poll_stations(void *arg)
|
||||||
|
{
|
||||||
|
struct wifi_iface *wif = NULL;
|
||||||
|
|
||||||
|
avl_for_each_element(&wif_tree, wif, avl) {
|
||||||
|
struct nl_msg *msg;
|
||||||
|
|
||||||
|
msg = unl_genl_msg(&unl, NL80211_CMD_GET_STATION, true);
|
||||||
|
nla_put_u32(msg, NL80211_ATTR_IFINDEX, wif->ifidx);
|
||||||
|
unl_genl_request(&unl, msg, nl80211_recv, NULL);
|
||||||
|
}
|
||||||
|
evsched_task_reschedule_ms(EVSCHED_SEC(10));
|
||||||
|
}
|
||||||
|
|
||||||
int radio_nl80211_init(void)
|
int radio_nl80211_init(void)
|
||||||
{
|
{
|
||||||
struct nl_msg *msg;
|
struct nl_msg *msg;
|
||||||
@ -439,8 +496,6 @@ int radio_nl80211_init(void)
|
|||||||
unl_genl_request(&unl, msg, nl80211_recv, NULL);
|
unl_genl_request(&unl, msg, nl80211_recv, NULL);
|
||||||
msg = unl_genl_msg(&unl, NL80211_CMD_GET_INTERFACE, true);
|
msg = unl_genl_msg(&unl, NL80211_CMD_GET_INTERFACE, true);
|
||||||
unl_genl_request(&unl, msg, nl80211_recv, NULL);
|
unl_genl_request(&unl, msg, nl80211_recv, NULL);
|
||||||
msg = unl_genl_msg(&unl, NL80211_CMD_GET_STATION, true);
|
|
||||||
unl_genl_request(&unl, msg, nl80211_recv, NULL);
|
|
||||||
|
|
||||||
unl_genl_subscribe(&unl, "config");
|
unl_genl_subscribe(&unl, "config");
|
||||||
unl_genl_subscribe(&unl, "mlme");
|
unl_genl_subscribe(&unl, "mlme");
|
||||||
@ -448,6 +503,7 @@ int radio_nl80211_init(void)
|
|||||||
|
|
||||||
ev_io_init(&unl_io, nl80211_ev, unl.sock->s_fd, EV_READ);
|
ev_io_init(&unl_io, nl80211_ev, unl.sock->s_fd, EV_READ);
|
||||||
ev_io_start(wifihal_evloop, &unl_io);
|
ev_io_start(wifihal_evloop, &unl_io);
|
||||||
|
evsched_task(&vif_poll_stations, NULL, EVSCHED_SEC(5));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user