Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 111632
b: refs/heads/master
c: 98c8fcc
h: refs/heads/master
v: v3
  • Loading branch information
Johannes Berg authored and John W. Linville committed Sep 11, 2008
1 parent 49b4aad commit 65692cc
Show file tree
Hide file tree
Showing 4 changed files with 195 additions and 137 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 0a51b27e956bd9580296c48191b78175ed8b5971
refs/heads/master: 98c8fccfaea838e62ffde2f2e44568844e0e5472
9 changes: 9 additions & 0 deletions trunk/net/mac80211/ieee80211_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -937,6 +937,15 @@ void ieee802_11_parse_elems(u8 *start, size_t len,
void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local);
int ieee80211_sta_start_scan(struct ieee80211_sub_if_data *scan_sdata,
u8 *ssid, size_t ssid_len);
struct ieee80211_sta_bss *
ieee80211_bss_info_update(struct ieee80211_local *local,
struct ieee80211_rx_status *rx_status,
struct ieee80211_mgmt *mgmt,
size_t len,
struct ieee802_11_elems *elems,
int freq, bool beacon);
void ieee80211_rx_bss_put(struct ieee80211_local *local,
struct ieee80211_sta_bss *bss);

#ifdef CONFIG_MAC80211_MESH
void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata);
Expand Down
253 changes: 117 additions & 136 deletions trunk/net/mac80211/mlme.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,10 +128,9 @@ static void __ieee80211_rx_bss_hash_del(struct ieee80211_local *local,
}

static struct ieee80211_sta_bss *
ieee80211_rx_bss_add(struct ieee80211_sub_if_data *sdata, u8 *bssid, int freq,
ieee80211_rx_bss_add(struct ieee80211_local *local, u8 *bssid, int freq,
u8 *ssid, u8 ssid_len)
{
struct ieee80211_local *local = sdata->local;
struct ieee80211_sta_bss *bss;

bss = kzalloc(sizeof(*bss), GFP_ATOMIC);
Expand Down Expand Up @@ -230,8 +229,8 @@ static void ieee80211_rx_bss_free(struct ieee80211_sta_bss *bss)
kfree(bss);
}

static void ieee80211_rx_bss_put(struct ieee80211_local *local,
struct ieee80211_sta_bss *bss)
void ieee80211_rx_bss_put(struct ieee80211_local *local,
struct ieee80211_sta_bss *bss)
{
local_bh_disable();
if (!atomic_dec_and_lock(&bss->users, &local->sta_bss_lock)) {
Expand Down Expand Up @@ -2443,74 +2442,16 @@ static u64 ieee80211_sta_get_mandatory_rates(struct ieee80211_local *local,
return mandatory_rates;
}

static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
struct ieee80211_mgmt *mgmt,
size_t len,
struct ieee80211_rx_status *rx_status,
struct ieee802_11_elems *elems)
struct ieee80211_sta_bss *
ieee80211_bss_info_update(struct ieee80211_local *local,
struct ieee80211_rx_status *rx_status,
struct ieee80211_mgmt *mgmt,
size_t len,
struct ieee802_11_elems *elems,
int freq, bool beacon)
{
struct ieee80211_local *local = sdata->local;
int freq, clen;
struct ieee80211_sta_bss *bss;
struct sta_info *sta;
struct ieee80211_channel *channel;
u64 beacon_timestamp, rx_timestamp;
u64 supp_rates = 0;
bool beacon = ieee80211_is_beacon(mgmt->frame_control);
enum ieee80211_band band = rx_status->band;
DECLARE_MAC_BUF(mac);
DECLARE_MAC_BUF(mac2);

if (elems->ds_params && elems->ds_params_len == 1)
freq = ieee80211_channel_to_frequency(elems->ds_params[0]);
else
freq = rx_status->freq;

channel = ieee80211_get_channel(local->hw.wiphy, freq);

if (!channel || channel->flags & IEEE80211_CHAN_DISABLED)
return;

if (ieee80211_vif_is_mesh(&sdata->vif) && elems->mesh_id &&
elems->mesh_config && mesh_matches_local(elems, sdata)) {
supp_rates = ieee80211_sta_get_rates(local, elems, band);

mesh_neighbour_update(mgmt->sa, supp_rates, sdata,
mesh_peer_accepts_plinks(elems));
}

if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && elems->supp_rates &&
memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0) {
supp_rates = ieee80211_sta_get_rates(local, elems, band);

rcu_read_lock();

sta = sta_info_get(local, mgmt->sa);
if (sta) {
u64 prev_rates;

prev_rates = sta->supp_rates[band];
/* make sure mandatory rates are always added */
sta->supp_rates[band] = supp_rates |
ieee80211_sta_get_mandatory_rates(local, band);

#ifdef CONFIG_MAC80211_IBSS_DEBUG
if (sta->supp_rates[band] != prev_rates)
printk(KERN_DEBUG "%s: updated supp_rates set "
"for %s based on beacon info (0x%llx | "
"0x%llx -> 0x%llx)\n",
sdata->dev->name, print_mac(mac, sta->addr),
(unsigned long long) prev_rates,
(unsigned long long) supp_rates,
(unsigned long long) sta->supp_rates[band]);
#endif
} else {
ieee80211_ibss_add_sta(sdata, NULL, mgmt->bssid,
mgmt->sa, supp_rates);
}

rcu_read_unlock();
}
int clen;

#ifdef CONFIG_MAC80211_MESH
if (elems->mesh_config)
Expand All @@ -2528,10 +2469,10 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
elems->mesh_config_len, freq);
else
#endif
bss = ieee80211_rx_bss_add(sdata, mgmt->bssid, freq,
bss = ieee80211_rx_bss_add(local, mgmt->bssid, freq,
elems->ssid, elems->ssid_len);
if (!bss)
return;
return NULL;
} else {
#if 0
/* TODO: order by RSSI? */
Expand Down Expand Up @@ -2578,17 +2519,114 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
bss->supp_rates_len += clen;
}

bss->band = band;
bss->band = rx_status->band;

beacon_timestamp = le64_to_cpu(mgmt->u.beacon.timestamp);

bss->timestamp = beacon_timestamp;
bss->timestamp = le64_to_cpu(mgmt->u.beacon.timestamp);
bss->last_update = jiffies;
bss->signal = rx_status->signal;
bss->noise = rx_status->noise;
bss->qual = rx_status->qual;
bss->wmm_used = elems->wmm_param || elems->wmm_info;

if (!beacon)
bss->last_probe_resp = jiffies;

/*
* For probe responses, or if we don't have any information yet,
* use the IEs from the beacon.
*/
if (!bss->ies || !beacon) {
if (bss->ies == NULL || bss->ies_len < elems->total_len) {
kfree(bss->ies);
bss->ies = kmalloc(elems->total_len, GFP_ATOMIC);
}
if (bss->ies) {
memcpy(bss->ies, elems->ie_start, elems->total_len);
bss->ies_len = elems->total_len;
} else
bss->ies_len = 0;
}

return bss;
}

