1*73b01e57SJeff Chen // SPDX-License-Identifier: GPL-2.0-only
2*73b01e57SJeff Chen /*
3*73b01e57SJeff Chen * NXP Wireless LAN device driver: station RX data handling
4*73b01e57SJeff Chen *
5*73b01e57SJeff Chen * Copyright 2011-2024 NXP
6*73b01e57SJeff Chen */
7*73b01e57SJeff Chen
8*73b01e57SJeff Chen #include <uapi/linux/ipv6.h>
9*73b01e57SJeff Chen #include <net/ndisc.h>
10*73b01e57SJeff Chen #include "cfg.h"
11*73b01e57SJeff Chen #include "util.h"
12*73b01e57SJeff Chen #include "fw.h"
13*73b01e57SJeff Chen #include "main.h"
14*73b01e57SJeff Chen #include "11n_aggr.h"
15*73b01e57SJeff Chen #include "11n_rxreorder.h"
16*73b01e57SJeff Chen
17*73b01e57SJeff Chen /*
18*73b01e57SJeff Chen * Drop gratuitous IPv4 ARP and IPv6 neighbour advertisements when
19*73b01e57SJeff Chen * source and destination addresses are identical.
20*73b01e57SJeff Chen */
21*73b01e57SJeff Chen static bool
nxpwifi_discard_gratuitous_arp(struct nxpwifi_private * priv,struct sk_buff * skb)22*73b01e57SJeff Chen nxpwifi_discard_gratuitous_arp(struct nxpwifi_private *priv,
23*73b01e57SJeff Chen struct sk_buff *skb)
24*73b01e57SJeff Chen {
25*73b01e57SJeff Chen const struct nxpwifi_arp_eth_header *arp;
26*73b01e57SJeff Chen struct ethhdr *eth;
27*73b01e57SJeff Chen struct ipv6hdr *ipv6;
28*73b01e57SJeff Chen struct icmp6hdr *icmpv6;
29*73b01e57SJeff Chen
30*73b01e57SJeff Chen eth = (struct ethhdr *)skb->data;
31*73b01e57SJeff Chen switch (ntohs(eth->h_proto)) {
32*73b01e57SJeff Chen case ETH_P_ARP:
33*73b01e57SJeff Chen arp = (void *)(skb->data + sizeof(struct ethhdr));
34*73b01e57SJeff Chen if (arp->hdr.ar_op == htons(ARPOP_REPLY) ||
35*73b01e57SJeff Chen arp->hdr.ar_op == htons(ARPOP_REQUEST)) {
36*73b01e57SJeff Chen if (!memcmp(arp->ar_sip, arp->ar_tip, 4))
37*73b01e57SJeff Chen return true;
38*73b01e57SJeff Chen }
39*73b01e57SJeff Chen break;
40*73b01e57SJeff Chen case ETH_P_IPV6:
41*73b01e57SJeff Chen ipv6 = (void *)(skb->data + sizeof(struct ethhdr));
42*73b01e57SJeff Chen icmpv6 = (void *)(skb->data + sizeof(struct ethhdr) +
43*73b01e57SJeff Chen sizeof(struct ipv6hdr));
44*73b01e57SJeff Chen if (icmpv6->icmp6_type == NDISC_NEIGHBOUR_ADVERTISEMENT) {
45*73b01e57SJeff Chen if (!memcmp(&ipv6->saddr, &ipv6->daddr,
46*73b01e57SJeff Chen sizeof(struct in6_addr)))
47*73b01e57SJeff Chen return true;
48*73b01e57SJeff Chen }
49*73b01e57SJeff Chen break;
50*73b01e57SJeff Chen default:
51*73b01e57SJeff Chen break;
52*73b01e57SJeff Chen }
53*73b01e57SJeff Chen
54*73b01e57SJeff Chen return false;
55*73b01e57SJeff Chen }
56*73b01e57SJeff Chen
57*73b01e57SJeff Chen /*
58*73b01e57SJeff Chen * Process a received data packet.
59*73b01e57SJeff Chen * Convert 802.2/LLC/SNAP to Ethernet II when appropriate, trim the
60*73b01e57SJeff Chen * rxpd and extra headers, optionally drop gratuitous ARP/NA, cache
61*73b01e57SJeff Chen * RX rate for unicast, then deliver to the stack.
62*73b01e57SJeff Chen */
nxpwifi_process_rx_packet(struct nxpwifi_private * priv,struct sk_buff * skb)63*73b01e57SJeff Chen int nxpwifi_process_rx_packet(struct nxpwifi_private *priv,
64*73b01e57SJeff Chen struct sk_buff *skb)
65*73b01e57SJeff Chen {
66*73b01e57SJeff Chen int ret;
67*73b01e57SJeff Chen struct rx_packet_hdr *rx_pkt_hdr;
68*73b01e57SJeff Chen struct rxpd *local_rx_pd;
69*73b01e57SJeff Chen int hdr_chop;
70*73b01e57SJeff Chen struct ethhdr *eth;
71*73b01e57SJeff Chen u16 rx_pkt_off;
72*73b01e57SJeff Chen u8 adj_rx_rate = 0;
73*73b01e57SJeff Chen
74*73b01e57SJeff Chen local_rx_pd = (struct rxpd *)(skb->data);
75*73b01e57SJeff Chen
76*73b01e57SJeff Chen rx_pkt_off = le16_to_cpu(local_rx_pd->rx_pkt_offset);
77*73b01e57SJeff Chen rx_pkt_hdr = (void *)local_rx_pd + rx_pkt_off;
78*73b01e57SJeff Chen
79*73b01e57SJeff Chen if (sizeof(rx_pkt_hdr->eth803_hdr) + sizeof(rfc1042_header) +
80*73b01e57SJeff Chen rx_pkt_off > skb->len) {
81*73b01e57SJeff Chen priv->stats.rx_dropped++;
82*73b01e57SJeff Chen dev_kfree_skb_any(skb);
83*73b01e57SJeff Chen return -EINVAL;
84*73b01e57SJeff Chen }
85*73b01e57SJeff Chen
86*73b01e57SJeff Chen if (sizeof(*rx_pkt_hdr) + rx_pkt_off <= skb->len &&
87*73b01e57SJeff Chen ((!memcmp(&rx_pkt_hdr->rfc1042_hdr, bridge_tunnel_header,
88*73b01e57SJeff Chen sizeof(bridge_tunnel_header))) ||
89*73b01e57SJeff Chen (!memcmp(&rx_pkt_hdr->rfc1042_hdr, rfc1042_header,
90*73b01e57SJeff Chen sizeof(rfc1042_header)) &&
91*73b01e57SJeff Chen rx_pkt_hdr->rfc1042_hdr.snap_type != htons(ETH_P_AARP) &&
92*73b01e57SJeff Chen rx_pkt_hdr->rfc1042_hdr.snap_type != htons(ETH_P_IPX)))) {
93*73b01e57SJeff Chen /*
94*73b01e57SJeff Chen * Replace the 803 header and rfc1042 header (llc/snap) with an
95*73b01e57SJeff Chen * EthernetII header, keep the src/dst and snap_type
96*73b01e57SJeff Chen * (ethertype).
97*73b01e57SJeff Chen * The firmware only passes up SNAP frames converting
98*73b01e57SJeff Chen * all RX Data from 802.11 to 802.2/LLC/SNAP frames.
99*73b01e57SJeff Chen * To create the Ethernet II, just move the src, dst address
100*73b01e57SJeff Chen * right before the snap_type.
101*73b01e57SJeff Chen */
102*73b01e57SJeff Chen eth = (struct ethhdr *)
103*73b01e57SJeff Chen ((u8 *)&rx_pkt_hdr->eth803_hdr
104*73b01e57SJeff Chen + sizeof(rx_pkt_hdr->eth803_hdr) +
105*73b01e57SJeff Chen sizeof(rx_pkt_hdr->rfc1042_hdr)
106*73b01e57SJeff Chen - sizeof(rx_pkt_hdr->eth803_hdr.h_dest)
107*73b01e57SJeff Chen - sizeof(rx_pkt_hdr->eth803_hdr.h_source)
108*73b01e57SJeff Chen - sizeof(rx_pkt_hdr->rfc1042_hdr.snap_type));
109*73b01e57SJeff Chen
110*73b01e57SJeff Chen memcpy(eth->h_source, rx_pkt_hdr->eth803_hdr.h_source,
111*73b01e57SJeff Chen sizeof(eth->h_source));
112*73b01e57SJeff Chen memcpy(eth->h_dest, rx_pkt_hdr->eth803_hdr.h_dest,
113*73b01e57SJeff Chen sizeof(eth->h_dest));
114*73b01e57SJeff Chen
115*73b01e57SJeff Chen /*
116*73b01e57SJeff Chen * Chop off the rxpd + the excess memory from the 802.2/llc/snap
117*73b01e57SJeff Chen * header that was removed.
118*73b01e57SJeff Chen */
119*73b01e57SJeff Chen hdr_chop = (u8 *)eth - (u8 *)local_rx_pd;
120*73b01e57SJeff Chen } else {
121*73b01e57SJeff Chen /* Chop off the rxpd */
122*73b01e57SJeff Chen hdr_chop = (u8 *)&rx_pkt_hdr->eth803_hdr - (u8 *)local_rx_pd;
123*73b01e57SJeff Chen }
124*73b01e57SJeff Chen
125*73b01e57SJeff Chen /*
126*73b01e57SJeff Chen * Chop off the leading header bytes so the it points to the start of
127*73b01e57SJeff Chen * either the reconstructed EthII frame or the 802.2/llc/snap frame
128*73b01e57SJeff Chen */
129*73b01e57SJeff Chen skb_pull(skb, hdr_chop);
130*73b01e57SJeff Chen
131*73b01e57SJeff Chen if (priv->hs2_enabled &&
132*73b01e57SJeff Chen nxpwifi_discard_gratuitous_arp(priv, skb)) {
133*73b01e57SJeff Chen nxpwifi_dbg(priv->adapter, INFO, "Bypassed Gratuitous ARP\n");
134*73b01e57SJeff Chen dev_kfree_skb_any(skb);
135*73b01e57SJeff Chen return 0;
136*73b01e57SJeff Chen }
137*73b01e57SJeff Chen
138*73b01e57SJeff Chen /* Only stash RX bitrate for unicast packets. */
139*73b01e57SJeff Chen if (likely(!is_multicast_ether_addr(rx_pkt_hdr->eth803_hdr.h_dest))) {
140*73b01e57SJeff Chen priv->rxpd_rate = local_rx_pd->rx_rate;
141*73b01e57SJeff Chen priv->rxpd_htinfo = local_rx_pd->rate_info;
142*73b01e57SJeff Chen }
143*73b01e57SJeff Chen
144*73b01e57SJeff Chen if (GET_BSS_ROLE(priv) == NXPWIFI_BSS_ROLE_STA ||
145*73b01e57SJeff Chen GET_BSS_ROLE(priv) == NXPWIFI_BSS_ROLE_UAP) {
146*73b01e57SJeff Chen adj_rx_rate = nxpwifi_adjust_data_rate(priv,
147*73b01e57SJeff Chen local_rx_pd->rx_rate,
148*73b01e57SJeff Chen local_rx_pd->rate_info);
149*73b01e57SJeff Chen nxpwifi_hist_data_add(priv, adj_rx_rate, local_rx_pd->snr,
150*73b01e57SJeff Chen local_rx_pd->nf);
151*73b01e57SJeff Chen }
152*73b01e57SJeff Chen
153*73b01e57SJeff Chen ret = nxpwifi_recv_packet(priv, skb);
154*73b01e57SJeff Chen if (ret)
155*73b01e57SJeff Chen nxpwifi_dbg(priv->adapter, ERROR,
156*73b01e57SJeff Chen "recv packet failed\n");
157*73b01e57SJeff Chen
158*73b01e57SJeff Chen return ret;
159*73b01e57SJeff Chen }
160*73b01e57SJeff Chen
161*73b01e57SJeff Chen /*
162*73b01e57SJeff Chen * Process a received buffer on the STA path.
163*73b01e57SJeff Chen * Validate RxPD and lengths, handle monitor/mgmt frames, fast-path
164*73b01e57SJeff Chen * non-unicast frames, and feed unicast data into 11n reorder/BA logic.
165*73b01e57SJeff Chen */
nxpwifi_process_sta_rx_packet(struct nxpwifi_private * priv,struct sk_buff * skb)166*73b01e57SJeff Chen int nxpwifi_process_sta_rx_packet(struct nxpwifi_private *priv,
167*73b01e57SJeff Chen struct sk_buff *skb)
168*73b01e57SJeff Chen {
169*73b01e57SJeff Chen struct nxpwifi_adapter *adapter = priv->adapter;
170*73b01e57SJeff Chen int ret = 0;
171*73b01e57SJeff Chen struct rxpd *local_rx_pd;
172*73b01e57SJeff Chen struct rx_packet_hdr *rx_pkt_hdr;
173*73b01e57SJeff Chen u8 ta[ETH_ALEN];
174*73b01e57SJeff Chen u16 rx_pkt_type, rx_pkt_offset, rx_pkt_length, seq_num;
175*73b01e57SJeff Chen
176*73b01e57SJeff Chen local_rx_pd = (struct rxpd *)(skb->data);
177*73b01e57SJeff Chen rx_pkt_type = le16_to_cpu(local_rx_pd->rx_pkt_type);
178*73b01e57SJeff Chen rx_pkt_offset = le16_to_cpu(local_rx_pd->rx_pkt_offset);
179*73b01e57SJeff Chen rx_pkt_length = le16_to_cpu(local_rx_pd->rx_pkt_length);
180*73b01e57SJeff Chen seq_num = le16_to_cpu(local_rx_pd->seq_num);
181*73b01e57SJeff Chen
182*73b01e57SJeff Chen rx_pkt_hdr = (void *)local_rx_pd + rx_pkt_offset;
183*73b01e57SJeff Chen
184*73b01e57SJeff Chen if ((rx_pkt_offset + rx_pkt_length) > skb->len ||
185*73b01e57SJeff Chen sizeof(rx_pkt_hdr->eth803_hdr) + rx_pkt_offset > skb->len) {
186*73b01e57SJeff Chen nxpwifi_dbg(adapter, ERROR,
187*73b01e57SJeff Chen "wrong rx packet: len=%d, rx_pkt_offset=%d, rx_pkt_length=%d\n",
188*73b01e57SJeff Chen skb->len, rx_pkt_offset, rx_pkt_length);
189*73b01e57SJeff Chen priv->stats.rx_dropped++;
190*73b01e57SJeff Chen dev_kfree_skb_any(skb);
191*73b01e57SJeff Chen return ret;
192*73b01e57SJeff Chen }
193*73b01e57SJeff Chen
194*73b01e57SJeff Chen if (priv->adapter->enable_net_mon && rx_pkt_type == PKT_TYPE_802DOT11) {
195*73b01e57SJeff Chen ret = nxpwifi_recv_packet_to_monif(priv, skb);
196*73b01e57SJeff Chen if (ret)
197*73b01e57SJeff Chen dev_kfree_skb_any(skb);
198*73b01e57SJeff Chen return ret;
199*73b01e57SJeff Chen }
200*73b01e57SJeff Chen
201*73b01e57SJeff Chen if (rx_pkt_type == PKT_TYPE_MGMT) {
202*73b01e57SJeff Chen ret = nxpwifi_process_mgmt_packet(priv, skb);
203*73b01e57SJeff Chen if (ret && (ret != -EINPROGRESS))
204*73b01e57SJeff Chen nxpwifi_dbg(adapter, DATA, "Rx of mgmt packet failed");
205*73b01e57SJeff Chen if (ret != -EINPROGRESS)
206*73b01e57SJeff Chen dev_kfree_skb_any(skb);
207*73b01e57SJeff Chen return ret;
208*73b01e57SJeff Chen }
209*73b01e57SJeff Chen
210*73b01e57SJeff Chen /*
211*73b01e57SJeff Chen * If the packet is not an unicast packet then send the packet
212*73b01e57SJeff Chen * directly to os. Don't pass thru rx reordering
213*73b01e57SJeff Chen */
214*73b01e57SJeff Chen if (!IS_11N_ENABLED(priv) ||
215*73b01e57SJeff Chen !ether_addr_equal_unaligned(priv->curr_addr,
216*73b01e57SJeff Chen rx_pkt_hdr->eth803_hdr.h_dest)) {
217*73b01e57SJeff Chen nxpwifi_process_rx_packet(priv, skb);
218*73b01e57SJeff Chen return ret;
219*73b01e57SJeff Chen }
220*73b01e57SJeff Chen
221*73b01e57SJeff Chen if (nxpwifi_queuing_ra_based(priv)) {
222*73b01e57SJeff Chen memcpy(ta, rx_pkt_hdr->eth803_hdr.h_source, ETH_ALEN);
223*73b01e57SJeff Chen } else {
224*73b01e57SJeff Chen if (rx_pkt_type != PKT_TYPE_BAR &&
225*73b01e57SJeff Chen local_rx_pd->priority < MAX_NUM_TID)
226*73b01e57SJeff Chen priv->rx_seq[local_rx_pd->priority] = seq_num;
227*73b01e57SJeff Chen memcpy(ta, priv->curr_bss_params.bss_descriptor.mac_address,
228*73b01e57SJeff Chen ETH_ALEN);
229*73b01e57SJeff Chen }
230*73b01e57SJeff Chen
231*73b01e57SJeff Chen /* Reorder and send to OS */
232*73b01e57SJeff Chen ret = nxpwifi_11n_rx_reorder_pkt(priv, seq_num, local_rx_pd->priority,
233*73b01e57SJeff Chen ta, (u8)rx_pkt_type, skb);
234*73b01e57SJeff Chen
235*73b01e57SJeff Chen if (ret || rx_pkt_type == PKT_TYPE_BAR)
236*73b01e57SJeff Chen dev_kfree_skb_any(skb);
237*73b01e57SJeff Chen
238*73b01e57SJeff Chen if (ret)
239*73b01e57SJeff Chen priv->stats.rx_dropped++;
240*73b01e57SJeff Chen
241*73b01e57SJeff Chen return ret;
242*73b01e57SJeff Chen }
243