Application / Framework Callbacks

The High MAC Framework interfaces to the MAC application in CPU High via callback functions. The high MAC application must implement functions with specific prototypes and register these as callbacks with the High MAC Framework. The framework then calls these application-supplied functions for specific MAC events at runtime.

The High MAC Framework sets all callbacks to a null function by default. The high MAC application must register each callback it implements with the framework. Not all MAC applications will implement all callbacks.

The reference AP, STA, and IBSS applications provide reference implementations of these callback functions.

This table summarizes the callback functions supported by the High MAC Framework. The purpose and prototype of each function is detailed in the sections below.

Callback Setter
Tx Poll Queues Callback wlan_mac_high_set_poll_tx_queues_callback()
Low Tx Report Callback wlan_mac_high_set_mpdu_tx_low_done_callback()
Wireless MPDU Tx Done Callback wlan_mac_high_set_mpdu_tx_high_done_callback()
Beacon Tx Done Callback wlan_mac_high_set_beacon_tx_done_callback()
Wireless MPDU Rx Callback wlan_mac_high_set_mpdu_rx_callback()
CPU Low Reboot Callback wlan_mac_high_set_cpu_low_reboot_callback()
Switches & Buttons Callbacks wlan_mac_high_set_buttons_callback() wlan_mac_high_set_switches_callback()
UART Rx Callback wlan_mac_high_set_uart_rx_callback()
Ethernet Rx Callback wlan_mac_util_set_eth_rx_callback()
LTG Event Callback wlan_mac_ltg_sched_set_callback()
Tx Queue State Change Callback queue_set_state_change_callback()
Network Scan State Change Callback wlan_mac_scan_set_state_change_callback()
Network Scan Probe Request Tx Callback wlan_mac_scan_set_tx_probe_request_callback()

Tx Queue Poll Callback

The High MAC Framework implements a flexible queuing system. The high MAC applications use this queuing system to manage their Tx queues. The AP, for example, maintains a Tx queue for each associated station plus one each for multicast and management traffic.

At various points in the High MAC Framework’s handling of Tx events the framework informs the application that the application should attempt to dequeue its next Tx packet into a Tx packet buffer. The MAC application must implement this behavior as a callback function which dequeues packets into available Tx packet buffers.

The application’s Tx queue polling callback function can implement arbitrary queue priorities. The reference AP/STA/IBSS applications use a round-robin scheme.

The High MAC Framework calls the application’s Tx Queue Poll Callback in two places:

  1. When starting processing of a TX_MPDU_DONE message from CPU Low
  2. After enqueueing a packet in any Tx queue

Together these calls are sufficient for an application to implement an efficient ping/pong scheme in the Tx packet buffers.

The Tx Queue Poll Callback has a simple prototype:

// Tx Queue Poll Callback prototype
void poll_tx_queues();

The callback implementation should use the following framework functions:

  • wlan_mac_num_tx_pkt_buf_available() - determine number of available Tx packet buffers
  • dequeue_from_head() - dequeue a packet from a Tx queue
  • transmit_checkin() - submit a packet for transmission and recycle the queue entry

Low Tx Report Callback

CPU High submits Tx packets to CPU Low for processing by the low MAC and transmission by the Tx PHY. CPU High sends a TX_PKT_BUF_READY IPC message once per Tx packet; CPU sends a single TX_PKT_BUF_DONE message when the low MAC is finished transmitting the packet.

In between these IPC messages the low MAC might transmit the packet multiple times, such as retransmissions by the DCF. In order to communicate actual Tx events to CPU High, the low MAC sends a PHY_TX_REPORT IPC message immediately after each PHY transmission of a given packet. The High MAC Framework passes these messages to the high application via the Low Tx Report Callback.

A Low Tx Report Callback is not required for most MAC applications. The High MAC Framework handles the logging of every Tx event and creates the TX_LOW log entry for each PHY_TX_REPORT IPC message. The MAC application only needs a Low Tx Report Callback if it needs to modify the default log entry, or update some MAC state on per-transmission timescales.

The Low Tx Report Callback must have the following prototype:

