Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 265613
b: refs/heads/master
c: 082ebb0
h: refs/heads/master
i:
  265611: e80b1bc
v: v3
  • Loading branch information
Thomas Pedersen authored and John W. Linville committed Aug 22, 2011
1 parent 4f85471 commit db4dd12
Show file tree
Hide file tree
Showing 5 changed files with 197 additions and 63 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: f6a3e99da82167e066ebde975ec604638b42d816
refs/heads/master: 082ebb0c258d28af7452b19df9ef8b7553f37690
223 changes: 164 additions & 59 deletions trunk/net/mac80211/mesh.c
Original file line number Diff line number Diff line change
Expand Up @@ -204,90 +204,195 @@ int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr,
return 0;
}

void mesh_mgmt_ies_add(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata)
int
mesh_add_meshconf_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
u8 *pos, neighbors;
u8 meshconf_len = sizeof(struct ieee80211_meshconf_ie);

if (skb_tailroom(skb) < 2 + meshconf_len)
return -ENOMEM;

pos = skb_put(skb, 2 + meshconf_len);
*pos++ = WLAN_EID_MESH_CONFIG;
*pos++ = meshconf_len;

/* Active path selection protocol ID */
*pos++ = ifmsh->mesh_pp_id;
/* Active path selection metric ID */
*pos++ = ifmsh->mesh_pm_id;
/* Congestion control mode identifier */
*pos++ = ifmsh->mesh_cc_id;
/* Synchronization protocol identifier */
*pos++ = ifmsh->mesh_sp_id;
/* Authentication Protocol identifier */
*pos++ = ifmsh->mesh_auth_id;
/* Mesh Formation Info - number of neighbors */
neighbors = atomic_read(&ifmsh->mshstats.estab_plinks);
/* Number of neighbor mesh STAs or 15 whichever is smaller */
neighbors = (neighbors > 15) ? 15 : neighbors;
*pos++ = neighbors << 1;
/* Mesh capability */
ifmsh->accepting_plinks = mesh_plink_availables(sdata);
*pos = MESHCONF_CAPAB_FORWARDING;
*pos++ |= ifmsh->accepting_plinks ?
MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00;
*pos++ = 0x00;

return 0;
}

int
mesh_add_meshid_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
u8 *pos;

if (skb_tailroom(skb) < 2 + ifmsh->mesh_id_len)
return -ENOMEM;

pos = skb_put(skb, 2 + ifmsh->mesh_id_len);
*pos++ = WLAN_EID_MESH_ID;
*pos++ = ifmsh->mesh_id_len;
if (ifmsh->mesh_id_len)
memcpy(pos, ifmsh->mesh_id, ifmsh->mesh_id_len);

return 0;
}

int
mesh_add_vendor_ies(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
u8 offset, len;
const u8 *data;

if (!ifmsh->ie || !ifmsh->ie_len)
return 0;

/* fast-forward to vendor IEs */
offset = ieee80211_ie_split_vendor(ifmsh->ie, ifmsh->ie_len, 0);

if (offset) {
len = ifmsh->ie_len - offset;
data = ifmsh->ie + offset;
if (skb_tailroom(skb) < len)
return -ENOMEM;
memcpy(skb_put(skb, len), data, len);
}

return 0;
}

int
mesh_add_rsn_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
u8 len = 0;
const u8 *data;

if (!ifmsh->ie || !ifmsh->ie_len)
return 0;

/* find RSN IE */
data = ifmsh->ie;
while (data < ifmsh->ie + ifmsh->ie_len) {
if (*data == WLAN_EID_RSN) {
len = data[1] + 2;
break;
}
data++;
}

if (len) {
if (skb_tailroom(skb) < len)
return -ENOMEM;
memcpy(skb_put(skb, len), data, len);
}

return 0;
}

int
mesh_add_srates_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_local *local = sdata->local;
struct ieee80211_supported_band *sband;
u8 *pos;
int len, i, rate;
u8 neighbors;
int rate;
u8 i, rates, *pos;

sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
len = sband->n_bitrates;
if (len > 8)
len = 8;
pos = skb_put(skb, len + 2);
rates = sband->n_bitrates;
if (rates > 8)
rates = 8;

if (skb_tailroom(skb) < rates + 2)
return -ENOMEM;

