From 22d7a3c629e00aa7c6ecfa965d09c068eb0c17b0 Mon Sep 17 00:00:00 2001 From: Andrew Zaborowski Date: Wed, 18 Mar 2020 15:45:28 +0100 Subject: [PATCH] frame-xchg: Optimize frame_watch_remove_by_handler scenarios Since frame_watch_remove_by_handler only forgets a given function + user data pointers, and doesn't remove the frame prefixes added in the kernel, we can avoid later re-registering those prefixes with the kernel by keeping them in our local watchlist, and only replacing the handler pointer with a dummy function. --- src/frame-xchg.c | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/src/frame-xchg.c b/src/frame-xchg.c index 992149ee..d69fff7c 100644 --- a/src/frame-xchg.c +++ b/src/frame-xchg.c @@ -472,6 +472,12 @@ static void frame_watch_register_cb(struct l_genl_msg *msg, void *user_data) L_PTR_TO_UINT(user_data), l_genl_msg_get_error(msg)); } +static void frame_watch_notify_empty(const struct mmpdu_header *mpdu, + const void *body, size_t body_len, + int rssi, void *user_data) +{ +} + struct frame_duplicate_info { uint64_t wdev_id; uint16_t frame_type; @@ -506,6 +512,17 @@ static bool frame_watch_check_duplicate(void *data, void *user_data) */ info->registered = true; + /* + * If we previously had a watch registered on this socket, + * with the same or a more specific prefix, we can now forget + * its entry as the new watch is going to hold enough + * information to keep us from registering redundant prefixes + * in the future. + */ + if (info->prefix_len <= watch->prefix_len && + watch->super.notify == frame_watch_notify_empty) + goto drop; + if (info->handler != watch->super.notify || info->user_data != watch->super.notify_data) return false; @@ -522,6 +539,7 @@ static bool frame_watch_check_duplicate(void *data, void *user_data) return false; } +drop: /* Drop the existing watch as a duplicate of the new one */ frame_watch_free(&watch->super); return true; @@ -665,11 +683,19 @@ static bool frame_watch_item_remove_by_handler(void *data, void *user_data) watch->super.notify_data != info->user_data) return false; - if (watch->super.destroy) + if (watch->super.destroy) { watch->super.destroy(watch->super.notify_data); + watch->super.destroy = NULL; + } - frame_watch_free(&watch->super); - return true; + /* + * Keep the entry, with a dummy callback, in order to keep us from + * re-registering its prefix in future frame_watch_add calls. We + * can drop the entry in some circumstances but checking the + * conditions for this costs more than it is worth right now. + */ + watch->super.notify = frame_watch_notify_empty; + return false; } /*