The following series implements IBSS merging.
it is based on wireless-2.6 everything.
bruno
---
Bruno Randolf (3):
mac80211: enable IBSS merging
mac80211: move function ieee80211_sta_join_ibss()
mac80211: better definition of mactime
include/net/mac80211.h | 6 -
net/mac80211/ieee80211_sta.c | 407 +++++++++++++++++++++++-------------------
net/mac80211/rx.c | 5 -
3 files changed, 228 insertions(+), 190 deletions(-)
--
define mactime as the time when the first data symbol arrived at the HW. the
old definition was questionable because 802.11 defines timestamp only for
beacon and probe response frames, and there it means the timestamp field.
a stricter definition of mactime is necessary for correct merging of IBSS.
note that it is up to the driver to convert whatever its hardware returns to
this definition. unfortunately we don't know for example when atheros hardware
takes its rx timestamp exactly :(
Signed-off-by: Bruno Randolf <[email protected]>
Acked-by: Johannes Berg <[email protected]>
---
include/net/mac80211.h | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 460da54..1b807f4 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -295,7 +295,8 @@ enum mac80211_rx_flags {
* The low-level driver should provide this information (the subset
* supported by hardware) to the 802.11 code with each received
* frame.
- * @mactime: MAC timestamp as defined by 802.11
+ * @mactime: value in microseconds of the 64-bit Time Synchronization Function
+ * (TSF) timer when the first data symbol (MPDU) arrived at the hardware.
* @band: the active band when this frame was received
* @freq: frequency the radio was tuned to when receiving this frame, in MHz
* @ssi: signal strength when receiving this frame
On Fri, 2008-02-15 at 16:01 +0900, Bruno Randolf wrote:
> define mactime as the time when the first data symbol arrived at the HW. the
> old definition was questionable because 802.11 defines timestamp only for
> beacon and probe response frames, and there it means the timestamp field.
>
> a stricter definition of mactime is necessary for correct merging of IBSS.
>
> note that it is up to the driver to convert whatever its hardware returns to
> this definition. unfortunately we don't know for example when atheros hardware
> takes its rx timestamp exactly :(
>
> Signed-off-by: Bruno Randolf <[email protected]>
Acked-by: Johannes Berg <[email protected]>
> ---
>
> include/net/mac80211.h | 3 ++-
> 1 files changed, 2 insertions(+), 1 deletions(-)
>
>
> diff --git a/include/net/mac80211.h b/include/net/mac80211.h
> index 460da54..1b807f4 100644
> --- a/include/net/mac80211.h
> +++ b/include/net/mac80211.h
> @@ -295,7 +295,8 @@ enum mac80211_rx_flags {
> * The low-level driver should provide this information (the subset
> * supported by hardware) to the 802.11 code with each received
> * frame.
> - * @mactime: MAC timestamp as defined by 802.11
> + * @mactime: value in microseconds of the 64-bit Time Synchronization Function
> + * (TSF) timer when the first data symbol (MPDU) arrived at the hardware.
> * @band: the active band when this frame was received
> * @freq: frequency the radio was tuned to when receiving this frame, in MHz
> * @ssi: signal strength when receiving this frame
>
>
enable IBSS cell merging. if an IBSS beacon with the same channel, same=
ESSID
and a TSF higher than the local TSF (mactime) is received, we have to j=
oin its
BSSID. while this might not be immediately apparent from reading the 80=
2.11
standard it is compliant and necessary to make IBSS mode functional in =
many
cases. most drivers have a similar behaviour.
* move the relevant code section (previously only containing debug code=
) down
to the end of the function, so we can reuse the bss structure.
* we have to compare the mactime (TSF at the time of packet receive) ra=
ther
than the current TSF. since mactime is defined as the time the first da=
ta
symbol arrived we add the time until byte 24 where the timestamp reside=
s, since
this is how the beacon timestamp is defined. as some some drivers are n=
ot able
to give a reliable mactime we fall back to use the current TSF, which w=
ill be
enough to catch most (but not all) cases where an IBSS merge is necessa=
ry.
* in IBSS mode we want to allow beacons to override probe response info=
so we
can correctly do merges.
* we don't only configure beacons based on scan results, so change that
message.
* to enable this we have to let all beacons thru in IBSS mode, even if =
they
have a different BSSID.
Signed-off-by: Bruno Randolf <[email protected]>
Acked-by: Johannes Berg <[email protected]>
---
include/net/mac80211.h | 3 +
net/mac80211/ieee80211_sta.c | 90 ++++++++++++++++++++++++++++------=
--------
net/mac80211/rx.c | 5 ++
3 files changed, 67 insertions(+), 31 deletions(-)
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 1b807f4..c634607 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -276,7 +276,8 @@ struct ieee80211_tx_control {
* @RX_FLAG_FAILED_PLCP_CRC: Set this flag if the PCLP check failed on
* the frame.
* @RX_FLAG_TSFT: The timestamp passed in the RX status (@mactime fiel=
d)
- * is valid.
+ * is valid. This is useful in monitor mode and necessary for beacon f=
rames
+ * to enable IBSS merging.
*/
enum mac80211_rx_flags {
RX_FLAG_MMIC_ERROR =3D 1<<0,
diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.=
c
index 72d7a86..fb96b51 100644
--- a/net/mac80211/ieee80211_sta.c
+++ b/net/mac80211/ieee80211_sta.c
@@ -2202,7 +2202,7 @@ static void ieee80211_rx_bss_info(struct net_devi=
ce *dev,
struct ieee80211_sta_bss *bss;
struct sta_info *sta;
struct ieee80211_sub_if_data *sdata =3D IEEE80211_DEV_TO_SUB_IF(dev);
- u64 timestamp;
+ u64 beacon_timestamp, rx_timestamp;
DECLARE_MAC_BUF(mac);
DECLARE_MAC_BUF(mac2);
=20
@@ -2219,31 +2219,7 @@ static void ieee80211_rx_bss_info(struct net_dev=
ice *dev,
if (baselen > len)
return;
=20
- timestamp =3D le64_to_cpu(mgmt->u.beacon.timestamp);
-
- if (sdata->vif.type =3D=3D IEEE80211_IF_TYPE_IBSS && beacon &&
- memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) =3D=3D 0) {
-#ifdef CONFIG_MAC80211_IBSS_DEBUG
- static unsigned long last_tsf_debug =3D 0;
- u64 tsf;
- if (local->ops->get_tsf)
- tsf =3D local->ops->get_tsf(local_to_hw(local));
- else
- tsf =3D -1LLU;
- if (time_after(jiffies, last_tsf_debug + 5 * HZ)) {
- printk(KERN_DEBUG "RX beacon SA=3D%s BSSID=3D"
- "%s TSF=3D0x%llx BCN=3D0x%llx diff=3D%lld "
- "@%lu\n",
- print_mac(mac, mgmt->sa), print_mac(mac2, mgmt->bssid),
- (unsigned long long)tsf,
- (unsigned long long)timestamp,
- (unsigned long long)(tsf - timestamp),
- jiffies);
- last_tsf_debug =3D jiffies;
- }
-#endif /* CONFIG_MAC80211_IBSS_DEBUG */
- }
-
+ beacon_timestamp =3D le64_to_cpu(mgmt->u.beacon.timestamp);
ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems=
);
=20
if (sdata->vif.type =3D=3D IEEE80211_IF_TYPE_IBSS && elems.supp_rates=
&&
@@ -2329,8 +2305,10 @@ static void ieee80211_rx_bss_info(struct net_dev=
ice *dev,
=20
bss->band =3D rx_status->band;
=20
- if (bss->probe_resp && beacon) {
- /* Do not allow beacon to override data from Probe Response. */
+ if (sdata->vif.type !=3D IEEE80211_IF_TYPE_IBSS &&
+ bss->probe_resp && beacon) {
+ /* STA mode:
+ * Do not allow beacon to override data from Probe Response. */
ieee80211_rx_bss_put(dev, bss);
return;
}
@@ -2427,13 +2405,67 @@ static void ieee80211_rx_bss_info(struct net_de=
vice *dev,
bss->ht_ie_len =3D 0;
}
=20
- bss->timestamp =3D timestamp;
+ bss->timestamp =3D beacon_timestamp;
bss->last_update =3D jiffies;
bss->rssi =3D rx_status->ssi;
bss->signal =3D rx_status->signal;
bss->noise =3D rx_status->noise;
if (!beacon)
bss->probe_resp++;
+
+ /* check if we need to merge IBSS */
+ if (sdata->vif.type =3D=3D IEEE80211_IF_TYPE_IBSS && beacon &&
+ !local->sta_sw_scanning && !local->sta_hw_scanning &&
+ mgmt->u.beacon.capab_info & WLAN_CAPABILITY_IBSS &&
+ bss->freq =3D=3D local->oper_channel->center_freq &&
+ elems.ssid_len =3D=3D sdata->u.sta.ssid_len &&
+ memcmp(elems.ssid, sdata->u.sta.ssid, sdata->u.sta.ssid_len) =3D=3D=
0) {
+ if (rx_status->flag & RX_FLAG_TSFT) {
+ /* in order for correct IBSS merging we need mactime
+ *
+ * since mactime is defined as the time the first data
+ * symbol of the frame hits the PHY, and the timestamp
+ * of the beacon is defined as "the time that the data
+ * symbol containing the first bit of the timestamp is
+ * transmitted to the PHY plus the transmitting STA=E2=80=99s
+ * delays through its local PHY from the MAC-PHY
+ * interface to its interface with the WM"
+ * (802.11 11.1.2) - equals the time this bit arrives at
+ * the receiver - we have to take into account the
+ * offset between the two.
+ * e.g: at 1 MBit that means mactime is 192 usec earlier
+ * (=3D24 bytes * 8 usecs/byte) than the beacon timestamp.
+ */
+ int rate =3D local->hw.wiphy->bands[rx_status->band]->
+ bitrates[rx_status->rate_idx].bitrate;
+ rx_timestamp =3D rx_status->mactime + (24 * 8 * 10 / rate);
+ } else if (local && local->ops && local->ops->get_tsf)
+ /* second best option: get current TSF */
+ rx_timestamp =3D local->ops->get_tsf(local_to_hw(local));
+ else
+ /* can't merge without knowing the TSF */
+ rx_timestamp =3D -1LLU;
+#ifdef CONFIG_MAC80211_IBSS_DEBUG
+ printk(KERN_DEBUG "RX beacon SA=3D%s BSSID=3D"
+ "%s TSF=3D0x%llx BCN=3D0x%llx diff=3D%lld @%lu\n",
+ print_mac(mac, mgmt->sa),
+ print_mac(mac2, mgmt->bssid),
+ (unsigned long long)rx_timestamp,
+ (unsigned long long)beacon_timestamp,
+ (unsigned long long)(rx_timestamp - beacon_timestamp),
+ jiffies);
+#endif /* CONFIG_MAC80211_IBSS_DEBUG */
+ if (beacon_timestamp > rx_timestamp) {
+ if (CONFIG_MAC80211_IBSS_DEBUG || net_ratelimit())
+ printk(KERN_DEBUG "%s: beacon TSF higher than "
+ "local TSF - IBSS merge with BSSID %s\n",
+ dev->name, print_mac(mac, mgmt->bssid));
+ ieee80211_sta_join_ibss(dev, &sdata->u.sta, bss);
+ ieee80211_ibss_add_sta(dev, NULL,
+ mgmt->bssid, mgmt->sa);
+ }
+ }
+
ieee80211_rx_bss_put(dev, bss);
}
=20
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index b1fc112..064adda 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1694,7 +1694,10 @@ static int prepare_for_handlers(struct ieee80211=
_sub_if_data *sdata,
case IEEE80211_IF_TYPE_IBSS:
if (!bssid)
return 0;
- if (!ieee80211_bssid_match(bssid, sdata->u.sta.bssid)) {
+ if ((rx->fc & IEEE80211_FCTL_FTYPE) =3D=3D IEEE80211_FTYPE_MGMT &&
+ (rx->fc & IEEE80211_FCTL_STYPE) =3D=3D IEEE80211_STYPE_BEACON)
+ return 1;
+ else if (!ieee80211_bssid_match(bssid, sdata->u.sta.bssid)) {
if (!(rx->flags & IEEE80211_TXRXD_RXIN_SCAN))
return 0;
rx->flags &=3D ~IEEE80211_TXRXD_RXRA_MATCH;
this moves ieee80211_sta_join_ibss() up for the next patch (ibss merge).
Signed-off-by: Bruno Randolf <[email protected]>
Acked-by: Johannes Berg <[email protected]>
---
net/mac80211/ieee80211_sta.c | 317 +++++++++++++++++++++---------------------
1 files changed, 159 insertions(+), 158 deletions(-)
diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c
index 2c7b8be..72d7a86 100644
--- a/net/mac80211/ieee80211_sta.c
+++ b/net/mac80211/ieee80211_sta.c
@@ -2030,6 +2030,165 @@ void ieee80211_rx_bss_list_deinit(struct net_device *dev)
}
+static int ieee80211_sta_join_ibss(struct net_device *dev,
+ struct ieee80211_if_sta *ifsta,
+ struct ieee80211_sta_bss *bss)
+{
+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+ int res, rates, i, j;
+ struct sk_buff *skb;
+ struct ieee80211_mgmt *mgmt;
+ struct ieee80211_tx_control control;
+ struct rate_selection ratesel;
+ u8 *pos;
+ struct ieee80211_sub_if_data *sdata;
+ struct ieee80211_supported_band *sband;
+
+ sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
+
+ /* Remove possible STA entries from other IBSS networks. */
+ sta_info_flush(local, NULL);
+
+ if (local->ops->reset_tsf) {
+ /* Reset own TSF to allow time synchronization work. */
+ local->ops->reset_tsf(local_to_hw(local));
+ }
+ memcpy(ifsta->bssid, bss->bssid, ETH_ALEN);
+ res = ieee80211_if_config(dev);
+ if (res)
+ return res;
+
+ local->hw.conf.beacon_int = bss->beacon_int >= 10 ? bss->beacon_int : 10;
+
+ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ sdata->drop_unencrypted = bss->capability &
+ WLAN_CAPABILITY_PRIVACY ? 1 : 0;
+
+ res = ieee80211_set_freq(local, bss->freq);
+
+ if (local->oper_channel->flags & IEEE80211_CHAN_NO_IBSS) {
+ printk(KERN_DEBUG "%s: IBSS not allowed on frequency "
+ "%d MHz\n", dev->name, local->oper_channel->center_freq);
+ return -1;
+ }
+
+ /* Set beacon template */
+ skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400);
+ do {
+ if (!skb)
+ break;
+
+ skb_reserve(skb, local->hw.extra_tx_headroom);
+
+ mgmt = (struct ieee80211_mgmt *)
+ skb_put(skb, 24 + sizeof(mgmt->u.beacon));
+ memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon));
+ mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
+ IEEE80211_STYPE_BEACON);
+ memset(mgmt->da, 0xff, ETH_ALEN);
+ memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
+ memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
+ mgmt->u.beacon.beacon_int =
+ cpu_to_le16(local->hw.conf.beacon_int);
+ mgmt->u.beacon.capab_info = cpu_to_le16(bss->capability);
+
+ pos = skb_put(skb, 2 + ifsta->ssid_len);
+ *pos++ = WLAN_EID_SSID;
+ *pos++ = ifsta->ssid_len;
+ memcpy(pos, ifsta->ssid, ifsta->ssid_len);
+
+ rates = bss->supp_rates_len;
+ if (rates > 8)
+ rates = 8;
+ pos = skb_put(skb, 2 + rates);
+ *pos++ = WLAN_EID_SUPP_RATES;
+ *pos++ = rates;
+ memcpy(pos, bss->supp_rates, rates);
+
+ if (bss->band == IEEE80211_BAND_2GHZ) {
+ pos = skb_put(skb, 2 + 1);
+ *pos++ = WLAN_EID_DS_PARAMS;
+ *pos++ = 1;
+ *pos++ = ieee80211_frequency_to_channel(bss->freq);
+ }
+
+ pos = skb_put(skb, 2 + 2);
+ *pos++ = WLAN_EID_IBSS_PARAMS;
+ *pos++ = 2;
+ /* FIX: set ATIM window based on scan results */
+ *pos++ = 0;
+ *pos++ = 0;
+
+ if (bss->supp_rates_len > 8) {
+ rates = bss->supp_rates_len - 8;
+ pos = skb_put(skb, 2 + rates);
+ *pos++ = WLAN_EID_EXT_SUPP_RATES;
+ *pos++ = rates;
+ memcpy(pos, &bss->supp_rates[8], rates);
+ }
+
+ memset(&control, 0, sizeof(control));
+ rate_control_get_rate(dev, sband, skb, &ratesel);
+ if (!ratesel.rate) {
+ printk(KERN_DEBUG "%s: Failed to determine TX rate "
+ "for IBSS beacon\n", dev->name);
+ break;
+ }
+ control.vif = &sdata->vif;
+ control.tx_rate = ratesel.rate;
+ if (sdata->bss_conf.use_short_preamble &&
+ ratesel.rate->flags & IEEE80211_RATE_SHORT_PREAMBLE)
+ control.flags |= IEEE80211_TXCTL_SHORT_PREAMBLE;
+ control.antenna_sel_tx = local->hw.conf.antenna_sel_tx;
+ control.flags |= IEEE80211_TXCTL_NO_ACK;
+ control.retry_limit = 1;
+
+ ifsta->probe_resp = skb_copy(skb, GFP_ATOMIC);
+ if (ifsta->probe_resp) {
+ mgmt = (struct ieee80211_mgmt *)
+ ifsta->probe_resp->data;
+ mgmt->frame_control =
+ IEEE80211_FC(IEEE80211_FTYPE_MGMT,
+ IEEE80211_STYPE_PROBE_RESP);
+ } else {
+ printk(KERN_DEBUG "%s: Could not allocate ProbeResp "
+ "template for IBSS\n", dev->name);
+ }
+
+ if (local->ops->beacon_update &&
+ local->ops->beacon_update(local_to_hw(local),
+ skb, &control) == 0) {
+ printk(KERN_DEBUG "%s: Configured IBSS beacon "
+ "template\n", dev->name);
+ skb = NULL;
+ }
+
+ rates = 0;
+ sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
+ for (i = 0; i < bss->supp_rates_len; i++) {
+ int bitrate = (bss->supp_rates[i] & 0x7f) * 5;
+ for (j = 0; j < sband->n_bitrates; j++)
+ if (sband->bitrates[j].bitrate == bitrate)
+ rates |= BIT(j);
+ }
+ ifsta->supp_rates_bits[local->hw.conf.channel->band] = rates;
+ } while (0);
+
+ if (skb) {
+ printk(KERN_DEBUG "%s: Failed to configure IBSS beacon "
+ "template\n", dev->name);
+ dev_kfree_skb(skb);
+ }
+
+ ifsta->state = IEEE80211_IBSS_JOINED;
+ mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL);
+
+ ieee80211_rx_bss_put(dev, bss);
+
+ return res;
+}
+
+
static void ieee80211_rx_bss_info(struct net_device *dev,
struct ieee80211_mgmt *mgmt,
size_t len,
@@ -2896,164 +3055,6 @@ static int ieee80211_sta_config_auth(struct net_device *dev,
return -1;
}
-static int ieee80211_sta_join_ibss(struct net_device *dev,
- struct ieee80211_if_sta *ifsta,
- struct ieee80211_sta_bss *bss)
-{
- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
- int res, rates, i, j;
- struct sk_buff *skb;
- struct ieee80211_mgmt *mgmt;
- struct ieee80211_tx_control control;
- struct rate_selection ratesel;
- u8 *pos;
- struct ieee80211_sub_if_data *sdata;
- struct ieee80211_supported_band *sband;
-
- sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
-
- /* Remove possible STA entries from other IBSS networks. */
- sta_info_flush(local, NULL);
-
- if (local->ops->reset_tsf) {
- /* Reset own TSF to allow time synchronization work. */
- local->ops->reset_tsf(local_to_hw(local));
- }
- memcpy(ifsta->bssid, bss->bssid, ETH_ALEN);
- res = ieee80211_if_config(dev);
- if (res)
- return res;
-
- local->hw.conf.beacon_int = bss->beacon_int >= 10 ? bss->beacon_int : 10;
-
- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- sdata->drop_unencrypted = bss->capability &
- WLAN_CAPABILITY_PRIVACY ? 1 : 0;
-
- res = ieee80211_set_freq(local, bss->freq);
-
- if (local->oper_channel->flags & IEEE80211_CHAN_NO_IBSS) {
- printk(KERN_DEBUG "%s: IBSS not allowed on frequency "
- "%d MHz\n", dev->name, local->oper_channel->center_freq);
- return -1;
- }
-
- /* Set beacon template based on scan results */
- skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400);
- do {
- if (!skb)
- break;
-
- skb_reserve(skb, local->hw.extra_tx_headroom);
-
- mgmt = (struct ieee80211_mgmt *)
- skb_put(skb, 24 + sizeof(mgmt->u.beacon));
- memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon));
- mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
- IEEE80211_STYPE_BEACON);
- memset(mgmt->da, 0xff, ETH_ALEN);
- memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
- memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
- mgmt->u.beacon.beacon_int =
- cpu_to_le16(local->hw.conf.beacon_int);
- mgmt->u.beacon.capab_info = cpu_to_le16(bss->capability);
-
- pos = skb_put(skb, 2 + ifsta->ssid_len);
- *pos++ = WLAN_EID_SSID;
- *pos++ = ifsta->ssid_len;
- memcpy(pos, ifsta->ssid, ifsta->ssid_len);
-
- rates = bss->supp_rates_len;
- if (rates > 8)
- rates = 8;
- pos = skb_put(skb, 2 + rates);
- *pos++ = WLAN_EID_SUPP_RATES;
- *pos++ = rates;
- memcpy(pos, bss->supp_rates, rates);
-
- if (bss->band == IEEE80211_BAND_2GHZ) {
- pos = skb_put(skb, 2 + 1);
- *pos++ = WLAN_EID_DS_PARAMS;
- *pos++ = 1;
- *pos++ = ieee80211_frequency_to_channel(bss->freq);
- }
-
- pos = skb_put(skb, 2 + 2);
- *pos++ = WLAN_EID_IBSS_PARAMS;
- *pos++ = 2;
- /* FIX: set ATIM window based on scan results */
- *pos++ = 0;
- *pos++ = 0;
-
- if (bss->supp_rates_len > 8) {
- rates = bss->supp_rates_len - 8;
- pos = skb_put(skb, 2 + rates);
- *pos++ = WLAN_EID_EXT_SUPP_RATES;
- *pos++ = rates;
- memcpy(pos, &bss->supp_rates[8], rates);
- }
-
- memset(&control, 0, sizeof(control));
- rate_control_get_rate(dev, sband, skb, &ratesel);
- if (!ratesel.rate) {
- printk(KERN_DEBUG "%s: Failed to determine TX rate "
- "for IBSS beacon\n", dev->name);
- break;
- }
- control.vif = &sdata->vif;
- control.tx_rate = ratesel.rate;
- if (sdata->bss_conf.use_short_preamble &&
- ratesel.rate->flags & IEEE80211_RATE_SHORT_PREAMBLE)
- control.flags |= IEEE80211_TXCTL_SHORT_PREAMBLE;
- control.antenna_sel_tx = local->hw.conf.antenna_sel_tx;
- control.flags |= IEEE80211_TXCTL_NO_ACK;
- control.retry_limit = 1;
-
- ifsta->probe_resp = skb_copy(skb, GFP_ATOMIC);
- if (ifsta->probe_resp) {
- mgmt = (struct ieee80211_mgmt *)
- ifsta->probe_resp->data;
- mgmt->frame_control =
- IEEE80211_FC(IEEE80211_FTYPE_MGMT,
- IEEE80211_STYPE_PROBE_RESP);
- } else {
- printk(KERN_DEBUG "%s: Could not allocate ProbeResp "
- "template for IBSS\n", dev->name);
- }
-
- if (local->ops->beacon_update &&
- local->ops->beacon_update(local_to_hw(local),
- skb, &control) == 0) {
- printk(KERN_DEBUG "%s: Configured IBSS beacon "
- "template based on scan results\n", dev->name);
- skb = NULL;
- }
-
- rates = 0;
- sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
- for (i = 0; i < bss->supp_rates_len; i++) {
- int bitrate = (bss->supp_rates[i] & 0x7f) * 5;
- for (j = 0; j < sband->n_bitrates; j++)
- if (sband->bitrates[j].bitrate == bitrate)
- rates |= BIT(j);
- }
- ifsta->supp_rates_bits[local->hw.conf.channel->band] = rates;
- } while (0);
-
- if (skb) {
- printk(KERN_DEBUG "%s: Failed to configure IBSS beacon "
- "template\n", dev->name);
- dev_kfree_skb(skb);
- }
-
- ifsta->state = IEEE80211_IBSS_JOINED;
- mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL);
-
- ieee80211_rx_bss_put(dev, bss);
-
- return res;
-}
-
static int ieee80211_sta_create_ibss(struct net_device *dev,
struct ieee80211_if_sta *ifsta)