source: ReferenceDesigns/w3_802.11/c/wlan_mac_high_framework/wlan_mac_network_info.c

Last change on this file was 6319, checked in by chunter, 5 years ago

1.8.0 release wlan-mac-se

File size: 26.2 KB
Line 
1/** @file wlan_mac_bss_info.c
2 *  @brief BSS Info Subsystem
3 *
4 *  This contains code tracking BSS information. It also contains code for managing
5 *  the active scan state machine.
6 *
7 *  @copyright Copyright 2014-2019, Mango Communications. All rights reserved.
8 *          Distributed under the Mango Communications Reference Design License
9 *              See LICENSE.txt included in the design archive or
10 *              at http://mangocomm.com/802.11/license
11 *
12 *  This file is part of the Mango 802.11 Reference Design (https://mangocomm.com/802.11)
13 */
14
15/***************************** Include Files *********************************/
16
17#include "wlan_mac_high_sw_config.h"
18
19#include "xil_types.h"
20#include "stdlib.h"
21#include "stdio.h"
22#include "wlan_platform_common.h"
23#include "wlan_platform_high.h"
24#include "xparameters.h"
25#include "string.h"
26
27#include "wlan_mac_pkt_buf_util.h"
28#include "wlan_mac_high.h"
29#include "wlan_mac_network_info.h"
30#include "wlan_mac_station_info.h"
31#include "wlan_mac_dl_list.h"
32#include "wlan_mac_802_11_defs.h"
33#include "wlan_mac_schedule.h"
34#include "wlan_mac_mgmt_tags.h"
35#include "wlan_mac_packet_types.h"
36#include "wlan_mac_common.h"
37#include "wlan_mac_queue.h"
38
39/*********************** Global Variable Definitions *************************/
40
41extern platform_high_dev_info_t platform_high_dev_info;
42extern volatile function_ptr_t tx_queue_state_change_callback; ///< User callback for Tx queue state changes
43
44/*************************** Variable Definitions ****************************/
45
46/// The network_info_list is stored chronologically from .first being oldest
47/// and .last being newest. The "find" function search from last to first
48/// to minimize search time for new BSSes you hear from often.
49static dl_list               network_info_list; ///< Filled network info
50static dl_list               network_info_free; ///< Available network info
51static dl_list               network_info_matching_ssid_list; ///< Filled network info that match the SSID provided to wlan_mac_high_find_network_info_SSID
52
53
54/*************************** Functions Prototypes ****************************/
55
56network_info_entry_t* wlan_mac_high_find_network_info_oldest();
57
58
59/******************************** Functions **********************************/
60
61void network_info_init() {
62
63    u32 i;
64    u32 num_network_info;
65    network_info_entry_t* network_info_entry_base;
66
67    dl_list_init(&network_info_free);
68    dl_list_init(&network_info_list);
69    dl_list_init(&network_info_matching_ssid_list);
70
71    // Clear the memory in the dram used for bss_infos
72    bzero((void*)BSS_INFO_BUFFER_BASE, BSS_INFO_BUFFER_SIZE);
73
74    // The number of BSS info elements we can initialize is limited by the smaller of two values:
75    //     (1) The number of network_info_entry_t structs we can squeeze into BSS_INFO_DL_ENTRY_MEM_SIZE
76    //     (2) The number of bss_info structs we can squeeze into BSS_INFO_BUFFER_SIZE
77    num_network_info = WLAN_MIN(BSS_INFO_DL_ENTRY_MEM_SIZE/sizeof(network_info_entry_t), BSS_INFO_BUFFER_SIZE/sizeof(network_info_t));
78
79    // At boot, every dl_entry buffer descriptor is free
80    // To set up the doubly linked list, we exploit the fact that we know the starting state is sequential.
81    // This matrix addressing is not safe once the queue is used. The insert/remove helper functions should be used
82    network_info_entry_base = (network_info_entry_t*)(BSS_INFO_DL_ENTRY_MEM_BASE);
83
84    for (i = 0; i < num_network_info; i++) {
85        network_info_entry_base[i].data = (void*)(BSS_INFO_BUFFER_BASE + (i*sizeof(network_info_t)));
86        dl_entry_insertEnd(&network_info_free, (dl_entry*)&(network_info_entry_base[i]));
87    }
88
89    xil_printf("Network Info list (len %d) placed in DRAM: using %d kB\n", num_network_info, (num_network_info*sizeof(network_info_t))/1024);
90
91    return;
92}
93
94
95
96void network_info_init_finish(){
97    //Will be called after interrupts have been started. Safe to use scheduler now.
98    wlan_mac_schedule_add_event(SCHEDULE_ID_COARSE, 10000000, SCHEDULE_REPEAT_FOREVER, (void*)network_info_timestamp_check);
99}
100
101
102
103inline void network_info_rx_process(void* pkt_buf_addr) {
104
105    rx_frame_info_t* rx_frame_info = (rx_frame_info_t*)pkt_buf_addr;
106    void* mac_payload = (u8*)pkt_buf_addr + PHY_RX_PKT_BUF_MPDU_OFFSET;
107    u8* mac_payload_ptr_u8 = (u8*)mac_payload;
108    char* ssid;
109    u8 ssid_length;
110    mac_header_80211* rx_80211_header = (mac_header_80211*)((void *)mac_payload_ptr_u8);
111    network_info_entry_t* curr_network_info_entry;
112    network_info_t* curr_network_info;
113    u8 unicast_to_me;
114    u8 to_multicast;
115    u8 update_rx_power = 0;
116    u8 update_timestamp = 0;
117    u16 length = rx_frame_info->phy_details.length;
118
119    // Determine destination of packet
120    unicast_to_me = wlan_addr_eq(rx_80211_header->address_1, get_mac_hw_addr_wlan());
121    to_multicast  = wlan_addr_mcast(rx_80211_header->address_1);
122
123    if ((rx_frame_info->flags & RX_FRAME_INFO_FLAGS_FCS_GOOD) && (unicast_to_me || to_multicast) ) {
124        switch(rx_80211_header->frame_control_1) {
125            case (MAC_FRAME_CTRL1_SUBTYPE_BEACON):
126                update_rx_power = 1;
127                update_timestamp = 1;
128                /* no break */
129            case (MAC_FRAME_CTRL1_SUBTYPE_PROBE_RESP):
130            case (MAC_FRAME_CTRL1_SUBTYPE_ASSOC_RESP):
131
132            curr_network_info_entry = wlan_mac_high_find_network_info_BSSID(rx_80211_header->address_3);
133
134                if(curr_network_info_entry != NULL){
135                    curr_network_info = curr_network_info_entry->data;
136
137                    // Remove entry from bss_info_list; Will be added back at the bottom of the function
138                    dl_entry_remove(&network_info_list, (dl_entry*)curr_network_info_entry);
139                } else {
140                    // We haven't seen this BSS ID before, so we'll attempt to checkout a new dl_entry
141                    // struct from the free pool
142                    curr_network_info_entry = network_info_checkout();
143
144                    if (curr_network_info_entry == NULL){
145                        // No free dl_entry!
146                        // We'll have to reallocate the oldest entry in the filled list
147                        curr_network_info_entry = wlan_mac_high_find_network_info_oldest();
148
149                        if (curr_network_info_entry != NULL) {
150                            dl_entry_remove(&network_info_list, (dl_entry*)curr_network_info_entry);
151                        } else {
152                            xil_printf("Cannot create network_info_t.\n");
153                            return;
154                        }
155                    }
156
157                    curr_network_info = curr_network_info_entry->data;
158
159                    // Clear any old information from the network info
160                    wlan_mac_high_clear_network_info(curr_network_info);
161
162                    // Initialize the members stations list
163                    dl_list_init(&(curr_network_info->members));
164
165                    // Copy BSSID into network_info_t struct
166                    memcpy(curr_network_info->bss_config.bssid, rx_80211_header->address_3, MAC_ADDR_LEN);
167
168                    // Copy BSSID into network_info_entry_t struct
169                    memcpy(curr_network_info_entry->bssid, rx_80211_header->address_3, MAC_ADDR_LEN);
170
171                }
172
173                // Move the packet pointer to after the header
174                mac_payload_ptr_u8 += sizeof(mac_header_80211);
175
176                if((rx_80211_header->frame_control_1 == MAC_FRAME_CTRL1_SUBTYPE_BEACON) || (rx_80211_header->frame_control_1 == MAC_FRAME_CTRL1_SUBTYPE_PROBE_RESP)){
177                    //Set values to zero that will be updated when processing tags
178                    curr_network_info->capabilities = 0;
179                    curr_network_info->bss_config.ht_capable = 0;
180                    curr_network_info->bss_config.dtim_period = 0;
181
182                    // Copy beacon capabilities into bss_info struct
183                    //     - Only a subset of beacon capabilities are recorded
184                    curr_network_info->capabilities |= (((beacon_probe_frame*)mac_payload_ptr_u8)->capabilities & BSS_CAPABILITIES_BEACON_MASK);
185
186                    // Copy beacon interval into bss_info struct
187                    curr_network_info->bss_config.beacon_interval = ((beacon_probe_frame*)mac_payload_ptr_u8)->beacon_interval;
188
189                    // Move the packet pointer to after the beacon/probe frame
190                    mac_payload_ptr_u8 += sizeof(beacon_probe_frame);
191                } else {
192                    // This must be an association response
193                    mac_payload_ptr_u8 += sizeof(association_response_frame);
194                }
195
196                // Copy the channel on which this packet was received into the network_info struct
197                //     - chan_spec will be overwritten later in this function if a HT
198                //       capabilities tag is discovered
199                curr_network_info->bss_config.chan_spec.chan_pri = rx_frame_info->channel;
200                curr_network_info->bss_config.chan_spec.chan_type = CHAN_TYPE_BW20;
201
202
203                // Parse the tagged parameters
204                while( (((u32)mac_payload_ptr_u8) - ((u32)mac_payload)) < (length - WLAN_PHY_FCS_NBYTES)) {
205
206                    // Parse each of the tags
207                    switch(mac_payload_ptr_u8[0]){
208
209                        //-------------------------------------------------
210                        case MGMT_TAG_SSID:
211                            // SSID parameter set
212                            //
213                            ssid        = (char*)(&(mac_payload_ptr_u8[2]));
214                            ssid_length = WLAN_MIN(mac_payload_ptr_u8[1],SSID_LEN_MAX);
215
216                            memcpy(curr_network_info->bss_config.ssid, ssid, ssid_length);
217
218                            // Terminate the string
219                            (curr_network_info->bss_config.ssid)[ssid_length] = 0;
220                        break;
221
222                        //-------------------------------------------------
223                        case MGMT_TAG_HT_CAPABILITIES:
224                            curr_network_info->bss_config.ht_capable = 1;
225                        break;
226
227                        //-------------------------------------------------
228                        case MGMT_TAG_HT_OPERATION:
229                            curr_network_info->bss_config.chan_spec.chan_pri = mac_payload_ptr_u8[2];
230                            if(mac_payload_ptr_u8[2] & 0x4){
231                                // Channel widths larger than 20MHz are supported by this BSS
232                                if((mac_payload_ptr_u8[2] & 0x3) == 0x3){
233                                    //Secondary Channel is below primary channel
234                                    curr_network_info->bss_config.chan_spec.chan_type = CHAN_TYPE_BW40_SEC_BELOW;
235                                } else if((mac_payload_ptr_u8[2] & 0x3) == 0x1){
236                                    //Secondary Channel is above primary channel
237                                    curr_network_info->bss_config.chan_spec.chan_type = CHAN_TYPE_BW40_SEC_ABOVE;
238                                }
239                            }
240                        break;
241
242                        //-------------------------------------------------
243                        case MGMT_TAG_DSSS_PARAMETER_SET:
244                            // DS Parameter set (e.g. channel)
245                            curr_network_info->bss_config.chan_spec.chan_pri = mac_payload_ptr_u8[2];
246                        break;
247
248                        //-------------------------------------------------
249                        case MGMT_TAG_TIM:
250                            curr_network_info->bss_config.dtim_period = mac_payload_ptr_u8[3];
251                        break;
252                    }
253
254                    // Increment packet pointer to the next tag
255                    mac_payload_ptr_u8 += mac_payload_ptr_u8[1]+2;
256                }
257
258                // Update the beacon Rx power
259                if (update_rx_power) curr_network_info->latest_beacon_rx_power = rx_frame_info->rx_power;
260
261                // Update the beacon timestamp
262                if (update_timestamp) curr_network_info->latest_beacon_rx_time = get_system_time_usec();
263
264                // TODO: Potential here for a application-specific callback on new BSS capabilities
265
266                // Add network info into bss_info_list
267                dl_entry_insertEnd(&network_info_list, (dl_entry*)curr_network_info_entry);
268            break;
269
270
271            //---------------------------------------------------------------------
272            default:
273                // Only need to process MAC_FRAME_CTRL1_SUBTYPE_BEACON, MAC_FRAME_CTRL1_SUBTYPE_PROBE_RESP
274                // to update BSS information.
275            break;
276        }
277    }
278}
279
280
281
282void print_network_info(){
283    int iter;
284    u32 i;
285    network_info_entry_t* curr_network_info_entry;
286    network_info_t* curr_network_info;
287
288    i = 0;
289    iter = network_info_list.length;
290    curr_network_info_entry = (network_info_entry_t*)network_info_list.last;
291
292    // Print the header
293    xil_printf("************************ Network Info *************************\n");
294
295    while ((curr_network_info_entry != NULL) && (iter-- > 0)) {
296        curr_network_info = curr_network_info_entry->data;
297
298        xil_printf("[%d] SSID:     %s ", i, curr_network_info->bss_config.ssid);
299
300        if(curr_network_info->capabilities & BSS_CAPABILITIES_PRIVACY){
301            xil_printf("(*)");
302        }
303        if(curr_network_info->capabilities & BSS_CAPABILITIES_IBSS){
304            xil_printf("(I)");
305        }
306        if(curr_network_info->flags & NETWORK_FLAGS_KEEP){
307            xil_printf("(my BSS)");
308        }
309        xil_printf("\n");
310
311        xil_printf("    BSSID:         %02x-%02x-%02x-%02x-%02x-%02x\n", curr_network_info->bss_config.bssid[0], curr_network_info->bss_config.bssid[1],
312                                                                         curr_network_info->bss_config.bssid[2], curr_network_info->bss_config.bssid[3],
313                                                                         curr_network_info->bss_config.bssid[4], curr_network_info->bss_config.bssid[5]);
314        xil_printf("    Channel:       %d\n", wlan_mac_high_bss_channel_spec_to_radio_chan(curr_network_info->bss_config.chan_spec));
315
316        xil_printf("    DTIM Period:   %d\n", curr_network_info->bss_config.dtim_period);
317
318        xil_printf("    HT Capable:    %d\n", curr_network_info->bss_config.ht_capable);
319
320        xil_printf("    Last update:   %d msec ago\n", (u32)((get_system_time_usec() - curr_network_info->latest_beacon_rx_time)/1000));
321
322        xil_printf("    Capabilities:  0x%04x\n", curr_network_info->capabilities);
323        curr_network_info_entry = dl_entry_prev(curr_network_info_entry);
324        i++;
325    }
326}
327
328
329
330void network_info_timestamp_check() {
331    network_info_entry_t* curr_network_info_entry;
332    network_info_t* curr_network_info;
333    curr_network_info_entry = (network_info_entry_t*)network_info_list.first;
334
335    while(curr_network_info_entry != NULL){
336        curr_network_info = curr_network_info_entry->data;
337
338        if((get_system_time_usec() - curr_network_info->latest_beacon_rx_time) > NETWORK_INFO_TIMEOUT_USEC){
339            if((curr_network_info->flags & NETWORK_FLAGS_KEEP) == 0){
340                wlan_mac_high_clear_network_info(curr_network_info);
341                dl_entry_remove(&network_info_list, (dl_entry*)curr_network_info_entry);
342                network_info_checkin(curr_network_info_entry);
343            }
344        } else {
345            // Nothing after this entry is older, so it's safe to quit
346            return;
347        }
348
349        curr_network_info_entry = dl_entry_next(curr_network_info_entry);
350    }
351}
352
353
354
355network_info_entry_t* network_info_checkout(){
356    network_info_entry_t* network_info_entry;
357    network_info_t* curr_network_info;
358
359    if(network_info_free.length > 0){
360        network_info_entry = ((network_info_entry_t*)(network_info_free.first));
361        dl_entry_remove(&network_info_free,network_info_free.first);
362
363        curr_network_info = network_info_entry->data;
364        dl_list_init(&(curr_network_info->members));
365        return network_info_entry;
366    } else {
367        return NULL;
368    }
369}
370
371void network_info_checkin(network_info_entry_t* network_info_entry){
372    dl_entry_insertEnd(&network_info_free, (dl_entry*)network_info_entry);
373    return;
374}
375
376
377dl_list* wlan_mac_high_find_network_info_SSID(char* ssid){
378    // This function will return a pointer to a dl_list that contains every
379    // network_info_t struct that matches the SSID argument.
380
381    int iter;
382    network_info_entry_t* curr_network_info_entry_primary_list;
383    network_info_entry_t* curr_network_info_entry_match_list;
384    network_info_entry_t* next_network_info_entry_match_list;
385    network_info_t* curr_network_info;
386
387    // Remove/free any members of network_info_matching_ssid_list that exist since the last time
388    // this function was called
389
390    iter = network_info_matching_ssid_list.length;
391    curr_network_info_entry_match_list = (network_info_entry_t*)network_info_matching_ssid_list.first;
392
393    while ((curr_network_info_entry_match_list != NULL) && (iter-- > 0)) {
394        next_network_info_entry_match_list = dl_entry_next(curr_network_info_entry_match_list);
395        dl_entry_remove(&network_info_matching_ssid_list, (dl_entry*)curr_network_info_entry_match_list);
396        wlan_mac_high_free(curr_network_info_entry_match_list);
397        curr_network_info_entry_match_list = next_network_info_entry_match_list;
398    }
399
400    // At this point in the code, network_info_matching_ssid_list is guaranteed to be empty.
401    // We will fill it with new network_info_entry_t that point to existing network_info_t structs that
402    // match the SSID argument to this function. Note: these network_info_t structs will continue
403    // to be pointed to by the existing network_info_entry_t
404
405    iter = network_info_list.length;
406    curr_network_info_entry_primary_list = (network_info_entry_t*)network_info_list.last;
407
408    while ((curr_network_info_entry_primary_list != NULL) && (iter-- > 0)) {
409        curr_network_info = curr_network_info_entry_primary_list->data;
410
411        if (strcmp(ssid, curr_network_info->bss_config.ssid) == 0) {
412            curr_network_info_entry_match_list = wlan_mac_high_malloc(sizeof(network_info_entry_t));
413            curr_network_info_entry_match_list->data = curr_network_info;
414            memcpy(curr_network_info_entry_match_list->bssid, curr_network_info->bss_config.bssid, MAC_ADDR_LEN);
415            dl_entry_insertEnd(&network_info_matching_ssid_list, (dl_entry*)curr_network_info_entry_match_list);
416        }
417
418        curr_network_info_entry_primary_list = dl_entry_prev(curr_network_info_entry_primary_list);
419    }
420
421    return &network_info_matching_ssid_list;
422}
423
424
425network_info_entry_t* wlan_mac_high_find_network_info_BSSID(u8* bssid){
426    int iter;
427    network_info_entry_t* curr_network_info_entry;
428
429    iter = network_info_list.length;
430    curr_network_info_entry = (network_info_entry_t*)network_info_list.last;
431
432    while ((curr_network_info_entry != NULL) && (iter-- > 0)) {
433        if (wlan_addr_eq(bssid,curr_network_info_entry->bssid)) {
434            return curr_network_info_entry;
435        }
436        curr_network_info_entry = dl_entry_prev(curr_network_info_entry);
437    }
438    return NULL;
439}
440
441network_info_entry_t* wlan_mac_high_find_network_info_oldest(){
442    int iter;
443    network_info_entry_t* curr_network_info_entry;
444    network_info_t* curr_network_info;
445
446    iter = network_info_list.length;
447    curr_network_info_entry = (network_info_entry_t*)network_info_list.first;
448
449    while ((curr_network_info_entry != NULL) && (iter-- > 0)) {
450        curr_network_info = curr_network_info_entry->data;
451
452        if ((curr_network_info->flags & NETWORK_FLAGS_KEEP) == 0) {
453            return curr_network_info_entry;
454        }
455
456        curr_network_info_entry = dl_entry_next(curr_network_info_entry);
457    }
458    return NULL;
459}
460
461
462
463// Function will create a bss_info and make sure that the BSS ID is unique
464// in the bss_info list.
465//
466network_info_t* wlan_mac_high_create_network_info(u8* bssid, char* ssid, u8 chan){
467    network_info_entry_t* curr_network_info_entry;
468    network_info_t* curr_network_info = NULL;
469
470    curr_network_info_entry = wlan_mac_high_find_network_info_BSSID(bssid);
471
472    if (curr_network_info_entry != NULL){
473        // Get the BSS info from the entry
474        curr_network_info = curr_network_info_entry->data;
475
476        // Remove the entry from the info list so it can be added back later
477        dl_entry_remove(&network_info_list, (dl_entry*)curr_network_info_entry);
478    } else {
479        // Have not seen this BSS ID before; attempt to grab a new network_info_entry_t
480        // struct from the free pool
481        curr_network_info_entry = network_info_checkout();
482
483        if (curr_network_info_entry == NULL){
484            // No free network_info_entry_t; Re-allocate the oldest entry in the filled list
485            curr_network_info_entry = wlan_mac_high_find_network_info_oldest();
486
487            if (curr_network_info_entry != NULL) {
488                dl_entry_remove(&network_info_list, (dl_entry*)curr_network_info_entry);
489            } else {
490                xil_printf("Cannot create network_info_t.\n");
491                return NULL;
492            }
493        }
494
495        // Get the network_info_t from the entry
496        curr_network_info = curr_network_info_entry->data;
497
498        // Clear any old information from the network info
499        wlan_mac_high_clear_network_info(curr_network_info);
500
501        // Initialize the associated stations list
502        dl_list_init(&(curr_network_info->members));
503
504        // Copy the BSS ID to the network_info_t struct
505        memcpy(curr_network_info->bss_config.bssid, bssid, MAC_ADDR_LEN);
506
507        // Copy the BSS ID to the network_info_entry_t struct
508        memcpy(curr_network_info_entry->bssid, bssid, MAC_ADDR_LEN);
509    }
510
511    // Update the fields of the BSS Info
512    strncpy(curr_network_info->bss_config.ssid, ssid, SSID_LEN_MAX);
513    curr_network_info->bss_config.chan_spec.chan_pri       = chan;
514    curr_network_info->bss_config.chan_spec.chan_type      = CHAN_TYPE_BW20;
515    curr_network_info->latest_beacon_rx_time    = get_system_time_usec();
516    curr_network_info->latest_beacon_rx_power   = 127; //Maximum s8 value with unrealistic power value. This let's downstream
517                                                       // processes know that no beacon has actually ever been received if they
518                                                       // see this value
519
520    //
521    // The following fields have their previous value retained if the were
522    // in the network list (i.e. wlan_mac_high_find_bss_info_BSSID() returned
523    // a non-NULL entry):
524    //    - latest_beacon_rx_power
525    //    - capabilities
526    //    - beacon_interval
527    //    - flags
528    //    - station_info_list
529    //
530
531    // Insert the updated entry into the network list
532    dl_entry_insertEnd(&network_info_list, (dl_entry*)curr_network_info_entry);
533
534    return curr_network_info;
535}
536
537/**
538 * @brief Reset List of Networks
539 *
540 * Reset all BSS Info except ones flagged to be kept
541 *
542 * @param  None
543 * @return None
544 */
545void wlan_mac_high_reset_network_list(){
546    network_info_entry_t* next_network_info_entry = (network_info_entry_t*)network_info_list.first;
547    network_info_entry_t* curr_network_info_entry;
548    network_info_t* curr_network_info;
549    int iter = network_info_list.length;
550
551    while( (next_network_info_entry != NULL) && (iter-- > 0) ){
552        curr_network_info_entry = next_network_info_entry;
553        next_network_info_entry = dl_entry_next(curr_network_info_entry);
554        curr_network_info = curr_network_info_entry->data;
555
556        if( (curr_network_info->flags & NETWORK_FLAGS_KEEP) == 0){
557            wlan_mac_high_clear_network_info(curr_network_info);
558            dl_entry_remove(&network_info_list, (dl_entry*)curr_network_info_entry);
559            network_info_checkin(curr_network_info_entry);
560        }
561    }
562}
563
564void wlan_mac_high_clear_network_info(network_info_t* info){
565    int iter;
566    station_info_t* curr_station_info;
567    station_info_entry_t* next_station_info_entry;
568    station_info_entry_t* curr_station_info_entry;
569
570    if (info != NULL){
571        // Remove any station infos
572        iter                    = info->members.length;
573        next_station_info_entry = (station_info_entry_t*)(info->members.first);
574
575        if (((info->flags & NETWORK_FLAGS_KEEP) == 0) && (next_station_info_entry != NULL)) {
576            xil_printf("WARNING:  network_info_t not flagged to be kept but contained station_info_t entries.\n");
577        }
578
579        // Set any members to ~STATION_INFO_FLAG_KEEP so the framework can remove them
580        while ((next_station_info_entry != NULL) && (iter-- > 0)) {
581            curr_station_info_entry = next_station_info_entry;
582            next_station_info_entry = dl_entry_next(curr_station_info_entry);
583
584            curr_station_info       = curr_station_info_entry->data;
585
586            // Remove the "keep" flag for this station_info so the framework can cleanup later.
587            curr_station_info->flags &= ~STATION_INFO_FLAG_KEEP;
588            network_info_remove_member(info, curr_station_info->addr);
589        }
590
591
592        // Clear the bss_info
593        bzero(info, sizeof(network_info_t));
594
595        // Set beacon_interval to "unknown"
596        info->bss_config.beacon_interval = BEACON_INTERVAL_UNKNOWN;
597    }
598}
599
600station_info_t* network_info_add_member(network_info_t* network_info, u8* addr, u32 max_queue_size){
601
602    // This function always:
603    //  1) keeps the ID fields of each station_info_t orthogonal, starting with the value 1 and packed such that
604    //     any holes are filled before larger IDs are used.
605    //  2) opens a Tx queue fo this station
606    //
607    //  Both of the above behaviors would need to be made optional before promiscuously adding station_info_t
608    //  into non-active network_info_t
609
610    station_info_entry_t* station_info_entry = NULL;
611    station_info_t* station_info = NULL;
612    s16 max_existing_ID = 0;
613    s16 new_ID = 0;
614    u8* ones_array;
615    u32 i;
616
617    if(network_info == NULL) return NULL;
618
619    station_info_entry = station_info_find_by_addr(addr, &(network_info->members));
620
621    // If we found a this station is already a member, return it.
622    if(station_info_entry) return station_info_entry->data;
623
624    // 1) Select a valid ID for this member. network_info->members is not ordered.
625    //    We need to, first, find any gaps in currently used IDs and fill those. If
626    //    no gaps exist, we will use an ID higher that the current maximum.
627    station_info_entry = (station_info_entry_t*)(network_info->members.first);
628    for(i = 0; i < network_info->members.length; i++){
629        max_existing_ID = WLAN_MAX(max_existing_ID, station_info_entry->data->ID);
630        station_info_entry = dl_entry_next(station_info_entry);
631    }
632
633    if(max_existing_ID > 0){
634        ones_array = wlan_mac_high_malloc(max_existing_ID * sizeof(u8));
635
636        if(ones_array){
637            // Set ones_array to all ones
638            memset(ones_array, 1, max_existing_ID * sizeof(u8));
639
640            station_info_entry = (station_info_entry_t*)(network_info->members.first);
641            for(i = 0; i < network_info->members.length; i++){
642                if(station_info_entry->data->ID > 0){
643                    // Mark this ID has used
644                    ones_array[ (station_info_entry->data->ID) - 1 ] = 0;
645                }
646                station_info_entry = dl_entry_next(station_info_entry);
647            }
648
649            //Find the first unused ID in the ones_array
650            for(i = 0; i < (u32)max_existing_ID; i++){
651                if(ones_array[i]){
652                    new_ID = i+1;
653                    break;
654                }
655            }
656            wlan_mac_high_free(ones_array);
657        }
658    }
659
660    if(new_ID == 0){
661        // If we didn't find any gaps in the existing IDs, we will use a new
662        // maximum value.
663        new_ID = max_existing_ID + 1;
664    }
665
666    // If not, we need to add it to the member list
667    station_info = station_info_add_to_list(&(network_info->members), addr);
668
669    if(station_info == NULL) return NULL;
670
671
672    station_info->ID = new_ID;
673    station_info->QID = queue_open(tx_queue_state_change_callback, new_ID, max_queue_size);
674
675    // Initialize the latest activity timestamp
676    //     NOTE:  This is so we don't run into a race condition when we try to check the association timeout
677    //
678    station_info->latest_rx_timestamp = get_system_time_usec();
679
680    // Set the last received sequence number to something invalid so we don't accidentally
681    // de-duplicate the next reception if that sequence number is 0.
682    station_info->latest_rx_seq = 0xFFFF; //Sequence numbers are only 12 bits long. This is intentionally invalid.
683
684    return station_info;
685
686}
687
688int network_info_remove_member(network_info_t* network_info, u8* addr){
689
690    station_info_entry_t* station_info_entry;
691
692    if(network_info == NULL) return WLAN_FAILURE;
693
694    station_info_entry = station_info_find_by_addr(addr, &(network_info->members));
695
696    if(station_info_entry){
697        if(station_info_entry->data->QID >= 0) queue_close(station_info_entry->data->QID);
698        station_info_entry->data->QID = -1;
699        station_info_entry->data->ID = -1;
700        station_info_remove_from_list(&(network_info->members), addr);
701        return WLAN_SUCCESS;
702    } else {
703        return WLAN_FAILURE;
704    }
705
706}
707
708inline dl_list* wlan_mac_high_get_network_info_list(){
709    return &network_info_list;
710}
Note: See TracBrowser for help on using the repository browser.