netdev: Monitor CQM RSSI level, emit RSSI LOW/HIGH events
This commit is contained in:
parent
fbb7a72643
commit
c36d0fcfa4
|
@ -619,6 +619,9 @@ static void device_netdev_event(struct netdev *netdev, enum netdev_event event,
|
||||||
case NETDEV_EVENT_DISCONNECT_BY_SME:
|
case NETDEV_EVENT_DISCONNECT_BY_SME:
|
||||||
device_disassociated(device);
|
device_disassociated(device);
|
||||||
break;
|
break;
|
||||||
|
case NETDEV_EVENT_RSSI_THRESHOLD_LOW:
|
||||||
|
case NETDEV_EVENT_RSSI_THRESHOLD_HIGH:
|
||||||
|
break;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
62
src/netdev.c
62
src/netdev.c
|
@ -410,6 +410,26 @@ static void netdev_lost_beacon(struct netdev *netdev)
|
||||||
netdev_connect_free(netdev);
|
netdev_connect_free(netdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void netdev_rssi_threshold(struct netdev *netdev, uint32_t rssi_event)
|
||||||
|
{
|
||||||
|
if (!netdev->connected)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (rssi_event != NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW &&
|
||||||
|
rssi_event != NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (netdev->event_filter) {
|
||||||
|
int event;
|
||||||
|
|
||||||
|
event = (rssi_event == NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW) ?
|
||||||
|
NETDEV_EVENT_RSSI_THRESHOLD_LOW :
|
||||||
|
NETDEV_EVENT_RSSI_THRESHOLD_HIGH;
|
||||||
|
|
||||||
|
netdev->event_filter(netdev, event, netdev->user_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void netdev_cqm_event(struct l_genl_msg *msg, struct netdev *netdev)
|
static void netdev_cqm_event(struct l_genl_msg *msg, struct netdev *netdev)
|
||||||
{
|
{
|
||||||
struct l_genl_attr attr;
|
struct l_genl_attr attr;
|
||||||
|
@ -431,6 +451,14 @@ static void netdev_cqm_event(struct l_genl_msg *msg, struct netdev *netdev)
|
||||||
case NL80211_ATTR_CQM_BEACON_LOSS_EVENT:
|
case NL80211_ATTR_CQM_BEACON_LOSS_EVENT:
|
||||||
netdev_lost_beacon(netdev);
|
netdev_lost_beacon(netdev);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT:
|
||||||
|
if (len != 4)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
netdev_rssi_threshold(netdev,
|
||||||
|
*(uint32_t *) data);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1979,6 +2007,29 @@ static void netdev_register_frame(struct netdev *netdev, uint16_t frame_type,
|
||||||
l_genl_family_send(nl80211, msg, NULL, NULL, NULL);
|
l_genl_family_send(nl80211, msg, NULL, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct l_genl_msg *netdev_build_cmd_set_cqm_rssi(struct netdev *netdev)
|
||||||
|
{
|
||||||
|
struct l_genl_msg *msg;
|
||||||
|
/* -70 dBm is a popular choice for low signal threshold */
|
||||||
|
int32_t thold = -70;
|
||||||
|
uint32_t hyst = 5;
|
||||||
|
|
||||||
|
msg = l_genl_msg_new_sized(NL80211_CMD_SET_CQM, 128);
|
||||||
|
l_genl_msg_append_attr(msg, NL80211_ATTR_IFINDEX, 4, &netdev->index);
|
||||||
|
l_genl_msg_enter_nested(msg, NL80211_ATTR_CQM);
|
||||||
|
l_genl_msg_append_attr(msg, NL80211_ATTR_CQM_RSSI_THOLD, 4, &thold);
|
||||||
|
l_genl_msg_append_attr(msg, NL80211_ATTR_CQM_RSSI_HYST, 4, &hyst);
|
||||||
|
l_genl_msg_leave_nested(msg);
|
||||||
|
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void netdev_cmd_set_cqm_cb(struct l_genl_msg *msg, void *user_data)
|
||||||
|
{
|
||||||
|
if (l_genl_msg_get_error(msg) < 0)
|
||||||
|
l_error("CMD_SET_CQM failed");
|
||||||
|
}
|
||||||
|
|
||||||
static void netdev_create_from_genl(struct l_genl_msg *msg)
|
static void netdev_create_from_genl(struct l_genl_msg *msg)
|
||||||
{
|
{
|
||||||
struct l_genl_attr attr;
|
struct l_genl_attr attr;
|
||||||
|
@ -1993,6 +2044,7 @@ static void netdev_create_from_genl(struct l_genl_msg *msg)
|
||||||
struct ifinfomsg *rtmmsg;
|
struct ifinfomsg *rtmmsg;
|
||||||
size_t bufsize;
|
size_t bufsize;
|
||||||
const uint8_t action_neighbor_report_prefix[2] = { 0x05, 0x05 };
|
const uint8_t action_neighbor_report_prefix[2] = { 0x05, 0x05 };
|
||||||
|
struct l_genl_msg *set_cqm_msg;
|
||||||
|
|
||||||
if (!l_genl_attr_init(&attr, msg))
|
if (!l_genl_attr_init(&attr, msg))
|
||||||
return;
|
return;
|
||||||
|
@ -2108,6 +2160,16 @@ static void netdev_create_from_genl(struct l_genl_msg *msg)
|
||||||
/* Subscribe to Management -> Action -> RM -> Neighbor Report frames */
|
/* Subscribe to Management -> Action -> RM -> Neighbor Report frames */
|
||||||
netdev_register_frame(netdev, 0x00d0, action_neighbor_report_prefix,
|
netdev_register_frame(netdev, 0x00d0, action_neighbor_report_prefix,
|
||||||
sizeof(action_neighbor_report_prefix));
|
sizeof(action_neighbor_report_prefix));
|
||||||
|
|
||||||
|
/* Set RSSI threshold for CQM notifications */
|
||||||
|
set_cqm_msg = netdev_build_cmd_set_cqm_rssi(netdev);
|
||||||
|
|
||||||
|
if (!l_genl_family_send(nl80211, set_cqm_msg, netdev_cmd_set_cqm_cb,
|
||||||
|
NULL, NULL)) {
|
||||||
|
l_error("CMD_SET_CQM failed");
|
||||||
|
|
||||||
|
l_genl_msg_unref(set_cqm_msg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void netdev_get_interface_callback(struct l_genl_msg *msg,
|
static void netdev_get_interface_callback(struct l_genl_msg *msg,
|
||||||
|
|
|
@ -44,6 +44,8 @@ enum netdev_event {
|
||||||
NETDEV_EVENT_LOST_BEACON,
|
NETDEV_EVENT_LOST_BEACON,
|
||||||
NETDEV_EVENT_DISCONNECT_BY_AP,
|
NETDEV_EVENT_DISCONNECT_BY_AP,
|
||||||
NETDEV_EVENT_DISCONNECT_BY_SME,
|
NETDEV_EVENT_DISCONNECT_BY_SME,
|
||||||
|
NETDEV_EVENT_RSSI_THRESHOLD_LOW,
|
||||||
|
NETDEV_EVENT_RSSI_THRESHOLD_HIGH,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum netdev_watch_event {
|
enum netdev_watch_event {
|
||||||
|
|
Loading…
Reference in New Issue