/* Low Tx Report Callback
 *
 * Arguments
 *  tx_frame_info  - The tx_frame_info for the just-transmitted packet
 *  station_info - The station_info for the intended receiver of the just-transmitted packet
 *  tx_low_details - Details from the low MAC and Tx PHY about the actual PHY transmission
 *  tx_low_event_log_entry - The TX_LOW log entry created by the High MAC Framework
 *
*/
void mpdu_tx_low_done_callback(tx_frame_info_t* tx_frame_info,
                               station_info_t* station_info,
                               tx_low_details_t* tx_low_details,
                               tx_low_event_log_entry_t* tx_low_event_log_entry);

Wireless MPDU Tx Done Callback

CPU High submits Tx packets to CPU Low for processing by the low MAC and transmission by the Tx PHY. CPU High sends a TX_PKT_BUF_READY IPC message once per Tx packet; CPU sends a single TX_PKT_BUF_DONE message when the low MAC is finished transmitting the packet. The High MAC Framework notifies the high MAC application of the completed transmission via the Wireless MPDU Tx Done Callback.

A Wireless MPDU Tx Done Callback is not required for most MAC applications. The High MAC Framework handles the logging of every TX_PKT_BUF_DONE event by creating the TX_HIGH entry. The MAC application only needs a MPDU Tx Done Callback if it needs to modify the default log entry or update some MAC state based on the Tx result.

The Wireless MPDU Tx Done Callback must have the following prototype:

/* High Tx Done Callback
 *
 * Arguments
 *  tx_frame_info  - The tx_frame_info for the just-transmitted packet
 *  station_info - The station_info for the intended receiver of the just-transmitted packet
 *  tx_low_details - Details from the low MAC and Tx PHY about the actual PHY transmission
 *  tx_low_event_log_entry - The TX_LOW log entry created by the High MAC Framework
 *
*/
void mpdu_tx_high_done_callback(tx_frame_info_t* tx_frame_info,
                                station_info_t* station_info,
                                tx_high_event_log_entry_t* tx_high_event_log_entry);

Beacon Tx Done Callback

AP and IBSS nodes periodically transmit beacons to advertise network parameters, MAC/PHY capabilities, and to synchronize members of the wireless network. Both CPUs are involved in beacon transmissions:

  • CPU High: the High MAC application (i.e. AP, IBSS) dedicates a Tx packet buffer to a Beacon Template. This template is a complete 802.11 Beacon packet except for the TIMESTAMP field. CPU High informs CPU Low that the Beacon Template is ready with the IPC_MBOX_TXRX_BEACON_CONFIG message via the IPC mailbox.
  • CPU Low: once notified by CPU High that the Beacon Template is ready, the Low MAC application (i.e. DCF) transmits the beacon packet whenever required by the MAC protocol. For the default 802.11 DCF the lower MAC transmits beacons every 102.4 usec starting at MAC Time zero. CPU Low transmits the Beacon Template as-is, only modifying the TIMESTAMP field to reflect the MAC Time of the actual beacon waveform transmission. After each beacon transmission CPU Low sends CPU High a TX_BEACON_DONE IPC message.

The High MAC Framework informs the high MAC application that a beacon transmission has occurred via the Beacon Tx Done Callback.

A Beacon Tx Done Callback is not required for most MAC applications. The High MAC Framework handles the logging of every TX_BEACON_DONE event by creating the appropriate TX_LOW entry. The MAC application only needs a Beacon Tx Done Callback if it needs to modify the default log entry or update some MAC state based on the beacon transmission.

The Beacon Tx Done Callback must have the following prototype:

/* Beacon Tx Done Callback
 *
 * Arguments
 *  tx_frame_info  - The tx_frame_info for the just-transmitted packet
 *  tx_low_details - Details from the low MAC and Tx PHY about the actual PHY transmission
 *  tx_low_event_log_entry - The TX_LOW log entry created by the High MAC Framework
 *
*/
void beacon_tx_done_callback(tx_frame_info_t* tx_frame_info,
                             tx_low_details_t* tx_low_details,
                             tx_low_event_log_entry_t* tx_low_event_log_entry);

