mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2025-01-03 19:02:34 +01:00
netdev: add netdev_get_station/current_station
This adds a generalized API for GET_STATION. This API handles calling and parsing the results into a new structure, netdev_station_info. This results structure will hold any data needed by consumers of netdev_get_station. A helper API (netdev_get_current_station) was added as a convenience which automatically passes handshake->aa as the MAC. For now only the RSSI is parsed as this is already being done for RSSI polling/events. Looking further more info will be added such as rx/tx rates and estimated throughput.
This commit is contained in:
parent
09b124f073
commit
cf17d42972
122
src/netdev.c
122
src/netdev.c
@ -132,6 +132,11 @@ struct netdev {
|
|||||||
void *set_powered_user_data;
|
void *set_powered_user_data;
|
||||||
netdev_destroy_func_t set_powered_destroy;
|
netdev_destroy_func_t set_powered_destroy;
|
||||||
|
|
||||||
|
uint32_t get_station_cmd_id;
|
||||||
|
netdev_get_station_cb_t get_station_cb;
|
||||||
|
void *get_station_data;
|
||||||
|
netdev_destroy_func_t get_station_destroy;
|
||||||
|
|
||||||
struct watchlist station_watches;
|
struct watchlist station_watches;
|
||||||
|
|
||||||
struct l_io *pae_io; /* for drivers without EAPoL over NL80211 */
|
struct l_io *pae_io; /* for drivers without EAPoL over NL80211 */
|
||||||
@ -363,6 +368,28 @@ int netdev_set_powered(struct netdev *netdev, bool powered,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool netdev_parse_sta_info(struct l_genl_attr *attr,
|
||||||
|
struct netdev_station_info *info)
|
||||||
|
{
|
||||||
|
uint16_t type, len;
|
||||||
|
const void *data;
|
||||||
|
|
||||||
|
while (l_genl_attr_next(attr, &type, &len, &data)) {
|
||||||
|
switch (type) {
|
||||||
|
case NL80211_STA_INFO_SIGNAL_AVG:
|
||||||
|
if (len != 1)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
info->cur_rssi = *(const int8_t *) data;
|
||||||
|
info->have_cur_rssi = true;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static void netdev_set_rssi_level_idx(struct netdev *netdev)
|
static void netdev_set_rssi_level_idx(struct netdev *netdev)
|
||||||
{
|
{
|
||||||
uint8_t new_level;
|
uint8_t new_level;
|
||||||
@ -636,6 +663,11 @@ static void netdev_free(void *data)
|
|||||||
netdev->mac_change_cmd_id = 0;
|
netdev->mac_change_cmd_id = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (netdev->get_station_cmd_id) {
|
||||||
|
l_genl_family_cancel(nl80211, netdev->get_station_cmd_id);
|
||||||
|
netdev->get_station_cmd_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (netdev->events_ready)
|
if (netdev->events_ready)
|
||||||
WATCHLIST_NOTIFY(&netdev_watches, netdev_watch_func_t,
|
WATCHLIST_NOTIFY(&netdev_watches, netdev_watch_func_t,
|
||||||
netdev, NETDEV_WATCH_EVENT_DEL);
|
netdev, NETDEV_WATCH_EVENT_DEL);
|
||||||
@ -4022,6 +4054,96 @@ done:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void netdev_get_station_cb(struct l_genl_msg *msg, void *user_data)
|
||||||
|
{
|
||||||
|
struct netdev *netdev = user_data;
|
||||||
|
struct l_genl_attr attr, nested;
|
||||||
|
uint16_t type, len;
|
||||||
|
const void *data;
|
||||||
|
struct netdev_station_info info;
|
||||||
|
|
||||||
|
netdev->get_station_cmd_id = 0;
|
||||||
|
|
||||||
|
if (!l_genl_attr_init(&attr, msg))
|
||||||
|
goto parse_error;
|
||||||
|
|
||||||
|
while (l_genl_attr_next(&attr, &type, &len, &data)) {
|
||||||
|
switch (type) {
|
||||||
|
case NL80211_ATTR_STA_INFO:
|
||||||
|
if (!l_genl_attr_recurse(&attr, &nested))
|
||||||
|
goto parse_error;
|
||||||
|
|
||||||
|
if (!netdev_parse_sta_info(&nested, &info))
|
||||||
|
goto parse_error;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NL80211_ATTR_MAC:
|
||||||
|
if (len != 6)
|
||||||
|
goto parse_error;
|
||||||
|
|
||||||
|
memcpy(info.addr, data, 6);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (netdev->get_station_cb)
|
||||||
|
netdev->get_station_cb(&info, netdev->get_station_data);
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
parse_error:
|
||||||
|
if (netdev->get_station_cb)
|
||||||
|
netdev->get_station_cb(NULL, netdev->get_station_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void netdev_get_station_destroy(void *user_data)
|
||||||
|
{
|
||||||
|
struct netdev *netdev = user_data;
|
||||||
|
|
||||||
|
netdev->get_station_cmd_id = 0;
|
||||||
|
|
||||||
|
if (netdev->get_station_destroy)
|
||||||
|
netdev->get_station_destroy(netdev->get_station_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
int netdev_get_station(struct netdev *netdev, const uint8_t *mac,
|
||||||
|
netdev_get_station_cb_t cb, void *user_data,
|
||||||
|
netdev_destroy_func_t destroy)
|
||||||
|
{
|
||||||
|
struct l_genl_msg *msg;
|
||||||
|
|
||||||
|
if (netdev->get_station_cmd_id)
|
||||||
|
return -EBUSY;
|
||||||
|
|
||||||
|
msg = l_genl_msg_new_sized(NL80211_CMD_GET_STATION, 64);
|
||||||
|
l_genl_msg_append_attr(msg, NL80211_ATTR_IFINDEX, 4, &netdev->index);
|
||||||
|
l_genl_msg_append_attr(msg, NL80211_ATTR_MAC, ETH_ALEN, mac);
|
||||||
|
|
||||||
|
netdev->get_station_cmd_id = l_genl_family_send(nl80211, msg,
|
||||||
|
netdev_get_station_cb, netdev,
|
||||||
|
netdev_get_station_destroy);
|
||||||
|
if (!netdev->get_station_cmd_id) {
|
||||||
|
l_genl_msg_unref(msg);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
netdev->get_station_cb = cb;
|
||||||
|
netdev->get_station_data = user_data;
|
||||||
|
netdev->get_station_destroy = destroy;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int netdev_get_current_station(struct netdev *netdev,
|
||||||
|
netdev_get_station_cb_t cb, void *user_data,
|
||||||
|
netdev_destroy_func_t destroy)
|
||||||
|
{
|
||||||
|
return netdev_get_station(netdev, netdev->handshake->aa, cb,
|
||||||
|
user_data, destroy);
|
||||||
|
}
|
||||||
|
|
||||||
static int netdev_cqm_rssi_update(struct netdev *netdev)
|
static int netdev_cqm_rssi_update(struct netdev *netdev)
|
||||||
{
|
{
|
||||||
struct l_genl_msg *msg;
|
struct l_genl_msg *msg;
|
||||||
|
17
src/netdev.h
17
src/netdev.h
@ -114,6 +114,16 @@ typedef void (*netdev_station_watch_func_t)(struct netdev *netdev,
|
|||||||
const uint8_t *mac, bool added,
|
const uint8_t *mac, bool added,
|
||||||
void *user_data);
|
void *user_data);
|
||||||
|
|
||||||
|
struct netdev_station_info {
|
||||||
|
uint8_t addr[6];
|
||||||
|
int8_t cur_rssi;
|
||||||
|
|
||||||
|
bool have_cur_rssi : 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef void (*netdev_get_station_cb_t)(const struct netdev_station_info *info,
|
||||||
|
void *user_data);
|
||||||
|
|
||||||
struct wiphy *netdev_get_wiphy(struct netdev *netdev);
|
struct wiphy *netdev_get_wiphy(struct netdev *netdev);
|
||||||
const uint8_t *netdev_get_address(struct netdev *netdev);
|
const uint8_t *netdev_get_address(struct netdev *netdev);
|
||||||
uint32_t netdev_get_ifindex(struct netdev *netdev);
|
uint32_t netdev_get_ifindex(struct netdev *netdev);
|
||||||
@ -174,6 +184,13 @@ int netdev_neighbor_report_req(struct netdev *netdev,
|
|||||||
int netdev_set_rssi_report_levels(struct netdev *netdev, const int8_t *levels,
|
int netdev_set_rssi_report_levels(struct netdev *netdev, const int8_t *levels,
|
||||||
size_t levels_num);
|
size_t levels_num);
|
||||||
|
|
||||||
|
int netdev_get_station(struct netdev *netdev, const uint8_t *mac,
|
||||||
|
netdev_get_station_cb_t cb, void *user_data,
|
||||||
|
netdev_destroy_func_t destroy);
|
||||||
|
int netdev_get_current_station(struct netdev *netdev,
|
||||||
|
netdev_get_station_cb_t cb, void *user_data,
|
||||||
|
netdev_destroy_func_t destroy);
|
||||||
|
|
||||||
void netdev_handshake_failed(struct handshake_state *hs, uint16_t reason_code);
|
void netdev_handshake_failed(struct handshake_state *hs, uint16_t reason_code);
|
||||||
|
|
||||||
struct netdev *netdev_find(int ifindex);
|
struct netdev *netdev_find(int ifindex);
|
||||||
|
Loading…
Reference in New Issue
Block a user