0001
0002
0003
0004
0005
0006 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0007
0008 #include <linux/etherdevice.h>
0009 #include <linux/hardirq.h>
0010 #include <linux/slab.h>
0011 #include <linux/types.h>
0012 #include <linux/export.h>
0013 #include <net/cfg80211.h>
0014
0015 #include "defs.h"
0016 #include "host.h"
0017 #include "radiotap.h"
0018 #include "decl.h"
0019 #include "dev.h"
0020 #include "mesh.h"
0021
0022 struct eth803hdr {
0023 u8 dest_addr[6];
0024 u8 src_addr[6];
0025 u16 h803_len;
0026 } __packed;
0027
0028 struct rfc1042hdr {
0029 u8 llc_dsap;
0030 u8 llc_ssap;
0031 u8 llc_ctrl;
0032 u8 snap_oui[3];
0033 u16 snap_type;
0034 } __packed;
0035
0036 struct rxpackethdr {
0037 struct eth803hdr eth803_hdr;
0038 struct rfc1042hdr rfc1042_hdr;
0039 } __packed;
0040
0041 struct rx80211packethdr {
0042 struct rxpd rx_pd;
0043 void *eth80211_hdr;
0044 } __packed;
0045
0046 static int process_rxed_802_11_packet(struct lbs_private *priv,
0047 struct sk_buff *skb);
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057 int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb)
0058 {
0059 int ret = 0;
0060 struct net_device *dev = priv->dev;
0061 struct rxpackethdr *p_rx_pkt;
0062 struct rxpd *p_rx_pd;
0063 int hdrchop;
0064 struct ethhdr *p_ethhdr;
0065
0066 BUG_ON(!skb);
0067
0068 skb->ip_summed = CHECKSUM_NONE;
0069
0070 if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR) {
0071 ret = process_rxed_802_11_packet(priv, skb);
0072 goto done;
0073 }
0074
0075 p_rx_pd = (struct rxpd *) skb->data;
0076 p_rx_pkt = (struct rxpackethdr *) ((u8 *)p_rx_pd +
0077 le32_to_cpu(p_rx_pd->pkt_ptr));
0078
0079 dev = lbs_mesh_set_dev(priv, dev, p_rx_pd);
0080
0081 lbs_deb_hex(LBS_DEB_RX, "RX Data: Before chop rxpd", skb->data,
0082 min_t(unsigned int, skb->len, 100));
0083
0084 if (skb->len < (ETH_HLEN + 8 + sizeof(struct rxpd))) {
0085 lbs_deb_rx("rx err: frame received with bad length\n");
0086 dev->stats.rx_length_errors++;
0087 ret = -EINVAL;
0088 dev_kfree_skb(skb);
0089 goto done;
0090 }
0091
0092 lbs_deb_rx("rx data: skb->len - pkt_ptr = %d-%zd = %zd\n",
0093 skb->len, (size_t)le32_to_cpu(p_rx_pd->pkt_ptr),
0094 skb->len - (size_t)le32_to_cpu(p_rx_pd->pkt_ptr));
0095
0096 lbs_deb_hex(LBS_DEB_RX, "RX Data: Dest", p_rx_pkt->eth803_hdr.dest_addr,
0097 sizeof(p_rx_pkt->eth803_hdr.dest_addr));
0098 lbs_deb_hex(LBS_DEB_RX, "RX Data: Src", p_rx_pkt->eth803_hdr.src_addr,
0099 sizeof(p_rx_pkt->eth803_hdr.src_addr));
0100
0101 if (memcmp(&p_rx_pkt->rfc1042_hdr,
0102 rfc1042_header, sizeof(rfc1042_header)) == 0) {
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113 p_ethhdr = (struct ethhdr *)
0114 ((u8 *) &p_rx_pkt->eth803_hdr
0115 + sizeof(p_rx_pkt->eth803_hdr) + sizeof(p_rx_pkt->rfc1042_hdr)
0116 - sizeof(p_rx_pkt->eth803_hdr.dest_addr)
0117 - sizeof(p_rx_pkt->eth803_hdr.src_addr)
0118 - sizeof(p_rx_pkt->rfc1042_hdr.snap_type));
0119
0120 memcpy(p_ethhdr->h_source, p_rx_pkt->eth803_hdr.src_addr,
0121 sizeof(p_ethhdr->h_source));
0122 memcpy(p_ethhdr->h_dest, p_rx_pkt->eth803_hdr.dest_addr,
0123 sizeof(p_ethhdr->h_dest));
0124
0125
0126
0127
0128 hdrchop = (u8 *)p_ethhdr - (u8 *)p_rx_pd;
0129 } else {
0130 lbs_deb_hex(LBS_DEB_RX, "RX Data: LLC/SNAP",
0131 (u8 *) &p_rx_pkt->rfc1042_hdr,
0132 sizeof(p_rx_pkt->rfc1042_hdr));
0133
0134
0135 hdrchop = (u8 *)&p_rx_pkt->eth803_hdr - (u8 *)p_rx_pd;
0136 }
0137
0138
0139
0140
0141 skb_pull(skb, hdrchop);
0142
0143 priv->cur_rate = lbs_fw_index_to_data_rate(p_rx_pd->rx_rate);
0144
0145 lbs_deb_rx("rx data: size of actual packet %d\n", skb->len);
0146 dev->stats.rx_bytes += skb->len;
0147 dev->stats.rx_packets++;
0148
0149 skb->protocol = eth_type_trans(skb, dev);
0150 netif_rx(skb);
0151
0152 ret = 0;
0153 done:
0154 return ret;
0155 }
0156 EXPORT_SYMBOL_GPL(lbs_process_rxed_packet);
0157
0158
0159
0160
0161
0162
0163
0164
0165 static u8 convert_mv_rate_to_radiotap(u8 rate)
0166 {
0167 switch (rate) {
0168 case 0:
0169 return 2;
0170 case 1:
0171 return 4;
0172 case 2:
0173 return 11;
0174 case 3:
0175 return 22;
0176
0177 case 5:
0178 return 12;
0179 case 6:
0180 return 18;
0181 case 7:
0182 return 24;
0183 case 8:
0184 return 36;
0185 case 9:
0186 return 48;
0187 case 10:
0188 return 72;
0189 case 11:
0190 return 96;
0191 case 12:
0192 return 108;
0193 }
0194 pr_alert("Invalid Marvell WLAN rate %i\n", rate);
0195 return 0;
0196 }
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206 static int process_rxed_802_11_packet(struct lbs_private *priv,
0207 struct sk_buff *skb)
0208 {
0209 int ret = 0;
0210 struct net_device *dev = priv->dev;
0211 struct rx80211packethdr *p_rx_pkt;
0212 struct rxpd *prxpd;
0213 struct rx_radiotap_hdr radiotap_hdr;
0214 struct rx_radiotap_hdr *pradiotap_hdr;
0215
0216 p_rx_pkt = (struct rx80211packethdr *) skb->data;
0217 prxpd = &p_rx_pkt->rx_pd;
0218
0219
0220
0221 if (skb->len < (ETH_HLEN + 8 + sizeof(struct rxpd))) {
0222 lbs_deb_rx("rx err: frame received with bad length\n");
0223 dev->stats.rx_length_errors++;
0224 ret = -EINVAL;
0225 kfree_skb(skb);
0226 goto done;
0227 }
0228
0229 lbs_deb_rx("rx data: skb->len-sizeof(RxPd) = %d-%zd = %zd\n",
0230 skb->len, sizeof(struct rxpd), skb->len - sizeof(struct rxpd));
0231
0232
0233
0234
0235 memset(&radiotap_hdr, 0, sizeof(radiotap_hdr));
0236
0237 radiotap_hdr.hdr.it_len = cpu_to_le16 (sizeof(struct rx_radiotap_hdr));
0238 radiotap_hdr.hdr.it_present = cpu_to_le32 (RX_RADIOTAP_PRESENT);
0239 radiotap_hdr.rate = convert_mv_rate_to_radiotap(prxpd->rx_rate);
0240
0241 radiotap_hdr.antsignal = prxpd->snr + prxpd->nf;
0242
0243
0244 skb_pull(skb, sizeof(struct rxpd));
0245
0246
0247 if ((skb_headroom(skb) < sizeof(struct rx_radiotap_hdr)) &&
0248 pskb_expand_head(skb, sizeof(struct rx_radiotap_hdr), 0, GFP_ATOMIC)) {
0249 netdev_alert(dev, "%s: couldn't pskb_expand_head\n", __func__);
0250 ret = -ENOMEM;
0251 kfree_skb(skb);
0252 goto done;
0253 }
0254
0255 pradiotap_hdr = skb_push(skb, sizeof(struct rx_radiotap_hdr));
0256 memcpy(pradiotap_hdr, &radiotap_hdr, sizeof(struct rx_radiotap_hdr));
0257
0258 priv->cur_rate = lbs_fw_index_to_data_rate(prxpd->rx_rate);
0259
0260 lbs_deb_rx("rx data: size of actual packet %d\n", skb->len);
0261 dev->stats.rx_bytes += skb->len;
0262 dev->stats.rx_packets++;
0263
0264 skb->protocol = eth_type_trans(skb, priv->dev);
0265 netif_rx(skb);
0266
0267 ret = 0;
0268
0269 done:
0270 return ret;
0271 }