Wireless MPDU Rx Callback

The Low MAC Framework notifies the High MAC Framework of a new wireless reception with an RX_PKT_BUF_READY IPC message. The High MAC Framework processes every reception, then calls the high MAC application’s MPDU Rx Callback to apply any application-specific processing.

The High MAC Framework creates an RX_OFDM or RX_DSSS log entry for each wireless reception. The framework supplies a pointer to this log entry to the MAC application in case the application needs to add or modify any logged data.

The Wireless MPDU Rx Callback must have the following prototype:

/* Beacon Tx Done Callback
 *
 * Arguments
 *  pkt_buf_addr  - Memory address of the Rx packet buffer containing the received packet
 *  station_info - Pointer to the station_info for the node which transmitted the packet
 *  rx_event_log_entry - Pointer to the RX_OFDM/RX_DSSS log entry for the new reception
 * Return
 *  u32 flags - Bitwise OR of ``MAC_RX_CALLBACK_RETURN_FLAG_`` values (see wlan_mac_high.h)
*/
u32 mpdu_rx_process(void* pkt_buf_addr,
                    station_info_t* station_info,
                    rx_common_entry* rx_event_log_entry);

The callback returns a u32 flags value which controls how the framework handles the reception. The callback should return a bitwise OR’d combination of zero or more of these flags:

  • MAC_RX_CALLBACK_RETURN_FLAG_DUP: indicates current reception is a duplicate of a previous reception; this affects how the Tx/Rx counts are updated based on this reception
  • MAC_RX_CALLBACK_RETURN_FLAG_NO_COUNTS: tells framework to not update Rx counts for transmitting node
  • MAC_RX_CALLBACK_RETURN_FLAG_NO_LOG_ENTRY: tells framework to not create Rx log entry for this packet

CPU Low Reboot Callback

The High MAC Framework is robust to CPU Low rebooting at runtime. This occurs, for example, when the SDK debugger is used to re-download the binary to CPU Low while CPU High continues running.

The High MAC Framework automatically updates settings CPU Low loses on reboot, such as the current radio channel and Tx power. The framework also informs the high MAC application in case the application needs to apply further configuration updates.

/* CPU Low Reboot Callback
 *
 * Arguments
 *  type  - ID of low MAC application
 *          (one of the WLAN_EXP_TYPE_DESIGN_80211_CPU_LOW_ constants defined in wlan_exp.h)
*/
void handle_cpu_low_reboot(u32 type);

Switches & Buttons Callbacks

Most FPGA development boards include buttons and switches connected to FPGA inputs. The 802.11 FPGA design includes logic to monitor these user inputs and raise an interrupt with an input changes. The High MAC Framework wraps the platform-specific user input configuration and provides two callback hooks for high MAC applications.

/* User inputs callbacks
 *
 * Arguments
 *  mask  - One-hot mask of which buttons/switches changed state
 *  state - One-hot mask indicating button/switch states
*/
void buttons_callback(u32 mask, u32 state);
void switches_callback(u32 mask, u32 state);

UART Rx Callback

Most FPGA development boards include a USB-UART transceiver. The UART interface is typically used as the stdin/stdout interface for the MicroBlaze CPUs in the FPGA design.

The UART peripheral in the FPGA design asserts an interrupt when a character is received from the connected serial terminal. The High MAC Framework handles this interrupt, then calls the high MAC application’s UART Rx callback. The framework calls the application’s UART Rx callback once per received character, including any newline characters sent by the connected terminal.

/* UART Rx callback
 *
 * Arguments
 *  rxByte - Byte received via UART interface
*/
void uart_rx(u8 rxByte);

Ethernet Rx Callback

The High MAC Framework services interrupts generated when packets are received by the Ethernet MAC core. The framework applies a standard wired-to-wireless transformation to each received packet (called Ethernet encapsulation). The encapsulation process preserves the Ethernet packet’s payload, prepends an encapsulation header, and leaves room for a standard 802.11 MAC header at the start of the new packet.

