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

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

1.8.0 release wlan-mac-se

File size: 27.1 KB
Line 
1/** @file wlan_exp_transport.c
2 *  @brief Experiment Framework (Transport)
3 *
4 *  Handles UDP transmissions and reception as well as process commands for the
5 *  transport group.
6 *
7 *  @copyright Copyright 2013-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#if WLAN_SW_CONFIG_ENABLE_WLAN_EXP
20
21#include <xparameters.h>
22#include <xil_io.h>
23#include <xstatus.h>
24#include <stdlib.h>
25#include <stdio.h>
26#include <string.h>
27
28#include "wlan_mac_common.h"
29#include "wlan_mac_high.h"
30#include "wlan_platform_high.h"
31#include "wlan_platform_common.h"
32#include "wlan_mac_dl_list.h"
33#include "wlan_mac_queue.h"
34#include "wlan_mac_network_info.h"
35#include "wlan_mac_station_info.h"
36
37#include "wlan_exp_common.h"
38#include "wlan_exp_node.h"
39#include "wlan_exp_transport.h"
40#include "wlan_exp_ip_udp_socket.h"
41
42// Internal structure to this file. It never is sent to a host OTW
43typedef struct _wlan_exp_transport_info_t{
44    u32 group_id;
45    u32 unicast_port;
46    u32 broadcast_port;
47    u32 max_pkt_words;
48    int socket_unicast;
49    int socket_broadcast;
50} _wlan_exp_transport_info_t;
51
52// Transport information
53static _wlan_exp_transport_info_t wlan_exp_transport_info;
54
55// Defined in wlan_exp_node.c
56extern platform_high_dev_info_t platform_high_dev_info;
57extern wlan_exp_node_info_t wlan_exp_node_info;
58
59// Defined in wlan_mac_high.c
60extern wlan_mac_hw_info_t wlan_mac_hw_info;
61
62// Queues for wlan_exp Rx/Tx
63static int _wlan_exp_eth_rx_qid;
64static int _wlan_exp_eth_tx_qid;
65
66static sockaddr_in_t* gl_tx_to;
67
68void _wlan_exp_tx_queue_occupancy_change(int callback_arg, u32 queue_len);
69int  _transport_config_socket(int* socket_index, u32 udp_port);
70
71/*****************************************************************************/
72/**
73 * @brief Transport subsystem initialization
74 *
75 * @return  int - WLAN_SUCCESS or WLAN_FAILURE
76 ******************************************************************************/
77int transport_init() {
78    u8 ip_addr[IP_ADDR_LEN];
79
80    int status = WLAN_SUCCESS;
81
82    // Open a queue for Rx Ethernet frames
83    _wlan_exp_eth_rx_qid = queue_open((void*)wlan_null_callback, 0, WLAN_EXP_MAX_QUEUE_LEN);
84
85    // Open a queue for Tx Ethernet frames
86    _wlan_exp_eth_tx_qid = queue_open((void*)_wlan_exp_tx_queue_occupancy_change, 0, WLAN_EXP_MAX_QUEUE_LEN);
87
88    if((_wlan_exp_eth_rx_qid == -1) || (_wlan_exp_eth_tx_qid == -1)) xil_printf("Error in wlan_eth_util_init(), unable to open queue\n");
89
90    ip_addr[0] = (WLAN_EXP_DEFAULT_IP_ADDR >> 24) & 0xFF;
91    ip_addr[1] = (WLAN_EXP_DEFAULT_IP_ADDR >> 16) & 0xFF;
92    ip_addr[2] = (WLAN_EXP_DEFAULT_IP_ADDR >>  8) & 0xFF;
93    ip_addr[3] = (WLAN_EXP_DEFAULT_IP_ADDR      ) & 0xFF;  // IP ADDR = w.x.y.z
94
95    // Initialize the wlan_exp IP/UDP transport
96    ip_udp_init(wlan_mac_hw_info.hw_addr_wlan_exp, ip_addr);
97
98    // Print MAC address and IP address
99    xil_printf("  wlan_exp MAC Address: %02x:%02x:%02x:%02x:%02x:%02x\n",
100            wlan_mac_hw_info.hw_addr_wlan_exp[0], wlan_mac_hw_info.hw_addr_wlan_exp[1], wlan_mac_hw_info.hw_addr_wlan_exp[2],
101            wlan_mac_hw_info.hw_addr_wlan_exp[3], wlan_mac_hw_info.hw_addr_wlan_exp[4], wlan_mac_hw_info.hw_addr_wlan_exp[5]);
102    xil_printf("  wlan_exp IP  Address: %d.%d.%d.%d\n",
103            ip_addr[0], ip_addr[1], ip_addr[2], ip_addr[3]);
104
105
106    // Initialize transport info structure
107    wlan_exp_transport_info.max_pkt_words = WLAN_EXP_DEFAULT_MAX_PACKET_WORDS;
108    wlan_exp_transport_info.socket_unicast = SOCKET_INVALID_SOCKET;
109    wlan_exp_transport_info.socket_broadcast = SOCKET_INVALID_SOCKET;
110
111    wlan_exp_transport_info.group_id = 0;
112    transport_set_ip_addr(ip_addr);
113
114    // Configure the Sockets for each Ethernet Interface
115    status = transport_config_sockets(WLAN_EXP_DEFAULT_UDP_UNICAST_PORT, WLAN_EXP_DEFAULT_UDP_MULTICAST_PORT);
116
117    if (status != WLAN_SUCCESS) {
118        wlan_exp_printf(WLAN_EXP_PRINT_ERROR, print_type_transport, "Cannot configure sockets for Ethernet\n");
119    }
120
121    gl_tx_to = NULL;
122
123    return status;
124}
125
126/*****************************************************************************/
127/**
128 * @brief Append a UDP reception for future processing
129 *
130 * This function accepts an Ethernet queue buffer and enqueues it for
131 * later processing by wlan_exp. The framework uses this structure to defer
132 * processing to outside of an interrupt context in platforms whose wlan_exp
133 * Ethernet peripheral is interrupt-based.
134 *
135 * @return  int - WLAN_SUCCESS or WLAN_FAILURE
136 ******************************************************************************/
137int wlan_exp_append_rx(dl_entry* queue_entry){
138    int status;
139
140    status = queue_enqueue(_wlan_exp_eth_rx_qid, queue_entry);
141    if( status == WLAN_FAILURE ){
142        queue_checkin(queue_entry);
143    }
144
145    return status;
146}
147
148/*****************************************************************************/
149/**
150 * @brief Append a UDP transmission for future processing
151 *
152 * This function accepts an Ethernet queue buffer and enqueues it for
153 * later transmission by the platform's wlan_exp Ethernet peripheral.
154 *
155 * @return  int - WLAN_SUCCESS or WLAN_FAILURE
156 ******************************************************************************/
157int wlan_exp_append_tx(dl_entry* queue_entry){
158    int status;
159    interrupt_state_t prev_interrupt_state;
160
161    prev_interrupt_state = wlan_platform_intc_stop();
162    status = queue_enqueue(_wlan_exp_eth_tx_qid, queue_entry);
163
164    if( status == WLAN_FAILURE ){
165        queue_checkin(queue_entry);
166    }
167    wlan_platform_intc_set_state(prev_interrupt_state);
168
169    return status;
170}
171
172/*****************************************************************************/
173/**
174 * @brief Get the current length of the wlan_exp Tx queue
175 *
176 * @return  int - length of the Tx queue
177 ******************************************************************************/
178int wlan_exp_get_tx_queue_length(){
179    return queue_length(_wlan_exp_eth_tx_qid);
180}
181
182
183/*****************************************************************************/
184/**
185 * @brief Poll enqueued UDP receptions
186 *
187 * This function is called by outside of an interrupt context and is used to process
188 * any received UDP frames enqueued by wlan_exp_append_rx(). By executing outside of
189 * an ISR, critical 802.11 behaviors are able to take priority over wlan_exp
190 * behaviors.
191 *
192 * @return  None
193 *
194 *****************************************************************************/
195void wlan_exp_transport_poll() {
196    u32 i;
197    u32 num_packets;
198    wlan_exp_eth_rx_queue_buffer_t* wlan_exp_eth_rx_queue_buffer;
199    dl_entry* wlan_exp_eth_rx_queue_entry;
200
201    num_packets = WLAN_MIN(queue_length(_wlan_exp_eth_rx_qid), WLAN_EXP_MAX_RX_PROC_PER_POLL);
202
203    for(i=0; i<num_packets; i++){
204
205        wlan_exp_eth_rx_queue_entry = queue_dequeue(_wlan_exp_eth_rx_qid);
206
207        if(wlan_exp_eth_rx_queue_entry == NULL){
208            // We are done processing the enqueued list of commands
209            return;
210        }
211
212        wlan_exp_eth_rx_queue_buffer = (wlan_exp_eth_rx_queue_buffer_t*)(wlan_exp_eth_rx_queue_entry->data);
213
214        // The only way for this to fail is if there are no available queue entries in the free pool.
215        // We are forced to skip processing this command if this is the case.
216
217        // We will need socket details about this reception in order to form a response. Rather than pass this information
218        //  through a series of context switches as function arguments, we will hold on to it in a global that is only
219        //  non-null for the duration of wlan_exp_transport_receive().
220        gl_tx_to = &(wlan_exp_eth_rx_queue_buffer->rx_from);
221        // Pass packet off to transport command processing
222        wlan_exp_transport_receive(wlan_exp_eth_rx_queue_buffer);
223        gl_tx_to = NULL;
224
225        // Return the received packet to the free pool
226        queue_checkin(wlan_exp_eth_rx_queue_entry);
227    }
228}
229
230/*****************************************************************************/
231/**
232 * @brief Fill IP/UDP headers in response packet
233 *
234 *  This function is the final step before a packet is ready to be sent. It fills
235 *  in the IP and UDP headers of the packet, which include a checksum that depends
236 *  on the total length of the frame.
237 *
238 * @return  WLAN_SUCCESS or WLAN_FAILURE
239 *****************************************************************************/
240int wlan_exp_transport_fill_headers_response(eth_tx_queue_buffer_t* eth_tx_queue_buffer){
241    // This function will fill in the Ethernet, IP, UDP, and transport headers needed
242    //  to send a response packet.
243
244    int length;
245    u32 unicast_port;
246
247    unicast_port = wlan_exp_transport_info.unicast_port;
248
249    if(eth_tx_queue_buffer == NULL) return WLAN_FAILURE;
250
251    // Fill in Ethernet, IP, and UDP headers using socket function
252
253    length = ip_udp_template_init(eth_tx_queue_buffer->seg0, unicast_port, gl_tx_to);
254    if(length == WLAN_FAILURE){
255        return WLAN_FAILURE;
256    }
257
258    // We do not need to update the length metadata in the packet queue buffer. We had already
259    //  set aside the necessary bytes of the headers in wlan_exp_transport_checkout_response()
260
261    return WLAN_SUCCESS;
262}
263
264/*****************************************************************************/
265/**
266 * @brief Handle wlan_exp Tx Queue
267 *
268 *  This function is called in an interrupt context and is responsible for
269 *  dequeuing packets from the wlan_exp Tx queue.
270 *
271 * @return u32 - the remaining length of the wlan_exp Tx queue after transmissions
272 *               are complete
273 *****************************************************************************/
274u32 wlan_exp_handle_tx_queue(){
275    dl_entry* packet_to_process;
276    u32 i;
277    int status;
278
279    for(i = 0; i < WLAN_MIN(queue_length(_wlan_exp_eth_tx_qid), WLAN_MAX_WLAN_EXP_ETH_TX_PROCESS_PER_ISR); i++){
280        packet_to_process = queue_dequeue(_wlan_exp_eth_tx_qid);
281        if(packet_to_process == NULL) return 0; // should not be possible
282
283        // Platform Ethernet Send functions are required to check in
284        //  packet_to_process when they are done with them if they were successful.
285        status = wlan_platform_wlan_exp_eth_send((eth_tx_queue_buffer_t*)(packet_to_process->data));
286
287        if(status != 0){
288            // We were unable to transmit this packet. This is mostly likely due to an ongoing transmission
289            //  causing there to be no free BDs. Re-enqueue this packet back into the head of the _eth_tx_qid
290            //  queue;
291            status = enqueue_head(_wlan_exp_eth_tx_qid, packet_to_process);
292
293            if( status == -1 ){
294                queue_checkin(packet_to_process);
295            }
296        }
297    }
298
299    return queue_length(_wlan_exp_eth_rx_qid);
300}
301
302
303
304
305/*****************************************************************************/
306/**
307 * @brief Process the received UDP packet by the transport
308 *
309 * @param   wlan_exp_eth_rx_queue_buffer* - Received Ethernet frame
310 *
311 * @return  None
312 *
313 *****************************************************************************/
314void wlan_exp_transport_receive(wlan_exp_eth_rx_queue_buffer_t* wlan_exp_eth_rx_queue_buffer){
315
316    int resp_sent;
317    u16 dest_id;
318    u16 src_id;
319    u16 seq_num;
320    u16 flags;
321    u32 node_id;
322    u32 group_id;
323    u16 resp_template_length = 0;
324
325    eth_tx_queue_buffer_t* eth_tx_queue_buffer = NULL;
326    wlan_exp_transport_header* transport_header_rx = NULL;
327    wlan_exp_transport_header* transport_header_tx = NULL;
328    dl_entry* eth_tx_queue_entry;
329
330    resp_sent = NO_RESP_SENT;
331
332    transport_header_rx = (wlan_exp_transport_header*)( wlan_exp_eth_rx_queue_buffer->pkt
333                                                        + sizeof(ethernet_header_t)
334                                                        + sizeof(ipv4_header_t)
335                                                        + sizeof(udp_header_t) );
336
337    // Extract values from the received transport header
338    //
339    dest_id  = Xil_Ntohs(transport_header_rx->dest_id);
340    src_id   = Xil_Ntohs(transport_header_rx->src_id);
341    seq_num  = Xil_Ntohs(transport_header_rx->seq_num);
342    flags    = Xil_Ntohs(transport_header_rx->flags);
343
344    node_id = wlan_exp_node_info.node_id;
345    group_id = wlan_exp_transport_info.group_id;
346
347    // If this message is not for the given node, then ignore it
348    if((dest_id != node_id) && (dest_id != TRANSPORT_BROADCAST_DEST_ID) && ((dest_id & (0xFF00 | group_id)) == 0)) { return; }
349
350    // We can now construct an outgoing response template
351    eth_tx_queue_entry = queue_checkout();
352
353    if(eth_tx_queue_entry == NULL){
354        xil_printf("Unable to checkout free queue entry for wlan_exp Eth response\n");
355        return;
356    }
357
358    eth_tx_queue_buffer = (eth_tx_queue_buffer_t*)eth_tx_queue_entry->data;
359
360    // Update segment 0 length to account for Eth/IP/UDP headers
361    eth_tx_queue_buffer->seg0_len = (sizeof(ethernet_header_t)
362                                     + sizeof(ipv4_header_t)
363                                     + sizeof(udp_header_t));
364    eth_tx_queue_buffer->seg1_len = 0;
365
366    // The response template has already been filled in with an Ethernet, IP, and UDP header.
367    //  we will point to the bytes after these headers to place the transport header.
368    transport_header_tx = (wlan_exp_transport_header*)(eth_tx_queue_buffer->seg0 + eth_tx_queue_buffer->seg0_len);
369
370    eth_tx_queue_buffer->seg0_len += sizeof(wlan_exp_transport_header);
371
372    resp_template_length = eth_tx_queue_buffer->seg0_len;
373
374
375    // Form outgoing Transport header for any outgoing packet in response to this message
376    //   The u16/u32 fields here will be endian swapped in wlan_exp_transport_send
377    //   The length field of the header will be set in wlan_exp_transport_send
378    //
379
380    transport_header_tx->dest_id  = src_id;
381    transport_header_tx->src_id   = node_id;
382    transport_header_tx->seq_num  = seq_num;
383    transport_header_tx->flags    = 0;
384
385    // Call the callback to further process the recv_buffer
386    resp_sent = process_msg_from_host(wlan_exp_eth_rx_queue_buffer, eth_tx_queue_buffer);
387
388    // Based on the status, return a message to the host
389    if(resp_sent == NO_RESP_SENT) {
390        // Check if the host requires a response from the node
391        if (flags & TRANSPORT_HDR_ROBUST_FLAG ) {
392
393            if( (eth_tx_queue_buffer->seg0_len) > resp_template_length ){
394            // Check that the node has something to send to the host
395                if ( (wlan_exp_transport_fill_headers_response(eth_tx_queue_buffer) == 0) ) {
396                    wlan_exp_transport_send(eth_tx_queue_buffer);
397                    return;
398                }
399            }else {
400                wlan_exp_printf(WLAN_EXP_PRINT_WARNING, print_type_transport, "Host requires response but node has nothing to send.\n");
401            }
402        }
403        queue_checkin(eth_tx_queue_entry);
404    }
405
406    return;
407}
408
409
410
411/*****************************************************************************/
412/**
413 * @brief Finish response packet and enqueue for transmission
414 *
415 * @param   eth_tx_queue_buffer_t* eth_tx_queue_buffer - packet queue buffer for outgoing Ethernet frame
416 *
417 * @return  None
418 *
419 *****************************************************************************/
420void wlan_exp_transport_send(eth_tx_queue_buffer_t* eth_tx_queue_buffer) {
421    wlan_exp_transport_prepare_headers(eth_tx_queue_buffer);
422    wlan_exp_append_tx(eth_tx_queue_buffer->pyld_queue_hdr.dle);
423}
424
425/*****************************************************************************/
426/**
427 * @brief Prepare headers in response packet for transmission
428 *
429 * This function will swap endianness of the wlan_exp_transport_header portion
430 * of the provided packet queue buffer, set the IP checksum for the finalized
431 * IP header contents, and enqueue the packet for transmission.
432 *
433 * @param   eth_tx_queue_buffer_t* eth_tx_queue_buffer - packet queue buffer for outgoing Ethernet frame
434 *
435 * @return  None
436 *
437 *****************************************************************************/
438void wlan_exp_transport_prepare_headers(eth_tx_queue_buffer_t* eth_tx_queue_buffer){
439    wlan_exp_transport_header* transport_header_tx;
440
441    transport_header_tx = (wlan_exp_transport_header*)(eth_tx_queue_buffer->seg0
442                                                       + sizeof(ethernet_header_t)
443                                                       + sizeof(ipv4_header_t)
444                                                       + sizeof(udp_header_t));
445
446    transport_header_tx->dest_id = Xil_Htons(transport_header_tx->dest_id);
447    transport_header_tx->src_id  = Xil_Htons(transport_header_tx->src_id);
448
449    // Transport header's length includes all data following the Eth/IP/UDP headers
450    transport_header_tx->length  = Xil_Htons(eth_tx_queue_buffer->seg0_len
451                                             + eth_tx_queue_buffer->seg1_len
452                                             - sizeof(ethernet_header_t)
453                                             - sizeof(ipv4_header_t)
454                                             - sizeof(udp_header_t));
455    transport_header_tx->seq_num = Xil_Htons(transport_header_tx->seq_num);
456    transport_header_tx->flags   = Xil_Htons(transport_header_tx->flags);
457
458    // Set the IP/UDP header lengths and update checksum
459    wlan_exp_ip_udp_set_length(eth_tx_queue_buffer->seg0, eth_tx_queue_buffer->seg0_len + eth_tx_queue_buffer->seg1_len);
460
461}
462
463
464/*****************************************************************************/
465/**
466 * @brief Process Transport Commands
467 *
468 * Process commands from a host meant for the transport group
469 *
470 * @param cmd_hdr - pointer to the command header
471 * @param eth_tx_queue_buffer - pointer to a Ethernet queue buffer that should be
472 *                              filled in with response arguments
473 *
474 * @return  int - NO_RESP_SENT or RESP_SENT
475 *
476 *****************************************************************************/
477int process_transport_cmd(cmd_resp_hdr_t* cmd_hdr, eth_tx_queue_buffer_t* eth_tx_queue_buffer) {
478
479    //
480    // IMPORTANT ENDIAN NOTES:
481    //     - command
482    //         - header - Already endian swapped by the framework (safe to access directly)
483    //         - args   - Must be endian swapped as necessary by code (framework does not know the contents of the command)
484    //     - response
485    //         - header - Will be endian swapped by the framework (safe to write directly)
486    //         - args   - Must be endian swapped as necessary by code (framework does not know the contents of the response)
487    //
488
489    // Standard variables
490    u32 resp_sent = NO_RESP_SENT;
491
492    u32 cmd_id = CMD_TO_CMDID(cmd_hdr->cmd);
493
494    // Segment 0 length includes a fully formed command response header
495    //  because one was created with default values suitable for a responseless
496    //  acknowledgment.
497    cmd_resp_hdr_t* resp_hdr = (cmd_resp_hdr_t*)(eth_tx_queue_buffer->seg0
498                                                 + eth_tx_queue_buffer->seg0_len
499                                                 - sizeof(cmd_resp_hdr_t));
500
501    u32* cmd_args_32 = (u32*)((u8*)cmd_hdr + sizeof(cmd_resp_hdr_t));
502
503    // Process the command
504    switch(cmd_id){
505
506        //---------------------------------------------------------------------
507        case CMDID_TRANSPORT_PING: {
508            //
509            // Nothing actually needs to be done when receiving the ping command. The framework is going
510            // to respond regardless, which is all the host wants.
511            //
512        }
513        break;
514
515        //---------------------------------------------------------------------
516        case CMDID_TRANSPORT_TEST_MTU: {
517            // Host requests a packet with a bogus payload with a specified length
518            //  Python already accounts for the transport and cmd-response headers
519            //  in computing the requested length to achieve the desired over-the-wire length
520
521            u32 req_length = Xil_Ntohl(cmd_args_32[0]);
522
523            // Copy the requested length as the only response argument
524            //  Python can compare this value to the requested length to confirm
525            //  this is a valid response, then examine the actual length of the
526            //  received packet to confirm the effective MTU
527            wlan_exp_add_u32_resp_arg(eth_tx_queue_buffer, resp_hdr, req_length);
528
529            // This command response header is unusual as it includes a single argument
530            //  (the requested response payload length) but a large payload that isn't
531            //  a "response argument". The large payload is bogus, only used to test MTU
532            //  along the node-to-host link. Other command/response code should *not*
533            //  mimic this unusual num_args/length mismatch
534            // The seg1_addr value below can be any DMA-accessible memory area
535            resp_hdr->length  += req_length;
536            eth_tx_queue_buffer->seg1_addr = (u8*)USER_SCRATCH_BASE;
537            eth_tx_queue_buffer->seg1_len = req_length;
538        }
539        break;
540
541        //---------------------------------------------------------------------
542        case CMDID_TRANSPORT_SET_MAX_RESP_WORDS: {
543            u32 max_words = Xil_Ntohl(cmd_args_32[0]);
544
545            // The wlan_exp host sets this node's maximum payload size for response packets
546            // The host determines this maximum based on its own configuration (host NIC MTU),
547            //  the MTU reported by this node during init (node_info.wlan_exp_eth_mtu) and the
548            //  result of the MTU test run during init.
549            // The C code keeps two MTU values at runtime:
550            //  - wlan_exp_node_info.wlan_exp_eth_mtu: the MTU in bytes of the node's Eth interface, set once at boot
551            //      Almost always 1500 (non-jumbo) or 9000 (jumbo)
552            //
553            //  - wlan_exp_transport_info.max_pkt_words: the maximum number of u32 payload words the node may packet
554            //      into a response packet sent to the host. This value describes only the wlan_exp payload, not the
555            //      IP/UDP/wlan_exp headers that precede the payload on the wire
556
557            // This is a blind setter - extra error checking here might be sensible, but this command
558            //  is currently only called after the MTU test, which itself has lots of error checking and printing
559            transport_set_max_resp_pkt_words(max_words);
560        }
561        break;
562
563        //---------------------------------------------------------------------
564        case CMDID_TRANSPORT_NODE_GROUP_ID_ADD: {
565            wlan_exp_transport_info.group_id = (wlan_exp_transport_info.group_id | Xil_Htonl(cmd_args_32[0]));
566        }
567        break;
568
569        //---------------------------------------------------------------------
570        case CMDID_TRANSPORT_NODE_GROUP_ID_CLEAR: {
571            wlan_exp_transport_info.group_id = (wlan_exp_transport_info.group_id & ~Xil_Htonl(cmd_args_32[0]));
572        }
573        break;
574
575        //---------------------------------------------------------------------
576        default: {
577            wlan_exp_printf(WLAN_EXP_PRINT_ERROR, print_type_transport, "Unknown user command ID: %d\n", cmd_id);
578        }
579        break;
580    }
581
582    return resp_sent;
583}
584
585/*****************************************************************************/
586/**
587 * @brief Configure unicast and broadcast sockets
588 *
589 * @param   unicast_port     - Unicast port for the node
590 * @param   broadcast_port   - Broadcast port for the node
591 *
592 * @return  int              - WLAN_SUCCESS or WLAN_FAILURE
593 *
594 *****************************************************************************/
595int transport_config_sockets(u32 unicast_port, u32 broadcast_port) {
596    int status = WLAN_SUCCESS;
597
598    status = _transport_config_socket(&(wlan_exp_transport_info.socket_unicast), unicast_port);
599    if (status == WLAN_FAILURE) { return status; }
600    wlan_exp_transport_info.unicast_port = unicast_port;
601
602    status = _transport_config_socket(&(wlan_exp_transport_info.socket_broadcast), broadcast_port);
603    if (status == WLAN_FAILURE) { return status; }
604    wlan_exp_transport_info.broadcast_port = broadcast_port;
605
606
607    xil_printf("  Listening on UDP ports %d (unicast) and %d (broadcast)\n", unicast_port, broadcast_port);
608
609
610    return status;
611}
612
613
614/*****************************************************************************/
615/**
616 * @brief Set the IP address of the node
617 *
618 * @return  None
619 *
620 *****************************************************************************/
621void transport_set_ip_addr(u8* ip_addr){
622
623    eth_set_ip_addr( ip_addr );
624
625    return;
626}
627
628/*****************************************************************************/
629/**
630 * @brief Get the IP address of the node
631 *
632 * @return  None
633 *
634 *****************************************************************************/
635void transport_get_ip_addr(u8 * ip_addr) {
636
637    eth_get_ip_addr( ip_addr );
638
639    return;
640}
641
642/*****************************************************************************/
643/**
644 * @brief Get the maximum number of u32 words this transport is able to send
645 *        in a single packet
646 *
647 * @return  u32 - number of u32 words
648 *
649 *****************************************************************************/
650u32 wlan_exp_transport_get_max_pkt_words(){
651    return wlan_exp_transport_info.max_pkt_words;
652}
653
654/*****************************************************************************/
655/**
656 * @brief Set the maximum number of u32 words this transport is able to send
657 *        in a single packet
658 *
659 * @param max_words - maximum number of u32 words
660 * @return  None
661 *
662 *****************************************************************************/
663void transport_set_max_resp_pkt_words(u32 max_words) {
664    // Update the maximum size for response packet payloads
665    // Used to reset the maximum on node init and to update
666    //  the maximum after the MTU test
667    wlan_exp_transport_info.max_pkt_words = max_words;
668}
669
670// Local functions
671/*****************************************************************************/
672/**
673 * @brief Update software interrupt signal based on Tx queue occupancy
674 *
675 * @param queue_len - current length of the Tx queue
676 * @return  None
677 *
678 *****************************************************************************/
679void _wlan_exp_tx_queue_occupancy_change(int callback_arg, u32 queue_len){
680    // callback_arg is not used. It was set to 0 when opening the queue
681
682    if(queue_len == 0){
683        wlan_platform_clear_sw_intr(SW_INTR_ID_WLAN_EXP_ETH_TX);
684    } else {
685        wlan_platform_assert_sw_intr(SW_INTR_ID_WLAN_EXP_ETH_TX);
686    }
687}
688
689/*****************************************************************************/
690/**
691 * @brief Create and bind a socket
692 *
693 * @param   socket_index     - Socket index (return value)
694 * @param   udp_port         - UDP port number
695 *
696 * @return  int              - WLAN_SUCCESS or WLAN_FAILURE
697 *
698 *****************************************************************************/
699int _transport_config_socket(int* socket_index, u32 udp_port) {
700
701    int status;
702    int tmp_socket  = *socket_index;
703
704    // Release socket if it is already bound
705    if (tmp_socket != SOCKET_INVALID_SOCKET) {
706        socket_close(tmp_socket);
707    }
708
709    // Create a new socket
710    tmp_socket = socket_alloc(AF_INET, SOCK_DGRAM, 0);
711
712    if (tmp_socket == SOCKET_INVALID_SOCKET) {
713        wlan_exp_printf(WLAN_EXP_PRINT_ERROR, print_type_transport, "Could not create socket\n");
714        *socket_index = SOCKET_INVALID_SOCKET;
715        return WLAN_FAILURE;
716    }
717
718    // Bind the socket
719    status = socket_bind_eth(tmp_socket, udp_port);
720
721    if (status == WLAN_FAILURE) {
722        wlan_exp_printf(WLAN_EXP_PRINT_ERROR, print_type_transport, "Unable to bind socket on port: %d\n", udp_port);
723        socket_close(tmp_socket);
724        *socket_index = SOCKET_INVALID_SOCKET;
725        return WLAN_FAILURE;
726    }
727
728    *socket_index = tmp_socket;
729
730    return WLAN_SUCCESS;
731}
732
733
734#endif
Note: See TracBrowser for help on using the repository browser.