aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/rx.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2008-05-15 03:52:37 -0400
committerDavid S. Miller <davem@davemloft.net>2008-05-15 03:52:37 -0400
commitf42a44494bcdf03fc851c03d438464d59c0ceaf5 (patch)
tree986ea7b54e9fc79a64863fd7e92eabd99ffd37a3 /net/mac80211/rx.c
parent63fe46da9c380b3f2bbdf3765044649517cc717c (diff)
parentef85ad541f9a6ccd3f89ec73f92b2d6f45a9d3e8 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Diffstat (limited to 'net/mac80211/rx.c')
-rw-r--r--net/mac80211/rx.c214
1 files changed, 143 insertions, 71 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 9b5a3cbec265..fa68305fd59e 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -77,6 +77,134 @@ static inline int should_drop_frame(struct ieee80211_rx_status *status,
77 return 0; 77 return 0;
78} 78}
79 79
80static int
81ieee80211_rx_radiotap_len(struct ieee80211_local *local,
82 struct ieee80211_rx_status *status)
83{
84 int len;
85
86 /* always present fields */
87 len = sizeof(struct ieee80211_radiotap_header) + 9;
88
89 if (status->flag & RX_FLAG_TSFT)
90 len += 8;
91 if (local->hw.flags & IEEE80211_HW_SIGNAL_DB ||
92 local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
93 len += 1;
94 if (local->hw.flags & IEEE80211_HW_NOISE_DBM)
95 len += 1;
96
97 if (len & 1) /* padding for RX_FLAGS if necessary */
98 len++;
99
100 /* make sure radiotap starts at a naturally aligned address */
101 if (len % 8)
102 len = roundup(len, 8);
103
104 return len;
105}
106
107/**
108 * ieee80211_add_rx_radiotap_header - add radiotap header
109 *
110 * add a radiotap header containing all the fields which the hardware provided.
111 */
112static void
113ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
114 struct sk_buff *skb,
115 struct ieee80211_rx_status *status,
116 struct ieee80211_rate *rate,
117 int rtap_len)
118{
119 struct ieee80211_radiotap_header *rthdr;
120 unsigned char *pos;
121
122 rthdr = (struct ieee80211_radiotap_header *)skb_push(skb, rtap_len);
123 memset(rthdr, 0, rtap_len);
124
125 /* radiotap header, set always present flags */
126 rthdr->it_present =
127 cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) |
128 (1 << IEEE80211_RADIOTAP_RATE) |
129 (1 << IEEE80211_RADIOTAP_CHANNEL) |
130 (1 << IEEE80211_RADIOTAP_ANTENNA) |
131 (1 << IEEE80211_RADIOTAP_RX_FLAGS));
132 rthdr->it_len = cpu_to_le16(rtap_len);
133
134 pos = (unsigned char *)(rthdr+1);
135
136 /* the order of the following fields is important */
137
138 /* IEEE80211_RADIOTAP_TSFT */
139 if (status->flag & RX_FLAG_TSFT) {
140 *(__le64 *)pos = cpu_to_le64(status->mactime);
141 rthdr->it_present |=
142 cpu_to_le32(1 << IEEE80211_RADIOTAP_TSFT);
143 pos += 8;
144 }
145
146 /* IEEE80211_RADIOTAP_FLAGS */
147 if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS)
148 *pos |= IEEE80211_RADIOTAP_F_FCS;
149 pos++;
150
151 /* IEEE80211_RADIOTAP_RATE */
152 *pos = rate->bitrate / 5;
153 pos++;
154
155 /* IEEE80211_RADIOTAP_CHANNEL */
156 *(__le16 *)pos = cpu_to_le16(status->freq);
157 pos += 2;
158 if (status->band == IEEE80211_BAND_5GHZ)
159 *(__le16 *)pos = cpu_to_le16(IEEE80211_CHAN_OFDM |
160 IEEE80211_CHAN_5GHZ);
161 else
162 *(__le16 *)pos = cpu_to_le16(IEEE80211_CHAN_DYN |
163 IEEE80211_CHAN_2GHZ);
164 pos += 2;
165
166 /* IEEE80211_RADIOTAP_DBM_ANTSIGNAL */
167 if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) {
168 *pos = status->signal;
169 rthdr->it_present |=
170 cpu_to_le32(1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL);
171 pos++;
172 }
173
174 /* IEEE80211_RADIOTAP_DBM_ANTNOISE */
175 if (local->hw.flags & IEEE80211_HW_NOISE_DBM) {
176 *pos = status->noise;
177 rthdr->it_present |=
178 cpu_to_le32(1 << IEEE80211_RADIOTAP_DBM_ANTNOISE);
179 pos++;
180 }
181
182 /* IEEE80211_RADIOTAP_LOCK_QUALITY is missing */
183
184 /* IEEE80211_RADIOTAP_ANTENNA */
185 *pos = status->antenna;
186 pos++;
187
188 /* IEEE80211_RADIOTAP_DB_ANTSIGNAL */
189 if (local->hw.flags & IEEE80211_HW_SIGNAL_DB) {
190 *pos = status->signal;
191 rthdr->it_present |=
192 cpu_to_le32(1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL);
193 pos++;
194 }
195
196 /* IEEE80211_RADIOTAP_DB_ANTNOISE is not used */
197
198 /* IEEE80211_RADIOTAP_RX_FLAGS */
199 /* ensure 2 byte alignment for the 2 byte field as required */
200 if ((pos - (unsigned char *)rthdr) & 1)
201 pos++;
202 /* FIXME: when radiotap gets a 'bad PLCP' flag use it here */
203 if (status->flag & (RX_FLAG_FAILED_FCS_CRC | RX_FLAG_FAILED_PLCP_CRC))
204 *(__le16 *)pos |= cpu_to_le16(IEEE80211_RADIOTAP_F_RX_BADFCS);
205 pos += 2;
206}
207
80/* 208/*
81 * This function copies a received frame to all monitor interfaces and 209 * This function copies a received frame to all monitor interfaces and
82 * returns a cleaned-up SKB that no longer includes the FCS nor the 210 * returns a cleaned-up SKB that no longer includes the FCS nor the
@@ -89,17 +217,6 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
89{ 217{
90 struct ieee80211_sub_if_data *sdata; 218 struct ieee80211_sub_if_data *sdata;
91 int needed_headroom = 0; 219 int needed_headroom = 0;
92 struct ieee80211_radiotap_header *rthdr;
93 __le64 *rttsft = NULL;
94 struct ieee80211_rtap_fixed_data {
95 u8 flags;
96 u8 rate;
97 __le16 chan_freq;
98 __le16 chan_flags;
99 u8 antsignal;
100 u8 padding_for_rxflags;
101 __le16 rx_flags;
102 } __attribute__ ((packed)) *rtfixed;
103 struct sk_buff *skb, *skb2; 220 struct sk_buff *skb, *skb2;
104 struct net_device *prev_dev = NULL; 221 struct net_device *prev_dev = NULL;
105 int present_fcs_len = 0; 222 int present_fcs_len = 0;
@@ -116,8 +233,8 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
116 if (status->flag & RX_FLAG_RADIOTAP) 233 if (status->flag & RX_FLAG_RADIOTAP)
117 rtap_len = ieee80211_get_radiotap_len(origskb->data); 234 rtap_len = ieee80211_get_radiotap_len(origskb->data);
118 else 235 else
119 /* room for radiotap header, always present fields and TSFT */ 236 /* room for the radiotap header based on driver features */
120 needed_headroom = sizeof(*rthdr) + sizeof(*rtfixed) + 8; 237 needed_headroom = ieee80211_rx_radiotap_len(local, status);
121 238
122 if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) 239 if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS)
123 present_fcs_len = FCS_LEN; 240 present_fcs_len = FCS_LEN;
@@ -163,55 +280,9 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
163 } 280 }
164 281
165 /* if necessary, prepend radiotap information */ 282 /* if necessary, prepend radiotap information */
166 if (!(status->flag & RX_FLAG_RADIOTAP)) { 283 if (!(status->flag & RX_FLAG_RADIOTAP))
167 rtfixed = (void *) skb_push(skb, sizeof(*rtfixed)); 284 ieee80211_add_rx_radiotap_header(local, skb, status, rate,
168 rtap_len = sizeof(*rthdr) + sizeof(*rtfixed); 285 needed_headroom);
169 if (status->flag & RX_FLAG_TSFT) {
170 rttsft = (void *) skb_push(skb, sizeof(*rttsft));
171 rtap_len += 8;
172 }
173 rthdr = (void *) skb_push(skb, sizeof(*rthdr));
174 memset(rthdr, 0, sizeof(*rthdr));
175 memset(rtfixed, 0, sizeof(*rtfixed));
176 rthdr->it_present =
177 cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) |
178 (1 << IEEE80211_RADIOTAP_RATE) |
179 (1 << IEEE80211_RADIOTAP_CHANNEL) |
180 (1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL) |
181 (1 << IEEE80211_RADIOTAP_RX_FLAGS));
182 rtfixed->flags = 0;
183 if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS)
184 rtfixed->flags |= IEEE80211_RADIOTAP_F_FCS;
185
186 if (rttsft) {
187 *rttsft = cpu_to_le64(status->mactime);
188 rthdr->it_present |=
189 cpu_to_le32(1 << IEEE80211_RADIOTAP_TSFT);
190 }
191
192 /* FIXME: when radiotap gets a 'bad PLCP' flag use it here */
193 rtfixed->rx_flags = 0;
194 if (status->flag &
195 (RX_FLAG_FAILED_FCS_CRC | RX_FLAG_FAILED_PLCP_CRC))
196 rtfixed->rx_flags |=
197 cpu_to_le16(IEEE80211_RADIOTAP_F_RX_BADFCS);
198
199 rtfixed->rate = rate->bitrate / 5;
200
201 rtfixed->chan_freq = cpu_to_le16(status->freq);
202
203 if (status->band == IEEE80211_BAND_5GHZ)
204 rtfixed->chan_flags =
205 cpu_to_le16(IEEE80211_CHAN_OFDM |
206 IEEE80211_CHAN_5GHZ);
207 else
208 rtfixed->chan_flags =
209 cpu_to_le16(IEEE80211_CHAN_DYN |
210 IEEE80211_CHAN_2GHZ);
211
212 rtfixed->antsignal = status->ssi;
213 rthdr->it_len = cpu_to_le16(rtap_len);
214 }
215 286
216 skb_reset_mac_header(skb); 287 skb_reset_mac_header(skb);
217 skb->ip_summed = CHECKSUM_UNNECESSARY; 288 skb->ip_summed = CHECKSUM_UNNECESSARY;
@@ -479,7 +550,7 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
479 ((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL && 550 ((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL &&
480 (rx->fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PSPOLL)) && 551 (rx->fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PSPOLL)) &&
481 rx->sdata->vif.type != IEEE80211_IF_TYPE_IBSS && 552 rx->sdata->vif.type != IEEE80211_IF_TYPE_IBSS &&
482 (!rx->sta || !(rx->sta->flags & WLAN_STA_ASSOC)))) { 553 (!rx->sta || !test_sta_flags(rx->sta, WLAN_STA_ASSOC)))) {
483 if ((!(rx->fc & IEEE80211_FCTL_FROMDS) && 554 if ((!(rx->fc & IEEE80211_FCTL_FROMDS) &&
484 !(rx->fc & IEEE80211_FCTL_TODS) && 555 !(rx->fc & IEEE80211_FCTL_TODS) &&
485 (rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) 556 (rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)
@@ -630,8 +701,7 @@ static void ap_sta_ps_start(struct net_device *dev, struct sta_info *sta)
630 701
631 if (sdata->bss) 702 if (sdata->bss)
632 atomic_inc(&sdata->bss->num_sta_ps); 703 atomic_inc(&sdata->bss->num_sta_ps);
633 sta->flags |= WLAN_STA_PS; 704 set_and_clear_sta_flags(sta, WLAN_STA_PS, WLAN_STA_PSPOLL);
634 sta->flags &= ~WLAN_STA_PSPOLL;
635#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG 705#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
636 printk(KERN_DEBUG "%s: STA %s aid %d enters power save mode\n", 706 printk(KERN_DEBUG "%s: STA %s aid %d enters power save mode\n",
637 dev->name, print_mac(mac, sta->addr), sta->aid); 707 dev->name, print_mac(mac, sta->addr), sta->aid);
@@ -652,7 +722,7 @@ static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta)
652 if (sdata->bss) 722 if (sdata->bss)
653 atomic_dec(&sdata->bss->num_sta_ps); 723 atomic_dec(&sdata->bss->num_sta_ps);
654 724
655 sta->flags &= ~(WLAN_STA_PS | WLAN_STA_PSPOLL); 725 clear_sta_flags(sta, WLAN_STA_PS | WLAN_STA_PSPOLL);
656 726
657 if (!skb_queue_empty(&sta->ps_tx_buf)) 727 if (!skb_queue_empty(&sta->ps_tx_buf))
658 sta_info_clear_tim_bit(sta); 728 sta_info_clear_tim_bit(sta);
@@ -720,16 +790,17 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
720 790
721 sta->rx_fragments++; 791 sta->rx_fragments++;
722 sta->rx_bytes += rx->skb->len; 792 sta->rx_bytes += rx->skb->len;
723 sta->last_rssi = rx->status->ssi;
724 sta->last_signal = rx->status->signal; 793 sta->last_signal = rx->status->signal;
794 sta->last_qual = rx->status->qual;
725 sta->last_noise = rx->status->noise; 795 sta->last_noise = rx->status->noise;
726 796
727 if (!(rx->fc & IEEE80211_FCTL_MOREFRAGS)) { 797 if (!(rx->fc & IEEE80211_FCTL_MOREFRAGS)) {
728 /* Change STA power saving mode only in the end of a frame 798 /* Change STA power saving mode only in the end of a frame
729 * exchange sequence */ 799 * exchange sequence */
730 if ((sta->flags & WLAN_STA_PS) && !(rx->fc & IEEE80211_FCTL_PM)) 800 if (test_sta_flags(sta, WLAN_STA_PS) &&
801 !(rx->fc & IEEE80211_FCTL_PM))
731 rx->sent_ps_buffered += ap_sta_ps_end(dev, sta); 802 rx->sent_ps_buffered += ap_sta_ps_end(dev, sta);
732 else if (!(sta->flags & WLAN_STA_PS) && 803 else if (!test_sta_flags(sta, WLAN_STA_PS) &&
733 (rx->fc & IEEE80211_FCTL_PM)) 804 (rx->fc & IEEE80211_FCTL_PM))
734 ap_sta_ps_start(dev, sta); 805 ap_sta_ps_start(dev, sta);
735 } 806 }
@@ -983,7 +1054,7 @@ ieee80211_rx_h_ps_poll(struct ieee80211_rx_data *rx)
983 * Tell TX path to send one frame even though the STA may 1054 * Tell TX path to send one frame even though the STA may
984 * still remain is PS mode after this frame exchange. 1055 * still remain is PS mode after this frame exchange.
985 */ 1056 */
986 rx->sta->flags |= WLAN_STA_PSPOLL; 1057 set_sta_flags(rx->sta, WLAN_STA_PSPOLL);
987 1058
988#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG 1059#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
989 printk(KERN_DEBUG "STA %s aid %d: PS Poll (entries after %d)\n", 1060 printk(KERN_DEBUG "STA %s aid %d: PS Poll (entries after %d)\n",
@@ -1046,7 +1117,8 @@ ieee80211_rx_h_remove_qos_control(struct ieee80211_rx_data *rx)
1046static int 1117static int
1047ieee80211_802_1x_port_control(struct ieee80211_rx_data *rx) 1118ieee80211_802_1x_port_control(struct ieee80211_rx_data *rx)
1048{ 1119{
1049 if (unlikely(!rx->sta || !(rx->sta->flags & WLAN_STA_AUTHORIZED))) { 1120 if (unlikely(!rx->sta ||
1121 !test_sta_flags(rx->sta, WLAN_STA_AUTHORIZED))) {
1050#ifdef CONFIG_MAC80211_DEBUG 1122#ifdef CONFIG_MAC80211_DEBUG
1051 if (net_ratelimit()) 1123 if (net_ratelimit())
1052 printk(KERN_DEBUG "%s: dropped frame " 1124 printk(KERN_DEBUG "%s: dropped frame "