source: ReferenceDesigns/w3_802.11/c/wlan_mac_high_ap/wlan_exp_node_ap.c

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

1.8.0 release wlan-mac-se

File size: 21.0 KB
Line 
1/** @file wlan_exp_node_ap.c
2 *  @brief Access Point WLAN Experiment
3 *
4 *  This contains code for the 802.11 Access Point's WLAN experiment interface.
5 *
6 *  @copyright Copyright 2013-2019, Mango Communications. All rights reserved.
7 *          Distributed under the Mango Communications Reference Design License
8 *              See LICENSE.txt included in the design archive or
9 *              at http://mangocomm.com/802.11/license
10 *
11 *  This file is part of the Mango 802.11 Reference Design (https://mangocomm.com/802.11)
12 */
13
14/***************************** Include Files *********************************/
15
16#include "wlan_mac_high_sw_config.h"
17
18#if WLAN_SW_CONFIG_ENABLE_WLAN_EXP
19
20#include "wlan_platform_common.h"
21#include "wlan_platform_high.h"
22
23#include "wlan_exp_node.h"
24#include "wlan_exp_node_ap.h"
25
26#include "wlan_mac_common.h"
27#include "wlan_mac_entries.h"
28#include "wlan_mac_ltg.h"
29#include "wlan_mac_addr_filter.h"
30#include "wlan_mac_event_log.h"
31#include "wlan_mac_high.h"
32#include "wlan_mac_ap.h"
33#include "wlan_mac_network_info.h"
34#include "wlan_mac_station_info.h"
35#include "wlan_mac_queue.h"
36
37#include "xil_io.h"
38
39
40// Check that there is enough memory to support MAX_NUM_ASSOC
41CASSERT( (MAX_NUM_ASSOC ) <= STATION_INFO_DL_ENTRY_MEM_NUM, insufficient_WLAN_OPTIONS_AUX_SIZE_KB_STATION_INFO_for_max_associations )
42
43/*************************** Constant Definitions ****************************/
44
45
46/*********************** Global Variable Definitions *************************/
47
48extern network_info_t* active_network_info;
49
50extern function_ptr_t wlan_exp_purge_all_wireless_tx_queue_callback;
51extern u8 gl_dtim_mcast_buffer_enable;
52
53extern u32 max_queue_size;
54
55
56/*************************** Variable Definitions ****************************/
57
58
59/*************************** Functions Prototypes ****************************/
60
61
62/******************************** Functions **********************************/
63
64
65/*****************************************************************************/
66/**
67 * Process Node Commands
68 *
69 * This function is part of the Ethernet processing system and will process the
70 * various node related commands.
71 *
72 * @return  int              - Status of the command:
73 *                                 NO_RESP_SENT - No response has been sent
74 *                                 RESP_SENT    - A response has been sent
75 *
76 * @note    See on-line documentation for more information about the Ethernet
77 *          packet structure:  www.warpproject.org
78 *
79 *****************************************************************************/
80
81int process_wlan_exp_app_cmd(cmd_resp_hdr_t* cmd_hdr, eth_tx_queue_buffer_t* eth_tx_queue_buffer) {
82
83    //
84    // IMPORTANT ENDIAN NOTES:
85    //     - command
86    //         - header - Already endian swapped by the framework (safe to access directly)
87    //         - args   - Must be endian swapped as necessary by code (framework does not know the contents of the command)
88    //     - response
89    //         - header - Will be endian swapped by the framework (safe to write directly)
90    //         - args   - Must be endian swapped as necessary by code (framework does not know the contents of the response)
91    //
92
93    // Standard variables
94    u32 resp_sent = NO_RESP_SENT;
95
96    u32 cmd_id = CMD_TO_CMDID(cmd_hdr->cmd);
97
98    // Segment 0 length includes a fully formed command response header
99    //  because one was created with default values suitable for a responseless
100    //  acknowledgment.
101    cmd_resp_hdr_t* resp_hdr = (cmd_resp_hdr_t*)(eth_tx_queue_buffer->seg0
102                                                 + eth_tx_queue_buffer->seg0_len
103                                                 - sizeof(cmd_resp_hdr_t));
104
105    u32* cmd_args_32 = (u32*)((u8*)cmd_hdr + sizeof(cmd_resp_hdr_t));
106
107    //
108    // NOTE: Response header cmd, length, and num_args fields have already been initialized.
109    //
110
111    switch(cmd_id){
112
113//-----------------------------------------------------------------------------
114// WLAN Exp Node Commands that must be implemented in child classes
115//-----------------------------------------------------------------------------
116
117        //---------------------------------------------------------------------
118        case CMDID_NODE_RESET_STATE: {
119            // NODE_RESET_STATE Packet Format:
120            //   - cmd_args_32[0]  - Flags
121            //                     [0] - NODE_RESET_LOG
122            //                     [1] - NODE_RESET_TXRX_COUNTS
123            //                     [2] - NODE_RESET_LTG
124            //                     [3] - NODE_RESET_TX_DATA_QUEUE
125            //                     [4] - NODE_RESET_ASSOCIATIONS
126            //                     [5] - NODE_RESET_BSS_INFO
127            //
128            interrupt_state_t prev_interrupt_state;
129            u32 status = CMD_PARAM_SUCCESS;
130            u32 flags = Xil_Ntohl(cmd_args_32[0]);
131
132            // Disable interrupts so no packets interrupt the reset
133            prev_interrupt_state = wlan_platform_intc_stop();
134
135#if WLAN_SW_CONFIG_ENABLE_LOGGING
136            // Configure the LOG based on the flag bits
137            if (flags & CMD_PARAM_NODE_RESET_FLAG_LOG) {
138                wlan_exp_printf(WLAN_EXP_PRINT_INFO, print_type_event_log, "Reset log\n");
139                event_log_reset();
140            }
141#endif //WLAN_SW_CONFIG_ENABLE_LOGGING
142
143            if (flags & CMD_PARAM_NODE_RESET_FLAG_TXRX_COUNTS) {
144                wlan_exp_printf(WLAN_EXP_PRINT_INFO, print_type_counts, "Reseting Counts\n");
145#if WLAN_SW_CONFIG_ENABLE_TXRX_COUNTS
146                txrx_counts_zero_all();
147#endif //WLAN_SW_CONFIG_ENABLE_TXRX_COUNTS
148            }
149
150#if WLAN_SW_CONFIG_ENABLE_LTG
151            if (flags & CMD_PARAM_NODE_RESET_FLAG_LTG) {
152                status = ltg_sched_remove(LTG_REMOVE_ALL);
153
154                if (status != 0) {
155                    wlan_exp_printf(WLAN_EXP_PRINT_ERROR, print_type_ltg, "Failed to remove all LTGs\n");
156                    status = CMD_PARAM_ERROR + CMD_PARAM_LTG_ERROR;
157                } else {
158                    wlan_exp_printf(WLAN_EXP_PRINT_INFO, print_type_ltg, "Removing All LTGs\n");
159                }
160            }
161#endif //WLAN_SW_CONFIG_ENABLE_LTG
162
163            if (flags & CMD_PARAM_NODE_RESET_FLAG_TX_DATA_QUEUE) {
164                wlan_exp_printf(WLAN_EXP_PRINT_INFO, print_type_queue, "Purging all data transmit queues\n");
165                wlan_exp_purge_all_wireless_tx_queue_callback();
166            }
167
168            if (flags & CMD_PARAM_NODE_RESET_FLAG_BSS) {
169                wlan_exp_printf(WLAN_EXP_PRINT_INFO, print_type_node, "Resetting BSS \n");
170
171                // Note: Interrupts are currently disabled
172
173                // Deauthenticate all stations
174                //     - This will send deauthentication packets to each Station
175                deauthenticate_all_stations();
176
177                // Set "active_bss_info" to NULL
178                configure_bss(NULL,0);
179            }
180
181            if (flags & CMD_PARAM_NODE_RESET_FLAG_NETWORK_LIST) {
182                wlan_exp_printf(WLAN_EXP_PRINT_INFO, print_type_node, "Resetting Network List\n");
183                wlan_mac_high_reset_network_list();
184            }
185
186            // Call MAC specific reset with the flags
187
188            // Re-enable interrupts
189            wlan_platform_intc_set_state(prev_interrupt_state);
190
191            // Send response of success
192            wlan_exp_add_u32_resp_arg(eth_tx_queue_buffer, resp_hdr, status);
193        }
194        break;
195
196
197        //---------------------------------------------------------------------
198        case CMDID_NODE_DISASSOCIATE: {
199            // Disassociate device from node
200            //
201            // Message format:
202            //     cmd_args_32[0:1]      MAC Address (All 0xFF means all station info)
203            //
204            // Response format:
205            //     resp_args_32[0]       Status
206            //
207            u8 mac_addr[MAC_ADDR_LEN];
208            station_info_entry_t* curr_entry;
209            station_info_t* curr_station_info;
210            interrupt_state_t prev_interrupt_state;
211            u32 status = CMD_PARAM_SUCCESS;
212
213            wlan_exp_printf(WLAN_EXP_PRINT_INFO, print_type_node, "Disassociate\n");
214
215            // Get MAC Address
216            wlan_exp_get_mac_addr(&((u32 *)cmd_args_32)[0], &mac_addr[0]);
217
218
219            // Depending on the mac_addr argument to this command, there are two actions that need to take place:
220            // 1) If the mac_addr is all zeros (00-00-00-00-00-00), this is a magic number that indicates
221            //    that all currently-associated stations must be removed from the network
222            // 2) If the mac_addr matches the MAC address of a currently associated station, it should be removed
223            //    from the network
224
225            prev_interrupt_state = wlan_platform_intc_stop();
226
227            // This function is safe to call even if get_network_member_list() is NULL.
228            //  In that case, it will search through the flat list of station_info_t managed
229            //  by the High Framework. So, a non-NULL curr_entry does not necessarily mean
230            //  an associated station with this address has been found. For that to be the
231            //  case, both curr_entry and get_network_member_list() must be non-NULL.
232            curr_entry = station_info_find_by_addr( mac_addr, get_network_member_list() );
233
234            if(wlan_addr_eq(mac_addr, zero_addr)){
235                // Remove all currently associated stations
236
237                deauthenticate_all_stations();
238
239                wlan_exp_printf(WLAN_EXP_PRINT_INFO, print_type_node, "Disassociated node: ");
240                wlan_exp_print_mac_address(WLAN_EXP_PRINT_INFO, &mac_addr[0]); wlan_exp_printf(WLAN_EXP_PRINT_INFO, NULL, "\n");
241            } else if(curr_entry && get_network_member_list()) {
242                // There is currently an active network and we found this MAC address in the member list.
243                //  We will remove this
244                curr_station_info = (curr_entry->data);
245
246                deauthenticate_station(curr_station_info);
247
248                // Set return parameters and print info to console
249                wlan_exp_printf(WLAN_EXP_PRINT_INFO, print_type_node, "Disassociated node: ");
250                wlan_exp_print_mac_address(WLAN_EXP_PRINT_INFO, &mac_addr[0]); wlan_exp_printf(WLAN_EXP_PRINT_INFO, NULL, "\n");
251            } else {
252                // Either we have no active network or there is no node in the member list matching this MAC address
253                wlan_exp_printf(WLAN_EXP_PRINT_INFO, print_type_node, "Could not find specified node: ");
254                wlan_exp_print_mac_address(WLAN_EXP_PRINT_INFO, &mac_addr[0]); wlan_exp_printf(WLAN_EXP_PRINT_INFO, NULL, "\n");
255
256                status = CMD_PARAM_ERROR;
257            }
258
259            wlan_platform_intc_set_state(prev_interrupt_state);
260
261            // Send response
262            wlan_exp_add_u32_resp_arg(eth_tx_queue_buffer, resp_hdr, status);
263        }
264        break;
265
266
267//-----------------------------------------------------------------------------
268// AP Specific Commands
269//-----------------------------------------------------------------------------
270
271
272        //---------------------------------------------------------------------
273        case CMDID_NODE_AP_CONFIG: {
274            // Set AP configuration flags
275            //
276            // Message format:
277            //     cmd_args_32[0]   Flags
278            //                          [ 0] - NODE_AP_CONFIG_FLAG_DTIM_MULTICAST_BUFFERING
279            //     cmd_args_32[1]   Mask for flags
280            //
281            // Response format:
282            //     resp_args_32[0]  Status (CMD_PARAM_SUCCESS/CMD_PARAM_ERROR)
283            //
284            u32 status = CMD_PARAM_SUCCESS;
285            u32 flags = Xil_Ntohl(cmd_args_32[0]);
286            u32 mask = Xil_Ntohl(cmd_args_32[1]);
287
288            wlan_exp_printf(WLAN_EXP_PRINT_INFO, print_type_node, "AP: Config flags = 0x%08x  mask = 0x%08x\n", flags, mask);
289
290            // Configure based on the flag bit / mask
291            if (mask & CMD_PARAM_NODE_AP_CONFIG_FLAG_DTIM_MULTICAST_BUFFER) {
292                if(flags & CMD_PARAM_NODE_AP_CONFIG_FLAG_DTIM_MULTICAST_BUFFER){
293                    gl_dtim_mcast_buffer_enable = 1;
294                    wlan_mac_high_enable_mcast_buffering(gl_dtim_mcast_buffer_enable);
295                } else {
296                    gl_dtim_mcast_buffer_enable = 0;
297                    wlan_mac_high_enable_mcast_buffering(gl_dtim_mcast_buffer_enable);
298                }
299            }
300
301            // Send response of status
302            wlan_exp_add_u32_resp_arg(eth_tx_queue_buffer, resp_hdr, status);
303        }
304        break;
305
306
307        //---------------------------------------------------------------------
308        case CMDID_NODE_AP_SET_AUTHENTICATION_ADDR_FILTER: {
309            // Allow / Disallow wireless authentications
310            //
311            // Message format:
312            //     cmd_args_32[0]   Command:
313            //                          - Write       (CMD_PARAM_WRITE_VAL)
314            //     cmd_args_32[1]   Number of address filters
315            //     cmd_args_32[2:N] [Compare address (u64), (Mask (u64)]
316            //
317            // Response format:
318            //     resp_args_32[0]  Status
319            //
320            u32 i;
321            u8 mac_addr[MAC_ADDR_LEN];
322            u8 mask[MAC_ADDR_LEN];
323            interrupt_state_t prev_interrupt_state;
324            u32 status = CMD_PARAM_SUCCESS;
325            u32 msg_cmd = Xil_Ntohl(cmd_args_32[0]);
326            u32 num_ranges = Xil_Ntohl(cmd_args_32[1]);
327
328            switch (msg_cmd) {
329                case CMD_PARAM_WRITE_VAL:
330                    // Need to disable interrupts during this operation so the filter does not have any holes
331                    prev_interrupt_state = wlan_platform_intc_stop();
332
333                    // Reset the current address filter
334                    wlan_mac_addr_filter_reset();
335
336                    // Add all the address ranges to the filter
337                    for (i = 0; i < num_ranges; i++) {
338                        // Extract the address and the mask
339                        wlan_exp_get_mac_addr(&((u32 *)cmd_args_32)[2 + (4*i)], &mac_addr[0]);
340                        wlan_exp_get_mac_addr(&((u32 *)cmd_args_32)[4 + (4*i)], &mask[0]);
341
342                        wlan_exp_printf(WLAN_EXP_PRINT_INFO, print_type_node, "Adding Address filter: (");
343                        wlan_exp_print_mac_address(WLAN_EXP_PRINT_INFO, mac_addr); wlan_exp_printf(WLAN_EXP_PRINT_INFO, NULL, ", ");
344                        wlan_exp_print_mac_address(WLAN_EXP_PRINT_INFO, mask); wlan_exp_printf(WLAN_EXP_PRINT_INFO, NULL, "\n");
345
346                        if (wlan_mac_addr_filter_add(mask, mac_addr) == -1) {
347                            status = CMD_PARAM_ERROR;
348                        }
349                    }
350
351                    wlan_platform_intc_set_state(prev_interrupt_state);
352                break;
353
354                default:
355                    wlan_exp_printf(WLAN_EXP_PRINT_ERROR, print_type_node, "Unknown command for 0x%6x: %d\n", cmd_id, msg_cmd);
356                    status = CMD_PARAM_ERROR;
357                break;
358            }
359
360            // Send response
361            wlan_exp_add_u32_resp_arg(eth_tx_queue_buffer, resp_hdr, status);
362        }
363        break;
364
365
366//-----------------------------------------------------------------------------
367// Association Commands
368//-----------------------------------------------------------------------------
369
370
371        //---------------------------------------------------------------------
372        case CMDID_NODE_ASSOCIATE: {
373            // Associate with the device
374            //
375            // Message format:
376            //     cmd_args_32[0]        Association flags
377            //                               CMD_PARAM_AP_ASSOCIATE_FLAG_ALLOW_TIMEOUT
378            //                               CMD_PARAM_AP_ASSOCIATE_FLAG_STATION_INFO_DO_NOT_REMOVE
379            //     cmd_args_32[1]        Association flags mask
380            //     cmd_args_32[2:3]      Association MAC Address
381            //
382            // Response format:
383            //     resp_args_32[0]       Status
384            //
385            u32 flags;
386            u32 mask;
387            u8 mac_addr[MAC_ADDR_LEN];
388            interrupt_state_t prev_interrupt_state;
389            u32 status = CMD_PARAM_SUCCESS;
390            station_info_entry_t* station_info_entry = NULL;
391            station_info_t* curr_station_info = NULL;
392            u8 station_flags = 0;
393            u16 station_capabilities = 0;
394            u32 error_reason = 0;
395
396            wlan_exp_printf(WLAN_EXP_PRINT_INFO, print_type_node, "AP: Associate\n");
397
398                // Get MAC Address
399                wlan_exp_get_mac_addr(&((u32 *)cmd_args_32)[2], &mac_addr[0]);
400
401            if(active_network_info != NULL){
402                station_info_entry = station_info_find_by_addr(mac_addr, &(active_network_info->members));
403            }
404
405            if ((active_network_info != NULL) && ((station_info_entry != NULL) || (active_network_info->members.length < MAX_NUM_ASSOC)) ) {
406
407                // Get flags
408                flags = Xil_Ntohl(cmd_args_32[0]);
409                mask  = Xil_Ntohl(cmd_args_32[1]);
410
411                wlan_exp_printf(WLAN_EXP_PRINT_INFO, print_type_node, "Associate flags = 0x%08x  mask = 0x%08x\n", flags, mask);
412
413                // Disable interrupts to avoid race conditions between wlan_exp and wireless Tx/Rx when
414                //  modifying the AP's association table
415                prev_interrupt_state = wlan_platform_intc_stop();
416
417                // Add association
418                curr_station_info = network_info_add_member(active_network_info, &mac_addr[0], max_queue_size);
419
420                // Set return parameters and print info to console
421                if (curr_station_info != NULL) {
422
423                // Update the new station_info flags field
424                //  Only override the defaults set by the framework add_station_info if the wlan_exp command explicitly included a flag
425                station_flags = curr_station_info->flags;
426
427                // Raise the KEEP flag to prevent the MAC High Framework from removing the struct
428                station_flags |= STATION_INFO_FLAG_KEEP;
429
430                if (mask & CMD_PARAM_AP_ASSOCIATE_FLAG_DISABLE_INACTIVITY_TIMEOUT) {
431                    if (flags & CMD_PARAM_AP_ASSOCIATE_FLAG_DISABLE_INACTIVITY_TIMEOUT) {
432                        station_flags |= STATION_INFO_FLAG_DISABLE_ASSOC_CHECK;
433                    } else {
434                        station_flags &= ~STATION_INFO_FLAG_DISABLE_ASSOC_CHECK;
435                    }
436                }
437
438                if (mask & CMD_PARAM_AP_ASSOCIATE_FLAG_HT_CAPABLE_STA) {
439                    if (flags & CMD_PARAM_AP_ASSOCIATE_FLAG_HT_CAPABLE_STA) {
440                        station_capabilities |= STATION_INFO_CAPABILITIES_HT_CAPABLE;
441                    } else {
442                        station_capabilities &= ~STATION_INFO_CAPABILITIES_HT_CAPABLE;
443                    }
444                }
445
446                // Update the station_info flags
447                curr_station_info->flags = station_flags;
448                curr_station_info->capabilities = station_capabilities;
449
450                // Re-enable interrupts
451                wlan_platform_intc_set_state(prev_interrupt_state);
452
453
454                    //
455                    // TODO:  (Optional) Log association state change
456                    //
457
458                    // Update the hex display
459                    wlan_platform_high_userio_disp_status(USERIO_DISP_STATUS_MEMBER_LIST_UPDATE, active_network_info->members.length);
460
461                    wlan_exp_printf(WLAN_EXP_PRINT_INFO, print_type_node, "Associated with node: ");
462                } else {
463
464                    // Re-enable interrupts
465                    wlan_platform_intc_set_state(prev_interrupt_state);
466
467                    wlan_exp_printf(WLAN_EXP_PRINT_INFO, print_type_node, "Could not associate with node: ");
468                    status = CMD_PARAM_ERROR;
469                    error_reason |= NODE_ASSOCIATE_ERROR_MEMORY;
470
471                }
472            } else {
473                wlan_exp_printf(WLAN_EXP_PRINT_INFO, print_type_node, "Could not associate with node: ");
474                status = CMD_PARAM_ERROR;
475                error_reason |= NODE_ASSOCIATE_ERROR_TOO_MANY_ASSOC;
476            }
477
478            wlan_exp_print_mac_address(WLAN_EXP_PRINT_INFO, &mac_addr[0]); wlan_exp_printf(WLAN_EXP_PRINT_INFO, NULL, "\n");
479
480            // Send response
481            wlan_exp_add_u32_resp_arg(eth_tx_queue_buffer, resp_hdr, status);
482
483            if (curr_station_info != NULL) {
484                wlan_exp_add_u32_resp_arg(eth_tx_queue_buffer, resp_hdr, curr_station_info->ID);
485            } else {
486                wlan_exp_add_u32_resp_arg(eth_tx_queue_buffer, resp_hdr, error_reason);
487            }
488        }
489        break;
490
491
492        //---------------------------------------------------------------------
493        default: {
494            wlan_exp_printf(WLAN_EXP_PRINT_ERROR, print_type_node, "Unknown node command: 0x%x\n", cmd_id);
495        }
496        break;
497    }
498
499    return resp_sent;
500}
501
502
503#endif
504
Note: See TracBrowser for help on using the repository browser.