2007-10-31 01:45:06

by Luis Carlos Cobo

[permalink] [raw]
Subject: [PATCH 6/7] o80211s: support for mesh beaconing


Signed-off-by: Luis Carlos Cobo <[email protected]>
---
net/mac80211/ieee80211.c | 7 +++
net/mac80211/ieee80211_i.h | 3 +
net/mac80211/ieee80211_sta.c | 88 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 98 insertions(+), 0 deletions(-)

diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c
index fc7c6a8..e6839fd 100644
--- a/net/mac80211/ieee80211.c
+++ b/net/mac80211/ieee80211.c
@@ -473,6 +473,13 @@ static int __ieee80211_if_config(struct net_device *dev,
conf.bssid = sdata->u.sta.bssid;
conf.ssid = sdata->u.sta.ssid;
conf.ssid_len = sdata->u.sta.ssid_len;
+ } else if (sdata->type == IEEE80211_IF_TYPE_MESH) {
+ /* SSID is wildcard (all 0s) */
+ conf.mesh_id = sdata->u.sta.mesh_id;
+ conf.mesh_id_len = sdata->u.sta.mesh_id_len;
+ ieee80211_set_mesh_beacon_template(dev, &conf);
+ local->hw.flags |= IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE;
+ ieee80211_start_mesh(dev);
} else if (sdata->type == IEEE80211_IF_TYPE_AP) {
conf.ssid = sdata->u.ap.ssid;
conf.ssid_len = sdata->u.ap.ssid_len;
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 518c55e..b66e000 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -766,6 +766,9 @@ int ieee80211_sta_disassociate(struct net_device *dev, u16 reason);
void ieee80211_erp_info_change_notify(struct net_device *dev, u8 changes);
void ieee80211_reset_erp_info(struct net_device *dev);
void ieee80211_start_mesh(struct net_device *dev);
+int ieee80211_set_mesh_beacon_template(struct net_device *dev,
+ struct ieee80211_if_conf *conf);
+

/* ieee80211_iface.c */
int ieee80211_if_add(struct net_device *dev, const char *name,
diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c
index 8c5f23a..2c24980 100644
--- a/net/mac80211/ieee80211_sta.c
+++ b/net/mac80211/ieee80211_sta.c
@@ -2213,6 +2213,94 @@ static int ieee80211_sta_config_auth(struct net_device *dev,
return -1;
}

+
+int ieee80211_set_mesh_beacon_template(struct net_device *dev,
+ struct ieee80211_if_conf *conf)
+{
+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+ struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400);
+ struct ieee80211_hw_mode *mode = local->oper_hw_mode;
+ struct ieee80211_mgmt *mgmt;
+ u8 *pos;
+ int rates, i;
+
+ if(!skb)
+ return -1;
+ 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);
+ /* SSID is left zeroed, wildcard value */
+ mgmt->u.beacon.beacon_int =
+ cpu_to_le16(local->hw.conf.beacon_int);
+ mgmt->u.beacon.capab_info = 0x0; /* 0x0 for MPs */
+
+ pos = skb_put(skb, 2);
+ *pos++ = WLAN_EID_SSID;
+ *pos++ = 0x0;
+
+ rates = mode->num_rates;
+ if (rates > 8)
+ rates = 8;
+ pos = skb_put(skb, 2 + rates);
+ *pos++ = WLAN_EID_SUPP_RATES;
+ *pos++ = rates;
+ for (i = 0; i < rates; i++) {
+ int rate = mode->rates[i].rate;
+ *pos++ = (u8) (rate / 5);
+ }
+
+ if (mode->num_rates > 8) {
+ rates = mode->num_rates - 8;
+ pos = skb_put(skb, 2 + rates);
+ *pos++ = WLAN_EID_EXT_SUPP_RATES;
+ *pos++ = rates;
+ for (i = 0; i < rates; i++) {
+ int rate = mode->rates[i+8].rate;
+ *pos++ = (u8) (rate / 5);
+ }
+ }
+
+ pos = skb_put(skb, 17);
+ *pos++ = WLAN_EID_MESH_CONFIG;
+ *pos++ = 15;
+ /* Version */
+ *pos++ = 1;
+
+ /* Active path selection protocol ID */
+ *pos++ = 0x00; /* 3 byte OUI: */
+ *pos++ = 0x0f; /* All other OUIs are */
+ *pos++ = 0xac; /* vendor specific. */
+ *pos++ = 0xff; /* Null protocol. */
+
+ /* Active path selection metric ID */
+ *pos++ = 0x00; /* 3 byte OUI */
+ *pos++ = 0x0f;
+ *pos++ = 0xac;
+ *pos++ = 0xff; /* Null metric */
+ /* Channel precedence:
+ * Not running simple channel unification protocol
+ */
+ memset(pos, 0x00, 4);
+ pos += 4;
+ /* Mesh capability */
+ memset(pos, 0x00, 2);
+
+ pos = skb_put(skb, 2 + conf->mesh_id_len);
+ *pos++ = WLAN_EID_MESH_ID;
+ *pos++ = conf->mesh_id_len;
+ if (conf->mesh_id_len)
+ memcpy(pos, conf->mesh_id, conf->mesh_id_len);
+
+ conf->beacon = skb;
+ return 0;
+}
+
+
static int ieee80211_sta_join_ibss(struct net_device *dev,
struct ieee80211_if_sta *ifsta,
struct ieee80211_sta_bss *bss)
--
1.5.2.5