summaryrefslogtreecommitdiffstats
path: root/net/mac80211/mesh.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/mesh.c')
-rw-r--r--net/mac80211/mesh.c115
1 files changed, 61 insertions, 54 deletions
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index a77d40ed4e61..b0223326d9cd 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -17,7 +17,7 @@
#define TMR_RUNNING_MP 1
#define TMR_RUNNING_MPR 2
-int mesh_allocated;
+static int mesh_allocated;
static struct kmem_cache *rm_cache;
bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt)
@@ -36,6 +36,8 @@ void ieee80211s_init(void)
void ieee80211s_stop(void)
{
+ if (!mesh_allocated)
+ return;
mesh_pathtbl_unregister();
kmem_cache_destroy(rm_cache);
}
@@ -90,24 +92,22 @@ bool mesh_matches_local(struct ieee80211_sub_if_data *sdata,
(ifmsh->mesh_cc_id == ie->mesh_config->meshconf_congest) &&
(ifmsh->mesh_sp_id == ie->mesh_config->meshconf_synch) &&
(ifmsh->mesh_auth_id == ie->mesh_config->meshconf_auth)))
- goto mismatch;
+ return false;
ieee80211_sta_get_rates(local, ie, ieee80211_get_sdata_band(sdata),
&basic_rates);
if (sdata->vif.bss_conf.basic_rates != basic_rates)
- goto mismatch;
+ return false;
ieee80211_ht_oper_to_chandef(sdata->vif.bss_conf.chandef.chan,
ie->ht_operation, &sta_chan_def);
if (!cfg80211_chandef_compatible(&sdata->vif.bss_conf.chandef,
&sta_chan_def))
- goto mismatch;
+ return false;
return true;
-mismatch:
- return false;
}
/**
@@ -118,7 +118,7 @@ mismatch:
bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie)
{
return (ie->mesh_config->meshconf_cap &
- IEEE80211_MESHCONF_CAPAB_ACCEPT_PLINKS) != 0;
+ IEEE80211_MESHCONF_CAPAB_ACCEPT_PLINKS) != 0;
}
/**
@@ -196,11 +196,12 @@ void mesh_rmc_free(struct ieee80211_sub_if_data *sdata)
if (!sdata->u.mesh.rmc)
return;
- for (i = 0; i < RMC_BUCKETS; i++)
+ for (i = 0; i < RMC_BUCKETS; i++) {
list_for_each_entry_safe(p, n, &rmc->bucket[i], list) {
list_del(&p->list);
kmem_cache_free(rm_cache, p);
}
+ }
kfree(rmc);
sdata->u.mesh.rmc = NULL;
@@ -209,6 +210,7 @@ void mesh_rmc_free(struct ieee80211_sub_if_data *sdata)
/**
* mesh_rmc_check - Check frame in recent multicast cache and add if absent.
*
+ * @sdata: interface
* @sa: source address
* @mesh_hdr: mesh_header
*
@@ -218,8 +220,8 @@ void mesh_rmc_free(struct ieee80211_sub_if_data *sdata)
* received this frame lately. If the frame is not in the cache, it is added to
* it.
*/
-int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr,
- struct ieee80211_sub_if_data *sdata)
+int mesh_rmc_check(struct ieee80211_sub_if_data *sdata,
+ const u8 *sa, struct ieee80211s_hdr *mesh_hdr)
{
struct mesh_rmc *rmc = sdata->u.mesh.rmc;
u32 seqnum = 0;
@@ -233,12 +235,11 @@ int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr,
list_for_each_entry_safe(p, n, &rmc->bucket[idx], list) {
++entries;
if (time_after(jiffies, p->exp_time) ||
- (entries == RMC_QUEUE_MAX_LEN)) {
+ entries == RMC_QUEUE_MAX_LEN) {
list_del(&p->list);
kmem_cache_free(rm_cache, p);
--entries;
- } else if ((seqnum == p->seqnum) &&
- (ether_addr_equal(sa, p->sa)))
+ } else if ((seqnum == p->seqnum) && ether_addr_equal(sa, p->sa))
return -1;
}
@@ -253,8 +254,8 @@ int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr,
return 0;
}
-int
-mesh_add_meshconf_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata)
+int mesh_add_meshconf_ie(struct ieee80211_sub_if_data *sdata,
+ struct sk_buff *skb)
{
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
u8 *pos, neighbors;
@@ -285,19 +286,18 @@ mesh_add_meshconf_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata)
/* Mesh capability */
*pos = IEEE80211_MESHCONF_CAPAB_FORWARDING;
*pos |= ifmsh->accepting_plinks ?
- IEEE80211_MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00;
+ IEEE80211_MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00;
/* Mesh PS mode. See IEEE802.11-2012 8.4.2.100.8 */
*pos |= ifmsh->ps_peers_deep_sleep ?
- IEEE80211_MESHCONF_CAPAB_POWER_SAVE_LEVEL : 0x00;
+ IEEE80211_MESHCONF_CAPAB_POWER_SAVE_LEVEL : 0x00;
*pos++ |= ifmsh->adjusting_tbtt ?
- IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING : 0x00;
+ IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING : 0x00;
*pos++ = 0x00;
return 0;
}
-int
-mesh_add_meshid_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata)
+int mesh_add_meshid_ie(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
{
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
u8 *pos;
@@ -314,8 +314,8 @@ mesh_add_meshid_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata)
return 0;
}
-int mesh_add_awake_window_ie(struct sk_buff *skb,
- struct ieee80211_sub_if_data *sdata)
+static int mesh_add_awake_window_ie(struct ieee80211_sub_if_data *sdata,
+ struct sk_buff *skb)
{
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
u8 *pos;
@@ -337,8 +337,8 @@ int mesh_add_awake_window_ie(struct sk_buff *skb,
return 0;
}
-int
-mesh_add_vendor_ies(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata)
+int mesh_add_vendor_ies(struct ieee80211_sub_if_data *sdata,
+ struct sk_buff *skb)
{
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
u8 offset, len;
@@ -361,8 +361,7 @@ mesh_add_vendor_ies(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata)
return 0;
}
-int
-mesh_add_rsn_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata)
+int mesh_add_rsn_ie(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
{
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
u8 len = 0;
@@ -390,8 +389,8 @@ mesh_add_rsn_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata)
return 0;
}
-int mesh_add_ds_params_ie(struct sk_buff *skb,
- struct ieee80211_sub_if_data *sdata)
+static int mesh_add_ds_params_ie(struct ieee80211_sub_if_data *sdata,
+ struct sk_buff *skb)
{
struct ieee80211_chanctx_conf *chanctx_conf;
struct ieee80211_channel *chan;
@@ -417,8 +416,8 @@ int mesh_add_ds_params_ie(struct sk_buff *skb,
return 0;
}
-int mesh_add_ht_cap_ie(struct sk_buff *skb,
- struct ieee80211_sub_if_data *sdata)
+int mesh_add_ht_cap_ie(struct ieee80211_sub_if_data *sdata,
+ struct sk_buff *skb)
{
struct ieee80211_local *local = sdata->local;
enum ieee80211_band band = ieee80211_get_sdata_band(sdata);
@@ -439,8 +438,8 @@ int mesh_add_ht_cap_ie(struct sk_buff *skb,
return 0;
}
-int mesh_add_ht_oper_ie(struct sk_buff *skb,
- struct ieee80211_sub_if_data *sdata)
+int mesh_add_ht_oper_ie(struct ieee80211_sub_if_data *sdata,
+ struct sk_buff *skb)
{
struct ieee80211_local *local = sdata->local;
struct ieee80211_chanctx_conf *chanctx_conf;
@@ -475,6 +474,7 @@ int mesh_add_ht_oper_ie(struct sk_buff *skb,
return 0;
}
+
static void ieee80211_mesh_path_timer(unsigned long data)
{
struct ieee80211_sub_if_data *sdata =
@@ -520,7 +520,7 @@ void ieee80211_mesh_root_setup(struct ieee80211_if_mesh *ifmsh)
/**
* ieee80211_fill_mesh_addresses - fill addresses of a locally originated mesh frame
- * @hdr: 802.11 frame header
+ * @hdr: 802.11 frame header
* @fc: frame control field
* @meshda: destination address in the mesh
* @meshsa: source address address in the mesh. Same as TA, as frame is
@@ -551,8 +551,8 @@ int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc,
/**
* ieee80211_new_mesh_header - create a new mesh header
- * @meshhdr: uninitialized mesh header
* @sdata: mesh interface to be used
+ * @meshhdr: uninitialized mesh header
* @addr4or5: 1st address in the ae header, which may correspond to address 4
* (if addr6 is NULL) or address 5 (if addr6 is present). It may
* be NULL.
@@ -561,32 +561,38 @@ int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc,
*
* Return the header length.
*/
-int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr,
- struct ieee80211_sub_if_data *sdata, char *addr4or5,
- char *addr6)
+int ieee80211_new_mesh_header(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211s_hdr *meshhdr,
+ const char *addr4or5, const char *addr6)
{
- int aelen = 0;
- BUG_ON(!addr4or5 && addr6);
+ if (WARN_ON(!addr4or5 && addr6))
+ return 0;
+
memset(meshhdr, 0, sizeof(*meshhdr));
+
meshhdr->ttl = sdata->u.mesh.mshcfg.dot11MeshTTL;
+
+ /* FIXME: racy -- TX on multiple queues can be concurrent */
put_unaligned(cpu_to_le32(sdata->u.mesh.mesh_seqnum), &meshhdr->seqnum);
sdata->u.mesh.mesh_seqnum++;
+
if (addr4or5 && !addr6) {
meshhdr->flags |= MESH_FLAGS_AE_A4;
- aelen += ETH_ALEN;
memcpy(meshhdr->eaddr1, addr4or5, ETH_ALEN);
+ return 2 * ETH_ALEN;
} else if (addr4or5 && addr6) {
meshhdr->flags |= MESH_FLAGS_AE_A5_A6;
- aelen += 2 * ETH_ALEN;
memcpy(meshhdr->eaddr1, addr4or5, ETH_ALEN);
memcpy(meshhdr->eaddr2, addr6, ETH_ALEN);
+ return 3 * ETH_ALEN;
}
- return 6 + aelen;
+
+ return ETH_ALEN;
}
-static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata,
- struct ieee80211_if_mesh *ifmsh)
+static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata)
{
+ struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
u32 changed;
ieee80211_sta_expire(sdata, IEEE80211_MESH_PEER_INACTIVITY_LIMIT);
@@ -596,7 +602,8 @@ static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata,
ieee80211_mbss_info_change_notify(sdata, changed);
mod_timer(&ifmsh->housekeeping_timer,
- round_jiffies(jiffies + IEEE80211_MESH_HOUSEKEEPING_INTERVAL));
+ round_jiffies(jiffies +
+ IEEE80211_MESH_HOUSEKEEPING_INTERVAL));
}
static void ieee80211_mesh_rootpath(struct ieee80211_sub_if_data *sdata)
@@ -708,7 +715,7 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh)
*pos++ = 0x0;
if (ieee80211_add_srates_ie(sdata, skb, true, band) ||
- mesh_add_ds_params_ie(skb, sdata))
+ mesh_add_ds_params_ie(sdata, skb))
goto out_free;
bcn->head_len = skb->len;
@@ -719,13 +726,13 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh)
bcn->tail = bcn->head + bcn->head_len;
if (ieee80211_add_ext_srates_ie(sdata, skb, true, band) ||
- mesh_add_rsn_ie(skb, sdata) ||
- mesh_add_ht_cap_ie(skb, sdata) ||
- mesh_add_ht_oper_ie(skb, sdata) ||
- mesh_add_meshid_ie(skb, sdata) ||
- mesh_add_meshconf_ie(skb, sdata) ||
- mesh_add_awake_window_ie(skb, sdata) ||
- mesh_add_vendor_ies(skb, sdata))
+ mesh_add_rsn_ie(sdata, skb) ||
+ mesh_add_ht_cap_ie(sdata, skb) ||
+ mesh_add_ht_oper_ie(sdata, skb) ||
+ mesh_add_meshid_ie(sdata, skb) ||
+ mesh_add_meshconf_ie(sdata, skb) ||
+ mesh_add_awake_window_ie(sdata, skb) ||
+ mesh_add_vendor_ies(sdata, skb))
goto out_free;
bcn->tail_len = skb->len;
@@ -1039,7 +1046,7 @@ void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata)
mesh_mpp_table_grow();
if (test_and_clear_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags))
- ieee80211_mesh_housekeeping(sdata, ifmsh);
+ ieee80211_mesh_housekeeping(sdata);
if (test_and_clear_bit(MESH_WORK_ROOT, &ifmsh->wrkq_flags))
ieee80211_mesh_rootpath(sdata);