Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * NXP Wireless LAN device driver: station RX data handling
0004  *
0005  * Copyright 2011-2020 NXP
0006  */
0007 
0008 #include <uapi/linux/ipv6.h>
0009 #include <net/ndisc.h>
0010 #include "decl.h"
0011 #include "ioctl.h"
0012 #include "util.h"
0013 #include "fw.h"
0014 #include "main.h"
0015 #include "11n_aggr.h"
0016 #include "11n_rxreorder.h"
0017 
0018 /* This function checks if a frame is IPv4 ARP or IPv6 Neighbour advertisement
0019  * frame. If frame has both source and destination mac address as same, this
0020  * function drops such gratuitous frames.
0021  */
0022 static bool
0023 mwifiex_discard_gratuitous_arp(struct mwifiex_private *priv,
0024                    struct sk_buff *skb)
0025 {
0026     const struct mwifiex_arp_eth_header *arp;
0027     struct ethhdr *eth;
0028     struct ipv6hdr *ipv6;
0029     struct icmp6hdr *icmpv6;
0030 
0031     eth = (struct ethhdr *)skb->data;
0032     switch (ntohs(eth->h_proto)) {
0033     case ETH_P_ARP:
0034         arp = (void *)(skb->data + sizeof(struct ethhdr));
0035         if (arp->hdr.ar_op == htons(ARPOP_REPLY) ||
0036             arp->hdr.ar_op == htons(ARPOP_REQUEST)) {
0037             if (!memcmp(arp->ar_sip, arp->ar_tip, 4))
0038                 return true;
0039         }
0040         break;
0041     case ETH_P_IPV6:
0042         ipv6 = (void *)(skb->data + sizeof(struct ethhdr));
0043         icmpv6 = (void *)(skb->data + sizeof(struct ethhdr) +
0044                   sizeof(struct ipv6hdr));
0045         if (NDISC_NEIGHBOUR_ADVERTISEMENT == icmpv6->icmp6_type) {
0046             if (!memcmp(&ipv6->saddr, &ipv6->daddr,
0047                     sizeof(struct in6_addr)))
0048                 return true;
0049         }
0050         break;
0051     default:
0052         break;
0053     }
0054 
0055     return false;
0056 }
0057 
0058 /*
0059  * This function processes the received packet and forwards it
0060  * to kernel/upper layer.
0061  *
0062  * This function parses through the received packet and determines
0063  * if it is a debug packet or normal packet.
0064  *
0065  * For non-debug packets, the function chops off unnecessary leading
0066  * header bytes, reconstructs the packet as an ethernet frame or
0067  * 802.2/llc/snap frame as required, and sends it to kernel/upper layer.
0068  *
0069  * The completion callback is called after processing in complete.
0070  */
0071 int mwifiex_process_rx_packet(struct mwifiex_private *priv,
0072                   struct sk_buff *skb)
0073 {
0074     int ret;
0075     struct rx_packet_hdr *rx_pkt_hdr;
0076     struct rxpd *local_rx_pd;
0077     int hdr_chop;
0078     struct ethhdr *eth;
0079     u16 rx_pkt_off, rx_pkt_len;
0080     u8 *offset;
0081     u8 adj_rx_rate = 0;
0082 
0083     local_rx_pd = (struct rxpd *) (skb->data);
0084 
0085     rx_pkt_off = le16_to_cpu(local_rx_pd->rx_pkt_offset);
0086     rx_pkt_len = le16_to_cpu(local_rx_pd->rx_pkt_length);
0087     rx_pkt_hdr = (void *)local_rx_pd + rx_pkt_off;
0088 
0089     if ((!memcmp(&rx_pkt_hdr->rfc1042_hdr, bridge_tunnel_header,
0090              sizeof(bridge_tunnel_header))) ||
0091         (!memcmp(&rx_pkt_hdr->rfc1042_hdr, rfc1042_header,
0092              sizeof(rfc1042_header)) &&
0093          ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_AARP &&
0094          ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_IPX)) {
0095         /*
0096          *  Replace the 803 header and rfc1042 header (llc/snap) with an
0097          *    EthernetII header, keep the src/dst and snap_type
0098          *    (ethertype).
0099          *  The firmware only passes up SNAP frames converting
0100          *    all RX Data from 802.11 to 802.2/LLC/SNAP frames.
0101          *  To create the Ethernet II, just move the src, dst address
0102          *    right before the snap_type.
0103          */
0104         eth = (struct ethhdr *)
0105             ((u8 *) &rx_pkt_hdr->eth803_hdr
0106              + sizeof(rx_pkt_hdr->eth803_hdr) +
0107              sizeof(rx_pkt_hdr->rfc1042_hdr)
0108              - sizeof(rx_pkt_hdr->eth803_hdr.h_dest)
0109              - sizeof(rx_pkt_hdr->eth803_hdr.h_source)
0110              - sizeof(rx_pkt_hdr->rfc1042_hdr.snap_type));
0111 
0112         memcpy(eth->h_source, rx_pkt_hdr->eth803_hdr.h_source,
0113                sizeof(eth->h_source));
0114         memcpy(eth->h_dest, rx_pkt_hdr->eth803_hdr.h_dest,
0115                sizeof(eth->h_dest));
0116 
0117         /* Chop off the rxpd + the excess memory from the 802.2/llc/snap
0118            header that was removed. */
0119         hdr_chop = (u8 *) eth - (u8 *) local_rx_pd;
0120     } else {
0121         /* Chop off the rxpd */
0122         hdr_chop = (u8 *) &rx_pkt_hdr->eth803_hdr -
0123             (u8 *) local_rx_pd;
0124     }
0125 
0126     /* Chop off the leading header bytes so the it points to the start of
0127        either the reconstructed EthII frame or the 802.2/llc/snap frame */
0128     skb_pull(skb, hdr_chop);
0129 
0130     if (priv->hs2_enabled &&
0131         mwifiex_discard_gratuitous_arp(priv, skb)) {
0132         mwifiex_dbg(priv->adapter, INFO, "Bypassed Gratuitous ARP\n");
0133         dev_kfree_skb_any(skb);
0134         return 0;
0135     }
0136 
0137     if (ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&
0138         ntohs(rx_pkt_hdr->eth803_hdr.h_proto) == ETH_P_TDLS) {
0139         offset = (u8 *)local_rx_pd + rx_pkt_off;
0140         mwifiex_process_tdls_action_frame(priv, offset, rx_pkt_len);
0141     }
0142 
0143     /* Only stash RX bitrate for unicast packets. */
0144     if (likely(!is_multicast_ether_addr(rx_pkt_hdr->eth803_hdr.h_dest))) {
0145         priv->rxpd_rate = local_rx_pd->rx_rate;
0146         priv->rxpd_htinfo = local_rx_pd->ht_info;
0147     }
0148 
0149     if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA ||
0150         GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) {
0151         adj_rx_rate = mwifiex_adjust_data_rate(priv,
0152                                local_rx_pd->rx_rate,
0153                                local_rx_pd->ht_info);
0154         mwifiex_hist_data_add(priv, adj_rx_rate, local_rx_pd->snr,
0155                       local_rx_pd->nf);
0156     }
0157 
0158     ret = mwifiex_recv_packet(priv, skb);
0159     if (ret == -1)
0160         mwifiex_dbg(priv->adapter, ERROR,
0161                 "recv packet failed\n");
0162 
0163     return ret;
0164 }
0165 
0166 /*
0167  * This function processes the received buffer.
0168  *
0169  * The function looks into the RxPD and performs sanity tests on the
0170  * received buffer to ensure its a valid packet, before processing it
0171  * further. If the packet is determined to be aggregated, it is
0172  * de-aggregated accordingly. Non-unicast packets are sent directly to
0173  * the kernel/upper layers. Unicast packets are handed over to the
0174  * Rx reordering routine if 11n is enabled.
0175  *
0176  * The completion callback is called after processing in complete.
0177  */
0178 int mwifiex_process_sta_rx_packet(struct mwifiex_private *priv,
0179                   struct sk_buff *skb)
0180 {
0181     struct mwifiex_adapter *adapter = priv->adapter;
0182     int ret = 0;
0183     struct rxpd *local_rx_pd;
0184     struct rx_packet_hdr *rx_pkt_hdr;
0185     u8 ta[ETH_ALEN];
0186     u16 rx_pkt_type, rx_pkt_offset, rx_pkt_length, seq_num;
0187     struct mwifiex_sta_node *sta_ptr;
0188 
0189     local_rx_pd = (struct rxpd *) (skb->data);
0190     rx_pkt_type = le16_to_cpu(local_rx_pd->rx_pkt_type);
0191     rx_pkt_offset = le16_to_cpu(local_rx_pd->rx_pkt_offset);
0192     rx_pkt_length = le16_to_cpu(local_rx_pd->rx_pkt_length);
0193     seq_num = le16_to_cpu(local_rx_pd->seq_num);
0194 
0195     rx_pkt_hdr = (void *)local_rx_pd + rx_pkt_offset;
0196 
0197     if ((rx_pkt_offset + rx_pkt_length) > (u16) skb->len) {
0198         mwifiex_dbg(adapter, ERROR,
0199                 "wrong rx packet: len=%d, rx_pkt_offset=%d, rx_pkt_length=%d\n",
0200                 skb->len, rx_pkt_offset, rx_pkt_length);
0201         priv->stats.rx_dropped++;
0202         dev_kfree_skb_any(skb);
0203         return ret;
0204     }
0205 
0206     if (rx_pkt_type == PKT_TYPE_MGMT) {
0207         ret = mwifiex_process_mgmt_packet(priv, skb);
0208         if (ret)
0209             mwifiex_dbg(adapter, DATA, "Rx of mgmt packet failed");
0210         dev_kfree_skb_any(skb);
0211         return ret;
0212     }
0213 
0214     /*
0215      * If the packet is not an unicast packet then send the packet
0216      * directly to os. Don't pass thru rx reordering
0217      */
0218     if ((!IS_11N_ENABLED(priv) &&
0219          !(ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&
0220            !(local_rx_pd->flags & MWIFIEX_RXPD_FLAGS_TDLS_PACKET))) ||
0221         !ether_addr_equal_unaligned(priv->curr_addr, rx_pkt_hdr->eth803_hdr.h_dest)) {
0222         mwifiex_process_rx_packet(priv, skb);
0223         return ret;
0224     }
0225 
0226     if (mwifiex_queuing_ra_based(priv) ||
0227         (ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&
0228          local_rx_pd->flags & MWIFIEX_RXPD_FLAGS_TDLS_PACKET)) {
0229         memcpy(ta, rx_pkt_hdr->eth803_hdr.h_source, ETH_ALEN);
0230         if (local_rx_pd->flags & MWIFIEX_RXPD_FLAGS_TDLS_PACKET &&
0231             local_rx_pd->priority < MAX_NUM_TID) {
0232             sta_ptr = mwifiex_get_sta_entry(priv, ta);
0233             if (sta_ptr)
0234                 sta_ptr->rx_seq[local_rx_pd->priority] =
0235                           le16_to_cpu(local_rx_pd->seq_num);
0236             mwifiex_auto_tdls_update_peer_signal(priv, ta,
0237                                  local_rx_pd->snr,
0238                                  local_rx_pd->nf);
0239         }
0240     } else {
0241         if (rx_pkt_type != PKT_TYPE_BAR &&
0242             local_rx_pd->priority < MAX_NUM_TID)
0243             priv->rx_seq[local_rx_pd->priority] = seq_num;
0244         memcpy(ta, priv->curr_bss_params.bss_descriptor.mac_address,
0245                ETH_ALEN);
0246     }
0247 
0248     /* Reorder and send to OS */
0249     ret = mwifiex_11n_rx_reorder_pkt(priv, seq_num, local_rx_pd->priority,
0250                      ta, (u8) rx_pkt_type, skb);
0251 
0252     if (ret || (rx_pkt_type == PKT_TYPE_BAR))
0253         dev_kfree_skb_any(skb);
0254 
0255     if (ret)
0256         priv->stats.rx_dropped++;
0257 
0258     return ret;
0259 }