mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2024-11-24 00:09:26 +01:00
dpp: tie frame registration to DPP state
Similar to several other modules DPP registers for its frame watches on init then ignores anything is receives unless DPP is actually running. Due to some recent issues surrounding ath10k and multicast frames it was discovered that simply registering for multicast RX frames causes a significant performance impact depending on the current channel load. Regardless of the impact to a single driver, it is actually more efficient to only register for the DPP frames when DPP starts rather than when IWD initializes. This prevents any of the frames from hitting userspace which would otherwise be ignored. Using the frame-xchg group ID's we can only register for DPP frames when needed, then close that group and the associated frame watches.
This commit is contained in:
parent
354bce64dd
commit
ca9b7ccaf6
150
src/dpp.c
150
src/dpp.c
@ -66,7 +66,6 @@ static struct l_genl_family *nl80211;
|
|||||||
static uint8_t broadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
static uint8_t broadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||||
static struct l_queue *dpp_list;
|
static struct l_queue *dpp_list;
|
||||||
static uint32_t mlme_watch;
|
static uint32_t mlme_watch;
|
||||||
static uint32_t unicast_watch;
|
|
||||||
|
|
||||||
static uint8_t dpp_prefix[] = { 0x04, 0x09, 0x50, 0x6f, 0x9a, 0x1a, 0x01 };
|
static uint8_t dpp_prefix[] = { 0x04, 0x09, 0x50, 0x6f, 0x9a, 0x1a, 0x01 };
|
||||||
|
|
||||||
@ -552,6 +551,8 @@ static void dpp_reset(struct dpp_sm *dpp)
|
|||||||
|
|
||||||
dpp_property_changed_notify(dpp);
|
dpp_property_changed_notify(dpp);
|
||||||
|
|
||||||
|
frame_watch_group_remove(dpp->wdev_id, FRAME_GROUP_DPP);
|
||||||
|
|
||||||
dpp->interface = DPP_INTERFACE_UNBOUND;
|
dpp->interface = DPP_INTERFACE_UNBOUND;
|
||||||
|
|
||||||
if (station) {
|
if (station) {
|
||||||
@ -3475,10 +3476,11 @@ failed:
|
|||||||
dpp_reset(dpp);
|
dpp_reset(dpp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dpp_handle_frame(struct dpp_sm *dpp,
|
static void dpp_handle_frame(const struct mmpdu_header *frame,
|
||||||
const struct mmpdu_header *frame,
|
const void *body, size_t body_len,
|
||||||
const void *body, size_t body_len)
|
int rssi, void *user_data)
|
||||||
{
|
{
|
||||||
|
struct dpp_sm *dpp = user_data;
|
||||||
const uint8_t *ptr;
|
const uint8_t *ptr;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -3638,99 +3640,6 @@ retransmit:
|
|||||||
dpp_frame_timeout, dpp, NULL);
|
dpp_frame_timeout, dpp, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dpp_unicast_notify(struct l_genl_msg *msg, void *user_data)
|
|
||||||
{
|
|
||||||
struct dpp_sm *dpp;
|
|
||||||
const uint64_t *wdev_id = NULL;
|
|
||||||
struct l_genl_attr attr;
|
|
||||||
uint16_t type, len, frame_len;
|
|
||||||
const void *data;
|
|
||||||
const struct mmpdu_header *mpdu = NULL;
|
|
||||||
const uint8_t *body;
|
|
||||||
size_t body_len;
|
|
||||||
|
|
||||||
if (l_genl_msg_get_command(msg) != NL80211_CMD_FRAME)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!l_genl_attr_init(&attr, msg))
|
|
||||||
return;
|
|
||||||
|
|
||||||
while (l_genl_attr_next(&attr, &type, &len, &data)) {
|
|
||||||
switch (type) {
|
|
||||||
case NL80211_ATTR_WDEV:
|
|
||||||
if (len != 8)
|
|
||||||
break;
|
|
||||||
|
|
||||||
wdev_id = data;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NL80211_ATTR_FRAME:
|
|
||||||
mpdu = mpdu_validate(data, len);
|
|
||||||
if (!mpdu) {
|
|
||||||
l_warn("Frame didn't validate as MMPDU");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
frame_len = len;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!wdev_id) {
|
|
||||||
l_warn("Bad wdev attribute");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
dpp = l_queue_find(dpp_list, match_wdev, wdev_id);
|
|
||||||
if (!dpp)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!mpdu) {
|
|
||||||
l_warn("Missing frame data");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
body = mmpdu_body(mpdu);
|
|
||||||
body_len = (const uint8_t *) mpdu + frame_len - body;
|
|
||||||
|
|
||||||
if (body_len < sizeof(dpp_prefix) ||
|
|
||||||
memcmp(body, dpp_prefix, sizeof(dpp_prefix)) != 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
dpp_handle_frame(dpp, mpdu, body, body_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void dpp_frame_watch_cb(struct l_genl_msg *msg, void *user_data)
|
|
||||||
{
|
|
||||||
if (l_genl_msg_get_error(msg) < 0)
|
|
||||||
l_error("Could not register frame watch type %04x: %i",
|
|
||||||
L_PTR_TO_UINT(user_data), l_genl_msg_get_error(msg));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Special case the frame watch which includes the presence frames since they
|
|
||||||
* require multicast support. This is only supported by ath9k, so adding
|
|
||||||
* general support to frame-xchg isn't desireable.
|
|
||||||
*/
|
|
||||||
static void dpp_frame_watch(struct dpp_sm *dpp, uint16_t frame_type,
|
|
||||||
const uint8_t *prefix, size_t prefix_len)
|
|
||||||
{
|
|
||||||
struct l_genl_msg *msg;
|
|
||||||
|
|
||||||
msg = l_genl_msg_new_sized(NL80211_CMD_REGISTER_FRAME, 32 + prefix_len);
|
|
||||||
|
|
||||||
l_genl_msg_append_attr(msg, NL80211_ATTR_WDEV, 8, &dpp->wdev_id);
|
|
||||||
l_genl_msg_append_attr(msg, NL80211_ATTR_FRAME_TYPE, 2, &frame_type);
|
|
||||||
l_genl_msg_append_attr(msg, NL80211_ATTR_FRAME_MATCH,
|
|
||||||
prefix_len, prefix);
|
|
||||||
if (dpp->mcast_support)
|
|
||||||
l_genl_msg_append_attr(msg, NL80211_ATTR_RECEIVE_MULTICAST,
|
|
||||||
0, NULL);
|
|
||||||
|
|
||||||
l_genl_family_send(nl80211, msg, dpp_frame_watch_cb,
|
|
||||||
L_UINT_TO_PTR(frame_type), NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void dpp_start_enrollee(struct dpp_sm *dpp);
|
static void dpp_start_enrollee(struct dpp_sm *dpp);
|
||||||
static bool dpp_start_pkex_enrollee(struct dpp_sm *dpp);
|
static bool dpp_start_pkex_enrollee(struct dpp_sm *dpp);
|
||||||
|
|
||||||
@ -3820,8 +3729,6 @@ static void dpp_create(struct netdev *netdev)
|
|||||||
{
|
{
|
||||||
struct l_dbus *dbus = dbus_get_bus();
|
struct l_dbus *dbus = dbus_get_bus();
|
||||||
struct dpp_sm *dpp = l_new(struct dpp_sm, 1);
|
struct dpp_sm *dpp = l_new(struct dpp_sm, 1);
|
||||||
uint8_t dpp_conf_response_prefix[] = { 0x04, 0x0b };
|
|
||||||
uint8_t dpp_conf_request_prefix[] = { 0x04, 0x0a };
|
|
||||||
uint64_t wdev_id = netdev_get_wdev_id(netdev);
|
uint64_t wdev_id = netdev_get_wdev_id(netdev);
|
||||||
|
|
||||||
dpp->netdev = netdev;
|
dpp->netdev = netdev;
|
||||||
@ -3857,17 +3764,6 @@ static void dpp_create(struct netdev *netdev)
|
|||||||
*/
|
*/
|
||||||
dpp->refcount = 2;
|
dpp->refcount = 2;
|
||||||
|
|
||||||
dpp_frame_watch(dpp, 0x00d0, dpp_prefix, sizeof(dpp_prefix));
|
|
||||||
|
|
||||||
frame_watch_add(netdev_get_wdev_id(netdev), 0, 0x00d0,
|
|
||||||
dpp_conf_response_prefix,
|
|
||||||
sizeof(dpp_conf_response_prefix), false,
|
|
||||||
dpp_handle_config_response_frame, dpp, NULL);
|
|
||||||
frame_watch_add(netdev_get_wdev_id(netdev), 0, 0x00d0,
|
|
||||||
dpp_conf_request_prefix,
|
|
||||||
sizeof(dpp_conf_request_prefix), false,
|
|
||||||
dpp_handle_config_request_frame, dpp, NULL);
|
|
||||||
|
|
||||||
dpp->known_network_watch = known_networks_watch_add(
|
dpp->known_network_watch = known_networks_watch_add(
|
||||||
dpp_known_network_watch, dpp, NULL);
|
dpp_known_network_watch, dpp, NULL);
|
||||||
|
|
||||||
@ -4012,6 +3908,26 @@ done:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void dpp_add_frame_watches(struct dpp_sm *dpp, bool multicast_rx)
|
||||||
|
{
|
||||||
|
uint8_t dpp_conf_response_prefix[] = { 0x04, 0x0b };
|
||||||
|
uint8_t dpp_conf_request_prefix[] = { 0x04, 0x0a };
|
||||||
|
|
||||||
|
frame_watch_add(dpp->wdev_id, FRAME_GROUP_DPP, 0x00d0,
|
||||||
|
dpp_prefix, sizeof(dpp_prefix), multicast_rx,
|
||||||
|
dpp_handle_frame, dpp, NULL);
|
||||||
|
|
||||||
|
frame_watch_add(dpp->wdev_id, FRAME_GROUP_DPP, 0x00d0,
|
||||||
|
dpp_conf_response_prefix,
|
||||||
|
sizeof(dpp_conf_response_prefix), false,
|
||||||
|
dpp_handle_config_response_frame, dpp, NULL);
|
||||||
|
|
||||||
|
frame_watch_add(dpp->wdev_id, FRAME_GROUP_DPP, 0x00d0,
|
||||||
|
dpp_conf_request_prefix,
|
||||||
|
sizeof(dpp_conf_request_prefix), false,
|
||||||
|
dpp_handle_config_request_frame, dpp, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static void dpp_start_enrollee(struct dpp_sm *dpp)
|
static void dpp_start_enrollee(struct dpp_sm *dpp)
|
||||||
{
|
{
|
||||||
uint32_t freq = band_channel_to_freq(6, BAND_FREQ_2_4_GHZ);
|
uint32_t freq = band_channel_to_freq(6, BAND_FREQ_2_4_GHZ);
|
||||||
@ -4051,6 +3967,8 @@ static struct l_dbus_message *dpp_dbus_start_enrollee(struct l_dbus *dbus,
|
|||||||
dpp->role = DPP_CAPABILITY_ENROLLEE;
|
dpp->role = DPP_CAPABILITY_ENROLLEE;
|
||||||
dpp->interface = DPP_INTERFACE_DPP;
|
dpp->interface = DPP_INTERFACE_DPP;
|
||||||
|
|
||||||
|
dpp_add_frame_watches(dpp, false);
|
||||||
|
|
||||||
ret = dpp_try_disconnect_station(dpp, &wait_for_disconnect);
|
ret = dpp_try_disconnect_station(dpp, &wait_for_disconnect);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dpp_reset(dpp);
|
dpp_reset(dpp);
|
||||||
@ -4188,6 +4106,8 @@ static struct l_dbus_message *dpp_start_configurator_common(
|
|||||||
} else
|
} else
|
||||||
dpp->current_freq = bss->frequency;
|
dpp->current_freq = bss->frequency;
|
||||||
|
|
||||||
|
dpp_add_frame_watches(dpp, responder);
|
||||||
|
|
||||||
dpp->uri = dpp_generate_uri(dpp->own_asn1, dpp->own_asn1_len, 2,
|
dpp->uri = dpp_generate_uri(dpp->own_asn1, dpp->own_asn1_len, 2,
|
||||||
netdev_get_address(dpp->netdev),
|
netdev_get_address(dpp->netdev),
|
||||||
&bss->frequency, 1, NULL, NULL);
|
&bss->frequency, 1, NULL, NULL);
|
||||||
@ -4517,6 +4437,8 @@ static struct l_dbus_message *dpp_dbus_pkex_start_enrollee(struct l_dbus *dbus,
|
|||||||
dpp->state = DPP_STATE_PKEX_EXCHANGE;
|
dpp->state = DPP_STATE_PKEX_EXCHANGE;
|
||||||
dpp->interface = DPP_INTERFACE_PKEX;
|
dpp->interface = DPP_INTERFACE_PKEX;
|
||||||
|
|
||||||
|
dpp_add_frame_watches(dpp, false);
|
||||||
|
|
||||||
ret = dpp_try_disconnect_station(dpp, &wait_for_disconnect);
|
ret = dpp_try_disconnect_station(dpp, &wait_for_disconnect);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dpp_reset(dpp);
|
dpp_reset(dpp);
|
||||||
@ -4613,6 +4535,7 @@ static struct l_dbus_message *dpp_start_pkex_configurator(struct dpp_sm *dpp,
|
|||||||
dpp->config = dpp_configuration_new(network_get_settings(network),
|
dpp->config = dpp_configuration_new(network_get_settings(network),
|
||||||
network_get_ssid(network),
|
network_get_ssid(network),
|
||||||
hs->akm_suite);
|
hs->akm_suite);
|
||||||
|
dpp_add_frame_watches(dpp, true);
|
||||||
|
|
||||||
dpp_reset_protocol_timer(dpp, DPP_PKEX_PROTO_TIMEOUT);
|
dpp_reset_protocol_timer(dpp, DPP_PKEX_PROTO_TIMEOUT);
|
||||||
dpp_property_changed_notify(dpp);
|
dpp_property_changed_notify(dpp);
|
||||||
@ -4741,11 +4664,6 @@ static int dpp_init(void)
|
|||||||
mlme_watch = l_genl_family_register(nl80211, "mlme", dpp_mlme_notify,
|
mlme_watch = l_genl_family_register(nl80211, "mlme", dpp_mlme_notify,
|
||||||
NULL, NULL);
|
NULL, NULL);
|
||||||
|
|
||||||
unicast_watch = l_genl_add_unicast_watch(iwd_get_genl(),
|
|
||||||
NL80211_GENL_NAME,
|
|
||||||
dpp_unicast_notify,
|
|
||||||
NULL, NULL);
|
|
||||||
|
|
||||||
dpp_list = l_queue_new();
|
dpp_list = l_queue_new();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -4760,8 +4678,6 @@ static void dpp_exit(void)
|
|||||||
|
|
||||||
netdev_watch_remove(netdev_watch);
|
netdev_watch_remove(netdev_watch);
|
||||||
|
|
||||||
l_genl_remove_unicast_watch(iwd_get_genl(), unicast_watch);
|
|
||||||
|
|
||||||
l_genl_family_unregister(nl80211, mlme_watch);
|
l_genl_family_unregister(nl80211, mlme_watch);
|
||||||
mlme_watch = 0;
|
mlme_watch = 0;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user