mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2024-11-26 18:59:22 +01:00
netdev: Simplify frame_watch using watchlist
This commit is contained in:
parent
fa7fab196e
commit
af124da544
78
src/netdev.c
78
src/netdev.c
@ -92,8 +92,7 @@ struct netdev {
|
|||||||
|
|
||||||
struct watchlist event_watches;
|
struct watchlist event_watches;
|
||||||
|
|
||||||
struct l_queue *frame_watches;
|
struct watchlist frame_watches;
|
||||||
uint32_t next_frame_watch_id;
|
|
||||||
|
|
||||||
bool connected : 1;
|
bool connected : 1;
|
||||||
bool operational : 1;
|
bool operational : 1;
|
||||||
@ -115,12 +114,10 @@ struct netdev_watch {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct netdev_frame_watch {
|
struct netdev_frame_watch {
|
||||||
uint32_t id;
|
|
||||||
uint16_t frame_type;
|
uint16_t frame_type;
|
||||||
uint8_t *prefix;
|
uint8_t *prefix;
|
||||||
size_t prefix_len;
|
size_t prefix_len;
|
||||||
netdev_frame_watch_func_t handler;
|
struct watchlist_item super;
|
||||||
void *user_data;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct l_netlink *rtnl = NULL;
|
static struct l_netlink *rtnl = NULL;
|
||||||
@ -508,14 +505,6 @@ static void netdev_connect_failed(struct l_genl_msg *msg, void *user_data)
|
|||||||
connect_data);
|
connect_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void netdev_frame_watch_free(void *data)
|
|
||||||
{
|
|
||||||
struct netdev_frame_watch *fw = data;
|
|
||||||
|
|
||||||
l_free(fw->prefix);
|
|
||||||
l_free(fw);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void netdev_free(void *data)
|
static void netdev_free(void *data)
|
||||||
{
|
{
|
||||||
struct netdev *netdev = data;
|
struct netdev *netdev = data;
|
||||||
@ -544,8 +533,7 @@ static void netdev_free(void *data)
|
|||||||
|
|
||||||
device_remove(netdev->device);
|
device_remove(netdev->device);
|
||||||
watchlist_destroy(&netdev->event_watches);
|
watchlist_destroy(&netdev->event_watches);
|
||||||
|
watchlist_destroy(&netdev->frame_watches);
|
||||||
l_queue_destroy(netdev->frame_watches, netdev_frame_watch_free);
|
|
||||||
|
|
||||||
l_free(netdev);
|
l_free(netdev);
|
||||||
}
|
}
|
||||||
@ -2817,7 +2805,9 @@ struct frame_prefix_info {
|
|||||||
|
|
||||||
static bool netdev_frame_watch_match_prefix(const void *a, const void *b)
|
static bool netdev_frame_watch_match_prefix(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
const struct netdev_frame_watch *fw = a;
|
const struct watchlist_item *item = a;
|
||||||
|
const struct netdev_frame_watch *fw =
|
||||||
|
container_of(item, struct netdev_frame_watch, super);
|
||||||
const struct frame_prefix_info *info = b;
|
const struct frame_prefix_info *info = b;
|
||||||
|
|
||||||
return fw->frame_type == info->frame_type &&
|
return fw->frame_type == info->frame_type &&
|
||||||
@ -2834,7 +2824,6 @@ static void netdev_mgmt_frame_event(struct l_genl_msg *msg,
|
|||||||
const struct mmpdu_header *mpdu = NULL;
|
const struct mmpdu_header *mpdu = NULL;
|
||||||
const uint8_t *body;
|
const uint8_t *body;
|
||||||
struct frame_prefix_info info;
|
struct frame_prefix_info info;
|
||||||
const struct l_queue_entry *fw_entry;
|
|
||||||
static const uint8_t bcast_addr[6] = {
|
static const uint8_t bcast_addr[6] = {
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff
|
||||||
};
|
};
|
||||||
@ -2872,15 +2861,10 @@ static void netdev_mgmt_frame_event(struct l_genl_msg *msg,
|
|||||||
info.body = (const uint8_t *) body;
|
info.body = (const uint8_t *) body;
|
||||||
info.body_len = (const uint8_t *) mpdu + frame_len - body;
|
info.body_len = (const uint8_t *) mpdu + frame_len - body;
|
||||||
|
|
||||||
for (fw_entry = l_queue_get_entries(netdev->frame_watches); fw_entry;
|
WATCHLIST_NOTIFY_MATCHES(&netdev->frame_watches,
|
||||||
fw_entry = fw_entry->next) {
|
netdev_frame_watch_match_prefix, &info,
|
||||||
const struct netdev_frame_watch *fw = fw_entry->data;
|
netdev_frame_watch_func_t,
|
||||||
|
netdev, mpdu, body, info.body_len);
|
||||||
if (!netdev_frame_watch_match_prefix(fw, &info))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
fw->handler(netdev, mpdu, body, info.body_len, fw->user_data);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void netdev_unicast_notify(struct l_genl_msg *msg, void *user_data)
|
static void netdev_unicast_notify(struct l_genl_msg *msg, void *user_data)
|
||||||
@ -3231,14 +3215,19 @@ check_blacklist:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool netdev_frame_watch_match_id(const void *a, const void *b)
|
static void netdev_frame_watch_free(struct watchlist_item *item)
|
||||||
{
|
{
|
||||||
const struct netdev_frame_watch *fw = a;
|
struct netdev_frame_watch *fw =
|
||||||
uint32_t id = L_PTR_TO_UINT(b);
|
container_of(item, struct netdev_frame_watch, super);
|
||||||
|
|
||||||
return fw->id == id;
|
l_free(fw->prefix);
|
||||||
|
l_free(fw);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const struct watchlist_ops netdev_frame_watch_ops = {
|
||||||
|
.item_free = netdev_frame_watch_free,
|
||||||
|
};
|
||||||
|
|
||||||
uint32_t netdev_frame_watch_add(struct netdev *netdev, uint16_t frame_type,
|
uint32_t netdev_frame_watch_add(struct netdev *netdev, uint16_t frame_type,
|
||||||
const uint8_t *prefix, size_t prefix_len,
|
const uint8_t *prefix, size_t prefix_len,
|
||||||
netdev_frame_watch_func_t handler,
|
netdev_frame_watch_func_t handler,
|
||||||
@ -3248,25 +3237,21 @@ uint32_t netdev_frame_watch_add(struct netdev *netdev, uint16_t frame_type,
|
|||||||
struct l_genl_msg *msg;
|
struct l_genl_msg *msg;
|
||||||
struct frame_prefix_info info = { frame_type, prefix, prefix_len };
|
struct frame_prefix_info info = { frame_type, prefix, prefix_len };
|
||||||
bool registered;
|
bool registered;
|
||||||
|
uint32_t id;
|
||||||
|
|
||||||
fw = l_new(struct netdev_frame_watch, 1);
|
fw = l_new(struct netdev_frame_watch, 1);
|
||||||
fw->id = netdev->next_frame_watch_id++;
|
|
||||||
fw->frame_type = frame_type;
|
fw->frame_type = frame_type;
|
||||||
fw->prefix = l_memdup(prefix, prefix_len);
|
fw->prefix = l_memdup(prefix, prefix_len);
|
||||||
fw->prefix_len = prefix_len;
|
fw->prefix_len = prefix_len;
|
||||||
fw->handler = handler;
|
id = watchlist_link(&netdev->frame_watches, &fw->super,
|
||||||
fw->user_data = user_data;
|
handler, user_data, NULL);
|
||||||
|
|
||||||
registered = l_queue_find(netdev->frame_watches,
|
registered = l_queue_find(netdev->frame_watches.items,
|
||||||
netdev_frame_watch_match_prefix,
|
netdev_frame_watch_match_prefix,
|
||||||
&info);
|
&info);
|
||||||
|
|
||||||
if (!netdev->frame_watches)
|
|
||||||
netdev->frame_watches = l_queue_new();
|
|
||||||
l_queue_push_tail(netdev->frame_watches, fw);
|
|
||||||
|
|
||||||
if (registered)
|
if (registered)
|
||||||
return fw->id;
|
return id;
|
||||||
|
|
||||||
msg = l_genl_msg_new_sized(NL80211_CMD_REGISTER_FRAME, 32 + prefix_len);
|
msg = l_genl_msg_new_sized(NL80211_CMD_REGISTER_FRAME, 32 + prefix_len);
|
||||||
|
|
||||||
@ -3277,27 +3262,17 @@ uint32_t netdev_frame_watch_add(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);
|
||||||
|
|
||||||
return fw->id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool netdev_frame_watch_remove(struct netdev *netdev, uint32_t id)
|
bool netdev_frame_watch_remove(struct netdev *netdev, uint32_t id)
|
||||||
{
|
{
|
||||||
struct netdev_frame_watch *fw;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* There's no way to unregister from notifications but that's not a
|
* There's no way to unregister from notifications but that's not a
|
||||||
* problem, we leave them active in the kernel but
|
* problem, we leave them active in the kernel but
|
||||||
* netdev_mgmt_frame_event will ignore these events.
|
* netdev_mgmt_frame_event will ignore these events.
|
||||||
*/
|
*/
|
||||||
|
return watchlist_remove(&netdev->frame_watches, id);
|
||||||
fw = l_queue_remove_if(netdev->frame_watches,
|
|
||||||
netdev_frame_watch_match_id, L_UINT_TO_PTR(id));
|
|
||||||
if (!fw)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
netdev_frame_watch_free(fw);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void netdev_create_from_genl(struct l_genl_msg *msg)
|
static void netdev_create_from_genl(struct l_genl_msg *msg)
|
||||||
@ -3399,6 +3374,7 @@ static void netdev_create_from_genl(struct l_genl_msg *msg)
|
|||||||
memcpy(netdev->name, ifname, ifname_len);
|
memcpy(netdev->name, ifname, ifname_len);
|
||||||
netdev->wiphy = wiphy;
|
netdev->wiphy = wiphy;
|
||||||
watchlist_init(&netdev->event_watches, NULL);
|
watchlist_init(&netdev->event_watches, NULL);
|
||||||
|
watchlist_init(&netdev->frame_watches, &netdev_frame_watch_ops);
|
||||||
|
|
||||||
l_queue_push_tail(netdev_list, netdev);
|
l_queue_push_tail(netdev_list, netdev);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user