258 lines
7.6 KiB
C
258 lines
7.6 KiB
C
/** @file mlan_sta_rx.c
|
|
*
|
|
* @brief This file provides handling of RX in MLA module.
|
|
*
|
|
* Copyright 2008-2022 NXP
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*
|
|
*/
|
|
|
|
/********************************************************
|
|
Change log:
|
|
10/27/2008: initial version
|
|
********************************************************/
|
|
#include <mlan_api.h>
|
|
|
|
/* Additional WMSDK header files */
|
|
#include <wmerrno.h>
|
|
#include <wm_os.h>
|
|
|
|
/* Always keep this include at the end of all include files */
|
|
#include <mlan_remap_mem_operations.h>
|
|
/********************************************************
|
|
Local Variables
|
|
********************************************************/
|
|
|
|
/** Ethernet II header */
|
|
typedef struct
|
|
{
|
|
/** Ethernet II header destination address */
|
|
t_u8 dest_addr[MLAN_MAC_ADDR_LENGTH];
|
|
/** Ethernet II header source address */
|
|
t_u8 src_addr[MLAN_MAC_ADDR_LENGTH];
|
|
/** Ethernet II header length */
|
|
t_u16 ethertype;
|
|
|
|
} EthII_Hdr_t;
|
|
|
|
/** IPv4 ARP request header */
|
|
typedef MLAN_PACK_START struct
|
|
{
|
|
/** Hardware type */
|
|
t_u16 Htype;
|
|
/** Protocol type */
|
|
t_u16 Ptype;
|
|
/** Hardware address length */
|
|
t_u8 addr_len;
|
|
/** Protocol address length */
|
|
t_u8 proto_len;
|
|
/** Operation code */
|
|
t_u16 op_code;
|
|
/** Source mac address */
|
|
t_u8 src_mac[MLAN_MAC_ADDR_LENGTH];
|
|
/** Sender IP address */
|
|
t_u8 src_ip[4];
|
|
/** Destination mac address */
|
|
t_u8 dst_mac[MLAN_MAC_ADDR_LENGTH];
|
|
/** Destination IP address */
|
|
t_u8 dst_ip[4];
|
|
} MLAN_PACK_END IPv4_ARP_t;
|
|
|
|
/** IPv6 Nadv packet header */
|
|
typedef MLAN_PACK_START struct
|
|
{
|
|
/** IP protocol version */
|
|
t_u8 version;
|
|
/** flow label */
|
|
t_u8 flow_lab[3];
|
|
/** Payload length */
|
|
t_u16 payload_len;
|
|
/** Next header type */
|
|
t_u8 next_hdr;
|
|
/** Hot limit */
|
|
t_u8 hop_limit;
|
|
/** Source address */
|
|
t_u8 src_addr[16];
|
|
/** Destination address */
|
|
t_u8 dst_addr[16];
|
|
/** ICMP type */
|
|
t_u8 icmp_type;
|
|
/** IPv6 Code */
|
|
t_u8 ipv6_code;
|
|
/** IPv6 Checksum */
|
|
t_u16 ipv6_checksum;
|
|
/** Flags */
|
|
t_u32 flags;
|
|
/** Target address */
|
|
t_u8 taget_addr[16];
|
|
/** Reserved */
|
|
t_u8 rev[8];
|
|
} MLAN_PACK_END IPv6_Nadv_t;
|
|
|
|
/********************************************************
|
|
Global Variables
|
|
********************************************************/
|
|
|
|
/********************************************************
|
|
Local Functions
|
|
********************************************************/
|
|
|
|
/********************************************************
|
|
Global functions
|
|
********************************************************/
|
|
/**
|
|
* @brief This function processes received packet and forwards it
|
|
* to kernel/upper layer
|
|
*
|
|
* @param pmadapter A pointer to mlan_adapter
|
|
* @param pmbuf A pointer to mlan_buffer which includes the received packet
|
|
*
|
|
* @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
|
|
*/
|
|
mlan_status wlan_process_rx_packet(pmlan_adapter pmadapter, pmlan_buffer pmbuf)
|
|
{
|
|
mlan_status ret = MLAN_STATUS_SUCCESS;
|
|
pmlan_private priv = pmadapter->priv[pmbuf->bss_index];
|
|
/* RxPacketHdr_t *prx_pkt; */
|
|
RxPD *prx_pd;
|
|
ENTER();
|
|
|
|
prx_pd = (RxPD *)(void *)(pmbuf->pbuf + pmbuf->data_offset);
|
|
/* Note: Important. We do not have actual data @ prx_pd->rx_pkt_offset */
|
|
/* prx_pkt = (RxPacketHdr_t *) ((t_u8 *) prx_pd + prx_pd->rx_pkt_offset); */
|
|
/* prx_pkt = (RxPacketHdr_t *)pmbuf->pdesc; */
|
|
|
|
/** Small debug type */
|
|
#define DBG_TYPE_SMALL 2
|
|
/** Size of debugging structure */
|
|
#define SIZE_OF_DBG_STRUCT 4
|
|
/*
|
|
This additional processing does not seem to be required by us for
|
|
the moment. Let skip it for now. They seem to be doing some kind of
|
|
ethernet header processing.
|
|
*/
|
|
|
|
priv->rxpd_rate = prx_pd->rx_rate;
|
|
#ifdef SD8801
|
|
priv->rxpd_htinfo = prx_pd->ht_info;
|
|
#else
|
|
priv->rxpd_rate_info = prx_pd->rate_info;
|
|
#endif
|
|
|
|
ret = pmadapter->callbacks.moal_recv_packet(pmadapter->pmoal_handle, pmbuf);
|
|
if (ret == MLAN_STATUS_FAILURE)
|
|
{
|
|
pmbuf->status_code = (t_u32)MLAN_ERROR_PKT_INVALID;
|
|
PRINTM(MERROR, "STA Rx Error: moal_recv_packet returned error\n");
|
|
}
|
|
/* done: */
|
|
if (ret != MLAN_STATUS_PENDING)
|
|
{
|
|
wlan_free_mlan_buffer(pmadapter, pmbuf);
|
|
}
|
|
LEAVE();
|
|
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief This function processes the received buffer
|
|
*
|
|
* @param adapter A pointer to mlan_adapter
|
|
* @param pmbuf A pointer to the received buffer
|
|
*
|
|
* @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
|
|
*/
|
|
mlan_status wlan_ops_sta_process_rx_packet(IN t_void *adapter, IN pmlan_buffer pmbuf)
|
|
{
|
|
pmlan_adapter pmadapter = (pmlan_adapter)adapter;
|
|
mlan_status ret = MLAN_STATUS_SUCCESS;
|
|
RxPD *prx_pd;
|
|
RxPacketHdr_t *prx_pkt;
|
|
pmlan_private priv = pmadapter->priv[pmbuf->bss_index];
|
|
t_u8 ta[MLAN_MAC_ADDR_LENGTH] = {0};
|
|
t_u16 rx_pkt_type = 0;
|
|
ENTER();
|
|
|
|
prx_pd = (RxPD *)(void *)(pmbuf->pbuf + pmbuf->data_offset);
|
|
/* Endian conversion */
|
|
endian_convert_RxPD(prx_pd);
|
|
rx_pkt_type = prx_pd->rx_pkt_type;
|
|
|
|
/* Note: We do not have data @ some offset of pbuf. pbuf only has RxPD */
|
|
/* prx_pkt = (RxPacketHdr_t *) ((t_u8 *) prx_pd + prx_pd->rx_pkt_offset); */
|
|
prx_pkt = (RxPacketHdr_t *)pmbuf->pdesc;
|
|
|
|
/* PRINTM(MMSG, "%p + %d: O: %d PL: %d DL: %d\n\r", */
|
|
/* pmbuf->pbuf, pmbuf->data_offset, */
|
|
/* prx_pd->rx_pkt_offset, prx_pd->rx_pkt_length, pmbuf->data_len); */
|
|
|
|
if ((prx_pd->rx_pkt_offset + prx_pd->rx_pkt_length) > (t_u16)pmbuf->data_len)
|
|
{
|
|
PRINTM(MERROR,
|
|
"Wrong rx packet: len=%d,rx_pkt_offset=%d,"
|
|
" rx_pkt_length=%d\n",
|
|
pmbuf->data_len, prx_pd->rx_pkt_offset, prx_pd->rx_pkt_length);
|
|
pmbuf->status_code = (t_u32)MLAN_ERROR_PKT_SIZE_INVALID;
|
|
ret = MLAN_STATUS_FAILURE;
|
|
wlan_free_mlan_buffer(pmadapter, pmbuf);
|
|
goto done;
|
|
}
|
|
pmbuf->data_len = prx_pd->rx_pkt_offset + prx_pd->rx_pkt_length;
|
|
|
|
if (pmadapter->priv[pmbuf->bss_index]->mgmt_frame_passthru_mask && prx_pd->rx_pkt_type == PKT_TYPE_MGMT_FRAME)
|
|
{
|
|
/* Check if this is mgmt packet and needs to forwarded to app as an
|
|
event */
|
|
/* fixme */
|
|
PRINTM(MMSG, "Is a management packet expected here?\n\r");
|
|
(void)os_enter_critical_section();
|
|
while (true)
|
|
{
|
|
}
|
|
}
|
|
|
|
#ifdef DUMP_PACKET_MAC
|
|
dump_mac_addr("Own: ", priv->curr_addr);
|
|
dump_mac_addr("Dest: ", prx_pkt->eth803_hdr.dest_addr);
|
|
#endif /* DUMP_PACKET_MAC */
|
|
|
|
/*
|
|
* If the packet is not an unicast packet then send the packet
|
|
* directly to os. Don't pass thru rx reordering
|
|
*/
|
|
if (!IS_11N_ENABLED(priv) ||
|
|
__memcmp(priv->adapter, priv->curr_addr, prx_pkt->eth803_hdr.dest_addr, MLAN_MAC_ADDR_LENGTH))
|
|
{
|
|
(void)wlan_process_rx_packet(pmadapter, pmbuf);
|
|
goto done;
|
|
}
|
|
|
|
if (queuing_ra_based(priv) == MTRUE)
|
|
{
|
|
(void)__memcpy(pmadapter, ta, prx_pkt->eth803_hdr.src_addr, MLAN_MAC_ADDR_LENGTH);
|
|
}
|
|
else
|
|
{
|
|
if ((rx_pkt_type != PKT_TYPE_BAR) && (prx_pd->priority < MAX_NUM_TID))
|
|
{
|
|
priv->rx_seq[prx_pd->priority] = prx_pd->seq_num;
|
|
}
|
|
(void)__memcpy(pmadapter, ta, priv->curr_bss_params.bss_descriptor.mac_address, MLAN_MAC_ADDR_LENGTH);
|
|
}
|
|
|
|
/* Reorder and send to OS */
|
|
if ((ret = mlan_11n_rxreorder_pkt(priv, prx_pd->seq_num, prx_pd->priority, ta, (t_u8)prx_pd->rx_pkt_type,
|
|
(void *)pmbuf)) ||
|
|
(rx_pkt_type == PKT_TYPE_BAR))
|
|
{
|
|
wlan_free_mlan_buffer(pmadapter, pmbuf);
|
|
}
|
|
|
|
done:
|
|
|
|
LEAVE();
|
|
return (ret);
|
|
}
|