Skip to content

Commit bf00dc2

Browse files
Xinming HuKalle Valo
authored andcommitted
mwifiex: AMSDU Rx frame handling in AP mode
This patch processes sub AMSDU frame received in AP mode. If a packet is multicast/broadcast, it is sent to kernel/upper layer as well as queued back to AP TX queue so that it can be sent to other associated stations. If a packet is unicast and RA is present in associated station list, it is again requeued into AP TX queue. If a packet is unicast and RA is not in associated station list, packet is forwarded to kernel to handle routing logic. Signed-off-by: Xinming Hu <[email protected]> Signed-off-by: Cathy Luo <[email protected]> Signed-off-by: Amitkumar Karwar <[email protected]> Signed-off-by: Kalle Valo <[email protected]>
1 parent ad5ca84 commit bf00dc2

File tree

3 files changed

+96
-1
lines changed

3 files changed

+96
-1
lines changed

drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,10 @@ static int mwifiex_11n_dispatch_amsdu_pkt(struct mwifiex_private *priv,
5959
skb->len);
6060
}
6161

62-
ret = mwifiex_recv_packet(priv, rx_skb);
62+
if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
63+
ret = mwifiex_uap_recv_packet(priv, rx_skb);
64+
else
65+
ret = mwifiex_recv_packet(priv, rx_skb);
6366
if (ret == -1)
6467
mwifiex_dbg(priv->adapter, ERROR,
6568
"Rx of A-MSDU failed");

drivers/net/wireless/marvell/mwifiex/main.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1019,6 +1019,8 @@ int mwifiex_shutdown_fw_complete(struct mwifiex_adapter *adapter);
10191019
int mwifiex_dnld_fw(struct mwifiex_adapter *, struct mwifiex_fw_image *);
10201020

10211021
int mwifiex_recv_packet(struct mwifiex_private *priv, struct sk_buff *skb);
1022+
int mwifiex_uap_recv_packet(struct mwifiex_private *priv,
1023+
struct sk_buff *skb);
10221024

10231025
int mwifiex_process_mgmt_packet(struct mwifiex_private *priv,
10241026
struct sk_buff *skb);

drivers/net/wireless/marvell/mwifiex/uap_txrx.c

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,96 @@ int mwifiex_handle_uap_rx_forward(struct mwifiex_private *priv,
265265
return mwifiex_process_rx_packet(priv, skb);
266266
}
267267

268+
int mwifiex_uap_recv_packet(struct mwifiex_private *priv,
269+
struct sk_buff *skb)
270+
{
271+
struct mwifiex_adapter *adapter = adapter;
272+
struct mwifiex_sta_node *src_node;
273+
struct ethhdr *p_ethhdr;
274+
struct sk_buff *skb_uap;
275+
struct mwifiex_txinfo *tx_info;
276+
277+
if (!skb)
278+
return -1;
279+
280+
p_ethhdr = (void *)skb->data;
281+
src_node = mwifiex_get_sta_entry(priv, p_ethhdr->h_source);
282+
if (src_node) {
283+
src_node->stats.last_rx = jiffies;
284+
src_node->stats.rx_bytes += skb->len;
285+
src_node->stats.rx_packets++;
286+
}
287+
288+
skb->dev = priv->netdev;
289+
skb->protocol = eth_type_trans(skb, priv->netdev);
290+
skb->ip_summed = CHECKSUM_NONE;
291+
292+
/* This is required only in case of 11n and USB/PCIE as we alloc
293+
* a buffer of 4K only if its 11N (to be able to receive 4K
294+
* AMSDU packets). In case of SD we allocate buffers based
295+
* on the size of packet and hence this is not needed.
296+
*
297+
* Modifying the truesize here as our allocation for each
298+
* skb is 4K but we only receive 2K packets and this cause
299+
* the kernel to start dropping packets in case where
300+
* application has allocated buffer based on 2K size i.e.
301+
* if there a 64K packet received (in IP fragments and
302+
* application allocates 64K to receive this packet but
303+
* this packet would almost double up because we allocate
304+
* each 1.5K fragment in 4K and pass it up. As soon as the
305+
* 64K limit hits kernel will start to drop rest of the
306+
* fragments. Currently we fail the Filesndl-ht.scr script
307+
* for UDP, hence this fix
308+
*/
309+
if ((adapter->iface_type == MWIFIEX_USB ||
310+
adapter->iface_type == MWIFIEX_PCIE) &&
311+
(skb->truesize > MWIFIEX_RX_DATA_BUF_SIZE))
312+
skb->truesize += (skb->len - MWIFIEX_RX_DATA_BUF_SIZE);
313+
314+
if (is_multicast_ether_addr(p_ethhdr->h_dest) ||
315+
mwifiex_get_sta_entry(priv, p_ethhdr->h_dest)) {
316+
if (skb_headroom(skb) < MWIFIEX_MIN_DATA_HEADER_LEN)
317+
skb_uap =
318+
skb_realloc_headroom(skb, MWIFIEX_MIN_DATA_HEADER_LEN);
319+
else
320+
skb_uap = skb_copy(skb, GFP_ATOMIC);
321+
322+
if (likely(skb_uap)) {
323+
tx_info = MWIFIEX_SKB_TXCB(skb_uap);
324+
memset(tx_info, 0, sizeof(*tx_info));
325+
tx_info->bss_num = priv->bss_num;
326+
tx_info->bss_type = priv->bss_type;
327+
tx_info->flags |= MWIFIEX_BUF_FLAG_BRIDGED_PKT;
328+
__net_timestamp(skb_uap);
329+
mwifiex_wmm_add_buf_txqueue(priv, skb_uap);
330+
atomic_inc(&adapter->tx_pending);
331+
atomic_inc(&adapter->pending_bridged_pkts);
332+
if ((atomic_read(&adapter->pending_bridged_pkts) >=
333+
MWIFIEX_BRIDGED_PKTS_THR_HIGH)) {
334+
mwifiex_dbg(adapter, ERROR,
335+
"Tx: Bridge packet limit reached. Drop packet!\n");
336+
mwifiex_uap_cleanup_tx_queues(priv);
337+
}
338+
339+
} else {
340+
mwifiex_dbg(adapter, ERROR, "failed to allocate skb_uap");
341+
}
342+
343+
mwifiex_queue_main_work(adapter);
344+
/* Don't forward Intra-BSS unicast packet to upper layer*/
345+
if (mwifiex_get_sta_entry(priv, p_ethhdr->h_dest))
346+
return 0;
347+
}
348+
349+
/* Forward multicast/broadcast packet to upper layer*/
350+
if (in_interrupt())
351+
netif_rx(skb);
352+
else
353+
netif_rx_ni(skb);
354+
355+
return 0;
356+
}
357+
268358
/*
269359
* This function processes the packet received on AP interface.
270360
*

0 commit comments

Comments
 (0)