📄 orinoco.c
字号:
"to BAP\n", dev->name, err); goto busy; } /* Clear the 802.11 header and data length fields - some * firmwares (e.g. Lucent/Agere 8.xx) appear to get confused * if this isn't done. */ hermes_clear_words(hw, HERMES_DATA0, HERMES_802_3_OFFSET - HERMES_802_11_OFFSET); /* Encapsulate Ethernet-II frames */ if (ntohs(eh->h_proto) > ETH_DATA_LEN) { /* Ethernet-II frame */ struct header_struct { struct ethhdr eth; /* 802.3 header */ u8 encap[6]; /* 802.2 header */ } __attribute__ ((packed)) hdr; /* Strip destination and source from the data */ skb_pull(skb, 2 * ETH_ALEN); data_off = HERMES_802_2_OFFSET + sizeof(encaps_hdr); /* And move them to a separate header */ memcpy(&hdr.eth, eh, 2 * ETH_ALEN); hdr.eth.h_proto = htons(sizeof(encaps_hdr) + skb->len); memcpy(hdr.encap, encaps_hdr, sizeof(encaps_hdr)); err = hermes_bap_pwrite(hw, USER_BAP, &hdr, sizeof(hdr), txfid, HERMES_802_3_OFFSET); if (err) { if (net_ratelimit()) printk(KERN_ERR "%s: Error %d writing packet " "header to BAP\n", dev->name, err); goto busy; } } else { /* IEEE 802.3 frame */ data_off = HERMES_802_3_OFFSET; } err = hermes_bap_pwrite(hw, USER_BAP, skb->data, skb->len, txfid, data_off); if (err) { printk(KERN_ERR "%s: Error %d writing packet to BAP\n", dev->name, err); goto busy; } /* Finally, we actually initiate the send */ netif_stop_queue(dev); err = hermes_docmd_wait(hw, HERMES_CMD_TX | HERMES_CMD_RECL, txfid, NULL); if (err) { netif_start_queue(dev); if (net_ratelimit()) printk(KERN_ERR "%s: Error %d transmitting packet\n", dev->name, err); goto busy; } dev->trans_start = jiffies; stats->tx_bytes += data_off + skb->len; goto ok; drop: stats->tx_errors++; stats->tx_dropped++; ok: orinoco_unlock(priv, &flags); dev_kfree_skb(skb); return NETDEV_TX_OK; busy: if (err == -EIO) schedule_work(&priv->reset_work); orinoco_unlock(priv, &flags); return NETDEV_TX_BUSY;}static void __orinoco_ev_alloc(struct net_device *dev, hermes_t *hw){ struct orinoco_private *priv = netdev_priv(dev); u16 fid = hermes_read_regn(hw, ALLOCFID); if (fid != priv->txfid) { if (fid != DUMMY_FID) printk(KERN_WARNING "%s: Allocate event on unexpected fid (%04X)\n", dev->name, fid); return; } hermes_write_regn(hw, ALLOCFID, DUMMY_FID);}static void __orinoco_ev_tx(struct net_device *dev, hermes_t *hw){ struct orinoco_private *priv = netdev_priv(dev); struct net_device_stats *stats = &priv->stats; stats->tx_packets++; netif_wake_queue(dev); hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);}static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw){ struct orinoco_private *priv = netdev_priv(dev); struct net_device_stats *stats = &priv->stats; u16 fid = hermes_read_regn(hw, TXCOMPLFID); u16 status; struct hermes_txexc_data hdr; int err = 0; if (fid == DUMMY_FID) return; /* Nothing's really happened */ /* Read part of the frame header - we need status and addr1 */ err = hermes_bap_pread(hw, IRQ_BAP, &hdr, sizeof(struct hermes_txexc_data), fid, 0); hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID); stats->tx_errors++; if (err) { printk(KERN_WARNING "%s: Unable to read descriptor on Tx error " "(FID=%04X error %d)\n", dev->name, fid, err); return; } DEBUG(1, "%s: Tx error, err %d (FID=%04X)\n", dev->name, err, fid); /* We produce a TXDROP event only for retry or lifetime * exceeded, because that's the only status that really mean * that this particular node went away. * Other errors means that *we* screwed up. - Jean II */ status = le16_to_cpu(hdr.desc.status); if (status & (HERMES_TXSTAT_RETRYERR | HERMES_TXSTAT_AGEDERR)) { union iwreq_data wrqu; /* Copy 802.11 dest address. * We use the 802.11 header because the frame may * not be 802.3 or may be mangled... * In Ad-Hoc mode, it will be the node address. * In managed mode, it will be most likely the AP addr * User space will figure out how to convert it to * whatever it needs (IP address or else). * - Jean II */ memcpy(wrqu.addr.sa_data, hdr.addr1, ETH_ALEN); wrqu.addr.sa_family = ARPHRD_ETHER; /* Send event to user space */ wireless_send_event(dev, IWEVTXDROP, &wrqu, NULL); } netif_wake_queue(dev);}static void orinoco_tx_timeout(struct net_device *dev){ struct orinoco_private *priv = netdev_priv(dev); struct net_device_stats *stats = &priv->stats; struct hermes *hw = &priv->hw; printk(KERN_WARNING "%s: Tx timeout! " "ALLOCFID=%04x, TXCOMPLFID=%04x, EVSTAT=%04x\n", dev->name, hermes_read_regn(hw, ALLOCFID), hermes_read_regn(hw, TXCOMPLFID), hermes_read_regn(hw, EVSTAT)); stats->tx_errors++; schedule_work(&priv->reset_work);}/********************************************************************//* Rx path (data frames) *//********************************************************************//* Does the frame have a SNAP header indicating it should be * de-encapsulated to Ethernet-II? */static inline int is_ethersnap(void *_hdr){ u8 *hdr = _hdr; /* We de-encapsulate all packets which, a) have SNAP headers * (i.e. SSAP=DSAP=0xaa and CTRL=0x3 in the 802.2 LLC header * and where b) the OUI of the SNAP header is 00:00:00 or * 00:00:f8 - we need both because different APs appear to use * different OUIs for some reason */ return (memcmp(hdr, &encaps_hdr, 5) == 0) && ( (hdr[5] == 0x00) || (hdr[5] == 0xf8) );}static inline void orinoco_spy_gather(struct net_device *dev, u_char *mac, int level, int noise){ struct iw_quality wstats; wstats.level = level - 0x95; wstats.noise = noise - 0x95; wstats.qual = (level > noise) ? (level - noise) : 0; wstats.updated = 7; /* Update spy records */ wireless_spy_update(dev, mac, &wstats);}static void orinoco_stat_gather(struct net_device *dev, struct sk_buff *skb, struct hermes_rx_descriptor *desc){ struct orinoco_private *priv = netdev_priv(dev); /* Using spy support with lots of Rx packets, like in an * infrastructure (AP), will really slow down everything, because * the MAC address must be compared to each entry of the spy list. * If the user really asks for it (set some address in the * spy list), we do it, but he will pay the price. * Note that to get here, you need both WIRELESS_SPY * compiled in AND some addresses in the list !!! */ /* Note : gcc will optimise the whole section away if * WIRELESS_SPY is not defined... - Jean II */ if (SPY_NUMBER(priv)) { orinoco_spy_gather(dev, skb_mac_header(skb) + ETH_ALEN, desc->signal, desc->silence); }}/* * orinoco_rx_monitor - handle received monitor frames. * * Arguments: * dev network device * rxfid received FID * desc rx descriptor of the frame * * Call context: interrupt */static void orinoco_rx_monitor(struct net_device *dev, u16 rxfid, struct hermes_rx_descriptor *desc){ u32 hdrlen = 30; /* return full header by default */ u32 datalen = 0; u16 fc; int err; int len; struct sk_buff *skb; struct orinoco_private *priv = netdev_priv(dev); struct net_device_stats *stats = &priv->stats; hermes_t *hw = &priv->hw; len = le16_to_cpu(desc->data_len); /* Determine the size of the header and the data */ fc = le16_to_cpu(desc->frame_ctl); switch (fc & IEEE80211_FCTL_FTYPE) { case IEEE80211_FTYPE_DATA: if ((fc & IEEE80211_FCTL_TODS) && (fc & IEEE80211_FCTL_FROMDS)) hdrlen = 30; else hdrlen = 24; datalen = len; break; case IEEE80211_FTYPE_MGMT: hdrlen = 24; datalen = len; break; case IEEE80211_FTYPE_CTL: switch (fc & IEEE80211_FCTL_STYPE) { case IEEE80211_STYPE_PSPOLL: case IEEE80211_STYPE_RTS: case IEEE80211_STYPE_CFEND: case IEEE80211_STYPE_CFENDACK: hdrlen = 16; break; case IEEE80211_STYPE_CTS: case IEEE80211_STYPE_ACK: hdrlen = 10; break; } break; default: /* Unknown frame type */ break; } /* sanity check the length */ if (datalen > IEEE80211_DATA_LEN + 12) { printk(KERN_DEBUG "%s: oversized monitor frame, " "data length = %d\n", dev->name, datalen); stats->rx_length_errors++; goto update_stats; } skb = dev_alloc_skb(hdrlen + datalen); if (!skb) { printk(KERN_WARNING "%s: Cannot allocate skb for monitor frame\n", dev->name); goto update_stats; } /* Copy the 802.11 header to the skb */ memcpy(skb_put(skb, hdrlen), &(desc->frame_ctl), hdrlen); skb_reset_mac_header(skb); /* If any, copy the data from the card to the skb */ if (datalen > 0) { err = hermes_bap_pread(hw, IRQ_BAP, skb_put(skb, datalen), ALIGN(datalen, 2), rxfid, HERMES_802_2_OFFSET); if (err) { printk(KERN_ERR "%s: error %d reading monitor frame\n", dev->name, err); goto drop; } } skb->dev = dev; skb->ip_summed = CHECKSUM_NONE; skb->pkt_type = PACKET_OTHERHOST; skb->protocol = __constant_htons(ETH_P_802_2); dev->last_rx = jiffies; stats->rx_packets++; stats->rx_bytes += skb->len; netif_rx(skb); return; drop: dev_kfree_skb_irq(skb); update_stats: stats->rx_errors++; stats->rx_dropped++;}static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw){ struct orinoco_private *priv = netdev_priv(dev); struct net_device_stats *stats = &priv->stats; struct iw_statistics *wstats = &priv->wstats; struct sk_buff *skb = NULL; u16 rxfid, status, fc; int length; struct hermes_rx_descriptor desc; struct ethhdr *hdr; int err; rxfid = hermes_read_regn(hw, RXFID); err = hermes_bap_pread(hw, IRQ_BAP, &desc, sizeof(desc), rxfid, 0); if (err) { printk(KERN_ERR "%s: error %d reading Rx descriptor. " "Frame dropped.\n", dev->name, err); goto update_stats; } status = le16_to_cpu(desc.status); if (status & HERMES_RXSTAT_BADCRC) { DEBUG(1, "%s: Bad CRC on Rx. Frame dropped.\n", dev->name); stats->rx_crc_errors++; goto update_stats; } /* Handle frames in monitor mode */ if (priv->iw_mode == IW_MODE_MONITOR) { orinoco_rx_monitor(dev, rxfid, &desc); return; } if (status & HERMES_RXSTAT_UNDECRYPTABLE) { DEBUG(1, "%s: Undecryptable frame on Rx. Frame dropped.\n", dev->name); wstats->discard.code++; goto update_stats; } length = le16_to_cpu(desc.data_len); fc = le16_to_cpu(desc.frame_ctl); /* Sanity checks */ if (length < 3) { /* No for even an 802.2 LLC header */ /* At least on Symbol firmware with PCF we get quite a lot of these legitimately - Poll frames with no data. */ return; } if (length > IEEE80211_DATA_LEN) { printk(KERN_WARNING "%s: Oversized frame received (%d bytes)\n", dev->name, length); stats->rx_length_errors++; goto update_stats; } /* We need space for the packet data itself, plus an ethernet header, plus 2 bytes so we can align the IP header on a 32bit boundary, plus 1 byte so we can read in odd length packets from the card, which has an IO granularity of 16 bits */ skb = dev_alloc_skb(length+ETH_HLEN+2+1); if (!skb) { printk(KERN_WARNING "%s: Can't allocate skb for Rx\n", dev->name); goto update_stats; } /* We'll prepend the header, so reserve space for it. The worst case is no decapsulation, when 802.3 header is prepended and nothing is removed. 2 is for aligning the IP header. */ skb_reserve(skb, ETH_HLEN + 2); err = hermes_bap_pread(hw, IRQ_BAP, skb_put(skb, length), ALIGN(length, 2), rxfid, HERMES_802_2_OFFSET); if (err) { printk(KERN_ERR "%s: error %d reading frame. " "Frame dropped.\n", dev->name, err); goto drop; } /* Handle decapsulation * In most cases, the firmware tell us about SNAP frames. * For some reason, the SNAP frames sent by LinkSys APs * are not properly recognised by most firmwares. * So, check ourselves */ if (length >= ENCAPS_OVERHEAD && (((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_1042) || ((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_TUNNEL) || is_ethersnap(skb->data))) { /* These indicate a SNAP within 802.2 LLC within 802.11 frame which we'll need to de-encapsulate to the original EthernetII frame. */ hdr = (struct ethhdr *)skb_push(skb, ETH_HLEN - ENCAPS_OVERHEAD); } else { /* 802.3 frame - prepend 802.3 header as is */ hdr = (struct ethhdr *)skb_push(skb, ETH_HLEN); hdr->h_proto = htons(length); } memcpy(hdr->h_dest, desc.addr1, ETH_ALEN); if (fc & IEEE80211_FCTL_FROMDS) memcpy(hdr->h_source, desc.addr3, ETH_ALEN); else memcpy(hdr->h_source, desc.addr2, ETH_ALEN); dev->last_rx = jiffies; skb->protocol = eth_type_trans(skb, dev); skb->ip_summed = CHECKSUM_NONE; if (fc & IEEE80211_FCTL_TODS) skb->pkt_type = PACKET_OTHERHOST; /* Process the wireless stats if needed */ orinoco_stat_gather(dev, skb, &desc); /* Pass the packet to the networking stack */ netif_rx(skb); stats->rx_packets++; stats->rx_bytes += length;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -