mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-10-29 21:58:20 +00:00
u80211: sync with upstream and use new work system
This commit is contained in:
@@ -12,9 +12,10 @@
|
||||
typedef struct {
|
||||
void *completion_work;
|
||||
void *auth_timeout_work;
|
||||
void *auth_timeout_timer;
|
||||
void *assoc_timeout_work;
|
||||
void *assoc_timeout_timer;
|
||||
unsigned int generation;
|
||||
unsigned int timeouts_in_flight;
|
||||
u80211_device_t *device;
|
||||
u80211_ap_t *ap; // this keeps a reference, the reference in the device is only incremented only when fully associated
|
||||
void *information_elements;
|
||||
@@ -37,6 +38,8 @@ static void wake_association_waiters(u80211_device_t *device, int result) {
|
||||
}
|
||||
|
||||
static void destroy_association_context(u80211_association_context_t *association_context) {
|
||||
u80211_kernel_free_timer(association_context->auth_timeout_timer);
|
||||
u80211_kernel_free_timer(association_context->assoc_timeout_timer);
|
||||
u80211_kernel_free_work(association_context->completion_work);
|
||||
u80211_kernel_free_work(association_context->auth_timeout_work);
|
||||
u80211_kernel_free_work(association_context->assoc_timeout_work);
|
||||
@@ -74,6 +77,37 @@ static void release_disconnected_ap(void *ctx) {
|
||||
u80211_ap_release(ap);
|
||||
}
|
||||
|
||||
static void cleanup_association(void *ctx) {
|
||||
u80211_device_t *device = ctx;
|
||||
|
||||
u80211_kernel_acquire_spinlock(device->association_spinlock);
|
||||
u80211_association_context_t *association_context = device->association_cleanup_context;
|
||||
u80211_ap_t *disconnected_ap = device->disconnected_ap;
|
||||
device->disconnected_ap = NULL;
|
||||
u80211_kernel_release_spinlock(device->association_spinlock);
|
||||
|
||||
if (association_context != NULL) {
|
||||
u80211_ap_release(association_context->ap);
|
||||
destroy_association_context(association_context);
|
||||
}
|
||||
if (disconnected_ap != NULL)
|
||||
u80211_ap_release(disconnected_ap);
|
||||
|
||||
if (association_context != NULL) {
|
||||
u80211_kernel_acquire_spinlock(device->association_spinlock);
|
||||
device->association_cleanup_context = NULL;
|
||||
device->association_cleanup_pending = false;
|
||||
wake_association_waiters(device, device->association_result);
|
||||
u80211_kernel_release_spinlock(device->association_spinlock);
|
||||
}
|
||||
}
|
||||
|
||||
static void schedule_association_cleanup(u80211_device_t *device, u80211_association_context_t *association_context) {
|
||||
device->association_context = NULL;
|
||||
device->association_cleanup_context = association_context;
|
||||
device->association_cleanup_pending = true;
|
||||
}
|
||||
|
||||
static void association_process_teardown(u80211_device_t *device, const u80211_mac_address_t *address, bool deauthentication) {
|
||||
bool cleanup_needed = false;
|
||||
|
||||
@@ -91,9 +125,12 @@ static void association_process_teardown(u80211_device_t *device, const u80211_m
|
||||
goto leave;
|
||||
|
||||
if (attempt_in_progress) {
|
||||
device->association_context = NULL;
|
||||
u80211_association_context_t *association_context = device->association_context;
|
||||
if (association_context == NULL)
|
||||
goto leave;
|
||||
schedule_association_cleanup(device, association_context);
|
||||
device->association_result = U80211_STATUS_REJECTED;
|
||||
wake_association_waiters(device, device->association_result);
|
||||
cleanup_needed = true;
|
||||
} else {
|
||||
device->disconnected_ap = device->ap;
|
||||
cleanup_needed = true;
|
||||
@@ -105,7 +142,7 @@ static void association_process_teardown(u80211_device_t *device, const u80211_m
|
||||
leave:
|
||||
u80211_kernel_release_spinlock(device->association_spinlock);
|
||||
if (cleanup_needed)
|
||||
u80211_kernel_enqueue_work(device->association_cleanup_work, release_disconnected_ap, device, 0);
|
||||
u80211_kernel_enqueue_work(device->association_cleanup_work, cleanup_association, device);
|
||||
}
|
||||
|
||||
void u80211_association_process_deauthentication(u80211_device_t *device, u80211_deauthentication_data_t *deauthentication_data) {
|
||||
@@ -117,6 +154,7 @@ void u80211_association_process_disassociation(u80211_device_t *device, u80211_d
|
||||
}
|
||||
|
||||
void u80211_association_process_response(u80211_device_t *device, u80211_association_response_data_t *association_data) {
|
||||
bool cleanup_needed = false;
|
||||
u80211_kernel_acquire_spinlock(device->association_spinlock);
|
||||
|
||||
u80211_association_context_t *association_context = device->association_context;
|
||||
@@ -135,43 +173,41 @@ void u80211_association_process_response(u80211_device_t *device, u80211_associa
|
||||
else
|
||||
u80211_ap_hold(device->ap);
|
||||
|
||||
device->association_context = NULL;
|
||||
schedule_association_cleanup(device, association_context);
|
||||
++device->association_generation;
|
||||
device->association_result = association_data->status ? U80211_STATUS_REJECTED : U80211_STATUS_SUCCESS;
|
||||
wake_association_waiters(device, device->association_result);
|
||||
cleanup_needed = true;
|
||||
|
||||
leave:
|
||||
u80211_kernel_release_spinlock(device->association_spinlock);
|
||||
if (cleanup_needed)
|
||||
u80211_kernel_enqueue_work(device->association_cleanup_work, cleanup_association, device);
|
||||
}
|
||||
|
||||
static void association_timeout(void *ctx, int expected_state) {
|
||||
u80211_association_context_t *association_context = ctx;
|
||||
u80211_device_t *device = association_context->device;
|
||||
bool free = true;
|
||||
bool cleanup_needed = false;
|
||||
|
||||
u80211_kernel_acquire_spinlock(device->association_spinlock);
|
||||
|
||||
// not associating/different association generation
|
||||
if (!device->ap || device->association_generation != association_context->generation)
|
||||
if (device->association_context != association_context || !device->ap ||
|
||||
device->association_generation != association_context->generation)
|
||||
goto leave;
|
||||
|
||||
if (u80211_set_device_state(device, expected_state, U80211_DEVICE_STATE_DOWN)) {
|
||||
device->ap = NULL;
|
||||
device->association_context = NULL;
|
||||
schedule_association_cleanup(device, association_context);
|
||||
++device->association_generation;
|
||||
device->association_result = U80211_STATUS_TIMED_OUT;
|
||||
wake_association_waiters(device, device->association_result);
|
||||
} else {
|
||||
// already progressed
|
||||
free = false;
|
||||
cleanup_needed = true;
|
||||
}
|
||||
|
||||
leave:
|
||||
u80211_kernel_release_spinlock(device->association_spinlock);
|
||||
if (__atomic_sub_fetch(&association_context->timeouts_in_flight, 1, __ATOMIC_ACQ_REL) == 0 && free) {
|
||||
u80211_ap_release(association_context->ap);
|
||||
destroy_association_context(association_context);
|
||||
}
|
||||
if (cleanup_needed)
|
||||
u80211_kernel_enqueue_work(device->association_cleanup_work, cleanup_association, device);
|
||||
}
|
||||
|
||||
static void assoc_timeout(void *ctx) {
|
||||
@@ -183,11 +219,12 @@ static void auth_completion_work(void *ctx) {
|
||||
u80211_device_t *device = association_context->device;
|
||||
|
||||
u80211_send_association_request(device, association_context->information_elements, association_context->information_elements_size);
|
||||
__atomic_add_fetch(&association_context->timeouts_in_flight, 1, __ATOMIC_RELAXED);
|
||||
u80211_kernel_enqueue_work(association_context->assoc_timeout_work, assoc_timeout, association_context, ASSOC_TIMEOUT);
|
||||
u80211_kernel_enqueue_delayed_work(association_context->assoc_timeout_work, association_context->assoc_timeout_timer,
|
||||
assoc_timeout, association_context, ASSOC_TIMEOUT);
|
||||
}
|
||||
|
||||
void u80211_association_process_authentication(u80211_device_t *device, u80211_auth_data_t *auth_data) {
|
||||
bool cleanup_needed = false;
|
||||
u80211_kernel_acquire_spinlock(device->association_spinlock);
|
||||
|
||||
// not associating/different AP
|
||||
@@ -203,21 +240,24 @@ void u80211_association_process_authentication(u80211_device_t *device, u80211_a
|
||||
if (!u80211_set_device_state(device, U80211_DEVICE_STATE_AUTHENTICATING, U80211_DEVICE_STATE_DOWN))
|
||||
goto leave;
|
||||
|
||||
u80211_association_context_t *association_context = device->association_context;
|
||||
device->ap = NULL;
|
||||
device->association_context = NULL;
|
||||
schedule_association_cleanup(device, association_context);
|
||||
++device->association_generation;
|
||||
device->association_result = U80211_STATUS_REJECTED;
|
||||
wake_association_waiters(device, device->association_result);
|
||||
cleanup_needed = true;
|
||||
} else {
|
||||
if (!u80211_set_device_state(device, U80211_DEVICE_STATE_AUTHENTICATING, U80211_DEVICE_STATE_ASSOCIATING))
|
||||
goto leave;
|
||||
|
||||
u80211_association_context_t *ctx = device->association_context;
|
||||
u80211_kernel_enqueue_work(ctx->completion_work, auth_completion_work, ctx, 0);
|
||||
u80211_kernel_enqueue_work(ctx->completion_work, auth_completion_work, ctx);
|
||||
}
|
||||
|
||||
leave:
|
||||
u80211_kernel_release_spinlock(device->association_spinlock);
|
||||
if (cleanup_needed)
|
||||
u80211_kernel_enqueue_work(device->association_cleanup_work, cleanup_association, device);
|
||||
}
|
||||
|
||||
static void auth_timeout(void *ctx) {
|
||||
@@ -247,8 +287,27 @@ int u80211_associate(u80211_device_t *device, u80211_ap_t *ap, const void *infor
|
||||
return U80211_STATUS_ENOMEM;
|
||||
}
|
||||
|
||||
association_context->auth_timeout_timer = u80211_kernel_allocate_timer();
|
||||
if (association_context->auth_timeout_timer == NULL) {
|
||||
u80211_kernel_free_work(association_context->auth_timeout_work);
|
||||
u80211_kernel_free_work(association_context->completion_work);
|
||||
u80211_kernel_free(association_context);
|
||||
return U80211_STATUS_ENOMEM;
|
||||
}
|
||||
|
||||
association_context->assoc_timeout_work = u80211_kernel_allocate_work();
|
||||
if (association_context->assoc_timeout_work == NULL) {
|
||||
u80211_kernel_free_timer(association_context->auth_timeout_timer);
|
||||
u80211_kernel_free_work(association_context->auth_timeout_work);
|
||||
u80211_kernel_free_work(association_context->completion_work);
|
||||
u80211_kernel_free(association_context);
|
||||
return U80211_STATUS_ENOMEM;
|
||||
}
|
||||
|
||||
association_context->assoc_timeout_timer = u80211_kernel_allocate_timer();
|
||||
if (association_context->assoc_timeout_timer == NULL) {
|
||||
u80211_kernel_free_work(association_context->assoc_timeout_work);
|
||||
u80211_kernel_free_timer(association_context->auth_timeout_timer);
|
||||
u80211_kernel_free_work(association_context->auth_timeout_work);
|
||||
u80211_kernel_free_work(association_context->completion_work);
|
||||
u80211_kernel_free(association_context);
|
||||
@@ -269,10 +328,10 @@ int u80211_associate(u80211_device_t *device, u80211_ap_t *ap, const void *infor
|
||||
|
||||
association_context->device = device;
|
||||
association_context->ap = ap;
|
||||
__atomic_store_n(&association_context->timeouts_in_flight, 1, __ATOMIC_RELAXED);
|
||||
|
||||
u80211_kernel_acquire_spinlock(device->association_spinlock);
|
||||
if (!u80211_set_device_state(device, U80211_DEVICE_STATE_DOWN, U80211_DEVICE_STATE_AUTHENTICATING)) {
|
||||
if (device->association_cleanup_pending ||
|
||||
!u80211_set_device_state(device, U80211_DEVICE_STATE_DOWN, U80211_DEVICE_STATE_AUTHENTICATING)) {
|
||||
u80211_kernel_release_spinlock(device->association_spinlock);
|
||||
destroy_association_context(association_context);
|
||||
return U80211_STATUS_BUSY;
|
||||
@@ -296,7 +355,8 @@ int u80211_associate(u80211_device_t *device, u80211_ap_t *ap, const void *infor
|
||||
device->ops->set_channel(device, ap->channel);
|
||||
u80211_send_authentication(device, &auth_data);
|
||||
|
||||
u80211_kernel_enqueue_work(association_context->auth_timeout_work, auth_timeout, association_context, AUTH_TIMEOUT);
|
||||
u80211_kernel_enqueue_delayed_work(association_context->auth_timeout_work, association_context->auth_timeout_timer,
|
||||
auth_timeout, association_context, AUTH_TIMEOUT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -356,7 +416,8 @@ int u80211_wait_for_association_completion(u80211_device_t *device) {
|
||||
|
||||
u80211_kernel_acquire_spinlock(device->association_spinlock);
|
||||
int state = u80211_get_device_state(device);
|
||||
if (state != U80211_DEVICE_STATE_AUTHENTICATING && state != U80211_DEVICE_STATE_ASSOCIATING) {
|
||||
if (state != U80211_DEVICE_STATE_AUTHENTICATING && state != U80211_DEVICE_STATE_ASSOCIATING &&
|
||||
!device->association_cleanup_pending) {
|
||||
int result = device->association_result;
|
||||
u80211_kernel_release_spinlock(device->association_spinlock);
|
||||
u80211_kernel_free_semaphore(semaphore);
|
||||
|
||||
@@ -29,10 +29,18 @@ int u80211_register_device(const u80211_device_metadata_t *metadata, const u8021
|
||||
return U80211_STATUS_ENOMEM;
|
||||
}
|
||||
device->scan_context = NULL;
|
||||
device->scan_cleanup_work = u80211_kernel_allocate_work();
|
||||
if (device->scan_cleanup_work == NULL) {
|
||||
u80211_kernel_free_spinlock(device->scan_spinlock);
|
||||
u80211_key_state_deinit(device);
|
||||
u80211_kernel_free(device);
|
||||
return U80211_STATUS_ENOMEM;
|
||||
}
|
||||
u80211_list_init(&device->scan_waiters);
|
||||
|
||||
device->association_spinlock = u80211_kernel_allocate_spinlock();
|
||||
if (device->association_spinlock == NULL) {
|
||||
u80211_kernel_free_work(device->scan_cleanup_work);
|
||||
u80211_kernel_free_spinlock(device->scan_spinlock);
|
||||
u80211_key_state_deinit(device);
|
||||
u80211_kernel_free(device);
|
||||
@@ -41,12 +49,15 @@ int u80211_register_device(const u80211_device_metadata_t *metadata, const u8021
|
||||
device->association_cleanup_work = u80211_kernel_allocate_work();
|
||||
if (device->association_cleanup_work == NULL) {
|
||||
u80211_kernel_free_spinlock(device->association_spinlock);
|
||||
u80211_kernel_free_work(device->scan_cleanup_work);
|
||||
u80211_kernel_free_spinlock(device->scan_spinlock);
|
||||
u80211_key_state_deinit(device);
|
||||
u80211_kernel_free(device);
|
||||
return U80211_STATUS_ENOMEM;
|
||||
}
|
||||
device->association_context = NULL;
|
||||
device->association_cleanup_context = NULL;
|
||||
device->association_cleanup_pending = false;
|
||||
u80211_list_init(&device->association_waiters);
|
||||
device->association_generation = 0;
|
||||
device->association_result = U80211_STATUS_UNKNOWN_ERROR;
|
||||
@@ -60,6 +71,7 @@ int u80211_register_device(const u80211_device_metadata_t *metadata, const u8021
|
||||
if (status != U80211_STATUS_SUCCESS) {
|
||||
u80211_kernel_free_work(device->association_cleanup_work);
|
||||
u80211_kernel_free_spinlock(device->association_spinlock);
|
||||
u80211_kernel_free_work(device->scan_cleanup_work);
|
||||
u80211_kernel_free_spinlock(device->scan_spinlock);
|
||||
u80211_key_state_deinit(device);
|
||||
u80211_kernel_free(device);
|
||||
@@ -72,6 +84,7 @@ int u80211_register_device(const u80211_device_metadata_t *metadata, const u8021
|
||||
|
||||
void u80211_unregister_device(u80211_device_t *device) {
|
||||
u80211_key_state_deinit(device);
|
||||
u80211_kernel_free_work(device->scan_cleanup_work);
|
||||
u80211_kernel_free_work(device->association_cleanup_work);
|
||||
if (device->disconnected_ap != NULL)
|
||||
u80211_ap_release(device->disconnected_ap);
|
||||
|
||||
@@ -22,6 +22,7 @@ typedef struct {
|
||||
bool receiving;
|
||||
int current_channel;
|
||||
void *work;
|
||||
void *timer;
|
||||
} u80211_scan_state_t;
|
||||
|
||||
typedef struct {
|
||||
@@ -38,22 +39,34 @@ static void wake_scan_waiters(u80211_device_t *device) {
|
||||
}
|
||||
|
||||
static void destroy_scan_state(u80211_scan_state_t *scan_state) {
|
||||
u80211_kernel_free_timer(scan_state->timer);
|
||||
u80211_kernel_free_work(scan_state->work);
|
||||
u80211_ringbuffer_destroy(&scan_state->buffer);
|
||||
u80211_kernel_free(scan_state);
|
||||
}
|
||||
|
||||
static void cleanup_scan(void *ctx);
|
||||
|
||||
static void complete_scan(u80211_scan_state_t *scan_state) {
|
||||
u80211_device_t *device = scan_state->device;
|
||||
|
||||
u80211_kernel_acquire_spinlock(device->scan_spinlock);
|
||||
|
||||
u80211_set_device_state(device, U80211_DEVICE_STATE_SCANNING, U80211_DEVICE_STATE_DOWN);
|
||||
wake_scan_waiters(device);
|
||||
|
||||
device->scan_context = NULL;
|
||||
u80211_kernel_release_spinlock(device->scan_spinlock);
|
||||
|
||||
u80211_kernel_enqueue_work(device->scan_cleanup_work, cleanup_scan, scan_state);
|
||||
}
|
||||
|
||||
static void cleanup_scan(void *ctx) {
|
||||
u80211_scan_state_t *scan_state = ctx;
|
||||
u80211_device_t *device = scan_state->device;
|
||||
|
||||
destroy_scan_state(scan_state);
|
||||
|
||||
u80211_kernel_acquire_spinlock(device->scan_spinlock);
|
||||
u80211_set_device_state(device, U80211_DEVICE_STATE_SCANNING, U80211_DEVICE_STATE_DOWN);
|
||||
wake_scan_waiters(device);
|
||||
u80211_kernel_release_spinlock(device->scan_spinlock);
|
||||
}
|
||||
|
||||
void u80211_scan_process_response(u80211_device_t *device, u80211_beacon_data_t *beacon_data) {
|
||||
@@ -151,7 +164,7 @@ static void scan_work(void *ctx) {
|
||||
|
||||
u80211_send_probe_request(device);
|
||||
|
||||
u80211_kernel_enqueue_work(scan_state->work, scan_work, scan_state, WAIT_MS);
|
||||
u80211_kernel_enqueue_delayed_work(scan_state->work, scan_state->timer, scan_work, scan_state, WAIT_MS);
|
||||
}
|
||||
|
||||
int u80211_scan(u80211_device_t *device) {
|
||||
@@ -172,6 +185,14 @@ int u80211_scan(u80211_device_t *device) {
|
||||
return U80211_STATUS_ENOMEM;
|
||||
}
|
||||
|
||||
scan_state->timer = u80211_kernel_allocate_timer();
|
||||
if (scan_state->timer == NULL) {
|
||||
u80211_kernel_free_work(scan_state->work);
|
||||
u80211_ringbuffer_destroy(&scan_state->buffer);
|
||||
u80211_kernel_free(scan_state);
|
||||
return U80211_STATUS_ENOMEM;
|
||||
}
|
||||
|
||||
scan_state->receiving = false;
|
||||
scan_state->device = device;
|
||||
scan_state->current_channel = next_channel(0);
|
||||
@@ -199,7 +220,7 @@ int u80211_scan(u80211_device_t *device) {
|
||||
|
||||
u80211_send_probe_request(device);
|
||||
|
||||
u80211_kernel_enqueue_work(scan_state->work, scan_work, scan_state, WAIT_MS);
|
||||
u80211_kernel_enqueue_delayed_work(scan_state->work, scan_state->timer, scan_work, scan_state, WAIT_MS);
|
||||
|
||||
return U80211_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user