pos = skb_put(skb, rates + 2);
*pos++ = WLAN_EID_SUPP_RATES;
*pos++ = len;
for (i = 0; i < len; i++) {
*pos++ = rates;
for (i = 0; i < rates; i++) {
rate = sband->bitrates[i].bitrate;
*pos++ = (u8) (rate / 5);
}

if (sband->n_bitrates > len) {
pos = skb_put(skb, sband->n_bitrates - len + 2);
return 0;
}

int
mesh_add_ext_srates_ie(struct sk_buff *skb,
struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_local *local = sdata->local;
struct ieee80211_supported_band *sband;
int rate;
u8 i, exrates, *pos;

sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
exrates = sband->n_bitrates;
if (exrates > 8)
exrates -= 8;
else
exrates = 0;

if (skb_tailroom(skb) < exrates + 2)
return -ENOMEM;

if (exrates) {
pos = skb_put(skb, exrates + 2);
*pos++ = WLAN_EID_EXT_SUPP_RATES;
*pos++ = sband->n_bitrates - len;
for (i = len; i < sband->n_bitrates; i++) {
*pos++ = exrates;
for (i = 8; i < sband->n_bitrates; i++) {
rate = sband->bitrates[i].bitrate;
*pos++ = (u8) (rate / 5);
}
}
return 0;
}

int mesh_add_ds_params_ie(struct sk_buff *skb,
struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_local *local = sdata->local;
struct ieee80211_supported_band *sband;
u8 *pos;

if (skb_tailroom(skb) < 3)
return -ENOMEM;

sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
if (sband->band == IEEE80211_BAND_2GHZ) {
pos = skb_put(skb, 2 + 1);
*pos++ = WLAN_EID_DS_PARAMS;
*pos++ = 1;
*pos++ = ieee80211_frequency_to_channel(local->hw.conf.channel->center_freq);
}

pos = skb_put(skb, 2 + sdata->u.mesh.mesh_id_len);
*pos++ = WLAN_EID_MESH_ID;
*pos++ = sdata->u.mesh.mesh_id_len;
if (sdata->u.mesh.mesh_id_len)
memcpy(pos, sdata->u.mesh.mesh_id, sdata->u.mesh.mesh_id_len);

pos = skb_put(skb, 2 + sizeof(struct ieee80211_meshconf_ie));
*pos++ = WLAN_EID_MESH_CONFIG;
*pos++ = sizeof(struct ieee80211_meshconf_ie);

/* Active path selection protocol ID */
*pos++ = sdata->u.mesh.mesh_pp_id;

/* Active path selection metric ID */
*pos++ = sdata->u.mesh.mesh_pm_id;

/* Congestion control mode identifier */
*pos++ = sdata->u.mesh.mesh_cc_id;

/* Synchronization protocol identifier */
*pos++ = sdata->u.mesh.mesh_sp_id;

/* Authentication Protocol identifier */
*pos++ = sdata->u.mesh.mesh_auth_id;

/* Mesh Formation Info - number of neighbors */
neighbors = atomic_read(&sdata->u.mesh.mshstats.estab_plinks);
/* Number of neighbor mesh STAs or 15 whichever is smaller */
neighbors = (neighbors > 15) ? 15 : neighbors;
*pos++ = neighbors << 1;

/* Mesh capability */
sdata->u.mesh.accepting_plinks = mesh_plink_availables(sdata);
*pos = MESHCONF_CAPAB_FORWARDING;
*pos++ |= sdata->u.mesh.accepting_plinks ?
MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00;
*pos++ = 0x00;

if (sdata->u.mesh.ie) {
int len = sdata->u.mesh.ie_len;
const u8 *data = sdata->u.mesh.ie;
if (skb_tailroom(skb) > len)
memcpy(skb_put(skb, len), data, len);
}
return 0;
}


static void ieee80211_mesh_path_timer(unsigned long data)
{
struct ieee80211_sub_if_data *sdata =
Expand Down
14 changes: 14 additions & 0 deletions trunk/net/mac80211/mesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,20 @@ bool mesh_matches_local(struct ieee802_11_elems *ie,
void mesh_ids_set_default(struct ieee80211_if_mesh *mesh);
void mesh_mgmt_ies_add(struct sk_buff *skb,
struct ieee80211_sub_if_data *sdata);
int mesh_add_meshconf_ie(struct sk_buff *skb,
struct ieee80211_sub_if_data *sdata);
int mesh_add_meshid_ie(struct sk_buff *skb,
struct ieee80211_sub_if_data *sdata);
int mesh_add_rsn_ie(struct sk_buff *skb,
struct ieee80211_sub_if_data *sdata);
int mesh_add_vendor_ies(struct sk_buff *skb,
struct ieee80211_sub_if_data *sdata);
int mesh_add_srates_ie(struct sk_buff *skb,
struct ieee80211_sub_if_data *sdata);
int mesh_add_ext_srates_ie(struct sk_buff *skb,
struct ieee80211_sub_if_data *sdata);
int mesh_add_ds_params_ie(struct sk_buff *skb,
struct ieee80211_sub_if_data *sdata);
void mesh_rmc_free(struct ieee80211_sub_if_data *sdata);
int mesh_rmc_init(struct ieee80211_sub_if_data *sdata);
void ieee80211s_init(void);
Expand Down
7 changes: 6 additions & 1 deletion trunk/net/mac80211/mesh_plink.c
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,12 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
memset(pos, 0, 2);
memcpy(pos + 2, &plid, 2);
}
mesh_mgmt_ies_add(skb, sdata);
if (mesh_add_srates_ie(skb, sdata) ||
mesh_add_ext_srates_ie(skb, sdata) ||
mesh_add_rsn_ie(skb, sdata) ||
mesh_add_meshid_ie(skb, sdata) ||
mesh_add_meshconf_ie(skb, sdata))
return -1;
}

/* Add Peer Link Management element */
Expand Down
14 changes: 12 additions & 2 deletions trunk/net/mac80211/tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -2295,13 +2295,23 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
mgmt->u.beacon.beacon_int =
cpu_to_le16(sdata->vif.bss_conf.beacon_int);
mgmt->u.beacon.capab_info = 0x0; /* 0x0 for MPs */
mgmt->u.beacon.capab_info |= cpu_to_le16(
sdata->u.mesh.security ? WLAN_CAPABILITY_PRIVACY : 0);

pos = skb_put(skb, 2);
*pos++ = WLAN_EID_SSID;
*pos++ = 0x0;

mesh_mgmt_ies_add(skb, sdata);
if (mesh_add_srates_ie(skb, sdata) ||
mesh_add_ds_params_ie(skb, sdata) ||
mesh_add_ext_srates_ie(skb, sdata) ||
mesh_add_rsn_ie(skb, sdata) ||
mesh_add_meshid_ie(skb, sdata) ||
mesh_add_meshconf_ie(skb, sdata) ||
mesh_add_vendor_ies(skb, sdata)) {
pr_err("o11s: couldn't add ies!\n");
goto out;
}
} else {
WARN_ON(1);
goto out;
Expand Down

0 comments on commit db4dd12

Please sign in to comment.