After the framework encapsulates an Ethernet packet it calls the high MAC application’s Ethernet Rx callback. The callback arguments include a pointer to the encapsulated Ethernet packet and the header fields (source address, destination address, and length) from the original Ethernet packet.

The MAC application’s Ethernet Rx callback must analyze the Ethernet packet header fields to determine whether the packet should be:

  • Enqueued: the callback adds the packet to one of its Tx queues
  • Discarded: the callback does not enqueued the packet

If the application will enqueue the packet, this callback must prepare the 802.11 MAC header at the start of the packet. The Ethernet encapsulation process does not create the 802.11 MAC header.

The callback function must inform the framework whether the packet was enqueued with the function return value.

/* Ethernet Rx callback
 *
 * Arguments
 *  dl_entry* curr_tx_queue_element - Queue entry pointing to received/encapsulated packet
 *  u8* eth_dest - Destination MAC address from received Ethernet header
 *  u8* eth_src - Source MAC address from received Ethernet header
 *  u16 tx_length - Length in bytes of the encapsulated Ethernet packet;
 *                   includes length of 802.11 MAC header
 *
 * Returns
 *  int status - 1 if application enqueued packet, 0 if application discarded packet
*/
int ethernet_receive(dl_entry* curr_tx_queue_element, u8* eth_dest, u8* eth_src, u16 tx_length);

LTG Event Callback

The High MAC Framework’s Local Traffic Generator (LTG) subsystem simplifies the process of creating traffic flows for running experiments with 802.11 nodes.

An LTG flow is created either in application C code or via the wlan_exp Python framework. An LTG flow is configured with schedule and payload parameters. The High MAC Framework’s LTG code is responsible for maintaining the schedule for a given LTG flow. When the framework’s LTG code determines it is time for a new LTG packet to be created, it calls the application’s LTG Event Callback.

The framework calls the application’s LTG Evevent Callback for all active LTG flows. The callback is given the LTG flow’s ID and a copy of the LTG flow’s schedule and payload configuration. The application callback uses these arguments to construct new packets for transmission.

The callback can implement whatever packet creation behavior the application requires. A typical implementation creates and enqueues a single packet per execution of the callback.

/* LTG Event callback
 *
 * Arguments
 *  u32 id - ID for triggering LTG flow
 *  void* callback_arg - Callback argument provided at LTG creation time; interpretation depends on LTG type
*/
void ltg_event(u32 id, void* callback_arg);

Tx Queue State Change Callback

The High MAC Framework’s queueing subsystem calls an application callback any time a queue transitions between empty and non-empty. This hook simplifies the MAC’s implementation of the 802.11 TIM (Traffic Indication Map).

/* Queue State Change Callback
 *
 * Arguments
 *  u32 QID - Queue ID
 *  u8 queue_len - 0 if queue transitioned to empty, 1 if queue transitioned to non-empty
*/
void queue_state_change(u32 QID, u8 queue_len);

Network Scan State Change Callback

The High MAC Framework implements a network scanning state machine. This subsystem supports active and passive scanning for nearby wireless networks. The scan state machine can be started/paused/stopped any time. The MAC application is notified when the scan state machine changes states so the application can pause/resume its own activity during the scan.

/* Network Scan State Change Callback
 *
 * Arguments
 *  scan_state_t scan_state - The new scan state machine state
*/
void process_scan_state_change(scan_state_t scan_state);

Network Scan Probe Request Tx Callback

The High MAC Framework network scanning code supports active scanning. With active scanning the node jumps to a new channel and immediately transmits a series of Probe Request packets, hoping to receive Probe Responses from targeted networks. To support active scanning the MAC application must construct and enqueue a Probe Request packet whenever the High MAC Framework requests one. The scan state machine will request Probe Request packets at a fixed rate (set via the probe_tx_interval_usec scan config paramter).

The application callback has no arguments or return values. A typical implementation should construct a new Probe Request packet and enqueue the packet in the Management Queue for high-priority transmission. Any received Probe Response will be handled by the normal packet Rx flow.

/* Network Scan Probe Request Tx Callback
 *
*/
void process_scan_state_change();