diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2007-12-11 15:33:42 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-28 17:58:25 -0500 |
commit | c49e5ea322c2fb43f430abb3c4a49eae1394287e (patch) | |
tree | 53188c8aab638c95ed489eab0c796c8ba9543847 /net/mac80211 | |
parent | a07a5a86d091699fd5e791765b8a79e6b1ef96cb (diff) |
mac80211: conditionally include timestamp in radiotap information
This makes mac80211 include the low-level MAC timestamp
in the radiotap header if the driver indicated (by a new
RX flag) that the timestamp is valid.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/rx.c | 48 |
1 files changed, 32 insertions, 16 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index c542fc1c983d..9cd59ecbcd67 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -79,8 +79,9 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, | |||
79 | struct ieee80211_sub_if_data *sdata; | 79 | struct ieee80211_sub_if_data *sdata; |
80 | struct ieee80211_rate *rate; | 80 | struct ieee80211_rate *rate; |
81 | int needed_headroom = 0; | 81 | int needed_headroom = 0; |
82 | struct ieee80211_rtap_hdr { | 82 | struct ieee80211_radiotap_header *rthdr; |
83 | struct ieee80211_radiotap_header hdr; | 83 | __le64 *rttsft = NULL; |
84 | struct ieee80211_rtap_fixed_data { | ||
84 | u8 flags; | 85 | u8 flags; |
85 | u8 rate; | 86 | u8 rate; |
86 | __le16 chan_freq; | 87 | __le16 chan_freq; |
@@ -88,7 +89,7 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, | |||
88 | u8 antsignal; | 89 | u8 antsignal; |
89 | u8 padding_for_rxflags; | 90 | u8 padding_for_rxflags; |
90 | __le16 rx_flags; | 91 | __le16 rx_flags; |
91 | } __attribute__ ((packed)) *rthdr; | 92 | } __attribute__ ((packed)) *rtfixed; |
92 | struct sk_buff *skb, *skb2; | 93 | struct sk_buff *skb, *skb2; |
93 | struct net_device *prev_dev = NULL; | 94 | struct net_device *prev_dev = NULL; |
94 | int present_fcs_len = 0; | 95 | int present_fcs_len = 0; |
@@ -105,7 +106,8 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, | |||
105 | if (status->flag & RX_FLAG_RADIOTAP) | 106 | if (status->flag & RX_FLAG_RADIOTAP) |
106 | rtap_len = ieee80211_get_radiotap_len(origskb->data); | 107 | rtap_len = ieee80211_get_radiotap_len(origskb->data); |
107 | else | 108 | else |
108 | needed_headroom = sizeof(*rthdr); | 109 | /* room for radiotap header, always present fields and TSFT */ |
110 | needed_headroom = sizeof(*rthdr) + sizeof(*rtfixed) + 8; | ||
109 | 111 | ||
110 | if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) | 112 | if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) |
111 | present_fcs_len = FCS_LEN; | 113 | present_fcs_len = FCS_LEN; |
@@ -133,7 +135,7 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, | |||
133 | * them allocate enough headroom to start with. | 135 | * them allocate enough headroom to start with. |
134 | */ | 136 | */ |
135 | if (skb_headroom(skb) < needed_headroom && | 137 | if (skb_headroom(skb) < needed_headroom && |
136 | pskb_expand_head(skb, sizeof(*rthdr), 0, GFP_ATOMIC)) { | 138 | pskb_expand_head(skb, needed_headroom, 0, GFP_ATOMIC)) { |
137 | dev_kfree_skb(skb); | 139 | dev_kfree_skb(skb); |
138 | return NULL; | 140 | return NULL; |
139 | } | 141 | } |
@@ -152,42 +154,56 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, | |||
152 | 154 | ||
153 | /* if necessary, prepend radiotap information */ | 155 | /* if necessary, prepend radiotap information */ |
154 | if (!(status->flag & RX_FLAG_RADIOTAP)) { | 156 | if (!(status->flag & RX_FLAG_RADIOTAP)) { |
157 | rtfixed = (void *) skb_push(skb, sizeof(*rtfixed)); | ||
158 | rtap_len = sizeof(*rthdr) + sizeof(*rtfixed); | ||
159 | if (status->flag & RX_FLAG_TSFT) { | ||
160 | rttsft = (void *) skb_push(skb, sizeof(*rttsft)); | ||
161 | rtap_len += 8; | ||
162 | } | ||
155 | rthdr = (void *) skb_push(skb, sizeof(*rthdr)); | 163 | rthdr = (void *) skb_push(skb, sizeof(*rthdr)); |
156 | memset(rthdr, 0, sizeof(*rthdr)); | 164 | memset(rthdr, 0, sizeof(*rthdr)); |
157 | rthdr->hdr.it_len = cpu_to_le16(sizeof(*rthdr)); | 165 | memset(rtfixed, 0, sizeof(*rtfixed)); |
158 | rthdr->hdr.it_present = | 166 | rthdr->it_present = |
159 | cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) | | 167 | cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) | |
160 | (1 << IEEE80211_RADIOTAP_RATE) | | 168 | (1 << IEEE80211_RADIOTAP_RATE) | |
161 | (1 << IEEE80211_RADIOTAP_CHANNEL) | | 169 | (1 << IEEE80211_RADIOTAP_CHANNEL) | |
162 | (1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL) | | 170 | (1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL) | |
163 | (1 << IEEE80211_RADIOTAP_RX_FLAGS)); | 171 | (1 << IEEE80211_RADIOTAP_RX_FLAGS)); |
164 | rthdr->flags = local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS ? | 172 | rtfixed->flags = 0; |
165 | IEEE80211_RADIOTAP_F_FCS : 0; | 173 | if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) |
174 | rtfixed->flags |= IEEE80211_RADIOTAP_F_FCS; | ||
175 | |||
176 | if (rttsft) { | ||
177 | *rttsft = cpu_to_le64(status->mactime); | ||
178 | rthdr->it_present |= | ||
179 | cpu_to_le32(1 << IEEE80211_RADIOTAP_TSFT); | ||
180 | } | ||
166 | 181 | ||
167 | /* FIXME: when radiotap gets a 'bad PLCP' flag use it here */ | 182 | /* FIXME: when radiotap gets a 'bad PLCP' flag use it here */ |
168 | rthdr->rx_flags = 0; | 183 | rtfixed->rx_flags = 0; |
169 | if (status->flag & | 184 | if (status->flag & |
170 | (RX_FLAG_FAILED_FCS_CRC | RX_FLAG_FAILED_PLCP_CRC)) | 185 | (RX_FLAG_FAILED_FCS_CRC | RX_FLAG_FAILED_PLCP_CRC)) |
171 | rthdr->rx_flags |= | 186 | rtfixed->rx_flags |= |
172 | cpu_to_le16(IEEE80211_RADIOTAP_F_RX_BADFCS); | 187 | cpu_to_le16(IEEE80211_RADIOTAP_F_RX_BADFCS); |
173 | 188 | ||
174 | rate = ieee80211_get_rate(local, status->phymode, | 189 | rate = ieee80211_get_rate(local, status->phymode, |
175 | status->rate); | 190 | status->rate); |
176 | if (rate) | 191 | if (rate) |
177 | rthdr->rate = rate->rate / 5; | 192 | rtfixed->rate = rate->rate / 5; |
178 | 193 | ||
179 | rthdr->chan_freq = cpu_to_le16(status->freq); | 194 | rtfixed->chan_freq = cpu_to_le16(status->freq); |
180 | 195 | ||
181 | if (status->phymode == MODE_IEEE80211A) | 196 | if (status->phymode == MODE_IEEE80211A) |
182 | rthdr->chan_flags = | 197 | rtfixed->chan_flags = |
183 | cpu_to_le16(IEEE80211_CHAN_OFDM | | 198 | cpu_to_le16(IEEE80211_CHAN_OFDM | |
184 | IEEE80211_CHAN_5GHZ); | 199 | IEEE80211_CHAN_5GHZ); |
185 | else | 200 | else |
186 | rthdr->chan_flags = | 201 | rtfixed->chan_flags = |
187 | cpu_to_le16(IEEE80211_CHAN_DYN | | 202 | cpu_to_le16(IEEE80211_CHAN_DYN | |
188 | IEEE80211_CHAN_2GHZ); | 203 | IEEE80211_CHAN_2GHZ); |
189 | 204 | ||
190 | rthdr->antsignal = status->ssi; | 205 | rtfixed->antsignal = status->ssi; |
206 | rthdr->it_len = cpu_to_le16(rtap_len); | ||
191 | } | 207 | } |
192 | 208 | ||
193 | skb_set_mac_header(skb, 0); | 209 | skb_set_mac_header(skb, 0); |