static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
struct ieee80211_mgmt *mgmt,
size_t len,
struct ieee80211_rx_status *rx_status,
struct ieee802_11_elems *elems,
bool beacon)
{
struct ieee80211_local *local = sdata->local;
int freq;
struct ieee80211_sta_bss *bss;
struct sta_info *sta;
struct ieee80211_channel *channel;
u64 beacon_timestamp, rx_timestamp;
u64 supp_rates = 0;
enum ieee80211_band band = rx_status->band;
DECLARE_MAC_BUF(mac);
DECLARE_MAC_BUF(mac2);

if (elems->ds_params && elems->ds_params_len == 1)
freq = ieee80211_channel_to_frequency(elems->ds_params[0]);
else
freq = rx_status->freq;

channel = ieee80211_get_channel(local->hw.wiphy, freq);

if (!channel || channel->flags & IEEE80211_CHAN_DISABLED)
return;

if (ieee80211_vif_is_mesh(&sdata->vif) && elems->mesh_id &&
elems->mesh_config && mesh_matches_local(elems, sdata)) {
supp_rates = ieee80211_sta_get_rates(local, elems, band);

mesh_neighbour_update(mgmt->sa, supp_rates, sdata,
mesh_peer_accepts_plinks(elems));
}

if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && elems->supp_rates &&
memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0) {
supp_rates = ieee80211_sta_get_rates(local, elems, band);

rcu_read_lock();

sta = sta_info_get(local, mgmt->sa);
if (sta) {
u64 prev_rates;

prev_rates = sta->supp_rates[band];
/* make sure mandatory rates are always added */
sta->supp_rates[band] = supp_rates |
ieee80211_sta_get_mandatory_rates(local, band);

#ifdef CONFIG_MAC80211_IBSS_DEBUG
if (sta->supp_rates[band] != prev_rates)
printk(KERN_DEBUG "%s: updated supp_rates set "
"for %s based on beacon info (0x%llx | "
"0x%llx -> 0x%llx)\n",
sdata->dev->name, print_mac(mac, sta->addr),
(unsigned long long) prev_rates,
(unsigned long long) supp_rates,
(unsigned long long) sta->supp_rates[band]);
#endif
} else {
ieee80211_ibss_add_sta(sdata, NULL, mgmt->bssid,
mgmt->sa, supp_rates);
}

rcu_read_unlock();
}

bss = ieee80211_bss_info_update(local, rx_status, mgmt, len, elems,
freq, beacon);
if (!bss)
return;

/* was just updated in ieee80211_bss_info_update */
beacon_timestamp = bss->timestamp;

/*
* In STA mode, the remaining parameters should not be overridden
* by beacons because they're not necessarily accurate there.
Expand All @@ -2599,21 +2637,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
return;
}

if (bss->ies == NULL || bss->ies_len < elems->total_len) {
kfree(bss->ies);
bss->ies = kmalloc(elems->total_len, GFP_ATOMIC);
}
if (bss->ies) {
memcpy(bss->ies, elems->ie_start, elems->total_len);
bss->ies_len = elems->total_len;
} else
bss->ies_len = 0;

bss->wmm_used = elems->wmm_param || elems->wmm_info;

/* check if we need to merge IBSS */
if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && beacon &&
!local->sta_sw_scanning && !local->sta_hw_scanning &&
bss->capability & WLAN_CAPABILITY_IBSS &&
bss->freq == local->oper_channel->center_freq &&
elems->ssid_len == sdata->u.sta.ssid_len &&
Expand Down Expand Up @@ -2690,7 +2715,7 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata,
ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen,
&elems);

ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems);
ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, false);

/* direct probe may be part of the association flow */
if (test_and_clear_bit(IEEE80211_STA_REQ_DIRECT_PROBE,
Expand Down Expand Up @@ -2721,7 +2746,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,

ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems);

ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems);
ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, true);

if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
return;
Expand All @@ -2731,15 +2756,6 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
memcmp(ifsta->bssid, mgmt->bssid, ETH_ALEN) != 0)
return;

/* Do not send changes to driver if we are scanning. This removes
* requirement that a driver's bss_info_changed/conf_tx functions
* need to be atomic.
* This is really ugly code, we should rewrite scanning and make
* all this more understandable for humans.
*/
if (local->sta_sw_scanning || local->sta_hw_scanning)
return;

ieee80211_sta_wmm_params(local, ifsta, elems.wmm_param,
elems.wmm_param_len);

Expand Down Expand Up @@ -2982,41 +2998,6 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
}


ieee80211_rx_result
ieee80211_sta_rx_scan(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
struct ieee80211_rx_status *rx_status)
{
struct ieee80211_mgmt *mgmt;
__le16 fc;

if (skb->len < 2)
return RX_DROP_UNUSABLE;

mgmt = (struct ieee80211_mgmt *) skb->data;
fc = mgmt->frame_control;

if (ieee80211_is_ctl(fc))
return RX_CONTINUE;

if (skb->len < 24)
return RX_DROP_MONITOR;

if (ieee80211_is_probe_resp(fc)) {
ieee80211_rx_mgmt_probe_resp(sdata, mgmt, skb->len, rx_status);
dev_kfree_skb(skb);
return RX_QUEUED;
}

if (ieee80211_is_beacon(fc)) {
ieee80211_rx_mgmt_beacon(sdata, mgmt, skb->len, rx_status);
dev_kfree_skb(skb);
return RX_QUEUED;
}

return RX_CONTINUE;
}


static int ieee80211_sta_active_ibss(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_local *local = sdata->local;
Expand Down Expand Up @@ -3233,7 +3214,7 @@ static int ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata,
printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID %s\n",
sdata->dev->name, print_mac(mac, bssid));

bss = ieee80211_rx_bss_add(sdata, bssid,
bss = ieee80211_rx_bss_add(local, bssid,
local->hw.conf.channel->center_freq,
sdata->u.sta.ssid, sdata->u.sta.ssid_len);
if (!bss)
Expand Down
Loading

0 comments on commit 65692cc

Please sign in to comment.